Cabinet de stratégie IA · 100 % remote · France & Europe
CHAPITRE 4 / 8 14 min de lecture SECURITE

Sécuriser n8n en production : Caddy, fail2ban, 2FA.

HTTPS automatique avec Caddy en 5 minutes. UFW et fail2ban pour bloquer les bots. 2FA n8n pour vos comptes. Ce chapitre transforme votre installation en système production-ready.

Pourquoi Caddy plutôt que Nginx ?

Le débat reverse proxy fait rage depuis des années : Nginx est le standard mature et performant, Caddy est le challenger moderne axé sur la simplicité. Pour un déploiement n8n en PME, notre recommandation est claire : Caddy. Voici pourquoi.

Critère Nginx Caddy
HTTPS / Let's EncryptManuel (certbot)Automatique
Renouvellement TLSCron / systemd timerAutomatique
WebSocket (éditeur n8n)Config expliciteDétection auto
Config (Caddyfile vs nginx.conf)~80 lignes~20 lignes
Performance pureLégèrement supérieurTrès bon (Go natif)
Maturité écosystème20+ ans~5 ans (v2)

Pour une PME qui veut un système qui tourne sans intervention, Caddy élimine les 3 sources d'incident les plus courantes : oubli de renouvellement TLS, mauvaise config WebSocket qui casse l'éditeur n8n, mauvaise gestion des en-têtes de sécurité.

Configurer le DNS de votre sous-domaine.

Avant d'installer Caddy, votre sous-domaine doit pointer vers l'IP de votre VPS. Chez votre registrar (Gandi, OVH, Infomaniak, Cloudflare, etc.), créez un enregistrement DNS de type A :

Type Nom Valeur TTL
An8nVOTRE_IP_VPS3600

Pour votreboite.fr, vous obtenez n8n.votreboite.fr. Vérifiez la propagation DNS depuis votre poste :

dig +short n8n.votreboite.fr
# Doit retourner votre IP VPS apres quelques minutes (max 1h)

Installer Caddy sur Ubuntu 24.04.

Caddy fournit un repository officiel pour Ubuntu. Procédure officielle :

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl

curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
  | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg

curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
  | sudo tee /etc/apt/sources.list.d/caddy-stable.list

sudo apt update
sudo apt install -y caddy

# Verifier l'installation
caddy version

Caddy est installé en tant que service systemd. Il démarre automatiquement et est configuré pour redémarrer en cas de crash.

Le Caddyfile pour n8n.

Caddy se configure via un seul fichier appelé Caddyfile. Éditez-le :

sudo nano /etc/caddy/Caddyfile

Remplacez tout le contenu par cette configuration n8n production :

n8n.votreboite.fr {
    encode gzip zstd

    header {
        # HSTS : HTTPS forcé pour 1 an
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
        # Anti-clickjacking
        X-Frame-Options "DENY"
        # Anti-MIME sniffing
        X-Content-Type-Options "nosniff"
        # Référeur partiel
        Referrer-Policy "strict-origin-when-cross-origin"
        # Pas d'accès aux APIs sensibles
        Permissions-Policy "camera=(), microphone=(), geolocation=()"
        # Cacher les versions
        -Server
    }

    # n8n peut envoyer/recevoir de gros payloads (uploads, JSON, fichiers binaires)
    request_body {
        max_size 50MB
    }

    reverse_proxy 127.0.0.1:5678 {
        # WebSocket pour l'éditeur temps réel : détecté automatiquement par Caddy
        header_up Host {host}
        header_up X-Real-IP {remote_host}
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}

        transport http {
            read_timeout 300s
            write_timeout 300s
        }
    }
}

Remplacez n8n.votreboite.fr par votre vrai sous-domaine. Validez la syntaxe et rechargez Caddy :

sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy

En 30 secondes à 2 minutes, Caddy demande automatiquement un certificat Let's Encrypt à acme-v02.api.letsencrypt.org, le valide via challenge HTTP-01, et active HTTPS. Vérifiez les logs :

sudo journalctl -u caddy --tail=50

Cherchez la ligne "certificate obtained successfully". Ouvrez maintenant https://n8n.votreboite.fr dans votre navigateur. Vous devriez voir l'éditeur n8n avec un cadenas vert dans la barre d'adresse.

Activer la 2FA sur tous les comptes n8n.

n8n Community supporte la 2FA TOTP nativement (compatible Google Authenticator, Authy, Bitwarden Authenticator, 1Password). C'est gratuit, à activer immédiatement.

  1. Connectez-vous à n8n en tant qu'owner
  2. Cliquez sur votre avatar (haut droite) → Settings
  3. Onglet "Personal" → "Two-factor authentication" → "Enable"
  4. Scannez le QR code avec votre application TOTP
  5. Entrez le code à 6 chiffres pour valider
  6. Sauvegardez les codes de récupération dans votre gestionnaire de mots de passe

Imposez la 2FA à tous les utilisateurs futurs : Settings → Security → "Require 2FA for all users".

Installer fail2ban contre les bruteforce.

UFW bloque les ports non autorisés. Mais sur les ports ouverts (22, 80, 443), les bots tentent en permanence des attaques bruteforce. fail2ban analyse les logs en temps réel et bloque automatiquement les IPs suspectes.

sudo apt install -y fail2ban

# Creer la config locale (ne pas modifier /etc/fail2ban/jail.conf qui est ecrase aux maj)
sudo nano /etc/fail2ban/jail.local

Collez :

[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
banaction = ufw

[sshd]
enabled = true

[caddy-status]
enabled = true
filter = caddy-status
port = http,https
logpath = /var/log/caddy/access.log
maxretry = 10

Relancez fail2ban :

sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

Vous verrez le nombre de tentatives échouées et les IPs bannies. Au bout d'une heure, votre serveur aura déjà bloqué entre 10 et 100 bots, c'est totalement normal sur Internet 2026.

Rate limiting : protection des webhooks.

Si vous exposez des webhooks publics n8n (ex: réception de paiement Stripe, formulaire web), un attaquant peut tenter de les inonder de fausses requêtes. Ajoutez du rate limiting au Caddyfile :

{
    # Bloc global Caddy
    order rate_limit before reverse_proxy
}

n8n.votreboite.fr {
    # ... config existante ...

    @webhooks path /webhook/*
    rate_limit @webhooks {
        zone webhook_zone
        events 60
        window 1m
    }
}

Cette règle limite à 60 requêtes/minute par IP sur les endpoints webhook. Pour un usage normal c'est bien plus que suffisant, et ça arrête les attaques par déni de service basique.

Note : la directive rate_limit nécessite le module Caddy caddy-ratelimit. Sur Ubuntu il est inclus dans le paquet officiel depuis Caddy 2.7+.

Sécuriser les credentials n8n : la rotation de l'encryption key.

La N8N_ENCRYPTION_KEY ne doit jamais être perdue (chapitre 3), mais elle peut aussi être compromise (attaquant qui accède à votre .env). Si vous suspectez une compromission, voici la procédure de rotation officielle :

# 1. Snapshot complet du serveur (depuis hPanel Hostinger)

# 2. Export des credentials decryptes
docker compose exec n8n n8n export:credentials \
  --all --decrypted --output=/tmp/creds.json

# 3. Stop n8n
docker compose stop n8n

# 4. Generer nouvelle cle
NEW_KEY=$(openssl rand -hex 32)

# 5. Mettre a jour .env avec la nouvelle cle
nano .env  # remplacer N8N_ENCRYPTION_KEY=...

# 6. Restart n8n
docker compose up -d n8n

# 7. Re-importer les credentials avec la nouvelle cle
docker compose exec n8n n8n import:credentials --input=/tmp/creds.json

# 8. DETRUIRE le fichier creds.json (IMPORTANT)
shred -u /tmp/creds.json

Récapitulatif sécurité : votre checklist.

À la fin de ce chapitre, votre installation devrait avoir :

  • ✅ Caddy installé avec HTTPS automatique Let's Encrypt
  • ✅ Headers de sécurité (HSTS, X-Frame-Options, CSP, etc.)
  • ✅ Note SSL Labs A+ (vérifié sur ssllabs.com)
  • ✅ 2FA TOTP active sur le compte owner et codes de récupération sauvegardés
  • ✅ 2FA imposée à tous les futurs utilisateurs (Settings → Security)
  • ✅ fail2ban actif sur SSH
  • ✅ Rate limiting sur les webhooks publics
  • ✅ UFW bloque tous les ports sauf 22, 80, 443
  • ✅ N8N_ENCRYPTION_KEY sauvegardée dans 3 endroits
  • ✅ Procédure de rotation de la clé documentée et comprise

Vous avez maintenant un n8n production-ready. Le chapitre 5 attaque le sujet le plus important après la sécurité : les backups automatisés et chiffrés.

QUESTIONS FRÉQUENTES

Questions fréquentes.

Pourquoi Caddy demande-t-il automatiquement un certificat Let's Encrypt ?

C'est le comportement par défaut depuis Caddy v2 : dès qu'un site est configuré avec un nom de domaine valide pointant vers le serveur, Caddy initie automatiquement le challenge ACME HTTP-01 avec Let's Encrypt. Le certificat est obtenu en 30s à 2 min, stocké dans /var/lib/caddy/.local/share/caddy/, et renouvelé automatiquement 30 jours avant expiration. Aucune intervention manuelle requise.

Mon test SSL Labs me donne A et non A+, c'est grave ?

Non. La différence entre A et A+ vient généralement du HSTS qui n'est pas encore propagé (cookie navigateur), ou d'un détail mineur sur les ciphers. La sécurité réelle est identique. Revenez dans 24h après quelques visites de votre site, l'HSTS sera enregistré et vous passerez en A+. Si A persiste, vérifiez que la directive Strict-Transport-Security est bien dans le Caddyfile.

Que faire si je perds mon téléphone avec l'app TOTP n8n ?

Vous utilisez les codes de récupération sauvegardés dans votre gestionnaire de mots de passe lors de l'activation de la 2FA. Chaque code à usage unique permet une connexion. Après login, désactivez la 2FA et réactivez-la avec un nouveau téléphone. C'est pour ça qu'il est CRITIQUE de sauvegarder ces codes au moment où n8n vous les affiche, vous ne les reverrez jamais sinon.

fail2ban risque-t-il de bloquer ma propre IP par erreur ?

Oui si vous tapez 5 mauvais mots de passe SSH à la suite. Le ban dure 1h par défaut. Pour vous débloquer en urgence, utilisez la console web Hostinger (VNC, contourne SSH) et tapez : sudo fail2ban-client unban VOTRE_IP. Pour éviter ce souci, ajoutez votre IP fixe en whitelist dans /etc/fail2ban/jail.local : ignoreip = 127.0.0.1/8 VOTRE_IP_FIXE.

Les certificats Let's Encrypt expirent au bout de 90 jours, comment c'est géré ?

Caddy gère automatiquement le renouvellement 30 jours avant expiration (donc à J+60), via le même protocole ACME. Vous n'avez rien à faire. Si jamais le renouvellement échoue (problème DNS, port 80 bloqué, etc.), Caddy log l'erreur et retente toutes les heures jusqu'à succès. Vérifiez les logs avec : journalctl -u caddy --since '1 day ago'.

PROJET N8N AUTO-HÉBERGÉ ?

Cadrons votre projet en 45 minutes.

Audit gratuit pour évaluer votre besoin (cloud vs auto-hébergé), votre stack, votre conformité RGPD et IA Act. Sans engagement.

Réserver l'audit