Yapay Zeka Ajanları
n8n Learning Path
CHAPTER 12Advanced ~75 min

Self-Hosting and Production Deployment

Running n8n on your own server: Docker Compose with PostgreSQL, reverse proxy, backups and upgrade strategy.

In this chapter

n8n Cloud is a paid service (20-50€/month) limited by execution count. Self-hosting on your own server gives you: no execution limit, full data ownership, unlimited workflows — your only monthly cost is the server (typically 5-15€/month VPS). In exchange you manage install, updates, backups and HTTPS yourself. In this chapter you'll do a production-grade self-host end-to-end: Docker Compose with n8n + Postgres + Redis, HTTPS via Nginx/Caddy, environment management, automated backups and a safe upgrade strategy.

Topics

  • Docker Compose: n8n + Postgres + Redis
  • Environment variables and persistent volumes
  • HTTPS reverse proxy with Nginx / Caddy
  • Domain and subdomain configuration
  • Backups: workflow JSON + credential export
  • Version upgrades and rollback

Server choice: VPS, RAM, providers

Minimum 2 vCPU + 4 GB RAM; with 8 GB RAM you're much more comfortable for AI workflows. Hetzner CX22 (4€/month, 2 vCPU, 4 GB) is the best price/performance for small-to-mid. DigitalOcean Droplet, Contabo VPS, AWS Lightsail also work. SSD/NVMe is a must — execution logs grow fast. Location: the region closest to your users (Frankfurt or Helsinki for Europe). Install Ubuntu 22.04 LTS; nothing else needed.

Docker Compose: n8n + Postgres

In production use PostgreSQL instead of the default SQLite — you avoid file-lock issues on concurrent executions. One docker-compose.yml brings up both: a 'postgres' service (image: postgres:16, volume mount, healthcheck) and an 'n8n' service (image: docker.n8n.io/n8nio/n8n, depends_on: postgres, environment: DB_TYPE=postgresdb, DB_POSTGRESDB_HOST, USER, PASSWORD, DATABASE). Map N8N_HOST, N8N_PORT, N8N_PROTOCOL=https and WEBHOOK_URL to your domain. Start with 'docker compose up -d.'

docker-compose.yml
Postgres (volume)
n8n (volume)
n8n.yourdomain.com

N8N_ENCRYPTION_KEY and env management

n8n encrypts credentials using the N8N_ENCRYPTION_KEY environment variable — you MUST set it. If you don't, n8n generates one on first boot, but if you don't back it up and the server dies you lose every credential. Generate it with `openssl rand -hex 32`. Put it in .env, NEVER commit .env (add to .gitignore), and back it up in multiple places (1Password/Bitwarden + offline). Other important envs: GENERIC_TIMEZONE=Europe/Istanbul, N8N_LOG_LEVEL=info (not debug — fills disk), EXECUTIONS_DATA_PRUNE=true + EXECUTIONS_DATA_MAX_AGE=336 (delete old executions after 14 days).

HTTPS: Caddy in 2 lines, Nginx the classic way

In production n8n must run behind HTTPS (webhooks reject HTTP, OAuth callbacks require HTTPS). The easiest path is Caddy: add a caddy service to docker-compose, in the Caddyfile write 'n8n.yourdomain.com { reverse_proxy n8n:5678 }' — done. Let's Encrypt cert is auto-issued and auto-renewed. For Nginx the classic path: get a cert via certbot, write a server block (listen 443 ssl, proxy_pass http://n8n:5678, Upgrade/Connection headers for websockets). Don't forget to point your domain's DNS A record to the server IP.

Domain DNS A
{ }Caddy (HTTPS)
n8n container :5678
Editor + Webhooks

Queue mode: horizontal scale with Redis + workers

A single n8n instance comfortably runs 10-20 concurrent workflows. For more load switch to queue mode: the main n8n becomes a 'webhook receiver,' pushes executions into a Redis queue, and separate worker containers pull and run them. Add 'redis' (image: redis:7-alpine) to compose, set n8n env EXECUTIONS_MODE=queue, QUEUE_BULL_REDIS_HOST=redis, and add an 'n8n-worker' service (command: n8n worker, replicas: 3). If one worker crashes others keep going; raise the worker count as traffic grows. Crucial in AI workflows where LLM replies can take minutes.

Webhook → n8n main
Redis Queue
n8n-worker x3
Postgres

Backups: Postgres dump + workflow JSON + .env

Without backing up three things you lose everything on disaster. (1) PostgreSQL: daily cron 'pg_dump' → upload to S3/Backblaze B2, 30-day retention. (2) Workflow JSON files: 'n8n export:workflow --all --output=/backup' daily — commit to a git repo for version history. (3) .env and N8N_ENCRYPTION_KEY: password manager + offline copy. Run a restore drill every 3 months — the most common disaster is finding the backup is broken at the moment you need it.

Cron daily
pg_dump + n8n export
Restic/rclone
S3/Backblaze (30 day retention)

Version upgrades: safe upgrade flow

n8n ships a minor release weekly; breaking changes are rare but happen. Safe upgrade flow: (1) Read the release notes first (especially for MAJOR versions). (2) Take a Postgres + workflow backup. (3) Pin the image tag in docker-compose.yml (e.g. `n8nio/n8n:1.78.1` — `latest` is DANGEROUS in production). (4) Run `docker compose pull && docker compose up -d`. (5) Editor opens — manually test a critical workflow; if the last hour's success rate is intact you're OK. If broken, roll back the tag — restore Postgres from backup if needed. For MAJOR versions, run a staging soak for at least a week.

Monitoring: uptime, resources, health

The biggest self-host risk: the server dies and you find out two days later. Minimum monitoring: (1) Uptime Kuma or BetterStack pings n8n.yourdomain.com/healthz every minute; on failure ping Telegram. (2) Resource alarms in your provider console (CPU > 90%, disk > 80%, RAM > 85%). (3) Logs: route n8n's stdout via docker logs or to Loki + Grafana. (4) Execution success rate: from Chapter 11's audit log, alert when daily 'failure rate > 5%.' Without these four legs it isn't production.

This chapter's workflow (n8n editor view)

Docker Compose
n8n
Postgres
Nginx