cd /news/developer-tools/self-host-n8n-on-a-vps-with-docker Β· home β€Ί topics β€Ί developer-tools β€Ί article
[ARTICLE Β· art-39077] src=dev.to β†— pub= topic=developer-tools verified=true sentiment=Β· neutral

Self-host n8n on a VPS with Docker

A developer provides a step-by-step guide for self-hosting n8n on a VPS using Docker, emphasizing cost savings, data control, and security. The setup involves installing Docker, configuring a docker-compose.yml with n8n and Postgres, and accessing the instance via SSH tunnel or reverse proxy. The guide recommends a 2 GB VPS for most workloads and highlights the benefits of flat monthly pricing versus per-execution cloud seats.

read3 min views1 publishedJun 25, 2026

n8n is the kind of tool you start using lightly and then quietly route half your operations through. At which point "it's running on someone's cloud seat, metered per execution, with my API keys living on their servers" starts to feel less great. Self-hosting fixes all three β€” flat cost, no execution cap, and your keys stay on a box you own. With Docker it's a fifteen-minute job.

Honest numbers first, so you don't over- or under-buy:

n8n isn't CPU-hungry at rest; it spikes during runs. A 2-core box is fine for most setups. (More on matching specs to workload in the sizing guide.)

On a fresh Ubuntu/Debian box, install Docker:

curl -fsSL https://get.docker.com | sudo sh

Make a folder and a docker-compose.yml

β€” n8n with a persistent volume and Postgres:

services:
  n8n:
    image: docker.n8n.io/n8nio/n8n
    restart: always
    ports:
      - "127.0.0.1:5678:5678"
    environment:
      - N8N_HOST=n8n.yourdomain.com
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://n8n.yourdomain.com/
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=db
      - DB_POSTGRESDB_PASSWORD=change-me
    volumes:
      - ./n8n-data:/home/node/.n8n
    depends_on: [db]
  db:
    image: postgres:16
    restart: always
    environment:
      - POSTGRES_PASSWORD=change-me
      - POSTGRES_DB=n8n
    volumes:
      - ./db-data:/var/lib/postgresql/data
sudo docker compose up -d

Two things worth pointing out: the volumes (n8n-data

, db-data

) are what keep your workflows alive across restarts and upgrades β€” don't skip them. And n8n is bound to 127.0.0.1

, not 0.0.0.0

β€” it's not exposed to the internet directly. That's deliberate; the next step handles access safely.

127.0.0.1:5678

. This is where a ssh -L 5678:127.0.0.1:5678 user@server

, then open localhost:5678

. Works fine on a NAT VPS.n8n holds your API keys and credentials, so the box must be tight: do the security checklist (SSH keys, firewall, no password login) before you put real credentials in. restart: always

in the compose file already means Docker brings n8n back after a crash or reboot β€” that's your uptime handled.

Be honest with yourself about volume. If you run automations constantly, self-hosting wins on cost (flat vs per-execution) and removes any workflow/run limits. If you trigger a few flows a month, a hosted seat is less hassle. But the control argument stands regardless: your workflows, your data, your keys β€” on your server, not rented. For most people who got serious about n8n, that's the deciding factor.

A 2 GB box, a compose file, a domain (or a tunnel), and you're running your own automation hub β€” payable in crypto with no KYC, live in minutes.

Around 2 GB is the comfortable sweet spot for n8n plus its Postgres database and normal workflows. It runs in 1 GB if workflows are light, but you'll feel it during bigger runs. Heavy parallel executions or large payloads β€” go to 4 GB.

It's by far the easiest way β€” one compose file gives you n8n, a database and persistent storage, and upgrades are a single pull. You can install via npm instead, but Docker saves you the dependency and upgrade headaches.

If you run a steady stream of automations, yes β€” a flat monthly VPS beats per-execution pricing, and there's no workflow or execution cap. For a handful of runs a month, a hosted seat may be simpler. The other reason people self-host is control: your data and API keys never leave your server.

For OAuth-based nodes (Google, etc.) and clean HTTPS, yes β€” point a domain at the server and put n8n behind a reverse proxy with a certificate. For purely internal use you can reach it over an SSH tunnel without a domain.

Internal/SSH-tunnel use works on a NAT box. If you want a public URL with your own domain and HTTPS (needed for some OAuth callbacks and webhooks), a dedicated-IP plan is the cleaner fit since you control all ports.

Originally published at eqvps.com.

── more in #developer-tools 4 stories Β· sorted by recency
── more on @n8n 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/self-host-n8n-on-a-v…] indexed:0 read:3min 2026-06-25 Β· β€”