n8n is an open-source workflow automation platform. It connects APIs, databases, webhooks, and AI models into visual automations through a node-based editor. With more than 400 integrations and a fair-code licence, it is the closest self-hosted equivalent to Zapier or Make. When you run it on your own server, there is no execution count, no monthly cap, and your data never touches a third-party server.
Why self-host n8n?
The cloud version of n8n is generous, but paid tiers are priced per active workflow or execution. Self-hosting removes that ceiling entirely — you pay only for the VPS. For anyone running dozens of automations or processing sensitive data, that trade is worth it.
The other benefit is data control. Workflows that touch internal APIs, private spreadsheets, or confidential webhooks stay entirely within your infrastructure.
Honest trade-offs: you are responsible for keeping the container updated, backing up the data volume, and securing the server. Webhooks — the mechanism that lets external services trigger your workflows — also require a real, publicly reachable HTTPS URL. A local machine or a VPS with no domain will not work for webhook-driven automations.
Prerequisites
- A VPS with 1–2 GB RAM. n8n is not heavy at idle; 1 GB is fine for personal automations. Plan for more if you run many concurrent workflows. See Best VPS for Self-Hosting for current options.
- A domain or subdomain pointed at the server’s IP — for example,
n8n.yourdomain.com. The point a domain to a VPS guide covers this if it is new to you. - Docker and Docker Compose installed on the server.
- A reverse proxy for HTTPS termination (covered in Step 3).
Step 1 — Write the Compose file
Create a directory for n8n and place a compose.yaml file inside it:
services:
n8n:
image: n8nio/n8n:latest
restart: always
ports:
- "127.0.0.1:5678:5678"
environment:
- N8N_HOST=n8n.yourdomain.com
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://n8n.yourdomain.com/
- N8N_SECURE_COOKIE=true
- GENERIC_TIMEZONE=UTC
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_data:
A few things worth noting:
- Binding to
127.0.0.1:5678keeps the port off the public internet; the reverse proxy reaches it locally. WEBHOOK_URLmust exactly match the public HTTPS URL your reverse proxy exposes. If there is a mismatch, webhook triggers will silently generate wrong URLs.N8N_SECURE_COOKIE=trueis required when running behind HTTPS and prevents a login loop that appears when the cookie flag does not match the protocol.- Replace
UTCwith your local timezone string (for example,America/New_York) so cron-triggered workflows fire at the expected local time.
Step 2 — Start it
docker compose up -d
Check that the container is running:
docker compose ps
docker compose logs n8n
The process is ready when logs show something like n8n ready on 0.0.0.0, port 5678. It will not yet be reachable from the browser because there is no HTTPS in place.
Step 3 — HTTPS via a reverse proxy
Webhooks require a verifiable HTTPS URL — this step is not optional if you plan to use any webhook-triggered workflows.
The simplest approach is Nginx Proxy Manager, which provides a web UI for creating proxy hosts and issuing Let’s Encrypt certificates with a few clicks. Follow the Nginx Proxy Manager setup guide, then add a proxy host:
- Domain:
n8n.yourdomain.com - Forward hostname / IP: the internal IP of the n8n container (or the Docker host IP if both containers are on the same machine)
- Forward port:
5678 - Enable SSL and request a Let’s Encrypt certificate
Once the proxy is live, WEBHOOK_URL in your Compose file must match the domain exactly (including the trailing slash). If you later change the domain, update the environment variable and recreate the container with docker compose up -d --force-recreate.
Step 4 — First login and your first workflow
Open https://n8n.yourdomain.com in a browser. n8n will prompt you to create an owner account — fill in an email and password. This account has full admin access, so use a strong password.
After logging in, click New Workflow. Drag a Webhook node onto the canvas to get a URL you can call from external services, or start with a Schedule node for time-based automations. Each node has a built-in test mode that fires once with sample data so you can build and verify without touching production systems.
Scaling up
SQLite, the default database, is perfectly adequate for a single user running a few dozen workflows. When you start running many concurrent executions — or if you are sharing the instance with a team — switching to Postgres removes a significant bottleneck. n8n supports Postgres via the DB_TYPE, DB_POSTGRESDB_HOST, and related environment variables; the official docs walk through the migration.
For very high throughput, n8n also supports a queue mode backed by Redis, where worker containers pick up jobs from a queue rather than the main process handling everything. This is an advanced setup; most personal and small-team instances will never need it.
Troubleshooting
Webhooks not firing. The most common cause is a mismatch between WEBHOOK_URL and the actual public URL. Open the webhook node in the editor — if the displayed URL does not start with https://n8n.yourdomain.com/, the environment variable is wrong or was not applied after the last restart. Run docker compose up -d --force-recreate after correcting it.
Login loop after entering credentials. This happens when N8N_SECURE_COOKIE=true but n8n is being accessed over plain HTTP, or when the reverse proxy is not forwarding the X-Forwarded-Proto header. Confirm the proxy sends that header and that your SSL certificate is valid.
Data lost after a container restart. If the n8n_data volume was not declared in the Compose file — or the container was started with docker run without a -v flag — n8n writes data inside the container layer, which disappears on removal. Add the named volume, then restart. Going forward, back up the volume directory regularly.
Out-of-memory crash on large workflows. Workflows that process large files or run many parallel branches can exhaust a 1 GB instance. Upgrade to a 2 GB plan, or switch from SQLite to Postgres (which offloads execution data storage from the main process). Monitor memory with docker stats.
Which VPS to run it on
n8n is light enough to share a server with other self-hosted services. A 1–2 GB instance is a reasonable starting point:
- Hetzner — good European option with competitive per-GB pricing
- Vultr — global data centers, predictable pricing
If you prefer a managed environment with less server administration, Cloudways handles OS updates and backups for you.
For a full comparison of providers and plans, see Best VPS for Self-Hosting. If you are already running or planning to run Nextcloud on the same box, n8n pairs well with it — you can automate file-processing workflows that read from and write to Nextcloud through its API.