
Gitea en production : Installation Docker, Nginx et SSL
Guide technique complet pour déployer Gitea en production avec Docker Compose, reverse proxy Nginx, SSL Let's Encrypt et sauvegarde automatisée.
Architecture et prérequis
Gitea est une forge Git légère écrite en Go, capable de gérer des milliers de dépôts sur du matériel modeste. Cette installation utilise :
- Docker Compose pour l'orchestration
- SQLite3 pour les petites instances (< 20 utilisateurs)
- PostgreSQL recommandé pour les instances plus importantes
- Nginx comme reverse proxy
- Certbot pour les certificats SSL automatiques
Spécifications matérielles recommandées
| Configuration | CPU | RAM | Stockage | Utilisateurs |
|———————|——-|——-|—————|———————|
| Minimal | 1 cœur | 1 Go | 20 Go SSD | < 10 |
| Standard | 2 cœurs | 2 Go | 50 Go SSD | 10-50 |
| Production | 4 cœurs | 4 Go | 100 Go SSD | 50+ |
Étape 1 : Préparation du système
Mise à jour et dépendances
## Mettre à jour le système
sudo apt update && sudo apt upgrade -y
## Installer les dépendances
sudo apt install -y curl wget git nginx certbot python3-certbot-nginx ufw fail2banConfiguration du pare-feu UFW
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment 'SSH'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
sudo ufw enableConfiguration SSH pour Git
Gitea utilise le port 22 pour SSH natif. Si votre serveur utilise déjà ce port pour l'administration, modifiez /etc/ssh/sshd_config :
## Changer le port SSH du système
sudo sed -i 's/#Port 22/Port 2222/' /etc/ssh/sshd_config
sudo systemctl restart sshdÉtape 2 : Installation de Docker et Docker Compose
## Installation de Docker
curl -fsSL https://get.docker.com | sh
## Ajouter l'utilisateur au groupe docker
sudo usermod -aG docker $USER
newgrp docker
## Vérifier l'installation
docker —version
docker compose versionÉtape 3 : Configuration Docker Compose
Créer la structure de dossiers :
sudo mkdir -p /opt/gitea/{data,config,postgres}
sudo mkdir -p /opt/gitea/backups
sudo chown -R $USER:$USER /opt/giteaOption A : SQLite (simple, mono-instance)
## /opt/gitea/docker-compose.yml
version: "3.8"
services:
server:
image: gitea/gitea:1.22.3
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=sqlite3
- GITEA__database__PATH=/data/gitea.db
- GITEA__server__DOMAIN=git.example.com
- GITEA__server__ROOT_URL=https://git.example.com/
- GITEA__server__SSH_DOMAIN=git.example.com
- GITEA__server__SSH_PORT=22
- GITEA__server__SSH_LISTEN_PORT=22
- GITEA__service__DISABLE_REGISTRATION=false
- GITEA__service__REQUIRE_SIGNIN_VIEW=false
- GITEA__security__INSTALL_LOCK=true
restart: always
networks:
- gitea
volumes:
- ./data:/data
- ./config:/config
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "22:22"
networks:
gitea:
external: falseOption B : PostgreSQL (recommandé pour production)
## /opt/gitea/docker-compose.yml
version: "3.8"
services:
server:
image: gitea/gitea:1.22.3
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=gitea_secure_password
- GITEA__server__DOMAIN=git.example.com
- GITEA__server__ROOT_URL=https://git.example.com/
- GITEA__server__SSH_DOMAIN=git.example.com
- GITEA__server__SSH_PORT=22
- GITEA__server__SSH_LISTEN_PORT=22
- GITEA__security__INSTALL_LOCK=true
restart: always
networks:
- gitea
volumes:
- ./data:/data
- ./config:/config
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "22:22"
depends_on:
- db
db:
image: postgres:16-alpine
container_name: gitea-db
restart: always
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=gitea_secure_password
- POSTGRES_DB=gitea
networks:
- gitea
volumes:
- ./postgres:/var/lib/postgresql/data
networks:
gitea:
external: falseGénérer un mot de passe sécurisé pour la base de données :
openssl rand -base64 32Étape 4 : Déploiement initial
cd /opt/gitea
docker compose up -dVérifier les logs :
docker compose logs -f serverAttendre que Gitea soit prêt ("Listen on :3000" dans les logs).
Étape 5 : Configuration initiale via CLI
Créer le premier utilisateur administrateur :
docker exec -it gitea gitea admin user create \
—username admin \
—password SecurePassword123! \
—email admin@example.com \
—adminVerrouiller l'installation pour empêcher la réinitialisation via l'interface web :
docker exec -it gitea bash -c "echo '[security]\nINSTALL_LOCK = true' >> /data/gitea/conf/app.ini"
docker compose restartÉtape 6 : Configuration Nginx reverse proxy
Créer la configuration
## /etc/nginx/sites-available/git.example.com
upstream gitea {
server 127.0.0.1:3000;
keepalive 64;
}
server {
listen 80;
server_name git.example.com;
location / {
return 301 https://$server_name$request_uri;
}
}
server {
listen 443 ssl http2;
server_name git.example.com;
ssl_certificate /etc/letsencrypt/live/git.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/git.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/git.example.com/chain.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
location / {
proxy_pass http://gitea;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
client_max_body_size 512m;
}
}Activer le site
sudo ln -s /etc/nginx/sites-available/git.example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginxÉtape 7 : SSL avec Let's Encrypt
sudo certbot —nginx -d git.example.com —non-interactive —agree-tos —email admin@example.comVérifier le renouvellement automatique :
sudo certbot renew —dry-runÉtape 8 : Hardening sécurité
Configurer fail2ban
## /etc/fail2ban/jail.local
[gitea-auth]
enabled = true
port = http,https
filter = gitea-auth
logpath = /opt/gitea/data/log/gitea.log
maxretry = 5
bantime = 3600## /etc/fail2ban/filter.d/gitea-auth.conf
[Definition]
failregex = .*Failed authentication attempt for .* from <HOST>
ignoreregex =sudo systemctl restart fail2banHeaders de sécurité Nginx
Ajouter dans le bloc server HTTPS :
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:;" always;Étape 9 : Sauvegarde automatisée
Script de backup
## /opt/gitea/backup.sh
#!/bin/bash
BACKUP_DIR="/opt/gitea/backups"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7
## Créer le dossier de backup
mkdir -p $BACKUP_DIR
## Backup Gitea via la commande intégrée
docker exec gitea bash -c "gitea dump -c /data/gitea/conf/app.ini -w /tmp -f /data/backup_$DATE.zip"
## Déplacer le backup
mv /opt/gitea/data/backup_$DATE.zip $BACKUP_DIR/
## Backup des configurations
tar -czf $BACKUP_DIR/config_$DATE.tar.gz -C /opt/gitea config docker-compose.yml
## Suppression des vieux backups
find $BACKUP_DIR -name "backup_*.zip" -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR -name "config_*.tar.gz" -mtime +$RETENTION_DAYS -delete
echo "Backup completed: $DATE"chmod +x /opt/gitea/backup.shCron pour backup quotidien
## Éditer le crontab
crontab -e
## Ajouter cette ligne pour un backup quotidien à 2h du matin
0 2 * * * /opt/gitea/backup.sh >> /var/log/gitea-backup.log 2>&1Étape 10 : Restauration depuis un backup
## Arrêter Gitea
cd /opt/gitea
docker compose down
## Extraire le backup
unzip backups/backup_YYYYMMDD_HHMMSS.zip -d /tmp/gitea-restore
## Restaurer les données
sudo rm -rf data/*
sudo cp -r /tmp/gitea-restore/data/* data/
sudo chown -R 1000:1000 data
## Redémarrer
docker compose up -dDépannage
Erreur : Permission denied sur /data
sudo chown -R 1000:1000 /opt/gitea/data
sudo chmod -R 755 /opt/gitea/dataErreur : Port 22 déjà utilisé
Si le port 22 est occupé par le SSH système, modifier docker-compose.yml :
ports:
- "3000:3000"
- "2222:22" # SSH externe sur 2222Puis mettre à jour la configuration Gitea :
docker exec -it gitea bash -c "echo 'SSH_PORT = 2222' >> /data/gitea/conf/app.ini"
docker compose restartErreur : Database is locked (SQLite)
Passer à PostgreSQL ou augmenter les timeouts dans app.ini :
[database]
SQLITE_JOURNAL_MODE = wal
LOCK_TIMEOUT = 30Erreur : 502 Bad Gateway
Vérifier que Gitea est bien démarré :
docker compose ps
docker compose logs server —tail 50Vérifier la connectivité :
curl -I http://localhost:3000Monitoring
Healthcheck Docker
Ajouter au service server dans docker-compose.yml :
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/healthz"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sMétriques Prometheus (optionnel)
Activer dans app.ini :
[metrics]
ENABLED = true
TOKEN = votre_token_secretMise à jour de Gitea
cd /opt/gitea
docker compose pull
docker compose up -d
docker compose logs -f serverLa mise à jour est généralement sans coupure grâce au zero-downtime de Docker.
Conclusion
Votre instance Gitea est maintenant opérationnelle en production avec :
- Base de données PostgreSQL robuste
- Reverse proxy Nginx optimisé
- SSL/TLS avec renouvellement automatique
- Protection fail2ban contre les attaques par force brute
- Sauvegardes quotidiennes automatisées
- Headers de sécurité HTTP
Cette configuration supporte plusieurs dizaines d'utilisateurs et peut évoluer vers un cluster si nécessaire.
À lire aussi
CanisterWorm : le ver auto-propagé qui infecte 47 packages np...
Découvrez tous les détails dans notre analyse complète.
Installer Gitea : Votre GitHub personnel en 15 minutes
Apprenez à installer Gitea pour héberger vos projets Git chez vous. Guide simple pour créer votre propre forge logicielle auto-hébergée.
Jensen Huang défend le DLSS 5 : « ils ont tout faux »
Face au tollé sur le DLSS 5, le PDG de Nvidia Jensen Huang affirme que les critiques sont « complètement dans l'erreur ». Sa défense au GTC 2026.