n8n en HTTPS avec Cloudflare Tunnel : sans ouvrir de port, sans certificat
Publié le 3 août 2026 · 10 min de lecture
Pour mettre n8n en HTTPS sur son propre domaine, les deux voies classiques sont le reverse proxy avec certificat automatique — Traefik ou Caddy — et le montage plus manuel Nginx + Certbot. Les deux partagent un prérequis silencieux : une machine dont les ports 80 et 443 sont joignables depuis Internet. C'est le cas d'un VPS standard, mais pas d'un serveur posé derrière une box Internet, d'un mini-PC dans un placard, d'un NAS familial ou d'un réseau d'entreprise dont le pare-feu ne s'ouvrira pas pour vous. Et même sur un VPS, on peut légitimement ne pas avoir envie d'exposer le port 443 au monde entier.
Cloudflare Tunnel est la troisième voie : un petit connecteur, cloudflared, tourne à côté de n8n et établit une connexion sortante vers le réseau Cloudflare. Le trafic entrant emprunte le chemin inverse — Cloudflare, le tunnel, votre conteneur — sans qu'aucun port entrant ne soit jamais ouvert. TLS, certificat, renouvellement : tout est géré côté Cloudflare. Ce guide couvre la mise en place complète en Docker, les variables n8n sans lesquelles les webhooks pointeront vers localhost, la protection de l'éditeur avec Cloudflare Access, et les limites du modèle qu'il faut accepter en connaissance de cause.
Pourquoi ne pas ouvrir de port est un vrai argument
On sous-estime la vitesse à laquelle un port ouvert sur Internet est découvert. Ce n'est pas une question de chance : l'étude fondatrice de Durumeric, Wustrow et Halderman présentée à USENIX Security 2013, ZMap: Fast Internet-wide scanning and its security applications (voir sur Google Scholar), a montré qu'une seule machine correctement outillée peut scanner l'intégralité de l'espace d'adressage IPv4 en moins d'une heure. Autrement dit, tout service exposé — votre port 443, ou le 5678 si n8n est en accès direct — est trouvé et sondé par des scanners automatisés dans les heures qui suivent sa mise en ligne, pas dans les mois.
Un reverse proxy bien configuré encaisse très bien cette réalité ; ce n'est pas un argument pour fuir Traefik ou Nginx. Mais une machine qui n'expose aucun port entrant présente une surface d'attaque directe nulle pour ces scanners : il n'y a littéralement rien à sonder. C'est le modèle de Cloudflare Tunnel — utilisable de surcroît là où ouvrir un port est impossible : CGNAT d'opérateur, réseau d'entreprise verrouillé, ou box familiale qu'on ne veut pas toucher.
Comment ça marche, et ce qu'il vous faut
Le principe tient en trois mouvements :
- Le conteneur
cloudflareddémarre et ouvre des connexions sortantes persistantes vers le réseau Cloudflare (de la même façon que n'importe quel client HTTP sort de votre réseau — aucune règle de pare-feu ni redirection de port à créer). - Cloudflare associe votre tunnel à un nom d'hôte public, par exemple
n8n.mondomaine.fr, avec un enregistrement DNS créé automatiquement. - Quand quelqu'un visite
https://n8n.mondomaine.fr, la requête arrive sur le réseau Cloudflare, qui termine le TLS et la fait redescendre par le tunnel jusqu'au service que vous avez désigné — ici, le conteneur n8n sur son port 5678.
Le seul prérequis : un domaine dont les DNS sont gérés par Cloudflare. L'offre gratuite suffit — Cloudflare Tunnel y est inclus. Si votre domaine est chez OVH, Gandi ou ailleurs, inutile de le transférer : ajoutez-le à un compte Cloudflare et faites pointer ses serveurs de noms (NS) vers ceux de Cloudflare chez votre registrar.
Côté machine, ce guide suppose une instance n8n en Docker — notre guide d'installation Docker pose cette base si besoin. La machine peut être un VPS classique (voir notre guide de choix de VPS), mais l'intérêt du tunnel est justement qu'elle peut aussi être n'importe quoi d'autre : un mini-PC à 150 €, un vieux laptop, un Raspberry Pi derrière la box du salon.
Créer le tunnel dans le dashboard Zero Trust
La méthode recommandée passe par le dashboard, qui gère la configuration à distance (l'alternative en ligne de commande avec un fichier config.yml local existe, mais le dashboard est plus simple et suffit ici) :
- Connectez-vous au dashboard Cloudflare Zero Trust (section Zero Trust de votre compte Cloudflare — la première visite demande de choisir un nom d'équipe et un plan, le gratuit convient).
- Dans Networks → Tunnels, créez un tunnel de type Cloudflared et donnez-lui un nom (
n8n-maison, par exemple). - Cloudflare affiche alors un token — une longue chaîne commençant par
eyJ. C'est la seule information dont le conteneurcloudflaredaura besoin : copiez-la, c'est votreTUNNEL_TOKEN. Traitez-la comme un mot de passe. - Dans l'onglet Public Hostname du tunnel, ajoutez une entrée : sous-domaine
n8n, domainemondomaine.fr, service de typeHTTPet URLn8n:5678— c'est-à-dire le nom du service Docker de votre conteneur n8n, suivi de son port interne. Cloudflare crée automatiquement l'enregistrement DNS correspondant.
Ce dernier point est crucial : l'URL de service est résolue depuis le conteneur cloudflared, pas depuis votre machine. localhost:5678 désignerait cloudflared lui-même et ne mènerait nulle part — entre conteneurs d'un même réseau Docker, on s'adresse par nom de service.
Le docker-compose complet
Deux services sur le même réseau Docker : n8n, et cloudflared qui n'a besoin que de son token.
services:
n8n:
image: docker.n8n.io/n8nio/n8n
restart: unless-stopped
environment:
- N8N_HOST=n8n.mondomaine.fr
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://n8n.mondomaine.fr/
- N8N_EDITOR_BASE_URL=https://n8n.mondomaine.fr/
- GENERIC_TIMEZONE=Europe/Paris
volumes:
- n8n_data:/home/node/.n8n
networks:
- n8n-net
cloudflared:
image: cloudflare/cloudflared:latest
restart: unless-stopped
command: tunnel run
environment:
- TUNNEL_TOKEN=${TUNNEL_TOKEN}
networks:
- n8n-net
volumes:
n8n_data:
networks:
n8n-net:
Trois détails qui comptent :
- Aucun
ports:nulle part. C'est tout l'intérêt : n8n n'est pas publié sur la machine hôte, et cloudflared n'écoute rien — il ne fait que sortir. Si votre compose existant contient unports: - "5678:5678"sur n8n, supprimez-le : le laisser exposerait l'instance en HTTP à côté du tunnel, ce qui annulerait le bénéfice. - Le token vit dans un fichier
.envà côté du compose (TUNNEL_TOKEN=eyJ...), pas en dur dans le YAML — surtout si ce fichier finit dans un dépôt Git. - Le réseau partagé
n8n-netest ce qui permet à cloudflared de résoudre le nomn8n. Dans un compose unique comme ici, le réseau par défaut suffirait, mais le déclarer explicitement évite les surprises si les services sont un jour répartis sur plusieurs fichiers.
Un docker compose up -d plus tard, le tunnel apparaît « Healthy » dans le dashboard Zero Trust, et https://n8n.mondomaine.fr sert votre instance en HTTPS. Aucun certificat n'a été généré de votre côté, et il n'y en aura jamais à renouveler.
Les variables n8n qui font ou cassent les webhooks
Le tunnel transporte le trafic, mais n8n doit savoir sous quelle adresse publique il est servi — sinon il construit ses URLs à partir de ce qu'il voit localement, c'est-à-dire rien d'utile. Trois variables sont indispensables, déjà présentes dans le compose ci-dessus :
N8N_HOST=n8n.mondomaine.fr— le nom d'hôte public de l'instance.WEBHOOK_URL=https://n8n.mondomaine.fr/— la base de toutes les URLs de webhook générées. Sans elle, l'éditeur affiche des URLs enhttp://localhost:5678/webhook/...que Stripe, Typeform ou n'importe quel service externe ne pourra évidemment jamais appeler. C'est le symptôme numéro un d'une installation tunnel incomplète.N8N_EDITOR_BASE_URL=https://n8n.mondomaine.fr/— l'URL de base de l'éditeur, utilisée notamment dans les liens générés par l'instance (callbacks OAuth des credentials, liens dans les emails).
Après modification de ces variables, un docker compose up -d recrée le conteneur et les URLs affichées dans les nodes Webhook basculent sur le domaine public. Le fonctionnement des webhooks à travers le tunnel est ensuite strictement identique à celui derrière un reverse proxy — y compris pour ce qui est de les protéger : les bonnes pratiques de notre guide de sécurisation des webhooks (chemins non devinables, vérification de signature, header secret) s'appliquent à l'identique.
Bonus sécurité : Cloudflare Access devant l'éditeur
Votre instance est maintenant en HTTPS, mais son interface d'édition reste accessible à quiconque connaît l'URL — protégée uniquement par la page de connexion de n8n. Cloudflare Access, inclus dans la même offre Zero Trust, permet d'ajouter une couche d'authentification avant même que la requête n'atteigne n8n, directement sur le réseau Cloudflare.
Le principe : dans le dashboard Zero Trust, vous créez une application Access couvrant n8n.mondomaine.fr, avec une policy qui définit qui peut passer — par exemple « les adresses email de mon équipe, vérifiées par un code à usage unique envoyé par email ». Tout visiteur non authentifié tombe sur une page de connexion Cloudflare avant de voir quoi que ce soit de n8n. Une barrière remarquablement efficace pour un coût de mise en place minime.
La subtilité, c'est que les webhooks doivent rester publics : Stripe ou Typeform ne sauront jamais répondre à un challenge d'authentification Cloudflare. La solution est de créer une seconde application Access, plus spécifique, couvrant n8n.mondomaine.fr/webhook/* (et /webhook-test/* si vous testez depuis l'extérieur), avec une policy de bypass qui laisse passer tout le monde. Access applique la règle la plus spécifique : l'éditeur exige une authentification, les chemins de webhook non. La sécurité des webhooks eux-mêmes repose alors sur les mécanismes classiques — signature, secret partagé — décrits dans le guide dédié.
Les limites honnêtes du modèle
Cloudflare Tunnel est une excellente réponse à un problème précis, pas une solution universellement supérieure. Trois limites à accepter en connaissance de cause :
Une dépendance totale à Cloudflare. Panne du réseau, incident sur votre compte, suspension : l'instance devient injoignable de l'extérieur, sans plan B puisque aucun port n'est ouvert. Les workflows planifiés continuent de tourner localement, mais les webhooks entrants sont coupés le temps de l'incident. Avec un reverse proxy sur VPS, vous ne dépendez « que » de votre hébergeur ; ici, vous ajoutez un maillon.
Tout le trafic transite par Cloudflare. Le TLS étant terminé sur le réseau Cloudflare, celui-ci voit techniquement le trafic en clair, comme n'importe quel CDN en mode proxy. Pour la plupart des usages PME, c'est un compromis banal et assumé ; pour des données très sensibles ou des exigences de conformité strictes, c'est une question à trancher explicitement, pas à découvrir après coup.
Les requêtes HTTP longues. Cloudflare impose un délai maximal aux requêtes HTTP qui le traversent. Un webhook qui déclenche un workflow répondant en quelques secondes ne verra jamais la différence ; un workflow qui fait attendre l'appelant pendant un long traitement (agent IA, génération de document, gros scraping) risque de voir la connexion coupée par Cloudflare avant la réponse de n8n. La parade n'est pas de chercher à rallonger le délai, mais de basculer sur un pattern asynchrone — répondre immédiatement puis livrer le résultat par callback — comme détaillé dans notre guide sur les timeouts de webhook avec agents IA. C'est de toute façon la bonne architecture, tunnel ou pas.
Si aucune de ces limites ne vous concerne et que vous disposez d'un VPS avec ports ouvrables, les solutions Traefik/Caddy restent un choix parfaitement défendable, sans intermédiaire. Le tunnel gagne dès que l'ouverture de port est impossible, interdite ou simplement non souhaitée.
Pièges fréquents
- Pointer le public hostname vers
localhost:5678au lieu du nom de service Dockern8n:5678: depuis le conteneur cloudflared, localhost désigne cloudflared lui-même. Le tunnel est « Healthy » mais renvoie une erreur de connexion. - Oublier
WEBHOOK_URL: l'éditeur fonctionne parfaitement via le tunnel, mais toutes les URLs de webhook affichées pointent vers localhost — et rien d'externe ne peut les appeler. - Laisser un
ports:sur le service n8n dans le compose : l'instance reste alors exposée en HTTP direct sur la machine, à côté du tunnel, ce qui ruine l'argument « aucun port ouvert ». - Mettre le token en dur dans le docker-compose.yml puis pousser le fichier sur Git : le token donne le contrôle du tunnel ; il vit dans un
.envignoré par Git. - Protéger tout le domaine avec Cloudflare Access sans policy de bypass sur
/webhook/*: tous les webhooks externes se mettent à échouer silencieusement avec des redirections vers la page de connexion Cloudflare. - Faire attendre l'appelant pendant un long traitement à travers le tunnel : la coupure viendra de Cloudflare avant la fin. Répondez immédiatement, traitez en asynchrone.
- Confondre les deux modes de configuration : si vous suivez un tutoriel basé sur un fichier
config.ymllocal alors que votre tunnel est géré par le dashboard (token), les réglages du fichier sont ignorés. Choisissez un mode et tenez-vous-y — le dashboard pour la simplicité.
En résumé
Cloudflare Tunnel complète le trio des façons de servir n8n en HTTPS : Traefik/Caddy pour l'automatisation complète sur un VPS ouvert, Nginx pour le contrôle total, et le tunnel pour tous les cas où ouvrir un port est impossible ou indésirable — serveur derrière une box, mini-PC à la maison, pare-feu d'entreprise, ou simple préférence pour une surface d'attaque entrante nulle. Un conteneur cloudflared, un token, un public hostname pointant vers n8n:5678, les trois variables d'URL côté n8n, et l'instance est en production HTTPS sans certificat à gérer ni port à surveiller. Et une fois l'instance joignable publiquement en HTTPS, elle peut servir bien plus que des webhooks techniques : le Pack Assistant RAG (119 €) en fait le socle d'un chatbot documentaire complet — vos documents, un pipeline d'indexation, et un endpoint de chat public que ce tunnel expose proprement au monde.
FAQ
Questions fréquentes
Faut-il quand même un reverse proxy (Traefik, Caddy, Nginx) avec Cloudflare Tunnel ?
Non. Le connecteur cloudflared parle directement au conteneur n8n en HTTP sur le réseau Docker interne (http://n8n:5678), et Cloudflare termine le TLS de son côté. Aucun certificat à générer, aucun port 80 ou 443 à ouvrir sur la machine. Un reverse proxy local redevient utile seulement si vous hébergez plusieurs services derrière le même tunnel et voulez centraliser des règles locales — mais pour une instance n8n seule, cloudflared suffit.
Les webhooks n8n fonctionnent-ils à travers un Cloudflare Tunnel ?
Oui, exactement comme derrière un reverse proxy classique : une requête sur https://n8n.mondomaine.fr/webhook/... traverse le réseau Cloudflare, redescend par le tunnel et atteint le conteneur n8n. La condition indispensable est d'avoir défini WEBHOOK_URL=https://n8n.mondomaine.fr/ dans l'environnement de n8n, sinon les URLs affichées dans l'éditeur pointent vers localhost et aucun service externe ne pourra les appeler. Attention seulement aux exécutions longues en mode synchrone : Cloudflare impose un délai maximal sur les requêtes HTTP, il faut donc répondre vite et traiter en asynchrone.
Que se passe-t-il si Cloudflare tombe en panne ou suspend mon compte ?
Votre instance devient injoignable depuis l'extérieur : tout le trafic entrant passe par le réseau Cloudflare, il n'existe aucun chemin de secours puisque aucun port n'est ouvert sur la machine. L'instance continue de tourner localement (les workflows planifiés s'exécutent normalement), mais les webhooks entrants et l'accès à l'éditeur depuis Internet sont coupés. C'est le compromis à accepter en échange de la simplicité — pour un usage critique, gardez un accès local ou VPN de secours vers la machine.
Bundle FlowKit Complet
269 €