VPS Hosting (Hetzner, etc.) implementation checklist
This checklist outlines the essential steps for moving a production application from a managed environment to a self-managed VPS on providers like Hetzner, OVH, or Contabo. It focuses on security, reliability, and automation to ensure high availability without the overhead of managed platforms.
Initial Server Hardening
0/5Disable Root SSH Login
criticalModify /etc/ssh/sshd_config to set PermitRootLogin no and verify you can login as a sudo user.
Enforce SSH Key Authentication
criticalSet PasswordAuthentication no in SSH config to prevent brute-force password attacks.
Configure UFW/NFTables
criticalSet a default deny policy and explicitly allow only ports 22, 80, and 443.
Install Fail2Ban
recommendedConfigure jails for SSH and your web server to automatically ban IP addresses with multiple failed login attempts.
Enable Unattended Upgrades
recommendedInstall the unattended-upgrades package and configure it to automatically install security patches daily.
Reverse Proxy and SSL
0/5Automated SSL Renewal
criticalConfigure Caddy or Nginx with Certbot to ensure Let's Encrypt certificates renew before the 90-day expiration.
HSTS Header Implementation
recommendedAdd the Strict-Transport-Security header to proxy responses to force HTTPS-only connections.
IPv6 Connectivity
recommendedVerify the VPS has a valid AAAA record and the reverse proxy is listening on [::] to support European mobile networks.
Request Rate Limiting
recommendedDefine limit_req zones in Nginx or use Caddy's rate_limit directive to prevent application-layer DoS.
Proxy Health Checks
criticalConfigure the reverse proxy to check the backend service status before routing traffic to prevent 502 errors.
Container and App Management
0/5Docker Log Rotation
criticalSet max-size and max-file in /etc/docker/daemon.json to prevent container logs from filling the system disk.
Non-Root Container Users
recommendedVerify Dockerfiles include a USER directive so the application process does not run with root privileges inside the container.
Resource Constraints
recommendedApply memory and CPU limits in docker-compose.yml to prevent a single container from crashing the entire VPS.
Automated Image Pruning
optionalSchedule a weekly cron job for 'docker system prune -f' to remove unused images and build cache.
Kamal/Coolify Deployment Hooks
criticalConfigure post-deployment health checks to verify the new container is responding before shutting down the old one.
Backups and Disaster Recovery
0/5Provider-Level Snapshots
criticalEnable daily automated snapshots in the Hetzner or OVH control panel for full-server recovery.
Off-site Database Backups
criticalConfigure a cron job to stream encrypted database dumps to S3-compatible storage outside the VPS provider's network.
Backup Restoration Test
criticalManually restore a database backup to a local development environment to verify data integrity.
Volume Mounting for Persistence
recommendedEnsure all database data and user uploads are stored on attached block storage volumes, not the local OS disk.
Environment Variable Backup
recommendedStore an encrypted copy of the .env file or secrets in a secure password manager or vault.
Monitoring and Performance
0/5External Uptime Monitoring
criticalSet up an external service to ping the application's health endpoint every 60 seconds.
Disk Space Alerts
criticalConfigure a monitoring agent (e.g., Netdata or Prometheus) to alert when disk usage exceeds 80%.
Configure Swap Space
recommendedCreate a swap file (2-4GB) to provide a buffer for memory spikes on low-RAM VPS instances.
NTP Time Synchronization
recommendedEnsure systemd-timesyncd is active to prevent clock drift, which can cause issues with SSL and auth tokens.
Centralized Log Aggregation
optionalForward system and application logs to a dedicated logging server or service for post-mortem analysis.