Checks system health, hardware, and your running services every 5 minutes, and sends a Telegram message only when something changes state — no spam, no repeat alerts for a problem that's already been reported. Plus one daily heartbeat at 08:00 so you know the monitor itself hasn't died.
- Disk usage on
/(default threshold: 85%) - Memory usage (default threshold: 90%)
- CPU load (5-min load average vs core count)
- CPU temperature (default threshold: 75°C — reads
/sys/class/thermal, so it works on non-Pi hardware like your EeePC) - Services and ports — auto-discovered (see below)
- Internet reachability (ping 1.1.1.1)
- DNS resolution (confirms Pi-hole is actually resolving names, not just running)
Every run, the script scans:
- Listening TCP ports (via
ss), skipping anything bound only to loopback (internal plumbing, not a real "service") - Running systemd services (via
systemctl), skipping generic system internals (systemd-*,dbus*,user@*,getty@*) so you're not flooded with noise from things you didn't set up
First run: whatever's currently running/listening becomes the baseline silently — you won't get a wall of "new service!" messages for Pi-hole, Apache, lighttpd, your FastAPI app, and qBittorrent all at once.
After that:
- Add a new service or open a new port → you get one 🔵 "new service/port detected, now monitoring it" message, and it's tracked from then on automatically.
- A tracked service/port disappears (crash, or you stopped it) → you get one 🔴 alert. If you meant to decommission it, run the forget command below so it stops being tracked (otherwise it just stays quiet after the one alert — no repeat spam either way).
sudo /opt/health-monitor/health-monitor.sh --forget-port 8080
sudo /opt/health-monitor/health-monitor.sh --forget-service qbittorrent-noxsudo /opt/health-monitor/health-monitor.sh --statusShows every tracked port/service and its current OK/FAIL state, plus what's on the ignore lists.
- In Telegram, message @BotFather
- Send
/newbot, give it a name and a username (must end in "bot") - BotFather gives you a token like
123456789:ABCdefGhIJKlmNoPQRstuVWXyz— this is yourTELEGRAM_BOT_TOKEN
- Send any message to your new bot (e.g. "hi")
- Visit this URL in a browser (replace with your token):
https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates - Look for
"chat":{"id":123456789,...}— that number is yourTELEGRAM_CHAT_ID
sudo bash setup.shThen edit the generated env file and fill in your token/chat ID:
sudo nano /opt/health-monitor/health-monitor.envThis file is separate from the script on purpose — it's created with placeholders on first install and never touched by upgrades, so your real token never has to live inside the (version-controlled) script itself.
Test it manually:
sudo /opt/health-monitor/health-monitor.sh
tail -f /var/log/health-monitor.logYou should get a Telegram message the first time any check fails, and a
"recovered" message when it's fixed. To force a test alert, you could
temporarily stop a service you're monitoring (sudo systemctl stop lighttpd)
and watch for the alert within 5 minutes, then start it again.
Frequent enough to catch a service dying without much delay, infrequent enough that it won't add meaningful load to an EeePC. If you want it tighter or looser, edit the cron line directly:
crontab -eAll thresholds live in the CONFIG section at the top of health-monitor.sh:
DISK_WARN_PCT,MEM_WARN_PCT,LOAD_MULTIPLIER,TEMP_WARN_CSERVICE_IGNORE_PATTERNS— shell glob patterns for systemd services to never auto-track (default excludessystemd-*,dbus*,user@*,getty@*,serial-getty@*)HEARTBEAT_HOUR— hour (0–23) for the daily "still alive" ping
Note: ports are not filtered by pattern — every non-loopback listening port gets tracked. Use --forget-port for any you don't care about.
sudo crontab -l | grep -v health-monitor.sh | sudo crontab -
sudo rm -rf /opt/health-monitor /var/lib/health-monitor /var/log/health-monitor*.log
sudo rm -f /etc/logrotate.d/health-monitor