n8n + Cloudflare Tunnel Setup — Self-Hosting on Your Domain
Step 1: Directory and Docker Compose
Create the project directory:
mkdir -p ~/projects/n8n
cd ~/projects/n8n
Create docker-compose.yml:
services:
n8n:
image: n8nio/n8n:latest
container_name: n8n
restart: unless-stopped
ports:
- "5679:5678"
environment:
- N8N_HOST=n8n.yourdomain.com
- N8N_PORT=5678
- N8N_PROTOCOL=https
- N8N_EDITOR_BASE_URL=https://n8n.yourdomain.com
- WEBHOOK_URL=https://n8n.yourdomain.com/
- N8N_DEFAULT_BINARY_DATA_MODE=filesystem
- N8N_PROXY_HOPS=1
- N8N_RUNNERS_ENABLED=true
- GENERIC_TIMEZONE=UTC
volumes:
- n8n_data:/home/node/.n8n
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost:5678/healthz"]
interval: 30s
timeout: 10s
retries: 5
volumes:
n8n_data:
driver: local
networks:
default:
name: openwa-network
Replace n8n.yourdomain.com with your actual subdomain throughout.
Key Environment Variables Explained
N8N_HOST and N8N_EDITOR_BASE_URL must match your tunnel hostname exactly. n8n uses these to generate callback URLs in webhook responses, OAuth redirect URIs, and credential test payloads. If they do not match the browser URL, credential tests fail silently and workflows generate broken URLs.
N8N_PROTOCOL=https — n8n must know it is behind HTTPS even when the local connection is HTTP. Without this, internal links and form actions generate as http:// instead of https://.
N8N_PROXY_HOPS=1 — critical when behind Cloudflare Tunnel. n8n reads the X-Forwarded-Proto header to determine the protocol. Setting this to 1 tells n8n to trust one proxy layer. If you run additional reverse proxies in front of cloudflared, increment this value accordingly.
N8N_RUNNERS_ENABLED=true — enables the separate worker process for asynchronous workflow execution. Disabled by default. Production use always enables this — it prevents long-running workflows from blocking the main web server.
N8N_DEFAULT_BINARY_DATA_MODE=filesystem — stores workflow binary data on the filesystem instead of the database. Keep this. The alternative bloats your database and slows down workflow execution.
Step 2: Install cloudflared
cloudflared creates the tunnel from your server to Cloudflare.
On Ubuntu/Debian:
sudo apt install cloudflared
On other distros or if the package is outdated, download the binary directly:
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o /usr/local/bin/cloudflared
chmod +x /usr/local/bin/cloudflared
Verify:
cloudflared --version
Step 3: Create the Cloudflare Tunnel
Log into Cloudflare Zero Trust: dash.cloudflare.com → Zero Trust → Networks → Tunnels → Create a tunnel → Cloudflared → Give it a name like n8n-proxy.
Cloudflare will show an install command with your tunnel token. Run:
cloudflared tunnel create n8n-proxy
This creates a credentials file at ~/.cloudflared/. Keep it safe.
Step 4: Configure the Tunnel Ingress Rules
Create ~/.cloudflared/n8n-proxy.yml:
tunnel: n8n-proxy
credentials-file: ~/.cloudflared/.json
origincert: ~/.cloudflared/cert.pem
ingress:
- hostname: n8n.yourdomain.com
service: http://localhost:5679
- service: http_status:404
The tunnel connects to localhost:5679 — the Docker host port where n8n is mapped (container port 5678 mapped to host 5679). cloudflared runs on the host, not inside a container, so it connects to the host port.
Step 5: Route the Domain
In Cloudflare Zero Trust dashboard, go to the tunnel's Routes section. Add a route:
Cloudflare handles TLS termination at the edge. Your server never sees a plain HTTP request.
Step 6: Start Everything
cd ~/projects/n8n
sudo docker compose up -d
Wait for n8n to start, then start the tunnel:
cloudflared --config ~/.cloudflared/n8n-proxy.yml tunnel run n8n-proxy
Or use n8nctl which wraps both commands with health checks.
Verify the Tunnel is Live
The cloudflared log should show:
Registered tunnel connection connIndex=0 location=blr02 protocol=quic
Cloudflare assigns the nearest edges. A healthy tunnel shows 4 connections — one per edge pair. Multiple locations (blr02, bom09, bom12) means Cloudflare is load-balancing across PoPs.
Common issue — "Connection terminated" shortly after startup: this means cloudflared connected before n8n was ready. Restart the tunnel — n8n is already up, so the second connection succeeds immediately.
Your n8n is Now Live
Visit https://n8n.yourdomain.com. On first launch, n8n generates an encryption key for stored credentials and redirects you to the setup screen. Create your admin user.
Back up the n8n_data Docker volume. All workflows and credentials live there. Without it, you lose everything on container rebuild.
To back up:
docker run --rm -v n8n_n8n_data:/data -v $(pwd):/backup alpine tar czf n8n-backup.tar.gz -C /data .
Series: ← Overview | Next: n8nctl management script →
Related Posts
Built something similar or want to talk through the architecture? Get in touch.