DocsSelf-host n8n
01 / 01

Self-host n8n on a VPS

Set up your own n8n instance with SSL and a custom domain for ~€5/month.

Overview

This guide walks you through setting up your own n8n instance on a VPS (Virtual Private Server). Self-hosting gives you unlimited workflow executions for a fraction of the cost of cloud plans.

If you build in Make, skip this page - Make is hosted and needs no setup.

~€5
per month
~20
minutes setup
executions
Why self-host?

n8n Cloud costs $24/month for just 2,500 executions. Self-hosting on Hetzner gives you unlimited executions for ~€5/month. Perfect for learning, development, and production workloads.

Prerequisites

Before starting, make sure you have:

  • A Hetzner account - Sign up at hetzner.com/cloud
  • A domain you control - For SSL certificates (optional but recommended)
  • Terminal access - macOS Terminal, Windows PowerShell, or Linux terminal

Part 1: create the server

Step 1: create a Hetzner account

  1. Go to hetzner.com/cloud
  2. Sign up and add a payment method (~€20 initial charge becomes credit)

Step 2: create a new server

  1. Click "Add Server"
  2. Configure the following:
SettingValue
LocationNuremberg (or closest to you)
ImageUbuntu 24.04
TypeCX22 or CX23 (Shared, ~€4-5/month)
NetworkingIPv4 + IPv6

Step 3: set up an SSH key

Before creating the server, add your SSH key for secure access.

Check if you have an SSH key:

Terminal
cat ~/.ssh/id_rsa.pub

If no key exists, generate one:

Terminal
ssh-keygen -t rsa -b 4096
# Press Enter through all prompts

Copy your public key:

Terminal
cat ~/.ssh/id_rsa.pub

In Hetzner:

  1. Click "+ Add SSH key"
  2. Paste your public key
  3. Name it (e.g., "MacBook")

Step 4: finalize server creation

  • Volumes: Skip
  • Firewalls: Skip
  • Backups: Skip (optional, adds 20% cost)
  • Name: n8n-dev (or whatever you prefer)

Click "Create & Buy now" and wait for the green status dot.

Part 2: install Docker

Step 1: connect to your server

Terminal
ssh root@YOUR_SERVER_IP

Replace YOUR_SERVER_IP with the IPv4 address from your Hetzner dashboard. Type yes when asked about the fingerprint.

Step 2: update the system and install Docker

On your server
apt update && apt upgrade -y && apt install -y docker.io docker-compose-v2 && systemctl enable docker && systemctl start docker

Wait until the installation completes.

Part 3: basic n8n setup (no SSL)

Note

Use this for quick testing without a domain. Skip to Part 4 if you have a domain ready.

Step 1: create a project directory

On your server
mkdir -p /opt/n8n && cd /opt/n8n

Step 2: create the Docker Compose file

On your server
nano docker-compose.yml

Paste this configuration:

docker-compose.yml
services:
  n8n:
    image: n8nio/n8n
    restart: always
    ports:
      - "5678:5678"
    environment:
      - N8N_HOST=localhost
      - N8N_PORT=5678
      - N8N_PROTOCOL=http
      - WEBHOOK_URL=http://localhost:5678/
      - N8N_SECURE_COOKIE=false
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  n8n_data:

Save: Ctrl + X, then Y, then Enter

Step 3: start n8n

On your server
docker compose up -d

Step 4: access n8n

Open in your browser: http://YOUR_SERVER_IP:5678

Part 4: add a custom domain with SSL

Recommended for production

SSL is required for secure webhooks and is strongly recommended for any serious use.

Step 1: add a DNS record

In your domain provider (Hostinger, Cloudflare, Namecheap, etc.):

  1. Go to DNS settings for your domain
  2. Add an A Record:
FieldValue
Name/Hostn8n
Value/Points toYour server's IP address
TTL3600

This creates n8n.yourdomain.com. Wait a few minutes for DNS propagation.

Step 2: stop the current n8n (if running)

On your server
cd /opt/n8n
docker compose down

Step 3: update the config with SSL

On your server
rm docker-compose.yml && nano docker-compose.yml

Paste this configuration (replace YOUR_DOMAIN and YOUR_EMAIL):

docker-compose.yml
services:
  traefik:
    image: traefik:v3.0
    restart: always
    command:
      - "--api=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.email=YOUR_EMAIL"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - traefik_data:/letsencrypt
      - /var/run/docker.sock:/var/run/docker.sock:ro

  n8n:
    image: n8nio/n8n
    restart: always
    environment:
      - N8N_HOST=YOUR_DOMAIN
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://YOUR_DOMAIN/
      - N8N_SECURE_COOKIE=true
    volumes:
      - n8n_data:/home/node/.n8n
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.n8n.rule=Host(`YOUR_DOMAIN`)"
      - "traefik.http.routers.n8n.entrypoints=websecure"
      - "traefik.http.routers.n8n.tls.certresolver=letsencrypt"
      - "traefik.http.services.n8n.loadbalancer.server.port=5678"

volumes:
  traefik_data:
  n8n_data:
Replace these values
  • YOUR_EMAIL → your actual email (for SSL certificate notifications)
  • YOUR_DOMAIN → e.g., n8n.yourdomain.com (appears 4 times)

Step 4: start with SSL

On your server
docker compose up -d

Wait 30 seconds for SSL certificate provisioning.

Step 5: access n8n

Open in your browser: https://n8n.yourdomain.com

You should see a green padlock (secure connection).

Part 5: generate an API key

To connect n8n with external tools or MCP servers, generate an API key:

  1. In n8n, click your profile icon (bottom left)
  2. Go to Settings
  3. Click API or API Keys
  4. Click Create API Key
  5. Name it (e.g., "Claude MCP" or "External Access")
  6. Copy and save the key securely
Warning

Store your API key securely. It grants full access to your n8n instance.

Useful commands

Check if n8n is running

bash
docker ps

View logs

bash
cd /opt/n8n && docker compose logs -f

Restart n8n

bash
cd /opt/n8n && docker compose restart

Stop n8n

bash
cd /opt/n8n && docker compose down

Start n8n

bash
cd /opt/n8n && docker compose up -d

Update n8n to latest version

bash
cd /opt/n8n
docker compose down
docker pull n8nio/n8n
docker compose up -d

SSH into server

bash
ssh root@YOUR_SERVER_IP

Troubleshooting

Can't access n8n in browser

  • Check if container is running: docker ps
  • Check logs: docker compose logs
  • Verify firewall allows ports 80, 443, 5678

SSL not working

  • Ensure DNS is pointing to correct IP: ping n8n.yourdomain.com
  • Wait a few minutes for DNS propagation
  • Check Traefik logs: docker compose logs traefik

n8n showing old data after restart

  • Data persists in Docker volumes - this is normal behavior
  • To reset completely: docker volume rm n8n_n8n_data

Cost summary

ItemCost
Hetzner CX22/CX23~€4-5/month
Domain (if new)~€10/year
SSL CertificateFree (Let's Encrypt)
Total~€5/month

Comparison with n8n Cloud

Self-hosted (Hetzner)
€5/month • Unlimited executions
n8n Cloud Starter
$24/month • 2,500 executions
You're ready

Your self-hosted n8n instance is now running with SSL. You can create workflows, set up webhooks, and connect to Nodox briefs using your custom domain.