DEV Community

Nevik Schmidt
Nevik Schmidt

Posted on

Self-Hosting on Hetzner: My Complete €15/month Infrastructure Stack

Self-Hosting on Hetzner: My Complete €15/month Infrastructure Stack

I run 15+ services on a single Hetzner server for €15/month. Everything is GDPR-compliant because all data stays in Germany. Here's the full stack.

The Server

Hetzner CX32 (or equivalent):

  • 2 vCPU, 8GB RAM
  • 80GB SSD
  • €15/month
  • Location: Falkenstein, Germany 🇩🇪

This is enough to run everything a small business needs.

The Stack

Service Purpose Replaces
Nginx Proxy Manager Reverse Proxy + SSL Cloudflare, AWS ALB
Nextcloud File Sync & Share Google Drive, Dropbox
Matomo Web Analytics Google Analytics
Vaultwarden Password Manager 1Password, Bitwarden Cloud
n8n Workflow Automation Zapier ($20-600/mo)
Uptime Kuma Monitoring Pingdom, UptimeRobot
Paperless-ngx Document Management Google Docs
Gitea Git Hosting GitHub
Portainer Docker Management
SearXNG Private Search Google Search
Roundcube Webmail Gmail

Docker Compose Structure

I organize services into individual docker-compose.yml files in /opt/services/:

/opt/services/
├── proxy/docker-compose.yml
├── nextcloud/docker-compose.yml
├── matomo/docker-compose.yml
├── vaultwarden/docker-compose.yml
├── n8n/docker-compose.yml
├── uptime-kuma/docker-compose.yml
└── paperless/docker-compose.yml
Enter fullscreen mode Exit fullscreen mode

Each service gets its own Docker network. Nginx Proxy Manager sits in front and handles SSL termination.

Key Security Hardening

1. UFW Firewall (BUT Watch Out for Docker!)

Docker bypasses UFW by default. This is a common gotcha.

# Check what's actually exposed
ss -tlnp | grep 0.0.0.0

# Fix: Edit /etc/docker/daemon.json
{
  "iptables": false
}
# Then manage ALL firewall rules via UFW
Enter fullscreen mode Exit fullscreen mode

2. SSH Hardening

# /etc/ssh/sshd_config
PermitRootLogin prohibit-password
PasswordAuthentication no
Port 2222  # Non-standard port reduces noise
MaxAuthTries 3
Enter fullscreen mode Exit fullscreen mode

3. Fail2ban

apt install fail2ban
systemctl enable fail2ban
Enter fullscreen mode Exit fullscreen mode

Default config bans after 5 failed attempts for 1 hour.

4. Automatic Updates

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

5. Backup Strategy

#!/bin/bash
# daily-backup.sh
DATE=$(date +%Y-%m-%d)
pg_dumpall | gzip > /root/backups/$DATE/db.sql.gz
tar czf /root/backups/$DATE/services.tar.gz /opt/services/
find /root/backups/ -mtime +7 -delete
Enter fullscreen mode Exit fullscreen mode

Cron: 0 4 * * * /root/scripts/daily-backup.sh

GDPR Compliance Checklist

Since everything runs in Falkenstein, Germany:

  • ✅ Data never leaves the EU
  • ✅ No US cloud services processing personal data
  • ✅ Full control over data retention
  • ✅ Can fulfill data subject requests (export, delete) immediately
  • ✅ No third-party data processing agreements needed (except Hetzner as infrastructure provider)

Cost Comparison

Service Cloud Cost Self-Hosted Cost
Google Drive (2TB) €10/mo €0 (included)
1Password (family) €4/mo €0
Zapier (professional) €20/mo €0
Google Analytics 360 €150K/yr €0
Pingdom €15/mo €0
Total €49+/mo €15/mo (server)

Savings: €34+/month, plus full GDPR compliance and data sovereignty.

Monitoring

I use Uptime Kuma to monitor all services. If anything goes down, I get a Telegram notification immediately.


Want to know if your current website setup is GDPR-compliant? Run a free scan — it checks for Google Analytics, external fonts, missing legal pages, and more.

Top comments (0)