Self-host n8n in 10 minutes: the foundation for every AI automation workflow
TL;DR
n8n is a self-hostable “fair-code” workflow automation platform. To try it: create an n8n_data volume and docker run the n8n image on port 5678. For production: use Postgres, put it behind an HTTPS reverse proxy, set a fixed N8N_ENCRYPTION_KEY, back up regularly.
Most AI-automation articles on binhAI use n8n — a drag-and-drop workflow platform with hundreds of built-in integrations, an AI Agent node and, crucially, the option to self-host. This guide goes from a 2-minute trial on your laptop to an installation fit for real use: Postgres, HTTPS, encryption key, backups and updates.
Try it locally (2 minutes)
You need Docker Desktop (Mac, Windows, Linux) or Docker Engine on a Linux server.
docker volume create n8n_data
docker run -it --rm --name n8n -p 5678:5678 \
-e GENERIC_TIMEZONE="Asia/Ho_Chi_Minh" -e TZ="Asia/Ho_Chi_Minh" \
-e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true \
-v n8n_data:/home/node/.n8n \
docker.n8n.io/n8nio/n8n
# open http://localhost:5678
GENERIC_TIMEZONEsets the timezone for schedule nodes (Schedule Trigger);TZis the system timezone. Forget them and your “8 am” workflow runs at 3 pm.- The
n8n_datavolume holds the encryption key, logs and data — delete it and your credentials are gone. - Release channels:
stablefor production,betafor the newest, possibly unstable build.
The official docs stress that self-hosting needs technical skills; misconfiguration can cause data loss, security issues and downtime. If nobody on the team runs servers, n8n Cloud is the safer choice.
Production setup: Docker Compose + Postgres
n8n uses SQLite by default — fine for trying it, but once many workflows run concurrently and you need proper backups, switch to Postgres:
# docker-compose.yml (abridged)
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: n8n
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: n8n
volumes: [pg_data:/var/lib/postgresql/data]
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n8n"]
n8n:
image: n8nio/n8n:<pinned-version> # never :latest in production
ports: ["127.0.0.1:5678:5678"] # only the reverse proxy can reach it
environment:
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_DATABASE: n8n
DB_POSTGRESDB_USER: n8n
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
N8N_HOST: n8n.example.com
N8N_PROTOCOL: https
WEBHOOK_URL: https://n8n.example.com/
GENERIC_TIMEZONE: Asia/Ho_Chi_Minh
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
volumes: [n8n_data:/home/node/.n8n]
depends_on: [postgres]
volumes: { pg_data: {}, n8n_data: {} }
Keep the .n8n volume even with Postgres — it holds encryption keys, logs and source-control assets.
The three most important environment variables
| Variable | Why it matters |
|---|---|
N8N_ENCRYPTION_KEY | Encrypts every credential stored in the database. Change it and every saved credential becomes unusable. Generate it once (openssl rand -hex 32) and store it in a secret manager. |
WEBHOOK_URL | The public HTTPS address; n8n uses it to build webhook URLs for external services. Get it wrong and webhooks from GitHub, Stripe… never arrive. |
N8N_HOST / N8N_PROTOCOL | The instance’s public hostname and protocol. |
HTTPS and a reverse proxy
- Bind n8n to
127.0.0.1:5678and put Nginx, Caddy or a Cloudflare Tunnel in front for HTTPS. - With Nginx: enable WebSocket upgrade headers and raise
client_max_body_size(e.g. 50M) andproxy_read_timeout(e.g. 3600 s) so long executions aren’t cut off. - A $5–10/month VPS (Ubuntu 22.04/24.04) handles thousands of executions a day for typical workflows.
Backups and updates
| Component | How to back it up |
|---|---|
| Postgres database | Nightly pg_dump pushed to object storage (S3, B2…) |
n8n_data volume | Weekly tarball — attachments, custom nodes |
| Workflows | Export as JSON and keep in Git |
N8N_ENCRYPTION_KEY | Stored separately in a secret manager — lose it and you lose credentials |
Updating: bump the pinned image tag in a commit, read the changelog before major upgrades, snapshot Postgres first, then docker compose pull → down → up -d. If something breaks, roll back to the previous tag. Note that since n8n 2.0, N8N_RUNNERS_ENABLED is no longer needed.
Test your backups: a backup that has never been restored isn’t a backup yet.
Self-host or n8n Cloud?
| Self-host | n8n Cloud | |
|---|---|---|
| Data | On your infrastructure | On n8n’s infrastructure |
| Cost | Flat VPS cost, no execution limits | By plan and executions |
| Operations | You patch the OS, renew certificates, watch disks, back up | n8n does it |
| Extensibility | Install community nodes via npm | Per platform policy |
Licence: n8n uses the Sustainable Use License (fair-code) — internal use is fine, but if you plan to resell n8n as a service to others, read the terms carefully.
Minimum security
- Never expose port 5678 directly to the internet; only through an HTTPS reverse proxy.
- Enable two-factor authentication for admins; one account per person.
- Never commit the
.envfile with passwords and keys. - Credentials are encrypted in the database, not stored in workflow JSON — exported workflows are safer to share.
How to apply it
- Developers: Run the one-line Docker version on your laptop to learn, then move to a VPS with Compose + Postgres when a workflow needs to run 24/7.
- Tech Leads / DevOps: Keep
docker-compose.ymlin Git, pin image tags, automate backups and keep a restore runbook. - PMs: An internal n8n instance is the foundation for a whole range of automations: reports, ticket triage, digests. Infrastructure is cheap — the real cost is the person who runs it.
Sources & references
- Docker installation — n8n Docs
- Running n8n locally without regrets — DEV Community