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