1. Check from outside
If the server is down, it cannot tell you. Use an external uptime monitor (UptimeRobot, Better Stack, Uptime Kuma on another machine) that requests a page that exercises your application, not only the home page. Alert by email or push notification. A check every minute and a limit of two failures avoids false alarms.
2. Restart and alert on failure
systemd already restarts a crashed service (Restart=on-failure). Add a notification when a service fails:
sudo tee /etc/systemd/system/notify-failure@.service >/dev/null <<'EOF'
[Unit]
Description=Failure notice for %i
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'journalctl -u %i -n 30 --no-pager | mail -s "Service %i failed on $(hostname)" you@example.com'
EOF
sudo systemctl edit myapp # add the two lines below in the editor
# [Unit]
# OnFailure=notify-failure@%n.service
This needs a working mail command (for example msmtp with an SMTP account). Test it once by hand.
3. JVM metrics
For Spring Boot, add spring-boot-starter-actuator and expose health and metrics on localhost only:
management.endpoints.web.exposure.include=health,metrics,prometheus
management.server.address=127.0.0.1
management.server.port=8081
Never leave actuator endpoints open to the internet. Quarkus has SmallRye Health and Micrometer extensions with the same idea. For any JVM, these numbers matter most: heap after GC, GC pause time, thread count, and the connection pool usage.
Without code changes, jcmd and jstat give a quick view:
sudo -u appuser jstat -gcutil <pid> 5s 5
sudo -u appuser jcmd <pid> VM.native_memory summary # needs -XX:NativeMemoryTracking=summary
4. Server metrics
Install Prometheus node exporter, bound to localhost, or use a hosted agent. At minimum watch:
- Memory: available memory under 10% and any swap usage growing.
- Disk: over 80% full. Logs and heap dumps fill disks. Rotate logs.
- CPU: sustained above 90% or high load average on a small server.
- Certificate: days until the Let's Encrypt certificate expires (the uptime monitors above do this).
A cheap disk and memory alert without extra software:
sudo tee /usr/local/bin/health-check >/dev/null <<'EOF'
#!/usr/bin/env bash
disk=$(df --output=pcent / | tail -1 | tr -dc 0-9)
mem=$(free | awk '/Mem:/ {printf "%d", $7/$2*100}')
[ "$disk" -gt 80 ] && echo "Disk ${disk}% full on $(hostname)" | mail -s "Disk alert" you@example.com
[ "$mem" -lt 10 ] && echo "Only ${mem}% memory available on $(hostname)" | mail -s "Memory alert" you@example.com
exit 0
EOF
sudo chmod 755 /usr/local/bin/health-check
echo '*/10 * * * * root /usr/local/bin/health-check' | sudo tee /etc/cron.d/health-check
5. Logs
Journald keeps service logs; set a size cap in /etc/systemd/journald.conf (SystemMaxUse=500M). For Tomcat, rotate catalina.out with logrotate using copytruncate.
On managed Java hosting we monitor uptime, memory, CPU and disk and get alerted for you.
Last updated October 29, 2026.