← All posts
GuidesJul 7, 2026· 6 min read

Linux server alerts without a monitoring team: the 6 that matter

The six alerts that catch real outages on a Linux server (disk, memory, service down, SSL, load, failed SSH), the thresholds to use, and how to have them running in five minutes with no Prometheus or Grafana.

By The Opservo team

Your server goes down at 2 AM, and you find out from a user on Twitter. If you're running production infrastructure without a dedicated ops team, that scenario isn't hypothetical — it's a matter of when, not if. The good news: you don't need a full SRE team or an expensive observability stack to get meaningful alerts in place. You need a few focused checks, a reliable notification channel, and about an hour of setup time.

Decide What Actually Matters to Alert On

Before installing anything, define what a 'bad' server looks like for your specific workload. Too many teams alert on everything and then ignore everything. Start with the signals that directly correlate with user-facing impact.

  • CPU sustained above 85–90% for more than 5 minutes — spikes are normal, sustained load is a problem
  • Memory usage above 90% — swap thrashing will kill performance fast
  • Disk usage above 80% on any mounted filesystem — logs and databases fill disks silently
  • Load average exceeding 2–3× your CPU core count for more than a few minutes
  • A critical process (nginx, postgres, your app) is not running
  • Disk I/O wait above 20% consistently — often the real culprit behind slow apps

Keep this list short. Five to eight checks that page you with genuine urgency beat thirty checks that fade into background noise.

The Quickest Starting Point: Node Exporter + Alertmanager

The Prometheus ecosystem is the de facto standard for Linux metrics and for good reason — it's free, well-documented, and scales from one server to hundreds. Here's the minimal setup to get alerts firing.

Install Node Exporter on your server to expose system metrics on port 9100:

  • wget https://github.com/prometheus/node_exporter/releases/latest/download/node_exporter-*.linux-amd64.tar.gz
  • Extract it, move the binary to /usr/local/bin/node_exporter
  • Create a systemd service unit and enable it: systemctl enable --now node_exporter
  • Verify it's working: curl http://localhost:9100/metrics | head -20

Next, install Prometheus on the same machine (or a small VPS) and point it at your Node Exporter. Then add Alertmanager, which handles routing alerts to Slack, PagerDuty, email, or a webhook. The Prometheus docs have a quickstart that takes about 20 minutes end-to-end. The key file is your alert rules — a YAML file that defines thresholds. A disk alert looks like this: expr: (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 < 20, with a for: 5m duration so brief fluctuations don't wake you up.

A Simpler Option: Shell Scripts and Cron

If Prometheus feels like overkill for a single server, a few shell scripts run by cron can cover the basics in minutes. This approach has real limits — no historical data, no dashboards — but it works reliably and has zero dependencies.

A basic disk alert you can drop into /usr/local/bin/check_disk.sh and run every 10 minutes via cron:

  • THRESHOLD=80
  • USAGE=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
  • if [ "$USAGE" -gt "$THRESHOLD" ]; then echo "Disk at ${USAGE}%" | mail -s "ALERT: Disk usage critical" you@example.com; fi
  • Add to cron with: crontab -e, then: */10 * * * * /usr/local/bin/check_disk.sh

For process monitoring, use the same pattern with pgrep: pgrep -x nginx > /dev/null || systemctl restart nginx && mail -s 'ALERT: nginx restarted' you@example.com. Swap email for a curl call to a Slack webhook for faster delivery.

Don't Skip Uptime and External Checks

Internal metrics only tell you what the server sees from the inside. If your network drops or your web process crashes in a way that doesn't show up in CPU or memory, you need an external check. Free tools like UptimeRobot or Freshping will ping your URL every 1–5 minutes and alert you immediately when it stops responding. This takes five minutes to set up and is arguably more valuable than any internal metric — it represents exactly what your users experience. Run both internal and external checks together; they catch different failure modes.

Route Alerts to the Right Place — and Test Them

An alert that nobody sees is the same as no alert. Route critical alerts (disk full, process down) to wherever you'll actually notice at odd hours — typically a dedicated Slack channel with phone notifications enabled, or a free PagerDuty account. Route lower-priority warnings (CPU at 75%) to email or a separate low-noise channel. Then — and this step is almost always skipped — deliberately trigger each alert yourself. Fill a test partition to 85%, kill nginx manually, and verify the alert fires, routes correctly, and arrives within your expected window. If you can't trigger it on demand, you can't trust it at 3 AM.

An untested alert is a false sense of security. Verify every alert fires correctly before you rely on it in production.

When Manual Setup Becomes the Bottleneck

Shell scripts and Prometheus get you far, but they require ongoing maintenance — updating thresholds as workloads change, decoding cryptic metric names, and figuring out why an alert fired at all. This is where a tool like Opservo helps: it monitors your Linux servers, surfaces anomalies in plain English, and explains what's actually wrong rather than just which threshold was crossed. For small teams who need coverage without constant tuning, it fills the gap between 'no monitoring' and 'full observability stack.'

Whatever stack you choose, start today with the five most critical checks for your workload. A minimal alert setup running tonight is worth far more than a perfect one you'll build next quarter. Your future self — the one who gets a Slack message at 2 AM instead of a Twitter mention — will thank you.