nginx-tls.conf 208 lignes · 9106 octets
# =============================================================================
# Gitrust — Reverse proxy Nginx avec TLS (Let's Encrypt)
# =============================================================================
# Déploiement :
#   sudo cp template/reverse-proxy/nginx-tls.conf /etc/nginx/sites-available/gitrust
#   sudo ln -s /etc/nginx/sites-available/gitrust /etc/nginx/sites-enabled/gitrust
#   sudo nginx -t && sudo systemctl reload nginx
#
# TLS (Let's Encrypt, après que le bloc HTTP ci-dessous soit actif) :
#   sudo certbot --nginx -d <YOUR_DOMAIN>
#
# SSH git :
#   Nginx HTTP ne peut pas proxifier SSH. Deux options :
#   1) Exposer le port 2222 directement dans le firewall (recommandé, simple)
#   2) Proxy stream nginx sur :22 → 127.0.0.1:2222 (voir commentaire en bas)
#      Prérequis : paquet libnginx-mod-stream + bloc stream{} dans nginx.conf
# =============================================================================

upstream gitrust_backend {
    server 127.0.0.1:4000;
    keepalive 32;
}

# =============================================================================
# HTTP — redirection HTTPS + ACME challenge Let's Encrypt
# =============================================================================
server {
    listen 80;
    listen [::]:80;
    server_name <YOUR_DOMAIN>;    # Remplacer par le FQDN de l'instance

    # Répertoire de validation certbot — doit être accessible avant TLS
    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    # Tout le reste → HTTPS permanent
    location / {
        return 301 https://$host$request_uri;
    }
}

# =============================================================================
# HTTPS — reverse proxy vers gitrust
# =============================================================================
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    # Syntaxe nginx >= 1.25. Pour nginx <= 1.24, remplacer les deux lignes
    # listen ci-dessus par :
    #   listen 443 ssl http2;
    #   listen [::]:443 ssl http2;
    http2 on;
    server_name <YOUR_DOMAIN>;    # Remplacer par le FQDN de l'instance

    # -------------------------------------------------------------------------
    # TLS — certificats Let's Encrypt (remplis automatiquement par certbot)
    # -------------------------------------------------------------------------
    # Décommenter après : sudo certbot --nginx -d <YOUR_DOMAIN>
    # ssl_certificate     /etc/letsencrypt/live/<YOUR_DOMAIN>/fullchain.pem;
    # ssl_certificate_key /etc/letsencrypt/live/<YOUR_DOMAIN>/privkey.pem;
    # include /etc/letsencrypt/options-ssl-nginx.conf;
    # ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # Certificat auto-signé pour valider la config avant certbot (commenter après)
    ssl_certificate     /etc/ssl/certs/ssl-cert-snakeoil.pem;
    ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

    # Hardening TLS
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 1d;

    # -------------------------------------------------------------------------
    # En-têtes de sécurité
    # -------------------------------------------------------------------------
    # HSTS : force HTTPS pendant 1 an, inclut sous-domaines.
    # Attention : n'activer includeSubDomains que si TOUS les sous-domaines ont TLS.
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # Empêche le navigateur de détecter automatiquement le type MIME (MIME sniffing)
    add_header X-Content-Type-Options "nosniff" always;

    # Politique referrer : envoie l'origine complète pour requêtes same-origin,
    # uniquement l'origine (sans path) pour requêtes cross-origin HTTPS.
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # Empêche l'intégration dans des iframes d'autres origines
    add_header X-Frame-Options "SAMEORIGIN" always;

    # -------------------------------------------------------------------------
    # Taille max des corps de requête
    # -------------------------------------------------------------------------
    # 1G pour les git push HTTP de gros dépôts (monorepos, dépôts avec LFS,
    # binaires commités). Réduire si l'espace disque est contraint.
    # La location git spécifique ci-dessous passe à 2G pour les push volumineux.
    client_max_body_size 1G;
    client_body_buffer_size 128k;

    # -------------------------------------------------------------------------
    # Timeouts étendus pour clone/push de gros dépôts
    # -------------------------------------------------------------------------
    proxy_connect_timeout 300s;
    proxy_send_timeout    3600s;
    proxy_read_timeout    3600s;
    send_timeout          3600s;

    # -------------------------------------------------------------------------
    # Logs
    # -------------------------------------------------------------------------
    access_log /var/log/nginx/gitrust.access.log;
    error_log  /var/log/nginx/gitrust.error.log warn;

    # =========================================================================
    # Route principale — toutes les pages et l'API REST
    # =========================================================================
    location / {
        proxy_pass http://gitrust_backend;
        proxy_http_version 1.1;

        # En-têtes forwarded
        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;

        # Keep-alive vers l'upstream (connexion réutilisée)
        proxy_set_header Connection "";

        # SSE et WebSocket — désactiver la mise en tampon pour :
        #   - notifications temps réel (/notifications/stream)
        #   - logs CI en streaming (/repos/.../ci/.../logs)
        #   - HTMX SSE
        proxy_buffering    off;
        proxy_cache        off;
        proxy_set_header   X-Accel-Buffering no;
    }

    # =========================================================================
    # Git smart HTTP — clone et push via HTTPS
    # =========================================================================
    # Pattern : /<owner>/<repo>.git/info/refs, /git-upload-pack, /git-receive-pack
    location ~ ^/[^/]+/[^/]+\.git/ {
        proxy_pass http://gitrust_backend;
        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;

        # Désactiver la mise en tampon côté client ET serveur pour les push/clone
        proxy_buffering         off;
        proxy_request_buffering off;
        proxy_cache             off;

        # Push de gros dépôts peut dépasser 1G (monorepos lourds)
        client_max_body_size 2G;
    }

    # =========================================================================
    # Assets statiques — optionnel : servir directement depuis le filesystem
    # =========================================================================
    # Décommenter si les fichiers /opt/gitrust/static/ sont lisibles par www-data.
    # Réduit la charge sur gitrust pour CSS/JS/images (cache navigateur 7 jours).
    # location ^~ /static/ {
    #     alias /opt/gitrust/static/;
    #     expires 7d;
    #     add_header Cache-Control "public, immutable";
    #     try_files $uri @gitrust;
    # }
    # location @gitrust {
    #     proxy_pass http://gitrust_backend;
    # }
}

# =============================================================================
# BONUS — Proxy SSH git via nginx stream (port 22 → gitrust SSH :2222)
# =============================================================================
# ATTENTION : ce bloc `stream {}` est de niveau RACINE nginx et NE PEUT PAS
# être placé dans ce fichier (qui est inclus dans le bloc http{}).
# Le décommenter ici provoquerait : nginx: [emerg] "stream" directive is not allowed here
#
# Méthode correcte : ajouter le bloc ci-dessous À LA FIN de /etc/nginx/nginx.conf
# (hors du bloc http{}), ou dans /etc/nginx/conf.d-stream/gitrust-ssh.conf
# inclus au niveau racine.
#
# Prérequis :
#   - paquet libnginx-mod-stream installé (apt install libnginx-mod-stream)
#   - sshd système déplacé sur un autre port (ex: 2022) si l'hôte est aussi administré par SSH
#
# stream {
#     upstream gitrust_ssh {
#         server 127.0.0.1:2222;
#     }
#     server {
#         listen 22;
#         listen [::]:22;
#         proxy_pass gitrust_ssh;
#         proxy_timeout 1h;
#         proxy_connect_timeout 30s;
#         error_log /var/log/nginx/gitrust-ssh-stream.log;
#     }
# }
# =============================================================================