How to monitor a Hetzner server

Hetzner gives you great hardware at a great price. It doesn't give you monitoring. Here's how to set up uptime monitoring for apps running on Hetzner Cloud or dedicated servers.

Hetzner is one of the best deals in hosting. Solid hardware, excellent network, EU-based, and pricing that makes the US cloud providers look absurd. A lot of people run production workloads on Hetzner, from single VPS instances to multi-server clusters.

What Hetzner doesn't give you is monitoring. The Hetzner Cloud console shows you CPU, disk, and network graphs, and you can set up basic alerts for those metrics. But it doesn't check whether your app is actually responding to requests. Your server can have 5% CPU usage and plenty of free memory while your app is completely unresponsive because Nginx is misconfigured, a database migration failed, or a Docker container crashed.

What to monitor

Your app's public URL. The most important check. Whatever domain your users visit, monitor that. Not the server IP, not a health endpoint on a weird port. The actual URL, over HTTPS, the way a real user would access it. This tests the full stack: DNS, your reverse proxy, your app, your database connection.

Individual services behind a reverse proxy. If you're running multiple apps on a single Hetzner server (which is common, especially with tools like Dokploy, Coolify, or plain Docker Compose with Traefik or Nginx), each app needs its own monitor. One app crashing doesn't mean the others are down, and you want to know which one is having problems.

Your server's IP directly. This is a useful secondary check. If your domain-based check fails but the IP check succeeds, the problem is DNS or your reverse proxy configuration, not the server itself. If both fail, the server is unreachable.

SSL certificates. If you're managing your own certificates (via Certbot, Caddy's auto-HTTPS, or Traefik's ACME), you need to know when renewal fails. Monitor the certificate expiry as part of your HTTPS checks.

Common failure modes on Hetzner

Unattended upgrades break things. If you've enabled automatic security updates (which you should), there's always a small chance an update breaks a dependency, restarts a service unexpectedly, or fills up /boot with old kernel images. The server keeps running, but your app doesn't.

Disk fills up. Docker images, log files, database WAL segments. Hetzner's local SSDs are fast but not huge, especially on the smaller instances. When the disk fills up, things fail in unpredictable ways. Docker can't start containers, databases refuse writes, log rotation stops working. Your monitoring dashboard in Hetzner Cloud might show disk usage, but it won't tell you your app is down because of it.

OOM kills. The kernel's OOM killer takes out your app process, or worse, your database process. The server stays up, systemd might restart the service, but there's a gap. And if the OOM killer hits your database, the app might come back up but fail on every request that needs data.

Firewall changes. Hetzner has both their own firewall (configured in the Cloud console) and whatever you're running on the server (iptables, ufw, nftables). A change in either one can silently block traffic. The server is fine, you can SSH in, but HTTP traffic is being dropped.

Network maintenance. Hetzner occasionally does network maintenance on their infrastructure. They usually notify you in advance, but the notification goes to the email associated with your Hetzner account, which might not be the email you check regularly. Monitoring from multiple external locations catches these windows.

Setting it up

Create an HTTP monitor in Larm with your app's public URL. Larm checks from multiple global locations, so you'll catch issues regardless of where they originate.

Health check endpoints. If you can, add a health endpoint to your app that checks its dependencies. A simple GET /health that returns 200 when the app is ready and the database is reachable is much more useful than checking GET /, which might return 200 from a static error page.

TCP monitors for non-HTTP services. If you're running services that don't speak HTTP (a mail server, a custom TCP service, a game server), use a TCP monitor instead. Larm connects to the specified port and verifies it's accepting connections.

DNS monitors. If you're running your own DNS on Hetzner (or using Hetzner DNS), monitor that your DNS records are resolving correctly. A DNS monitor checks that a query for your domain returns the expected result.

If you're self-hosting a PaaS

A lot of Hetzner users run Dokploy, Coolify, or CapRover to manage their apps. These tools handle deploys, SSL, and reverse proxying, but they don't typically monitor whether the apps behind them are healthy.

If you're in this setup, monitor each app individually by its public domain. Don't rely on the PaaS dashboard being green. It tells you the container is running, not that the app inside the container is working.

For Dokploy specifically, there's a separate guide on monitoring Dokploy deployments.

Hetzner gives you the infrastructure. What you build on top of it is your responsibility to monitor. Larm's free plan gives you 15 monitors, which is usually enough to cover a single Hetzner server with multiple apps and services.

Start monitoring in minutes.

Free plan. 15 monitors. Multi-probe voting. No credit card.

Sign Up Free