Call-Informatique
Call-Informatique
Le média tech
Gitea en production : Installation Docker, Nginx et SSL
InformatiqueGuides8 min de lecture

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

bash
## 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 fail2ban

Configuration du pare-feu UFW

bash
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 enable

Configuration 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 :

bash
## 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

bash
## 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 :

bash
sudo mkdir -p /opt/gitea/{data,config,postgres}
sudo mkdir -p /opt/gitea/backups
sudo chown -R $USER:$USER /opt/gitea

Option A : SQLite (simple, mono-instance)

yaml
## /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: false

Option B : PostgreSQL (recommandé pour production)

yaml
## /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: false

Générer un mot de passe sécurisé pour la base de données :

bash
openssl rand -base64 32

Étape 4 : Déploiement initial

bash
cd /opt/gitea
docker compose up -d

Vérifier les logs :

bash
docker compose logs -f server

Attendre que Gitea soit prêt ("Listen on :3000" dans les logs).

Étape 5 : Configuration initiale via CLI

Créer le premier utilisateur administrateur :

bash
docker exec -it gitea gitea admin user create \
  —username admin \
  —password SecurePassword123! \
  —email admin@example.com \
  —admin

Verrouiller l'installation pour empêcher la réinitialisation via l'interface web :

bash
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

nginx
## /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

bash
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

bash
sudo certbot —nginx -d git.example.com —non-interactive —agree-tos —email admin@example.com

Vérifier le renouvellement automatique :

bash
sudo certbot renew —dry-run

Étape 8 : Hardening sécurité

Configurer fail2ban

bash
## /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
bash
## /etc/fail2ban/filter.d/gitea-auth.conf
[Definition]
failregex = .*Failed authentication attempt for .* from <HOST>
ignoreregex =
bash
sudo systemctl restart fail2ban

Headers de sécurité Nginx

Ajouter dans le bloc server HTTPS :

nginx
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

bash
## /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"
bash
chmod +x /opt/gitea/backup.sh

Cron pour backup quotidien

bash
## É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

bash
## 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 -d

Dépannage

Erreur : Permission denied sur /data

bash
sudo chown -R 1000:1000 /opt/gitea/data
sudo chmod -R 755 /opt/gitea/data

Erreur : Port 22 déjà utilisé

Si le port 22 est occupé par le SSH système, modifier docker-compose.yml :

yaml
ports:
  - "3000:3000"
  - "2222:22"  # SSH externe sur 2222

Puis mettre à jour la configuration Gitea :

bash
docker exec -it gitea bash -c "echo 'SSH_PORT = 2222' >> /data/gitea/conf/app.ini"
docker compose restart

Erreur : Database is locked (SQLite)

Passer à PostgreSQL ou augmenter les timeouts dans app.ini :

ini
[database]
SQLITE_JOURNAL_MODE = wal
LOCK_TIMEOUT = 30

Erreur : 502 Bad Gateway

Vérifier que Gitea est bien démarré :

bash
docker compose ps
docker compose logs server —tail 50

Vérifier la connectivité :

bash
curl -I http://localhost:3000

Monitoring

Healthcheck Docker

Ajouter au service server dans docker-compose.yml :

yaml
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:3000/api/healthz"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 40s

Métriques Prometheus (optionnel)

Activer dans app.ini :

ini
[metrics]
ENABLED = true
TOKEN = votre_token_secret

Mise à jour de Gitea

bash
cd /opt/gitea
docker compose pull
docker compose up -d
docker compose logs -f server

La 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.

Sur le même sujet

À lire aussi

#tutoriel#gitea#docker-compose#nginx#ssl#backup