Skip to content
Slow Life

Self-Hosted n8n with Cloudflare Tunnel – More Stable, No VPS Required

A step-by-step guide to self-hosting n8n using Docker Desktop combined with Cloudflare Tunnel for a permanent URL, free SSL, and no more URL changes like with ngrok.

Tutorials 8 min read
Cloudflare Tunnel
Cloudflare Tunnel

If you’ve been following this Automation series, you’re already familiar with the n8n journey from the very beginning:

  • Part 1: A general introduction to n8n — the powerful open-source workflow automation tool that’s gaining serious traction in the tech community.
  • Part 2: A guide to self-hosting n8n using Docker Desktop + ngrok — the fastest way to run n8n locally and expose it to the internet.

If you haven’t read those two posts yet, go back and check them out first to build a solid foundation, since this article builds directly on that knowledge.

In this post, we’re taking things up a notch: self-hosting n8n with Cloudflare Tunnel — the solution for anyone who needs a permanent URL, a stable connection, and proper SSL security, all while running entirely for free on a personal computer.


Both solve the same problem: exposing your local application to the internet without a VPS or a static IP address. But they have some important differences:

Criteriangrok (Free)Cloudflare Tunnel (Free)
Permanent URL❌ Changes every restart✅ Tied to your domain, fixed forever
Custom domain❌ Uses ngrok subdomain✅ Uses your own domain/subdomain
SSL/HTTPS✅ Yes (automatic)✅ Yes (automatic via Cloudflare)
Speed & latencyAverageLower (Cloudflare global CDN)
Connection limitsYes (Free plan)Unlimited
Setup complexity⭐ Very simple⭐⭐ Requires your own domain
Best forQuick testing, experimentationLong-term, stable production use

Quick verdict:

  • Use ngrok when you need to test something fast, don’t care about the URL changing, and don’t have a domain yet.
  • Use Cloudflare Tunnel when you want a permanent URL, long-term stability, and you already have (or are willing to buy) a domain name.

💡 Domain names like .io.vn or .id.vn currently cost around 30,000–60,000 VND/year — a worthwhile investment if you plan to use n8n seriously.


Instead of letting ngrok manage the tunnel, Cloudflare Tunnel uses a small process called cloudflared that runs on your machine. This process opens an outbound connection to Cloudflare’s infrastructure — no port forwarding, no firewall configuration, no static IP needed.

Internet user
https://n8n.yourdomain.com (Cloudflare DNS + SSL)
Cloudflare Edge Network
cloudflared (running on your machine)
http://localhost:5678 (n8n inside Docker)

The entire flow is encrypted, secure, and the URL never changes as long as you don’t delete the tunnel.


RequirementDetails
DeviceA computer running Windows, macOS, or Linux
Docker DesktopInstalled and running (see Part 2)
n8nAlready running successfully at http://localhost:5678 (see Part 2)
Domain nameAny domain with its nameservers pointed to Cloudflare
Cloudflare accountFree at cloudflare.com
Storage~100MB extra for cloudflared

⚠️ Prerequisite: You must have a domain name, and that domain must be managed by Cloudflare (nameservers pointing to Cloudflare). If you don’t have one yet, buy a domain from any registrar (Namecheap, GoDaddy, Tenten, etc.) and add it to Cloudflare following their guide.


If your domain is already managed by Cloudflare, skip this step.

  1. Log in to Cloudflare Dashboard.
  2. Click Add a Site and enter your domain name.
  3. Select the Free plan and follow the instructions to update your Nameservers at your domain registrar.
  4. Wait anywhere from a few minutes to a few hours for Cloudflare to verify ownership.

Once the dashboard shows an Active status in green, you’re ready for the next steps.


  1. From the Cloudflare Dashboard, click Zero Trust in the left sidebar (or go directly to one.dash.cloudflare.com).
  2. If this is your first time, Cloudflare will ask you to name your team — enter anything you like, for example: myteam.
  3. Select the Free plan and confirm.

  1. Inside the Zero Trust Dashboard, go to NetworksTunnels.
  2. Click Create a tunnel.
  3. Select Cloudflared as the connector type → Click Next.
  4. Give your tunnel a name, for example: n8n-local → Click Save tunnel.

Cloudflare will display an install command containing your token, which looks something like this:

Terminal window
cloudflared service install eyJhIjoiXXXXXXXXXXXXXXXXXXXX...

Copy the entire long token string (the part after install ) — you’ll need it in Step 4. You don’t need to run this command yet.


Still within the tunnel creation flow, Cloudflare will move to the Route tunnel screen. This is where you define which subdomain will point to n8n.

Fill in the fields as follows:

FieldValue
Subdomainn8n (or any name you prefer)
DomainSelect your domain from the list
TypeHTTP
URLlocalhost:5678

Result: your n8n instance will be accessible at https://n8n.yourdomain.com.

Click Save tunnel to finish the configuration.


Instead of installing cloudflared directly on your machine, we’ll run it as a service inside Docker Compose — cleaner and easier to manage.

Open the docker-compose.yaml file in your n8n project folder and add the cloudflared service:

services:
n8n:
image: n8nio/n8n:latest
container_name: n8n
restart: unless-stopped
ports:
- '5678:5678'
env_file:
- .env
volumes:
- ./n8n_data:/home/node/.n8n
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
command: tunnel --no-autoupdate run --token ${CLOUDFLARE_TUNNEL_TOKEN}
depends_on:
- n8n

💡 depends_on: - n8n ensures cloudflared only starts after the n8n container is ready.

Open your .env file and add the following line, pasting in the token you copied in Step 2.3:

N8N_HOST=localhost
N8N_PORT=5678
N8N_PROTOCOL=http
GENERIC_TIMEZONE=Asia/Ho_Chi_Minh
TZ=Asia/Ho_Chi_Minh
N8N_SECURE_COOKIE=false
WEBHOOK_URL=https://n8n.yourdomain.com
CLOUDFLARE_TUNNEL_TOKEN=eyJhIjoiXXXXXXXXXXXXXXXXXXXX...

Important notes:

  • Replace n8n.yourdomain.com with the actual subdomain you configured in Step 3.
  • Replace the token placeholder with your actual token.
  • Do not wrap the token in quotation marks.

From your project directory, run:

Terminal window
docker compose down
docker compose up -d

Docker will pull the cloudflare/cloudflared image and start both containers. The tunnel connection typically takes 10–30 seconds to establish.


Terminal window
docker compose logs cloudflared

If you see lines similar to the following, the tunnel is connected successfully:

INF Connection registered connIndex=0 ...
INF Connection registered connIndex=1 ...

Go back to Zero TrustNetworksTunnels. Your n8n-local tunnel should now show a Healthy status in green.

Open your browser and navigate to:

https://n8n.yourdomain.com

If the n8n login screen appears with a green HTTPS padlock in the address bar — congratulations, you’ve successfully self-hosted n8n with Cloudflare Tunnel! 🎉


n8n/
├── .env ← Contains configuration and CLOUDFLARE_TUNNEL_TOKEN
├── docker-compose.yaml ← Defines both the n8n and cloudflared services
└── n8n_data/ ← Auto-generated, stores the database and workflows

Problem with ngrokSolution with Cloudflare Tunnel
URL changes every restartPermanently fixed URL
Must update WEBHOOK_URL every timeConfigure once, use forever
Must restart Docker each time ngrok changes URLFully automatic, no manual steps needed
ngrok terminal must stay opencloudflared runs silently inside Docker, auto-starts with your machine

Secure your tunnel token The .env file contains a Cloudflare token that has full control over your tunnel. Never commit this file to Git or share it publicly. Add .env to your .gitignore if you use Git.

Your computer must be on Cloudflare Tunnel is only a bridge — n8n still runs on your local machine. If your computer shuts down or Docker stops, n8n will be inaccessible from the outside.

No port forwarding required Cloudflare Tunnel does not require you to open any ports on your router or firewall. All connections are initiated as outbound from your machine — a major security advantage over manual port-forwarding.

Back up your data All your workflows and credentials are stored in the n8n_data folder. Back up this directory regularly.


With a permanent URL and proper SSL, you can now integrate n8n with services that require a stable, unchanging webhook URL:

  • Stripe Webhooks — Receive real-time payment notifications automatically.
  • GitHub/GitLab Actions — Trigger workflows whenever new code is pushed to a repo.
  • Notion Database Trigger — React when data in Notion changes.
  • Telegram/Discord Bot — A bot that receives commands and replies 24/7 (as long as your machine stays on).
  • AI Content Pipeline — Collect data via Webhook → Process with OpenAI/Gemini/Claude → Auto-publish to your website.

The Local Docker + Cloudflare Tunnel setup addresses most of ngrok’s shortcomings and fits the needs of the majority of individual users. That said, consider upgrading to a VPS when:

  • You need the system to run truly 24/7, independent of your personal computer.
  • Your workload is large and requires dedicated resources (CPU/RAM).
  • You’re deploying for a business production environment with SLA and uptime requirements.

Good news: once you’re comfortable with Cloudflare Tunnel, moving to a VPS is straightforward — just install Docker on the VPS and run the same docker-compose.yaml file.


ngrokCloudflare Tunnel
Free
No VPS needed
Permanent URL
Automatic SSL
Requires own domain
Runs silently in Docker
Suitable for long-term use

With Cloudflare Tunnel, you now have a truly stable, secure, and professional self-hosted n8n setup — completely free, with the only cost being a domain name that runs a few dollars a year.

Good luck with your setup, and see you in the next post! 🚀

Comments