n8n is a self-hosted workflow automation tool, think Zapier or Make.com but running on your own server. It connects to 400+ apps and APIs, runs scheduled jobs, and processes webhooks. Hosting it yourself means no per-execution costs, your data stays under your control, and you can connect it to LLMs and internal APIs without the SaaS lock-in.
This tutorial walks through the full deployment on a fresh RareCloud KVM VPS: Docker Compose, automatic TLS via Caddy, persistent storage, and a daily backup hook.
What you need
- A RareCloud KVM VPS (1 GB RAM is plenty for personal use, the Core plan works great).
- A domain with DNS you control (any registrar).
- 5-10 minutes of focused time.
Step 1. Provision the VPS
Order a Core VPS from the dashboard (or use the API if you're already on RareCloud):
# If you have the rarecloud CLI installed:
rarecloud server create \
--plan core-vps \
--region the-hague-nl \
--image ubuntu-24.04 \
--name n8n
You'll receive the root password by email and an IP address. SSH in:
ssh root@<your-ip>
Step 2. Point DNS at the VPS
In your registrar's DNS panel, add an A record:
n8n.yourdomain.com β <your-vps-ip>
DNS typically propagates in a few minutes. Wait for dig n8n.yourdomain.com to return your VPS IP before continuing.
Step 3. Install Docker
Ubuntu 24.04 ships with Docker available via apt:
apt update
apt install -y docker.io docker-compose-v2
systemctl enable --now docker
Verify: docker --version should print Docker version 27.x.x or similar.
Step 4. Write docker-compose.yml
Create the working directory and the compose file:
mkdir -p /opt/n8n
cd /opt/n8n
Save the following as /opt/n8n/docker-compose.yml:
services:
n8n:
image: n8nio/n8n:latest
restart: unless-stopped
expose:
- "5678"
environment:
- N8N_HOST=n8n.yourdomain.com
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://n8n.yourdomain.com/
- N8N_PORT=5678
- GENERIC_TIMEZONE=Europe/Bucharest
- TZ=Europe/Bucharest
volumes:
- n8n_data:/home/node/.n8n
caddy:
image: caddy:2-alpine
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 /opt/n8n/Caddyfile:
n8n.yourdomain.com {
reverse_proxy n8n:5678
}
Step 5. Start it up
docker compose up -d
docker compose logs -f
First start pulls the n8n image (~400 MB) and the Caddy image (~30 MB). On a Core VPS with the standard 1 Gbps connection this takes 30-60 seconds.
Once you see Caddy log certificate obtained successfully, browse to https://n8n.yourdomain.com. You'll get the n8n owner-setup page, create your admin user.
Step 6. Backups (daily, automatic)
The n8n_data Docker volume holds your workflows + credentials + execution history. Back it up nightly:
cat > /etc/cron.daily/backup-n8n <<'EOF'
#!/bin/sh
DATE=$(date +%Y-%m-%d)
docker run --rm \
-v n8n_n8n_data:/data \
-v /opt/backups:/backup \
alpine \
tar czf /backup/n8n-${DATE}.tar.gz -C /data .
# Keep last 14 days
find /opt/backups -name 'n8n-*.tar.gz' -mtime +14 -delete
EOF
chmod +x /etc/cron.daily/backup-n8n
mkdir -p /opt/backups
For off-site backups, rsync /opt/backups/ to S3-compatible storage or to a second VPS.
You're done
You now have a production-grade n8n install with TLS, persistent storage, and daily backups for β¬5.50/month. If you outgrow Core, the Plus plan (β¬9.50/mo) gives 4 GB RAM, enough for hundreds of workflows running in parallel.
Troubleshooting
Caddy can't get a certificate. Check that DNS actually points at your VPS (dig n8n.yourdomain.com). Check that ports 80 and 443 are open (ufw status). Let's Encrypt has a rate limit of 5 failed validations per hour per hostname, wait if you've been retrying.
n8n won't start. Look at docker compose logs n8n. The most common issue is the wrong WEBHOOK_URL (it must match the public HTTPS URL exactly).
I want to change the timezone. Edit the GENERIC_TIMEZONE and TZ env vars in docker-compose.yml, then docker compose up -d to recreate the container.