AutomationFlowsTutorials › Deploy n8n on Hetzner Cloud

Deploy n8n on Hetzner Cloud

This tutorial guides you through deploying n8n on Hetzner Cloud using Docker Compose, including server selection, secure setup with Caddy for HTTPS, PostgreSQL as the database, encryption, and backups. It's for technical users familiar with n8n who want a reliable, low-cost self-hosted instance without relying on managed services.

Why this matters

Self-hosting n8n on Hetzner Cloud avoids vendor lock-in and high costs of cloud platforms like AWS or DigitalOcean, while providing scalable performance for automations. It solves the common trap of underpowered servers causing workflow failures during peak loads and ensures data sovereignty with encrypted, backed-up storage—all for €5-10 monthly.

Step-by-step

  1. Create a Hetzner Cloud account at console.hetzner.cloud if you haven't, then add a payment method. In the console, click "Add Project" and name it (e.g., "n8n-prod"). Select the Nuremberg (fsn1) location for lower latency in Europe.
  2. Deploy a server: Click "Add Server" in your project. Choose CX22 (2 vCPU, 4GB RAM, 40GB SSD) for starters—it's €5.50/month and handles moderate workflows; upgrade to CCX23 (€9/month) if you expect heavy use. Select Ubuntu 22.04 as the OS, add your SSH key under "Security", and deploy. Note the public IP once it's running (takes 1-2 minutes).
  3. SSH into the server: From your terminal, run ssh root@YOUR_SERVER_IP. Update packages with apt update && apt upgrade -y. Install Docker and Docker Compose: curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh && apt install docker-compose -y. Add your user to the Docker group: usermod -aG docker root and reboot with reboot.
  4. Set up PostgreSQL: Create a directory mkdir -p ~/n8n && cd ~/n8n. Generate a strong DB password: DB_PASS=$(openssl rand -base64 32). Create docker-compose.yml with this content (use nano or vim):
    version: '3.8'
    services:
     postgres:
     image: postgres:15
     restart: always
     environment:
     POSTGRES_DB: n8n
     POSTGRES_USER: n8n
     POSTGRES_PASSWORD: ${DB_PASS}
     volumes:
     - postgres_data:/var/lib/postgresql/data
     n8n:
     image: n8nio/n8n:latest
     restart: always
     ports:
     - "5678:5678"
     environment:
     DB_TYPE: postgresdb
     DB_POSTGRESDB_HOST: postgres
     DB_POSTGRESDB_PORT: 5432
     DB_POSTGRESDB_DATABASE: n8n
     DB_POSTGRESDB_USER: n8n
     DB_POSTGRESDB_PASSWORD: ${DB_PASS}
     N8N_BASIC_AUTH_ACTIVE: true
     N8N_BASIC_AUTH_USER: admin
     N8N_BASIC_AUTH_PASSWORD: your_strong_password
     N8N_ENCRYPTION_KEY: your_32_char_encryption_key_here
     WEBHOOK_URL: https://yourdomain.com/
     volumes:
     - n8n_data:/home/node/.n8n
     depends_on:
     - postgres
     caddy:
     image: caddy:2-alpine
     restart: always
     ports:
     - "80:80"
     - "443:443"
     volumes:
     -./Caddyfile:/etc/caddy/Caddyfile
     - caddy_data:/data
     - caddy_config:/config
    volumes:
     postgres_data:
     n8n_data:
     caddy_data:
     caddy_config:
    Replace placeholders like your_strong_password and generate an encryption key with openssl rand -base64 24.
  5. Configure Caddy for HTTPS: Create Caddyfile in ~/n8n: nano Caddyfile and add:
    yourdomain.com {
     reverse_proxy n8n:5678
     tls your-email@example.com
    }
    Point a domain (e.g., via Namecheap) A record to your server's IP. For free subdomains, use DuckDNS. Start services: docker-compose up -d. Check logs with docker-compose logs -f; expect Caddy to auto-obtain Let's Encrypt certs on first access.
  6. Set up encryption and security: In docker-compose.yml, ensure N8N_ENCRYPTION_KEY is set (store it securely, e.g., in Hetzner secrets or env file). For basic auth, access https://yourdomain.com and log in with admin/your_strong_password. Enable queue mode if scaling: Add EXECUTIONS_MODE: queue and a Redis service later.
  7. Implement backups: Install cron: apt install cron -y. Create a backup script nano backup.sh:
    #!/bin/bash
    docker-compose exec postgres pg_dump n8n > /backup/n8n-$(date +%Y%m%d).sql
    tar -czf /backup/n8n-volumes-$(date +%Y%m%d).tar.gz /n8n_data /postgres_data
    
    Make executable: chmod +x backup.sh. Create /backup dir: mkdir /backup. Add to crontab: crontab -e and insert 0 2 * * * cd ~/n8n &&./backup.sh && rsync -av /backup/ user@backup-server:/path/ for offsite (use Hetzner Storage Box, €3/month). Test with ./backup.sh.
  8. Monitor and scale: Install htop: apt install htop -y. Use docker stats to watch usage. For costs, CX22 stays under €6/month; add snapshots via Hetzner console for €0.01/GB. Access n8n UI, create a test workflow, and verify persistence in Postgres.

Worked example

A common pattern is automating RSS feeds to Slack notifications. Start with a Cron node set to trigger every hour. Connect to an RSS Feed Read node (type: n8n-nodes-base.rssFeedRead) using your feed URL, like "https://example.com/rss". Filter new items with an IF node (n8n-nodes-base.if) checking publish date. Then, use a Slack node (n8n-nodes-base.slack) to post a formatted message with title, link, and summary via webhook URL from your Slack app. End with an Email node (n8n-nodes-base.emailSend) for backups to your inbox. Deploy this on your Hetzner n8n: It pulls feeds securely over HTTPS, processes via Postgres-stored executions, and scales without downtime—total setup under 5 minutes in the UI.

Common pitfalls

Related workflows in the catalog

Explore the n8n catalog for importable starters like "RSS to Slack" or "API Monitoring with Alerts", which pair perfectly with this deployment for quick automation builds. With 14,000+ workflows available, search for "Hetzner integration" to find cloud-specific ones, such as auto-scaling scripts using Hetzner API nodes. Check pages like the official n8n community forum or workflow library at n8n.io/workflows for tailored examples that use your self-hosted setup.