Workflow automation has become essential for modern businesses, but SaaS solutions can become expensive as teams grow. We’ll show you how to set up your own n8n instance on Hetzner Cloud for under €5/month, giving you unlimited workflows and complete control over your automation platform.
What You’ll Build
By the end of this tutorial, you’ll have:
- ✅ Fully functional n8n installation with HTTPS
- ✅ Automatic SSL certificates via Let’s Encrypt
- ✅ Email integration for user accounts
- ✅ Automatic startup after server restarts
- ✅ Production-ready setup for professional use
Monthly cost: €4.51 (CX11 server) + domain costs
Prerequisites
- Domain name pointing to your server IP
- Basic command line knowledge
- Hetzner Cloud account
Step 1: Server Setup
Create Hetzner Cloud Server
- Log into Hetzner Cloud Console
- Create new project
- Add server with these specifications:
- Image: Ubuntu 24.04 LTS
- Type: CX11 (1 vCPU, 4 GB RAM, 20 GB disk)
- Location: Choose closest to your users
- SSH Key: Add your public key
Initial Server Configuration
Connect to your server:
ssh root@YOUR_SERVER_IP
Update the system:
apt update && apt upgrade -y
Step 2: Install Docker
Install Docker and Docker Compose:
# Install dependencies
apt install apt-transport-https ca-certificates curl software-properties-common gnupg -y
# Add Docker GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# Add Docker repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker
apt update
apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
# Create Docker network for our services
docker network create proxy
Verify Docker installation:
docker --version
docker compose version
Step 3: Configure Traefik Reverse Proxy
Create directory structure:
mkdir -p /opt/traefik/data
cd /opt/traefik
Create Traefik configuration file:
nano /opt/traefik/data/traefik.yml
Add this configuration:
api:
dashboard: false
entryPoints:
http:
address: ":80"
http:
redirections:
entryPoint:
to: https
scheme: https
https:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
certificatesResolvers:
letsencrypt:
acme:
email: your-email@example.com # Change this!
storage: acme.json
httpChallenge:
entryPoint: http
Create acme.json file for SSL certificates:
touch /opt/traefik/data/acme.json
chmod 600 /opt/traefik/data/acme.json
Create Traefik Docker Compose file:
nano /opt/traefik/docker-compose.yml
Add this configuration:
version: '3'
services:
traefik:
image: traefik:latest
container_name: traefik
restart: always
ports:
- "80:80"
- "443:443"
networks:
- proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/etc/traefik/traefik.yml
- ./data/acme.json:/acme.json
labels:
- "traefik.enable=true"
networks:
proxy:
external: true
Step 4: Set Up SMTP Relay (Optional but Recommended)
Create mailserver directory:
mkdir -p /opt/mailserver
cd /opt/mailserver
Create Docker Compose file:
nano /opt/mailserver/docker-compose.yml
Add this configuration:
version: '3'
services:
mailserver:
image: bytemark/smtp
restart: always
networks:
- proxy
environment:
- RELAY_HOST=smtp.gmail.com # Change to your SMTP provider
- RELAY_PORT=587
- RELAY_USERNAME=your-email@gmail.com # Change this
- RELAY_PASSWORD=your-app-password # Change this
- MAIL_DOMAIN=yourdomain.com # Change this
ports:
- "25:25"
networks:
proxy:
external: true
Note: For Gmail, you’ll need to:
- Enable 2-factor authentication
- Generate an App Password
- Use the App Password (not your regular password)
Step 5: Configure n8n
Create n8n directory:
mkdir -p /opt/n8n
cd /opt/n8n
Create Docker Compose file:
nano /opt/n8n/docker-compose.yml
Add this configuration:
version: '3'
services:
n8n:
image: n8nio/n8n:latest
restart: always
environment:
- N8N_HOST=n8n.yourdomain.com # Change this!
- NODE_ENV=production
- N8N_PROTOCOL=https
- N8N_PORT=5678
- N8N_EDITOR_BASE_URL=https://n8n.yourdomain.com # Change this!
# Email configuration
- N8N_EMAIL_MODE=smtp
- N8N_SMTP_HOST=mailserver
- N8N_SMTP_PORT=25
- N8N_SMTP_SSL=false
- N8N_SMTP_USER=
- N8N_SMTP_PASS=
- N8N_SMTP_SENDER=noreply@yourdomain.com # Change this!
# Important fixes for proxy setup
- N8N_TRUST_PROXY_HEADER=true
- N8N_RUNNERS_ENABLED=true
volumes:
- ./data:/home/node/.n8n
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.n8n.rule=Host(`n8n.yourdomain.com`)" # Change this!
- "traefik.http.routers.n8n.entrypoints=https"
- "traefik.http.routers.n8n.tls.certresolver=letsencrypt"
- "traefik.http.services.n8n.loadbalancer.server.port=5678"
networks:
proxy:
external: true
Step 6: Create Systemd Services for Auto-Start
Traefik Service
nano /etc/systemd/system/traefik-docker.service
Add this configuration:
[Unit]
Description=Traefik Docker Compose
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/traefik
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
[Install]
WantedBy=multi-user.target
Mailserver Service
nano /etc/systemd/system/mailserver-docker.service
Add this configuration:
[Unit]
Description=Mailserver Docker Compose
Requires=docker.service
After=docker.service
Before=n8n-docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/mailserver
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
[Install]
WantedBy=multi-user.target
n8n Service
nano /etc/systemd/system/n8n-docker.service
Add this configuration:
[Unit]
Description=n8n Docker Compose
Requires=docker.service
After=docker.service traefik-docker.service mailserver-docker.service
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/n8n
ExecStartPre=/bin/bash -c 'until docker container inspect traefik > /dev/null 2>&1; do sleep 2; done'
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
Restart=on-failure
RestartSec=30
TimeoutStartSec=180
[Install]
WantedBy=multi-user.target
Enable and Start Services
# Reload systemd daemon
systemctl daemon-reload
# Enable services to start on boot
systemctl enable traefik-docker.service
systemctl enable mailserver-docker.service
systemctl enable n8n-docker.service
# Start services
systemctl start traefik-docker.service
sleep 10
systemctl start mailserver-docker.service
sleep 10
systemctl start n8n-docker.service
Step 7: DNS Configuration
Point your domain to your server:
- Go to your domain registrar/DNS provider
- Create an A record:
- Name: n8n
- Type: A
- Value: YOUR_SERVER_IP
- TTL: 300 (or minimum allowed)
Wait for DNS propagation (can take up to 24 hours, usually much faster).
Step 8: Test Your Installation
Check if services are running:
docker ps
You should see three containers running: traefik, mailserver, and n8n.
Visit your n8n instance:
https://n8n.yourdomain.com
You should see the n8n setup page with a green lock icon (HTTPS working).
Troubleshooting Common Issues
SSL Certificate Not Working
Check Traefik logs:
docker logs traefik
Common causes:
- DNS not pointing to server
- Firewall blocking ports 80/443
- Wrong domain in configuration
n8n Not Accessible
Check n8n logs:
docker logs n8n-n8n-1
Common fixes:
- Verify domain configuration matches in all files
- Check if all containers are in the same network
Email Not Working
Check mailserver logs:
docker logs mailserver-mailserver-1
Verify SMTP credentials and settings.
Services Not Starting After Reboot
Check service status:
systemctl status traefik-docker.service
systemctl status n8n-docker.service
Restart if needed:
systemctl restart traefik-docker.service
systemctl restart n8n-docker.service
Maintenance and Updates
Regular Maintenance
Weekly checks:
# Check container status
docker ps
# Check disk space
df -h
# Check logs for errors
docker logs n8n-n8n-1 | grep -i error
Monthly updates:
# Update container images
cd /opt/n8n && docker compose pull && docker compose up -d
cd /opt/traefik && docker compose pull && docker compose up -d
cd /opt/mailserver && docker compose pull && docker compose up -d
# Clean up old images
docker system prune -f
Backup Your Data
Create backup script:
nano /opt/backup-n8n.sh
Add this content:
#!/bin/bash
mkdir -p /opt/backups
tar -czf /opt/backups/n8n-backup-$(date +%Y%m%d).tar.gz /opt/n8n/data
find /opt/backups -name "n8n-backup-*.tar.gz" -mtime +30 -delete
Make it executable and add to cron:
chmod +x /opt/backup-n8n.sh
# Add to crontab (daily backup at 2 AM)
crontab -e
# Add this line:
0 2 * * * /opt/backup-n8n.sh
Security Hardening
Configure Firewall
# Install UFW
apt install ufw
# Set defaults
ufw default deny incoming
ufw default allow outgoing
# Allow SSH
ufw allow 22
# Allow HTTP/HTTPS
ufw allow 80
ufw allow 443
# Enable firewall
ufw enable
Secure SSH
Edit SSH configuration:
nano /etc/ssh/sshd_config
Make these changes:
PermitRootLogin prohibit-password
PasswordAuthentication no
PubkeyAuthentication yes
Restart SSH:
systemctl restart ssh
Set Up Fail2Ban
apt install fail2ban
# Copy default configuration
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# Enable and start
systemctl enable fail2ban
systemctl start fail2ban
Cost Breakdown
Monthly costs:
- Hetzner CX11 server: €4.51
- Domain (yearly, varies): ~€10-15/year
- Total: ~€5-6/month
Compare to n8n Cloud:
- n8n Starter: $20/month
- n8n Pro: $50/month
- Savings: $180-540/year
Scaling Your Setup
Multiple n8n Instances
You can run multiple isolated n8n instances for different teams:
Create /opt/n8n-team2/docker-compose.yml
:
version: '3'
services:
n8n-team2:
image: n8nio/n8n:latest
restart: always
environment:
- N8N_HOST=team2.yourdomain.com
# ... rest of configuration
volumes:
- ./data:/home/node/.n8n
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.n8n-team2.rule=Host(`team2.yourdomain.com`)"
- "traefik.http.routers.n8n-team2.entrypoints=https"
- "traefik.http.routers.n8n-team2.tls.certresolver=letsencrypt"
- "traefik.http.services.n8n-team2.loadbalancer.server.port=5678"
networks:
proxy:
external: true
Upgrade Server Resources
If you need more power, upgrade your Hetzner server:
- CX21: 2 vCPU, 8 GB RAM (€8.46/month)
- CX31: 2 vCPU, 16 GB RAM (€16.07/month)
Conclusion
You now have a production-ready n8n installation that costs a fraction of hosted solutions while giving you complete control. The setup includes automatic HTTPS, email functionality, and robust service management.
Key benefits of this approach:
- Cost-effective: Save hundreds of dollars annually
- Full control: No usage limits or restrictions
- Privacy: Your data stays on your infrastructure
- Customizable: Modify and extend as needed
This configuration has been tested in production environments and provides enterprise-grade reliability at a fraction of the cost.
About tva
tva ensures comprehensive infrastructure management of database systems, cloud environments, and global supply chains. Our methodical approach combines rigorous security protocols with performance optimization, while strategic advisory services enable precise coordination of both digital capabilities and physical assets – maintaining the highest standards of operational excellence and compliance throughout all engagements.
Visit tva.sg for more information about our services.