Skip to main content

VPS Uptime Monitoring: Tools and Alert Setup

VDS / VPS · 19.04.2026 · 4 min read
Illustration for “VPS Uptime Monitoring: Tools and Alert Setup”

Without monitoring, you find out about server problems from unhappy customers. Uptime monitoring tools check availability every 1–5 minutes and instantly alert you to outages.

Free tools

ServiceFree planInterval
UptimeRobot50 monitors5 min
Hetrix Tools15 monitors3 min
Better Uptime10 monitors3 min
StatusCake10 monitors5 min

UptimeRobot: 5-minute setup

  1. Sign up at uptimerobot.com
  2. Add New Monitor → HTTP(s)
  3. URL: your site or IP
  4. Monitoring Interval: 5 minutes
  5. Alert Contacts: add email and/or Telegram
✅ UptimeRobot monitors 50 sites for free at a 5-minute interval. More than enough for most projects.

Local monitoring via script

#!/bin/bash
# /usr/local/bin/check-services.sh

services=("nginx" "mysql" "php8.2-fpm")
BOT_TOKEN="your_telegram_token"
CHAT_ID="your_chat_id"

for service in "${services[@]}"; do
    if ! systemctl is-active --quiet "$service"; then
        msg="ALERT: $service is DOWN on $(hostname)!"
        curl -s "https://api.telegram.org/bot$BOT_TOKEN/sendMessage"             -d "chat_id=$CHAT_ID&text=$msg" > /dev/null
        systemctl restart "$service"
    fi
done
# Add to cron (every 2 minutes)
*/2 * * * * /usr/local/bin/check-services.sh

Resource monitoring

# Netdata — a beautiful real-time dashboard
bash <(curl -Ss https://my-netdata.io/kickstart.sh)
# After installation: http://your-vps-ip:19999
⚠️ Close the Netdata port in UFW right after installation and open it only from your IP: sudo ufw allow from YOUR_IP to any port 19999

Common monitoring errors

UptimeRobot shows Up, but the site returns a 500 error — an external monitor checks only the HTTP status code by default. If the server returns "200 OK" with an empty error page inside (for example, a PHP exception was caught and a fallback page was shown), the monitor will not notice it.

# Check the response code manually
curl -o /dev/null -s -w "%{http_code}\n" https://example.com
200

# But the content inside is a PHP error
curl -s https://example.com | grep -i "fatal error"
Fatal error: Uncaught PDOException in /var/www/app/db.php:12

The fix is to set up Keyword Monitoring in UptimeRobot: specify a text string that must be present on the page during normal operation, and the monitor will mark the site as Down when that text is missing.

The local script restarts the service, but no Telegram alert arrives — the most common cause is incorrect escaping of the ampersand in the URL, or stray spaces from a line continuation with \.

curl: (3) URL using bad/illegal format or missing URL

This means the variable $msg contains spaces and is not quoted, or the line break after \ added an invisible character. Check the script line by line with bash -x check-services.sh.

Comparing monitoring methods

MethodWhat it checksDetection delayNeeds server access
UptimeRobot / external serviceSite availability from outside1-5 minutesNo
Local script + cronStatus of specific systemd services1-2 minutesYes
NetdataCPU, RAM, disk, network in real timeSeconds (but local)Yes
Grafana + PrometheusMetrics plus threshold alerts15-60 secondsYes

When external monitoring is not enough

  • You need to know the cause of an outage, not just the fact of it — an external monitor says "site unreachable" but will not show that memory ran out or disk is at 100%.
  • Reaction speed before user complaints matters — a 3-5 minute interval on an external service means some users already saw the error.
  • The service runs only on an internal network with no public IP — UptimeRobot and similar tools cannot reach a private address.
  • You need long-term metrics for trend analysis — free external monitors usually keep history for no more than 1-3 months.
  • You need to watch more than the web server — background jobs like cron or queues — an external HTTP monitor cannot see a hung queue worker; that needs separate heartbeat checks from inside the application itself.

Verifying the result

  1. In the UptimeRobot dashboard the monitor status must switch to Up within the first check cycle after setup.
  2. Stop Nginx manually (sudo systemctl stop nginx) and confirm the down alert arrives within the stated interval.
  3. Start Nginx again and confirm a recovery alert (Up) arrives, not just a down alert.
  4. For the local script, check the log: tail -20 /var/log/syslog | grep check-services — it must contain entries showing the cron job ran.

For deeper resource analysis after an alert, see Netdata, and for metrics with history and graphs, see Grafana with Prometheus.

Was this article helpful?
← Back to Knowledge Base Ask Support