DEV Community

Cover image for How to Host Your Own n8n Automation Server on Hetzner Cloud for Less Than $6/Month
Alexander Schneider
Alexander Schneider

Posted on

How to Host Your Own n8n Automation Server on Hetzner Cloud for Less Than $6/Month

If you're looking for a powerful automation platform that won't break the bank, self-hosting n8n on Hetzner Cloud might be the perfect solution. In this guide, I'll walk you through how we set up a production-ready n8n instance with enterprise-grade security for just ~$6.

Why Self-Host n8n?

n8n is an open-source workflow automation tool that rivals expensive solutions like Zapier or Make. By self-hosting, you get:

  • Complete data privacy and control
  • No workflow execution limits
  • Custom integrations and code
  • Full API access
  • Cost-effective scaling

The Setup: What We're Building

Here's what we'll deploy:

  • Server: Hetzner Cloud CX22 (2 vCPU, 4GB RAM)
  • Location: Falkenstein, Germany
  • Services: n8n (Docker), Caddy (reverse proxy with automatic SSL)
  • Security: UFW firewall, Fail2ban, audit logging, automated updates
  • Cost: ~$6 / month

Step 1: Creating the Hetzner Cloud Server

First, create a Hetzner Cloud account and set up a new server:

# Using Hetzner CLI (optional)
hcloud server create \
  --name n8n-server \
  --type cx22 \
  --image ubuntu-22.04 \
  --location fsn1 \
  --ssh-key ~/.ssh/id_rsa.pub
Enter fullscreen mode Exit fullscreen mode

Pro tip: The CX22 instance type offers the best price-performance ratio for n8n. With 2 vCPUs and 4GB RAM, it can handle substantial workflows without issues.

Step 2: Initial Server Security Hardening

Security first! Here's our hardening checklist:

Create a non-root user

# As root
adduser admin
usermod -aG sudo admin
mkdir -p /home/admin/.ssh
cp ~/.ssh/authorized_keys /home/admin/.ssh/
chown -R admin:admin /home/admin/.ssh
chmod 700 /home/admin/.ssh
chmod 600 /home/admin/.ssh/authorized_keys
Enter fullscreen mode Exit fullscreen mode

Disable root login and password authentication

# Edit SSH config
sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart sshd
Enter fullscreen mode Exit fullscreen mode

Set up UFW firewall

ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable
Enter fullscreen mode Exit fullscreen mode

Install and configure Fail2ban

apt update && apt install -y fail2ban
cat > /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
bantime = 2h
maxretry = 3
findtime = 10m

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
EOF

systemctl restart fail2ban
Enter fullscreen mode Exit fullscreen mode

Enable automatic security updates

apt install -y unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades
Enter fullscreen mode Exit fullscreen mode

Set up audit logging

apt install -y auditd
auditctl -w /etc/passwd -p wa -k passwd_changes
auditctl -w /etc/shadow -p wa -k shadow_changes
auditctl -w /var/log/auth.log -p wa -k auth_log
service auditd restart
Enter fullscreen mode Exit fullscreen mode

Step 3: Installing Docker and Docker Compose

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh

# Install Docker Compose
apt install -y docker-compose-plugin

# Verify installation
docker --version
docker compose version
Enter fullscreen mode Exit fullscreen mode

Step 4: Setting Up n8n with Docker Compose

Create the n8n directory and docker-compose file:

mkdir -p /root/n8n
cd /root/n8n
Enter fullscreen mode Exit fullscreen mode

Create a secure docker-compose.yml:

version: '3.8'

services:
  n8n:
    image: n8nio/n8n
    container_name: n8n
    restart: unless-stopped
    ports:
      - "127.0.0.1:5678:5678"  # Only accessible locally
    environment:
      - N8N_HOST=n8n.yourdomain.com
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://n8n.yourdomain.com/
      - GENERIC_TIMEZONE=Europe/Berlin
    volumes:
      - n8n_data:/home/node/.n8n
    security_opt:
      - no-new-privileges:true
    read_only: true
    tmpfs:
      - /tmp
      - /home/node/.n8n/cache

volumes:
  n8n_data:
Enter fullscreen mode Exit fullscreen mode

Security insights:

  • Binding to 127.0.0.1 ensures n8n is only accessible through our reverse proxy
  • read_only: true prevents container filesystem modifications
  • no-new-privileges prevents privilege escalation
  • Using tmpfs for temporary files improves security and performance

Step 5: Setting Up Caddy as Reverse Proxy

Caddy provides automatic HTTPS certificates and is much simpler than nginx:

# Install Caddy
apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt update && apt install -y caddy
Enter fullscreen mode Exit fullscreen mode

Configure Caddy:

cat > /etc/caddy/Caddyfile << 'EOF'
n8n.yourdomain.com {
    reverse_proxy localhost:5678 {
        header_up X-Real-IP {remote}
        header_up X-Forwarded-For {remote}
        header_up X-Forwarded-Proto {scheme}
    }

    # Security headers
    header {
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
        X-XSS-Protection "1; mode=block"
        Referrer-Policy strict-origin-when-cross-origin
        -Server
    }

    # Enable compression
    encode gzip
}
EOF

systemctl restart caddy
Enter fullscreen mode Exit fullscreen mode

Step 6: Starting n8n

cd /root/n8n
docker compose up -d
Enter fullscreen mode Exit fullscreen mode

Visit https://n8n.yourdomain.com and complete the initial setup!

Advanced Security Measures

1. Implement IP-based access control

If you have a static IP, limit access to n8n:

n8n.yourdomain.com {
    @allowed {
        remote_ip 1.2.3.4 192.168.0.0/16
    }
    handle @allowed {
        reverse_proxy localhost:5678
    }
    handle {
        respond "Access Denied" 403
    }
}
Enter fullscreen mode Exit fullscreen mode

2. Set up Fail2ban for n8n

Create a custom filter for failed n8n login attempts:

cat > /etc/fail2ban/filter.d/n8n-auth.conf << 'EOF'
[Definition]
failregex = ^.* 401 .* "POST /rest/auth/login.*" .*$
ignoreregex =
EOF

# Add to jail.local
cat >> /etc/fail2ban/jail.local << 'EOF'

[n8n-auth]
enabled = true
port = http,https
filter = n8n-auth
logpath = /var/log/caddy/access.log
maxretry = 5
bantime = 1h
EOF
Enter fullscreen mode Exit fullscreen mode

3. Regular backups

Create a backup script:

#!/bin/bash
# /root/backup-n8n.sh
BACKUP_DIR="/root/backups"
mkdir -p $BACKUP_DIR
docker compose -f /root/n8n/docker-compose.yml down
docker run --rm -v n8n_data:/data -v $BACKUP_DIR:/backup alpine tar czf /backup/n8n-backup-$(date +%Y%m%d).tar.gz -C /data .
docker compose -f /root/n8n/docker-compose.yml up -d
# Keep only last 7 backups
find $BACKUP_DIR -name "n8n-backup-*.tar.gz" -mtime +7 -delete
Enter fullscreen mode Exit fullscreen mode

Add to crontab:

0 3 * * * /root/backup-n8n.sh
Enter fullscreen mode Exit fullscreen mode

Performance Optimization Tips

  1. Enable Redis for scaling: Add a Redis container for better performance with multiple workers
  2. Use external database: For production workloads, consider PostgreSQL instead of SQLite
  3. Monitor resources: Install htop and set up monitoring with Prometheus/Grafana
  4. Optimize workflows: Use webhook triggers instead of polling when possible

Cost Breakdown

  • Hetzner CX22 Server: ~$6/month
  • Domain (use a subdomain): ~$0/year
  • Total monthly cost: ~$6/month

Compare this to n8n Cloud's pricing starting at $20/month for just 2,500 workflow executions!

Lessons Learned

  1. Start with security: It's easier to harden from the beginning than retrofit later
  2. Docker adds complexity but worth it: Container isolation and easy updates outweigh the overhead
  3. Caddy > Nginx for simple setups: Automatic HTTPS saves hours of configuration
  4. Monitor everything: Set up alerts for disk space, CPU usage, and failed login attempts
  5. Document everything: Future you will thank present you

Troubleshooting Common Issues

n8n won't start

# Check logs
docker logs n8n
# Common fix: permissions on data volume
docker volume rm n8n_data  # Warning: deletes data!
Enter fullscreen mode Exit fullscreen mode

SSL certificate issues

# Caddy logs
journalctl -u caddy -f
# Force certificate renewal
caddy reload --config /etc/caddy/Caddyfile
Enter fullscreen mode Exit fullscreen mode

High memory usage

# Add memory limits to docker-compose.yml
deploy:
  resources:
    limits:
      memory: 3g
Enter fullscreen mode Exit fullscreen mode

Conclusion

For less than the price of a Netflix subscription, you can run your own powerful automation platform with complete control over your data. The setup takes about an hour, but the flexibility and cost savings make it worthwhile for anyone serious about automation.

Have you set up your own n8n instance? What challenges did you face? Let me know in the comments!


Resources:

Top comments (0)