Skip to content

⚙️ 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:

  1. Tailscale — Provides a secure, encrypted network overlay and manages private/public access through Tailscale Serve and Tailscale Funnel.
  2. 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 ​

text
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:

dotenv
# ---------------------------
# 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/keys

TIP

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 ​

yaml
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 ​

  1. Install Docker & Docker Compose

    If not already installed:

    bash
    sudo apt update
    sudo apt install docker.io docker-compose -y
    sudo systemctl enable --now docker
  2. Create Project Directory

    bash
    mkdir -p ~/n8n-tailscale/{tailscale_state}
    cd ~/n8n-tailscale
  3. Create the .env File

    Use the sample above and fill in your Tailscale Auth Key and Tailnet domain.

  4. Create the External Volume

    bash
    docker volume create n8n-compose_n8n_data
  5. Deploy the Stack

    bash
    sudo docker compose up -d
  6. Check Logs and Status

    bash
    sudo docker compose logs -f
    sudo docker exec -it tailscale-n8n tailscale status

    When successful, you’ll see something like:

    text
    n8n 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.net

  • Public Access (via Tailscale Funnel):https://n8n.tailnet-name.ts.net (available to anyone if Funnel is enabled)

🧰 Useful Commands ​

CommandDescription
docker compose up -dStart stack
docker compose downStop stack
docker compose logs -fFollow logs
docker exec -it tailscale-n8n tailscale statusCheck Tailscale connection
docker exec -it tailscale-n8n tailscale ip -4Get Tailscale IP
docker exec -it tailscale-n8n tailscale serve statusCheck 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:

yaml
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 .env to change your Tailscale domain:

    dotenv
    TAILNET_DOMAIN=mytailnet.ts.net
  • Add more environment variables to customize n8n:

    dotenv
    N8N_BASIC_AUTH_ACTIVE=true
    N8N_BASIC_AUTH_USER=admin
    N8N_BASIC_AUTH_PASSWORD=yourpassword

🧾 References ​