AI Automation

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_TIMEZONE sets the timezone for schedule nodes (Schedule Trigger); TZ is the system timezone. Forget them and your “8 am” workflow runs at 3 pm.
  • The n8n_data volume holds the encryption key, logs and data — delete it and your credentials are gone.
  • Release channels: stable for production, beta for 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

VariableWhy it matters
N8N_ENCRYPTION_KEYEncrypts 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_URLThe 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_PROTOCOLThe instance’s public hostname and protocol.

HTTPS and a reverse proxy

  • Bind n8n to 127.0.0.1:5678 and 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) and proxy_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

ComponentHow to back it up
Postgres databaseNightly pg_dump pushed to object storage (S3, B2…)
n8n_data volumeWeekly tarball — attachments, custom nodes
WorkflowsExport as JSON and keep in Git
N8N_ENCRYPTION_KEYStored 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-hostn8n Cloud
DataOn your infrastructureOn n8n’s infrastructure
CostFlat VPS cost, no execution limitsBy plan and executions
OperationsYou patch the OS, renew certificates, watch disks, back upn8n does it
ExtensibilityInstall community nodes via npmPer 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 .env file 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.yml in 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

  1. Docker installation — n8n Docs
  2. Running n8n locally without regrets — DEV Community