Self-hosting n8n on a VPS: what to know before you start
Self-hosting n8n on a VPS means installing it on your own virtual server instead of paying for n8n's cloud plan by usage. Before you self-host n8n on a VPS, you need to size the server, pick Docker or npm, choose a database, set an encryption key, and plan backups so nothing is lost when something goes wrong.
Sizing your VPS by workload
A 2 vCPU, 2 GB RAM VPS runs n8n for a handful of simple workflows — sending Zalo messages, writing to Google Sheets, basic reconciliation. A 2 vCPU, 4 GB RAM VPS is more comfortable: around ten workflows running in parallel, with a PostgreSQL database on the same machine. A 20 GB SSD is enough for the OS, n8n and the database to start.
Once workflows call AI (generating content, processing images, multi-step agents) or automate video editing, RAM and CPU usage climbs faster because each task holds memory longer and handles heavier files than a typical text workflow — plan for 4 vCPUs and 8 GB RAM or more, and watch actual usage during the first week so you can scale up before the server slows down.
| Workload | Suggested sizing |
|---|---|
| A few simple workflows, running a handful of times an hour | 2 vCPU, 2 GB RAM, 20 GB SSD |
| Around ten workflows, with a dedicated PostgreSQL database | 2 vCPU, 4 GB RAM, 40 GB SSD |
| AI agents, image/video processing, many workflows running at once | 4 vCPUs or more, 8 GB RAM or more |
Installing n8n on a VPS: Docker Compose or npm
n8n supports two installation paths on a Linux VPS: Docker Compose or a direct npm/Node.js install. Docker Compose packages n8n with the exact Node.js version it needs inside one container, avoids conflicts with other software on the box, and lets you upgrade with a couple of commands that pull the new image.
Installing via npm suits teams already comfortable administering Linux and wanting control over each component, but you must install the exact Node.js version n8n requires yourself and configure n8n to restart with the server (via systemd or pm2). For anyone self-hosting for the first time, Docker Compose is the safer, easier-to-maintain choice.
- Docker Compose: a single configuration file; upgrade by pulling the new image and restarting the container
- npm: install the Node.js version n8n requires, install n8n globally, and configure it to run as a background service that restarts on reboot
- Either way, n8n must sit behind a reverse proxy — never expose n8n's default port straight to the internet
Domain, reverse proxy and SSL
n8n needs to run over HTTPS for webhooks to work reliably — many outside services (payment gateways, banks, Zalo OA) refuse to send data to an HTTP address. The standard approach is to point a subdomain (for example n8n.yourdomain.com) at the VPS's IP address, then run nginx or Caddy as a reverse proxy in front of n8n and request a free SSL certificate through certbot.
Once the domain and SSL are in place, n8n needs to know its own public address: set N8N_HOST to the domain, N8N_PROTOCOL=https, and N8N_WEBHOOK_URL to the full HTTPS URL — skip this and n8n shows the wrong internal address in webhook URLs, so calls from outside services fail. You also need to set N8N_PROXY_HOPS=1 as soon as n8n sits behind a single reverse proxy (nginx or Caddy) — even without Cloudflare in front — so n8n reads the visitor's real IP address instead of the proxy's; add one more hop for each additional proxy layer in front (Cloudflare, for example).
Choosing a database: SQLite by default or PostgreSQL
n8n uses SQLite as its default database — a single file, nothing extra to install, fine for trying things out or running a few lightweight workflows. The downside is that SQLite doesn't handle many concurrent writes well, so it can slow down or error out as the number of workflows and executions grows.
For a production environment running a business, switch to PostgreSQL from the start: set the environment variables that tell n8n to connect to PostgreSQL, and n8n creates the tables it needs on first startup. PostgreSQL is also a hard requirement if you later want to scale into queue mode with multiple parallel workers.
N8N_ENCRYPTION_KEY: the key you cannot lose
n8n generates a random encryption key the first time it starts, stores it in n8n's configuration folder on the VPS, and uses that key to encrypt every saved credential — passwords, API keys, tokens — before writing it to the database. Lose that key without a backup and every stored credential becomes unreadable, forcing you to re-enter login details for every workflow from scratch.
Set the key yourself via the N8N_ENCRYPTION_KEY environment variable during the first install, then store a copy somewhere safe away from the VPS. If you later run multiple worker processes (queue mode), every machine must use the exact same key to read the encrypted data correctly.
Backing up properly: not just the workflow files
Exporting each workflow's .json file is not enough — it doesn't contain saved credentials and can't restore the instance's configuration. Back up three things on a schedule: the database (the SQLite file or a PostgreSQL dump), the N8N_ENCRYPTION_KEY, and n8n's configuration folder on the VPS.
- Schedule automatic daily backups with cron and push copies off the VPS (email, Google Drive, or another server)
- Test a restore at least once — a backup that has never been restored is not a backup you can rely on
- Also export workflow .json files regularly, or connect them to Git to track changes over time
Day-to-day security
As of n8n 1.0, logging in with basic auth (a single shared username/password) no longer works — n8n uses its own user management system, with email/password accounts and owner and member roles (an admin role requires a paid Enterprise or Cloud plan; the self-hosted Community edition doesn't have it). Configure SMTP so n8n can send invites and password resets itself; skip that step and you'll need to send invite links by hand to each user.
- Only open ports 80 and 443 to the internet through a firewall; n8n's default port should only listen locally, behind the reverse proxy
- Update the n8n image regularly and read the release notes before major upgrades — some changes, like removing basic auth, have locked out users of older versions after an update
- For workflows that receive public webhooks, verify a signature or shared secret before processing the request, so not just anyone can call that webhook
Scaling with queue mode and keeping watch
When incoming webhook traffic spikes or long-running workflows clog the queue, n8n supports queue mode: a main process accepts webhooks and schedules, pushes the work into Redis, and separate worker processes pull jobs from Redis to run in parallel — add or remove workers as load changes. Queue mode requires switching to PostgreSQL first, since SQLite can't handle that many concurrent writes; every worker must also share the same N8N_ENCRYPTION_KEY as the main process.
Alongside that, monitor n8n instead of waiting for a customer to report a problem: check the list of failed executions in the n8n interface daily, or build a workflow that uses an Error Trigger to alert you over Zalo or email as soon as another workflow fails.
Real monthly costs
Self-hosting n8n on a VPS involves three costs: the VPS, the domain, and your own setup time. A 2-4 GB RAM VPS, enough for most small businesses, currently runs around VND 100,000-200,000 a month as a reference; a larger configuration for AI or video processing costs more than that, depending on the provider, so compare pricing before choosing one.
| Item | Reference cost/time |
|---|---|
| VPS with 2-4 GB RAM | VND 100,000-200,000/month |
| VPS with 8 GB RAM or more (AI, video) | More than the above, depending on the provider |
| Domain | Billed yearly, depending on the extension and registrar |
| Time for the first setup | Half a day to a few days, depending on your comfort with Linux and Docker |
