⚙️ n8n + Tailscale + Funnel Deployment (Docker Compose)
This guide explains how to deploy n8n, the powerful automation platform, behind Tailscale using Docker Compose. With this setup, your n8n instance becomes securely accessible via your Tailscale network — and optionally, publicly reachable via Tailscale Funnel, without any reverse proxy or firewall configuration.
🧩 Overview
This stack runs two main services:
- Tailscale — Provides a secure, encrypted network overlay and manages private/public access through Tailscale Serve and Tailscale Funnel.
- n8n — A self-hosted automation and workflow tool.
The n8n container runs inside the Tailscale network namespace, meaning:
- It does not expose any ports publicly.
- It can be accessed via Tailscale domain (private) or via Funnel (public).
📁 Project Structure
n8n-tailscale/
│
├── docker-compose.yml
├── .env
├── tailscale_state/ # Persistent Tailscale data
└── n8n-compose_n8n_data/ # Persistent n8n data (external volume)⚙️ Environment Variables (.env)
Create a .env file next to your docker-compose.yml with these values:
# ---------------------------
# General Settings
# ---------------------------
SERVICE=n8n
TZ=Asia/Kolkata # Your timezone, e.g., America/New_York
# ---------------------------
# n8n Configuration
# ---------------------------
N8N_VERSION=latest
N8N_PORT=5678
TAILNET_DOMAIN=tailnet-name.ts.net # Replace with your actual Tailscale tailnet domain
# ---------------------------
# Tailscale Configuration
# ---------------------------
TS_VERSION=latest
TS_AUTHKEY=tskey-xxxxxxxxxxxxxxxxxxxx # Generate from https://login.tailscale.com/admin/settings/keysTIP
You can create a reusable Auth Key in your Tailscale admin console. Choose Reusable, Ephemeral or Tagged depending on your use case.
🐳 Docker Compose File
services:
tailscale:
image: tailscale/tailscale:${TS_VERSION}
container_name: tailscale-${SERVICE}
restart: unless-stopped
environment:
- TS_STATE_DIR=/var/lib/tailscale
volumes:
- ./tailscale_state:/var/lib/tailscale
- /dev/net/tun:/dev/net/tun
cap_add:
- NET_ADMIN
- SYS_MODULE
dns:
- 1.1.1.1
- 8.8.8.8
command: >
sh -c "
tailscaled & sleep 8 &&
tailscale up --authkey=${TS_AUTHKEY} --hostname=${SERVICE} &&
echo 'Waiting for n8n to start...' &&
while ! nc -z 127.0.0.1 ${N8N_PORT}; do sleep 2; done &&
echo 'n8n detected, setting up Tailscale Serve...' &&
tailscale serve --bg http://127.0.0.1:${N8N_PORT} &&
tailscale funnel --bg http://127.0.0.1:${N8N_PORT} &&
tail -f /dev/null
"
n8n:
image: n8nio/n8n:${N8N_VERSION}
container_name: ${SERVICE}
restart: unless-stopped
depends_on:
- tailscale
network_mode: service:tailscale
environment:
- GENERIC_TIMEZONE=${TZ}
- TZ=${TZ}
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
- N8N_RUNNERS_ENABLED=true
- N8N_EDITOR_BASE_URL=https://${SERVICE}.${TAILNET_DOMAIN}
- WEBHOOK_URL=https://${SERVICE}.${TAILNET_DOMAIN}/
volumes:
- n8n-compose_n8n_data:/home/node/.n8n
volumes:
n8n-compose_n8n_data:
external: true🚀 Setup Instructions
Install Docker & Docker Compose
If not already installed:
bashsudo apt update sudo apt install docker.io docker-compose -y sudo systemctl enable --now dockerCreate Project Directory
bashmkdir -p ~/n8n-tailscale/{tailscale_state} cd ~/n8n-tailscaleCreate the
.envFileUse the sample above and fill in your Tailscale Auth Key and Tailnet domain.
Create the External Volume
bashdocker volume create n8n-compose_n8n_dataDeploy the Stack
bashsudo docker compose up -dCheck Logs and Status
bashsudo docker compose logs -f sudo docker exec -it tailscale-n8n tailscale statusWhen successful, you’ll see something like:
textn8n detected, setting up Tailscale Serve... Serving https://n8n.tailnet-name.ts.net → http://127.0.0.1:5678 Funnel enabled: https://n8n.tailnet-name.ts.net
🌐 Access Your n8n Instance
Once running, you can access your instance:
Private Access (via Tailscale VPN):
https://n8n.tailnet-name.ts.netPublic Access (via Tailscale Funnel):
https://n8n.tailnet-name.ts.net(available to anyone if Funnel is enabled)
🧰 Useful Commands
| Command | Description |
|---|---|
docker compose up -d | Start stack |
docker compose down | Stop stack |
docker compose logs -f | Follow logs |
docker exec -it tailscale-n8n tailscale status | Check Tailscale connection |
docker exec -it tailscale-n8n tailscale ip -4 | Get Tailscale IP |
docker exec -it tailscale-n8n tailscale serve status | Check Serve/Funnel status |
🛡️ Security Notes
- By default, n8n does not expose any public ports.
- Tailscale Serve provides HTTPS via your Tailscale domain.
- Tailscale Funnel can expose your service publicly (optional).
To restrict access, disable Funnel by removing this line from your docker-compose.yml:
tailscale funnel --bg http://127.0.0.1:${N8N_PORT}You can also disable public signups or external triggers in n8n if needed.
🔧 Customization Tips
Modify the hostname in
.envto change your Tailscale domain:dotenvTAILNET_DOMAIN=mytailnet.ts.netAdd more environment variables to customize n8n:
dotenvN8N_BASIC_AUTH_ACTIVE=true N8N_BASIC_AUTH_USER=admin N8N_BASIC_AUTH_PASSWORD=yourpassword