Pourquoi self-héberger Gitea sur un VPS
Gitea consomme à peine 200 à 300 Mo de RAM au repos, ce qui en fait l'une des forges Git les plus efficaces à auto-héberger. Sur un VPS, vous gardez la maîtrise totale de votre code source : aucune donnée n'est analysée par un tiers, aucune limite arbitraire sur le nombre de dépôts privés ou de collaborateurs, et aucun coût qui grimpe avec votre équipe. Pour une agence ou un développeur indépendant, un VPS unique peut héberger l'ensemble des projets clients avec des permissions cloisonnées par organisation. Gitea intègre nativement un CI/CD compatible avec les workflows GitHub Actions (Gitea Actions), un registre de paquets et un éditeur web, ce qui couvre la quasi-totalité d'un cycle de développement sans dépendance externe.
Bénéfices concrets d'un Gitea auto-hébergé
- Empreinte mémoire minime : tourne confortablement sur un VPS 2 Go de RAM même avec plusieurs dizaines d'utilisateurs.
- Dépôts privés sans facturation par siège ni limite imposée, contrairement aux offres SaaS.
- Gitea Actions intégré pour exécuter vos pipelines CI/CD sans service externe.
- Registre de paquets (Docker, npm, Composer, Maven) hébergé sur la même instance.
- Authentification fine : LDAP, OAuth2, jetons d'accès personnels et clés SSH par utilisateur.
- Sauvegarde triviale : tout tient dans un volume de données et une base de données.
Prérequis matériels et logiciels
Gitea est très frugal. Pour une petite équipe (jusqu'à 20 utilisateurs), un VPS avec 2 vCPU et 2 Go de RAM suffit largement ; comptez 4 Go si vous activez Gitea Actions avec des runners locaux qui compilent du code. Prévoyez au moins 20 à 40 Go de stockage SSD selon la taille de vos dépôts. Côté logiciel : Docker Engine et le plugin Docker Compose installés, un nom de domaine (ou sous-domaine type git.votredomaine.com) pointant vers l'IP du VPS via un enregistrement A, et le port 22 réservé au SSH du serveur — Gitea exposera son propre SSH sur un autre port pour éviter le conflit.
Déployer Gitea avec Docker et SSL
Préparer le VPS et Docker
Connectez-vous en SSH, mettez à jour le système puis installez Docker et le plugin Compose. Créez un répertoire dédié : mkdir -p /opt/gitea && cd /opt/gitea. Créez aussi un volume de données qui survivra aux mises à jour du conteneur.
Rédiger le docker-compose.yml
Définissez deux services : gitea (image gitea/gitea:latest) et une base postgres:16. Montez ./gitea:/data pour la persistance, fixez USER_UID/USER_GID à 1000, et mappez le SSH de Gitea sur le port hôte 2222 : "2222:22". Laissez le port HTTP 3000 interne, il sera servi par le reverse proxy.
Lancer les conteneurs
Exécutez docker compose up -d puis docker compose logs -f gitea pour suivre l'initialisation. Vérifiez que la connexion à PostgreSQL réussit avant de continuer.
Configurer le reverse proxy
Avec Caddy, une seule ligne suffit : git.votredomaine.com { reverse_proxy localhost:3000 }. Caddy obtient et renouvelle automatiquement le certificat Let's Encrypt. Avec Nginx, créez un server qui proxifie vers http://127.0.0.1:3000 et utilisez certbot --nginx pour le SSL.
Finaliser l'installation web
Ouvrez https://git.votredomaine.com, complétez l'assistant en renseignant l'URL de base HTTPS et l'hôte de la base de données (db:5432). Définissez le ROOT_URL correctement, sinon les liens de clonage seront erronés.
Sécuriser le SSH des dépôts
Configurez vos clients pour cloner via ssh://[email protected]:2222/..., ou ajoutez un bloc Host dans ~/.ssh/config pour masquer le port. Désactivez l'inscription publique dans l'admin si l'instance est privée.
Se connecter la première fois
Ouvrez l'URL : Gitea affiche sa page d'installation, base de données déjà pré-remplie — n'y touchez pas. Dépliez « Paramètres optionnels > Paramètres du compte administrateur », créez-y votre compte admin puis validez.
Activez Gitea Actions dès l'installation en ajoutant [actions] ENABLED = true dans app.ini, puis enregistrez un runner act_runner dans un conteneur séparé sur le même VPS. Limitez sa RAM via mem_limit pour qu'un build gourmand n'étouffe pas Gitea lui-même. Pour des pipelines lourds (compilation, tests d'intégration), dédiez plutôt un second VPS au runner et connectez-le au token d'enregistrement — vous gardez la forge réactive même pendant les builds.
Gitea ou Forgejo en 2026 : lequel choisir ?
| Critère | Gitea | Forgejo v16 |
|---|---|---|
| Gouvernance | Société commerciale (Gitea Ltd) | Association à but non lucratif (Codeberg e.V.) |
| Licence | MIT | MIT — 100 % logiciel libre, sans édition entreprise |
| Recommandé par Awesome-Selfhosted | Non (retiré en 2022) | Oui — recommandation par défaut depuis 2024 |
| Fédération ActivityPub | Non prévue | En déploiement progressif depuis Forgejo v7 |
| Compatibilité API Gitea | Référence | Compatible : même API, mêmes webhooks, même format de données |
| Sécurité — audits publics | Rares | Audits de code publiés par la communauté Codeberg |
| Roadmap communautaire | Pilotée par Gitea Ltd | Gouvernance ouverte, RFC publiques, vote des contributeurs |
| Migration depuis Gitea | N/A | Sans perte de données : même schéma de base et même format de volume |
Migrer de Gitea vers Forgejo
Sauvegarder l'instance Gitea
Avant toute opération, faites un dump complet : docker exec -u git gitea gitea admin dump -c /data/gitea/conf/app.ini. Récupérez l'archive générée hors du conteneur et vérifiez que le volume ./gitea est inclus dans votre snapshot VPS.
Vérifier la compatibilité de version
Forgejo v16 supporte la migration depuis Gitea 1.20 et ultérieur. Si votre instance tourne sur une version antérieure, montez d'abord à Gitea 1.21 ou 1.22 via docker compose pull && docker compose up -d, puis vérifiez l'absence d'erreurs dans les logs avant de continuer.
Remplacer l'image Docker
Dans votre docker-compose.yml, remplacez image: gitea/gitea:latest par image: codeberg.org/forgejo/forgejo:latest. Le volume de données (./gitea:/data) et la base PostgreSQL restent inchangés — Forgejo lit le même schéma et le même app.ini.
Redémarrer et laisser migrer
Exécutez docker compose pull && docker compose up -d. Forgejo applique automatiquement les migrations de schéma nécessaires au démarrage. Suivez docker compose logs -f forgejo jusqu'au message indiquant que le serveur HTTP écoute sur le port 3000.
Régénérer les clés SSH
Comme pour toute mise à jour qui change le binaire référencé dans authorized_keys, régénérez les entrées : docker exec -u git forgejo forgejo admin regenerate keys. Vérifiez ensuite qu'un git clone SSH réussit depuis un poste client.
Tester et valider
Ouvrez l'interface web, vérifiez les dépôts, les webhooks et les runners Forgejo Actions. Les runners act_runner enregistrés sous Gitea sont compatibles — reconnectez-les au nouveau token d'enregistrement si la clé a changé.
Forgejo v16 : les nouveautés clés (juillet 2026)
Forgejo v16.0.0 introduit la fédération ActivityPub en disponibilité générale pour les issues et les pull requests : une issue ouverte sur une instance Forgejo peut recevoir des commentaires d'utilisateurs d'une autre instance, sans compte partagé. La version intègre aussi un gestionnaire de secrets d'instance (chiffrement AES-256 au repos), un nouveau moteur de recherche de code basé sur l'index Bleve v2 avec support des expressions régulières, et des améliorations significatives du planificateur de tâches de fond. Sur le plan de la sécurité, les tokens d'API sont désormais hachés en base (bcrypt) et non stockés en clair — une migration automatique au démarrage convertit les tokens existants.
Passer à Gitea 1.27 sans perdre les accès SSH
La version 1.27 modifie le chemin interne du binaire gitea référencé dans authorized_keys. Lors de la mise à jour, les entrées existantes pointent vers l'ancien chemin : toute tentative de clone ou de push via SSH échoue silencieusement avec Permission denied (publickey), sans message d'erreur côté serveur qui pointe vers la mise à jour. Le service Gitea répond normalement via HTTPS, ce qui masque le problème. La cause n'est pas la clé de l'utilisateur mais le wrapper de commande que Gitea injecte dans authorized_keys. Après chaque mise à jour vers 1.27 (ou vers toute version qui change ce chemin), exécutez dans le conteneur : docker exec -u git gitea gitea admin regenerate keys. La commande réécrit toutes les entrées authorized_keys avec le bon chemin du binaire. Vérifiez ensuite qu'un git clone SSH réussit avant de déclarer la mise à jour terminée.
Dépannage : erreurs courantes lors de la migration
Permission denied (publickey) après migration vers Forgejo. Le binaire référencé dans authorized_keys a changé. Régénérez les entrées avec docker exec -u git forgejo forgejo admin regenerate keys.
Database migration failed: column already exists. La base a déjà reçu une migration partielle (arrêt pendant la montée). Restaurez le dump complet réalisé à l'étape 1, repartez d'un volume propre, puis relancez.
Les webhooks ne déclenchent plus après migration. Forgejo v16 renforce la validation des URLs de webhook : les URLs pointant vers localhost ou des plages RFC-1918 sont bloquées par défaut. Activez l'option ALLOWED_HOST_LIST dans la section [webhook] de app.ini si vos runners sont sur le même réseau privé.
Les runners act_runner rapportent token invalid. Forgejo v16 hache les tokens de runner en base. Supprimez l'ancien runner dans l'interface d'administration, réenregistrez-le avec act_runner register et le nouveau token généré.
JWT_SECRET_URI et JWT_SECRET ne doivent pas coexister dans app.ini. Si les deux clés sont présentes, Gitea ou Forgejo charge l'une ou l'autre selon l'ordre de lecture, ce qui invalide en silence tous les tokens OAuth2 et Actions émis avant la mise à jour. Les utilisateurs voient des erreurs d'authentification intermittentes, sans message qui désigne app.ini comme cause. Choisissez un seul mécanisme : JWT_SECRET (valeur en clair) ou JWT_SECRET_URI (chemin vers un fichier secret), puis supprimez l'autre. Redémarrez le conteneur après la modification.
La documentation officielle
Pour la configuration avancée et les options propres à l'outil, référez-vous à la documentation officielle de Gitea ou à la documentation Forgejo. Ce guide couvre la mise en ligne sur VPS et la migration ; les docs éditeurs restent la référence pour les réglages fins et les cas d'usage spécifiques.