Files
n8n-mobile/docs/HAPROXY.md
T
billisdead 92e67d0769 feat: application n8n Pilot complète (Expo managed workflow)
- Stack : Expo Router, Axios, Zustand, React Native Paper (thème sombre), date-fns
- Sécurité : secrets dans Android Keystore via expo-secure-store, TLS obligatoire,
  headers X-N8N-API-KEY + X-App-Token injectés par intercepteur Axios
- API : client.ts centralisé + workflows.ts + executions.ts (TypeScript strict)
- Store : Zustand appStore avec chargement depuis secure store au démarrage
- Hooks : usePolling (générique), useWorkflows, useExecutions
- Composants : StatusBadge, WorkflowCard, ExecutionCard, SkeletonLoader
- Screens : Dashboard, Workflows, Executions, Logs (détail exécution), Settings
- Navigation Expo Router : 4 tabs + stack Logs + écran Setup initial
- Docs : INSTALL.md, UPDATE.md, BACKUP.md, HAPROXY.md, SECURITY.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 17:31:55 +02:00

5.7 KiB

Configuration HAProxy pour n8n Pilot

Architecture

Android App → HTTPS → HAProxy (443) → HTTP → n8n (5678)
                        ↓
              Validation X-App-Token
              Rate limiting
              TLS termination

HAProxy agit comme reverse proxy devant n8n. Il :

  1. Termine TLS (certificat Let's Encrypt ou autosigné)
  2. Valide le header X-App-Token (token secret partagé)
  3. Applique du rate limiting pour protéger l'API
  4. Forward les requêtes vers n8n en HTTP interne

Configuration HAProxy complète

#---------------------------------------------------------------------
# global : paramètres du processus HAProxy
#---------------------------------------------------------------------
global
    log /dev/log local0
    log /dev/log local1 notice
    maxconn 2000
    daemon

#---------------------------------------------------------------------
# defaults : valeurs par défaut pour tous les frontends/backends
#---------------------------------------------------------------------
defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    timeout connect  5s
    timeout client   30s
    timeout server   30s
    # Timeout plus long pour les webhooks n8n qui peuvent prendre du temps
    timeout tunnel   3600s

#---------------------------------------------------------------------
# frontend : point d'entrée HTTPS sur le port 443
#---------------------------------------------------------------------
frontend n8n_pilot_frontend
    bind *:443 ssl crt /etc/ssl/n8n/fullchain.pem alpn h2,http/1.1

    # Sécurité TLS : désactiver les versions obsolètes
    ssl-min-ver TLSv1.2

    # Headers de sécurité injectés sur toutes les réponses
    http-response set-header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    http-response set-header X-Content-Type-Options "nosniff"
    http-response set-header X-Frame-Options "DENY"

    # ACL : vérification du X-App-Token
    # La valeur doit correspondre exactement au token configuré dans l'app
    acl valid_app_token req.hdr(X-App-Token) -m str "VOTRE_TOKEN_ICI"

    # Refuser les requêtes sans token valide avec 403
    http-request deny deny_status 403 if !valid_app_token

    # Rate limiting : max 60 requêtes par minute par IP
    # Protège contre les scripts de scan et les abus
    stick-table type ip size 100k expire 60s store http_req_rate(60s)
    http-request track-sc0 src
    http-request deny deny_status 429 if { sc_http_req_rate(0) gt 60 }

    # Redirection HTTP → HTTPS (optionnel si port 80 ouvert)
    # redirect scheme https if !{ ssl_fc }

    default_backend n8n_backend

#---------------------------------------------------------------------
# backend : instance n8n locale
#---------------------------------------------------------------------
backend n8n_backend
    balance roundrobin

    # Supprimer le X-App-Token avant de forwarder à n8n (ne doit pas atteindre n8n)
    http-request del-header X-App-Token

    # Health check : n8n répond sur /healthz
    option httpchk GET /healthz
    http-check expect status 200

    server n8n_local 127.0.0.1:5678 check inter 10s fall 3 rise 2

Rotation du X-App-Token

Le token doit être tourné régulièrement (recommandé : tous les 90 jours minimum).

Procédure de rotation sans downtime

  1. Générer un nouveau token :

    openssl rand -hex 32
    # Exemple : a3f8b2c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1
    
  2. Phase de transition — accepter les deux tokens :

    # Accepter l'ancien ET le nouveau pendant la transition
    acl valid_app_token req.hdr(X-App-Token) -m str "ANCIEN_TOKEN"
    acl valid_app_token_new req.hdr(X-App-Token) -m str "NOUVEAU_TOKEN"
    http-request deny deny_status 403 if !valid_app_token !valid_app_token_new
    
  3. Mettre à jour l'app sur tous les appareils (Paramètres > Token HAProxy > Sauvegarder)

  4. Retirer l'ancien token de HAProxy une fois tous les appareils mis à jour :

    acl valid_app_token req.hdr(X-App-Token) -m str "NOUVEAU_TOKEN"
    http-request deny deny_status 403 if !valid_app_token
    
  5. Recharger HAProxy sans coupure :

    haproxy -f /etc/haproxy/haproxy.cfg -c   # Valider la config
    systemctl reload haproxy                   # Rechargement gracieux
    

Troubleshooting

Erreur 403 Forbidden

Cause : X-App-Token absent ou incorrect.

Diagnostic :

# Tester manuellement avec curl
curl -v -H "X-App-Token: VOTRE_TOKEN" https://n8n.votre-domaine.com/api/v1/workflows

Solutions :

  • Vérifier que le token dans l'app (Paramètres) correspond exactement à la config HAProxy
  • Contrôler les espaces ou caractères invisibles dans le token
  • Vérifier les logs HAProxy : journalctl -u haproxy -f

Erreur 429 Too Many Requests

Cause : rate limit dépassé (> 60 req/min).

Solutions :

  • Augmenter l'intervalle de polling dans l'app (Paramètres > Intervalle)
  • Ajuster la limite dans HAProxy si l'usage légitime est plus élevé
  • Vérifier qu'aucun processus tiers ne spam l'endpoint

Timeout / connexion refusée

Cause : n8n inaccessible sur le port 5678, ou HAProxy mal configuré.

Diagnostic :

# Vérifier que n8n tourne
curl http://127.0.0.1:5678/healthz

# Vérifier le statut HAProxy
systemctl status haproxy
haproxy -f /etc/haproxy/haproxy.cfg -c

# Logs HAProxy en temps réel
journalctl -u haproxy -f

Certificat TLS expiré

# Renouveler avec Certbot
certbot renew --quiet
# Recharger HAProxy pour prendre en compte le nouveau certificat
systemctl reload haproxy

Automatiser le renouvellement :

# Ajouter dans crontab (root)
0 3 * * 1 certbot renew --quiet && systemctl reload haproxy