Your n8n Cloud bill stopped being cute the month your workflows actually started working. A few thousand executions here, an extra active workflow there, and suddenly the automation costs more than the app it automates.
So you look at the other door. You can self host n8n on a small Linux VPS, run as many executions as your CPU can chew through, and keep client payloads on a server you control. The trade is real, though: you're the ops team now. Nobody patches it at 2am except you.
Our team resolves 20-30 client server issues every day, and self-hosted automation containers have been landing in that queue every week since 2025 — this guide comes straight out of that work, written so you can do it yourself without opening a ticket. Hostaccent has been running Docker workloads on self-managed Ubuntu boxes for years (trading since 2012, UK-incorporated 2018), so what follows is what we'd actually deploy, not a reworded README.
Quick answer (as of July 2026): Self-hosting n8n needs a Linux VPS with 2GB RAM minimum (4GB if you run queue mode, Puppeteer or heavy AI nodes), Docker and Docker Compose, a domain pointed at the server, Nginx as a reverse proxy, and a free Let's Encrypt certificate. Budget 30-45 minutes for the first install and roughly $8-12/month for hardware that won't choke.
What You Actually Get When You Self Host n8n
Self-hosting swaps a subscription for a server. That's the whole trade in one sentence.
What you gain is worth naming precisely:
- Execution volume stops being a line item. A 2 vCPU box handles tens of thousands of runs a month without complaint. The meter is gone.
- Community nodes and custom code. The full node library plus your own JavaScript, no plan tier gating it.
- Data residency. Credentials, payloads and execution history live in your database, in the region you picked. For anyone under GDPR or a client DPA, that argument wins meetings.
What you lose is worth naming too, because most tutorials skip it:
- Upgrades are your problem. n8n ships fast. Breaking changes land in major versions.
- Downtime is silent. A stuck container doesn't email you. Your workflows just quietly stop.
- The first outage costs more than a year of cloud. If nobody notices for a week that the invoice sync died, the savings evaporate.
Here's the honest filter — call it the 3-Question Self-Host Test:
- Will you notice within an hour if it stops?
- Have you actually restored a backup, not just taken one?
- Is there a manual fallback if a workflow dies for a day?
Two yeses and you're fine. Zero yeses on a billing-critical workflow, and you should stay on the hosted plan and stop reading. That's not a sales line — it's the advice we give people whose setups we'd otherwise inherit.
Pro Tip: Read n8n's official self-hosting documentation alongside this guide, not instead of it. The docs track version-specific environment variables that change between releases; this guide covers the server side the docs assume you already know.
n8n Self Hosted Requirements: How to Size the VPS
Start here, because undersizing is the single most common reason a self-hosted instance feels broken.
n8n itself is a Node.js app. It idles at roughly 200-300MB RAM. The problem is never idle — it's what your workflows drag in: a Code node parsing a 40MB JSON payload, an AI node holding a context window, or Puppeteer launching a headless Chromium that wants 500MB+ on its own.
| VPS size | Good for | Watch out for | |---|---|---| | 2GB RAM, 1-2 vCPU, 20GB NVMe SSD | 10-30 workflows, webhooks, API calls, light schedules | Puppeteer, big file processing, SQLite under concurrency | | 4GB RAM, 2 vCPU, 50GB NVMe SSD | 50+ workflows, Postgres, AI nodes, browser automation | Long execution history retention filling the disk | | 8GB RAM, 4 vCPU, 100GB+ NVMe SSD | Queue mode with Redis and multiple workers | Nothing much — this is comfortable for most agencies |
Two hardware notes that matter more than the RAM number. First, use NVMe SSD storage, not spinning disks or network volumes — n8n writes an execution record for every single run, and database write latency is what makes the editor feel sluggish. Second, 1 vCPU is fine until it isn't: Node is single-threaded per process, so a heavy Code node blocks everything else on that instance.
Hostaccent's Basic VPS is 2GB RAM on NVMe, which is the tier we'd point a solo builder at; anyone running browser automation should start at 4GB and skip the experiment. In our experience the people who come back asking why n8n "keeps crashing" are almost always on a 1GB box with swap disabled — the OOM killer takes the container out and Docker restarts it, so the logs look mysterious until you check dmesg.
Insider Insight: Set your VPS swap to at least 2GB even on a 4GB server. It won't make n8n fast, but it turns a hard OOM kill into a slow, survivable minute — which is the difference between a degraded workflow and a lost one.
Before you install anything, get the base server right: a firewall, SSH keys, no root login. Our Linux VPS Security Baseline (Ubuntu 24.04) in 30 Min walks the whole thing, and it takes less time than debugging a compromised box for an afternoon. If you want alerting from day one, Setup Server Monitoring on VPS: Know Before Your Users Do covers the piece that stops silent failures.
The n8n Docker Install, Step by Step
The rest of this n8n VPS setup assumes Ubuntu 24.04 LTS, a domain you control, and Docker already installed. If Docker isn't on the box yet, use Install Docker on Ubuntu VPS: Secure Production Setup first — the rootless and daemon-hardening bits there matter for anything holding API credentials.
Step 1 — Point DNS at the server. Create an A record for n8n.yourdomain.com pointing at your VPS IP. Do this first; propagation runs in the background while you work, and Let's Encrypt will need it resolving later.
Step 2 — Create the project directory.
bashmkdir -p /opt/n8n && cd /opt/n8n mkdir -p ./n8n-data ./postgres-data
Step 3 — Write the compose file. This is the version we'd hand a client: Postgres instead of SQLite, timezone set, and — the line everyone forgets — an explicit WEBHOOK_URL.
yamlservices: postgres: image: postgres:16 restart: always environment: POSTGRES_USER: n8n POSTGRES_PASSWORD: change_this_now POSTGRES_DB: n8n volumes: - ./postgres-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U n8n"] interval: 10s retries: 5 n8n: image: docker.n8n.io/n8nio/n8n:latest restart: always ports: - "127.0.0.1:5678:5678" environment: - DB_TYPE=postgresdb - DB_POSTGRESDB_HOST=postgres - DB_POSTGRESDB_USER=n8n - DB_POSTGRESDB_PASSWORD=change_this_now - N8N_HOST=n8n.yourdomain.com - N8N_PROTOCOL=https - WEBHOOK_URL=https://n8n.yourdomain.com/ - GENERIC_TIMEZONE=Europe/London - N8N_ENCRYPTION_KEY=generate_a_long_random_string - EXECUTIONS_DATA_PRUNE=true - EXECUTIONS_DATA_MAX_AGE=336 volumes: - ./n8n-data:/home/node/.n8n depends_on: postgres: condition: service_healthy
Three of those lines deserve a callout:
127.0.0.1:5678:5678binds n8n to localhost only. Without the IP prefix, Docker punches a hole straight through UFW and your editor is on the public internet. That's not a theory — port-5678 scanning is a thing.N8N_ENCRYPTION_KEYencrypts stored credentials. Save it somewhere outside the server. Lose it and every credential in the instance is unrecoverable, even with a perfect database backup.EXECUTIONS_DATA_PRUNEwith a 336-hour (14-day) age limit is what stops your database eating the disk by month three. Leave it off and a busy instance can add gigabytes a month.
Step 4 — Bring it up.
bashdocker compose up -d docker compose logs -f n8n
Watch for the editor-ready line, then Ctrl+C. The container should show healthy in docker compose ps. The Docker Compose documentation covers the flags if you want to go deeper on restart policies.
Nginx, SSL, and Not Leaving the Front Door Open
n8n is now running on localhost, which means nobody can reach it — including you. Nginx fixes that and terminates SSL.
Install Nginx and Certbot, then create /etc/nginx/sites-available/n8n.conf:
nginxserver { listen 80; server_name n8n.yourdomain.com; location / { proxy_pass http://127.0.0.1:5678; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 3600s; } }
Enable it, test with nginx -t, reload, then run certbot --nginx -d n8n.yourdomain.com. Let's Encrypt issues the certificate free and Certbot renews it every 60 days on a timer.
The two lines people cut and then spend an evening debugging: the Upgrade/Connection headers (without them the editor loads but never updates — n8n uses WebSockets for live execution feedback) and proxy_read_timeout 3600s (the default 60s cuts off any workflow that runs longer than a minute). The Nginx documentation has the full proxy module reference if you want to tune buffers as well. If you've deployed Node apps behind Nginx before, this pattern will look familiar — it's the same shape as our Deploy Node.js App on Linux VPS: PM2 + Nginx Beginner Guide.
From our ticket queue: brute-force and malware incidents make up about 25% of the client issues we handle each month — first-party data from our own support queue. An n8n editor sitting on a public URL with a weak password is exactly the shape of target those scanners look for. Turn on n8n's own user management immediately, and put basic rate limiting in front of /rest/login. Nginx Rate Limiting: Basic DDoS & Bot Protection has the config.
Backups and Updates: The Part Everyone Skips
Here's the contrarian bit. Your workflows are not the valuable thing — you can export those as JSON in a minute. Your credentials and their encryption key are the valuable thing, and they're the two pieces most people back up incorrectly.
A working nightly job needs three items: a pg_dump of the Postgres database, a tar of the ./n8n-data volume (which holds the encryption key), and a copy of both pushed offsite. Local-only backups die with the disk they're on. We run offsite copies for exactly this reason, and we've done full restores under real pressure after hardware failure — the restore that works is always the one that was tested before it was needed. Linux VPS Backup Automation with Rsync + Cron has the cron pattern; point it at these two paths.
Updating is four commands, and the first one is the one people skip:
bash## 1. Back up first. Always. No exceptions. docker compose exec postgres pg_dump -U n8n n8n > backup-$(date +%F).sql ## 2. Pull, recreate, verify. docker compose pull docker compose up -d docker compose logs -f n8n
Read the release notes before a major version jump — n8n does ship breaking changes, and :latest will happily pull one at 3am if you've automated it. Pinning to a specific tag like n8nio/n8n:1.98.2 and updating deliberately is the boring, correct choice for anything business-critical.
Pro Tip: Test your restore once a month against a throwaway container, not the live one. Import the dump, mount a copy of the data volume, and open one credential. If it decrypts, your backup is real. If it doesn't, you learned that on a Tuesday afternoon instead of during an outage.
What Self-Hosting Really Costs (Honest Maths)
The savings are genuine, but the number people quote is usually wrong because they price the server and forget their own hours.
| Cost line | Self-hosted on a VPS | Reality check | |---|---|---| | Server | $7.99-$22/month | Fixed, regardless of execution count | | Executions | $0 | Limited only by CPU and RAM | | SSL | $0 (Let's Encrypt) | Auto-renews | | Your time | 1-2 hours setup, ~15 min/month | The line nobody budgets for | | Incident risk | Yours | Mitigated by backups + monitoring, not by hope |
For most people the maths lands like this: if you're running more than a few thousand executions a month, the server pays for itself in the first billing cycle. If you're running twelve workflows that fire once a day, the honest answer is that self-hosting is a hobby project, not a saving. Hostaccent's Standard tier at $12.00/mo (renews at $12.00/mo) is the sweet spot we see agencies settle on once they add Postgres, a staging instance and browser automation — the Basic tier runs a single-instance setup fine but gets tight the moment Chromium shows up.
Key Takeaways and Where to Run It
- Size for the workload, not the app. 2GB RAM and NVMe SSD storage for light use, 4GB the moment Puppeteer or AI nodes appear.
- Bind to 127.0.0.1 and proxy through Nginx with SSL, WebSocket headers and a long read timeout.
- Set
WEBHOOK_URLandN8N_ENCRYPTION_KEY— and store that key off the server. - Turn on execution pruning or your disk fills quietly.
- Back up the database and the data volume, then restore-test it monthly.
If you'd rather not build the base server before you build the automation, that's the part we handle. Our VPS Hosting plans start at $7.99/mo for the Basic tier (renews at $7.99/mo) on NVMe SSD, with a choice of 15 datacenter locations, a 99.9% uptime guarantee and a 30-day money-back guarantee — enough to self host n8n comfortably for a single-instance setup. Honest limitation: these are self-managed boxes, so you still own the container updates and backups. What you get is human support from our own engineers when the server layer misbehaves, which is where most people actually get stuck.
Frequently Asked Questions About Self-Hosting n8n
Is n8n free if I self-host it?
The Community Edition is free under n8n's fair-code licence, with no execution or workflow limits. You pay only for the server. Paid enterprise features like SSO, LDAP and advanced permissions stay behind a licence, but everything most solo builders and small agencies need is included at $0.
What are the minimum n8n self hosted requirements?
2GB RAM, 1-2 vCPU and 20GB of NVMe SSD storage runs a single instance with light-to-moderate workflows. Move to 4GB RAM and 2 vCPU if you use Puppeteer, AI nodes, or process large files. 1GB boxes technically boot but get killed by the OOM reaper under real load.
Can I self host n8n on a Raspberry Pi?
Yes, and it works for tinkering — n8n ships ARM64 images. But an SD card is a terrible database disk, and home internet plus a dynamic IP makes webhooks fragile. For anything a client depends on, a VPS with a static IP and NVMe storage is the better call, typically for under $10 a month.
Do I need Postgres, or is SQLite fine?
SQLite is fine for a handful of workflows and is the default. Switch to Postgres before you scale — SQLite locks under concurrent writes, which shows up as random execution failures that look like node bugs. Migrating later is possible but tedious. Starting on Postgres costs you five extra lines of compose config.
How do I update a self-hosted n8n instance safely?
Dump the database, pull the new image, recreate the container, then check the logs. Pin to a specific version tag rather than latest for production, and read the release notes before major version jumps. In our experience, the only updates that go badly are the ones run without a fresh backup sitting next to them.
Is self-hosted n8n secure enough for client data?
It can be more secure than a shared SaaS instance, because you control the perimeter — but only if you do the work: SSH keys, a firewall, n8n's user management on, rate limiting on the login route, and TLS everywhere. We found the recurring weak point isn't n8n itself; it's an editor left exposed on port 5678 with a reused password.












Discussion
Have a question or tip about this topic? Share it below — your comment will appear after review.