How to self-host n8n on a VPS in 10 minutes
n8n is an open-source automation tool, similar to Zapier or Make, that you can run on your own server. Self-hosting means your workflows, credentials and execution history stay on a machine you control, and you are not limited by per-task pricing.
This guide takes you from a fresh Ubuntu server to n8n running at https://n8n.example.com with a real HTTPS certificate. If your domain is ready, the hands-on part takes about ten minutes.
What you need
- A VPS running Ubuntu 24.04 (22.04 works too) with root SSH access and a public IPv4 address.
- A domain or subdomain you control, for example
n8n.example.com. - A terminal on your computer: Terminal on macOS and Linux, PowerShell or Windows Terminal on Windows.
Throughout this guide, replace n8n.example.com with your own subdomain and 203.0.113.10 with your server's IP address.
Step 1. Point your domain at the server
In your DNS provider's panel, create an A record:
- Name:
n8n(or whatever subdomain you want) - Value: your server's IPv4 address
DNS changes can take a few minutes to become visible. You can check from your computer:
nslookup n8n.example.com
When the answer shows your server's IP, you are ready for HTTPS.
Step 2. Connect and update the server
ssh root@203.0.113.10
apt update && apt upgrade -y
Step 3. Install Docker
Docker's official install script adds Docker Engine and the Compose plugin:
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
docker compose version
The last command should print a version number. If it does, Docker is installed.
Step 4. Open only the ports you need
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
Port 80 is needed so the HTTPS certificate can be issued; port 443 is where n8n will be served.
Docker publishes container ports around
ufw. That is why, below, only the Caddy web server publishes ports 80 and 443, and n8n itself is not published to the internet at all.
Step 5. Create the project files
mkdir -p /opt/n8n && cd /opt/n8n
Create a file called .env with your settings. The encryption key protects the credentials n8n stores, so generate a random one and keep a copy somewhere safe:
cat > .env <<EOF
N8N_HOST=n8n.example.com
GENERIC_TIMEZONE=Europe/Berlin
N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)
EOF
chmod 600 .env
Now create docker-compose.yml:
services:
n8n:
image: docker.n8n.io/n8nio/n8n
restart: unless-stopped
environment:
- N8N_HOST=${N8N_HOST}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://${N8N_HOST}/
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
- TZ=${GENERIC_TIMEZONE}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
volumes:
- n8n_data:/home/node/.n8n
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
volumes:
n8n_data:
caddy_data:
caddy_config:
And a Caddyfile for the web server. Caddy requests and renews the HTTPS certificate automatically:
n8n.example.com {
reverse_proxy n8n:5678
}
Step 6. Start n8n
docker compose up -d
docker compose logs -f
Wait until the logs show that n8n is ready and Caddy has obtained a certificate, then press Ctrl+C to stop following the logs (the containers keep running).
Open https://n8n.example.com in your browser. On the first visit n8n asks you to create the owner account. Do it right away: until you do, anyone who opens the address could claim it.
Keeping it healthy
Updates. New n8n versions come out often. To update:
cd /opt/n8n
docker compose pull
docker compose up -d
Read the n8n release notes before big version jumps, and take a backup first.
Backups. Your workflows and credentials live in the n8n_data volume. A simple manual backup:
cd /opt/n8n
docker compose stop n8n
docker run --rm -v n8n_n8n_data:/data -v "$PWD":/backup alpine tar czf /backup/n8n-backup.tar.gz -C /data .
docker compose start n8n
The volume name is the project folder plus the volume name (n8n_n8n_data here); docker volume ls shows the exact name. Copy the archive and your .env file off the server. Without the encryption key from .env, stored credentials cannot be decrypted.
Security basics.
- Keep the system updated:
apt update && apt upgrade -yfrom time to time, or enableunattended-upgrades. - Use SSH keys instead of a password for logging in.
- Never commit
.envto a Git repository.
Common problems
- The browser shows a certificate error. DNS probably did not point to the server yet when Caddy started. Check with
nslookup, then rundocker compose restart caddy. - Webhooks show
localhostURLs.WEBHOOK_URLis missing or wrong indocker-compose.yml. Fix it and rundocker compose up -d. - "Your n8n server is configured to use a secure cookie" message. You are opening n8n over plain
http. Use thehttps://address.
Where to go next
Once n8n is running, you can connect it to your CRM, email, Telegram or AI models and let workflows run around the clock, even when your laptop is closed. That is the main reason to self-host on a VPS instead of running n8n on your own computer.