How to Self-Host n8n with Docker

Updated May 2026

Step 1: Prepare Your Server

n8n runs well on modest hardware. A VPS with 2 CPU cores, 4GB RAM, and 40GB storage handles most workloads. For AI workflows with Ollama, increase to 4 cores and 16GB RAM minimum, with a GPU server if you want fast local inference. Recommended VPS providers include Hetzner (best value in Europe), DigitalOcean (solid reliability), and Vultr (good global coverage).

Install Docker and Docker Compose on your server. On Ubuntu 22.04 or later, install Docker using the official convenience script or the apt repository method from Docker's documentation. Docker Compose V2 is included with modern Docker installations. Verify both are working with docker --version and docker compose version.

Create a dedicated directory for your n8n deployment. A common location is /opt/n8n or ~/n8n. All configuration files, environment variables, and Docker Compose files will live in this directory.

Step 2: Configure Docker Compose

Create a docker-compose.yml file with two services: n8n and PostgreSQL. PostgreSQL is recommended over SQLite for any deployment beyond personal testing. The n8n service uses the n8nio/n8n:latest image, mounts a volume for file storage, and connects to the PostgreSQL service. The PostgreSQL service uses the standard postgres:16 image with a persistent volume for data.

Key volume mounts for the n8n service include /home/node/.n8n for n8n configuration and encryption keys, and optionally /files for file-based operations. The PostgreSQL service needs a volume for /var/lib/postgresql/data to persist the database across container restarts.

Set the network mode so both services share a Docker network and can communicate by service name. n8n connects to PostgreSQL using the service name "postgres" as the hostname.

Step 3: Set Environment Variables

Create a .env file with the required configuration. Essential variables include DB_TYPE=postgresdb, DB_POSTGRESDB_HOST=postgres, DB_POSTGRESDB_DATABASE=n8n, DB_POSTGRESDB_USER and DB_POSTGRESDB_PASSWORD (matching your PostgreSQL configuration), N8N_ENCRYPTION_KEY (a random 32-character string for encrypting credentials), and WEBHOOK_URL (your public URL for receiving webhooks).

For production, also set N8N_PROTOCOL=https, N8N_HOST to your domain name, GENERIC_TIMEZONE to your timezone, and N8N_DIAGNOSTICS_ENABLED=false if you prefer not to send telemetry. The EXECUTIONS_DATA_PRUNE=true and EXECUTIONS_DATA_MAX_AGE=168 settings automatically clean up old execution data after 7 days, preventing database bloat.

Step 4: Set Up a Reverse Proxy

n8n should not be exposed directly to the internet. Place it behind a reverse proxy that handles HTTPS termination, certificate management, and basic security. Caddy is the simplest option because it automatically obtains and renews Let's Encrypt SSL certificates with zero configuration.

Add a Caddy service to your Docker Compose file or install Caddy on the host system. The Caddyfile needs a single block: your domain name, followed by a reverse_proxy directive pointing to the n8n container's port (typically 5678). Caddy handles everything else: obtaining the certificate, configuring TLS, and routing requests to n8n.

If you prefer nginx, install it on the host, configure a server block with your domain, set up certbot for Let's Encrypt certificates, and proxy_pass to http://localhost:5678. The nginx configuration needs WebSocket support for n8n's real-time features, which requires the proxy_http_version 1.1 and Upgrade headers.

Step 5: Harden for Production

Set up automated PostgreSQL backups using pg_dump on a daily schedule. Store backups off-server (S3, another VPS, or a backup service). Test restore procedures periodically to ensure backups are valid.

Configure Docker to restart containers automatically with restart: unless-stopped in your Docker Compose file. This ensures n8n comes back up after server reboots or container crashes.

Set up basic monitoring. At minimum, monitor disk space (n8n execution logs and PostgreSQL data can grow quickly), memory usage (especially important with AI workloads), and container health (docker compose ps should show all services as "Up"). Tools like uptime-kuma provide simple, self-hosted monitoring dashboards.

For security, keep n8n behind the reverse proxy (never expose port 5678 directly), use strong passwords for PostgreSQL and n8n user accounts, keep Docker images updated regularly, and restrict SSH access to your server using key-based authentication only. If running AI workflows with Ollama, ensure the Ollama API port (11434) is not exposed to the public internet.

Update n8n by pulling the latest Docker image and restarting the service. Check the n8n changelog before major version updates to understand breaking changes. Test updates in a staging environment before applying to production if your workflows are business-critical.