SameOS ~/tools/server-webhook-monitoring.md

Server Status Webhook Alerts With a Shell Script

For one or two servers, a monitoring stack like Prometheus is overkill. What you actually need is a periodic "is CPU, memory, and disk okay right now" message in your messenger - and built-in Linux commands plus one webhook (a dedicated URL that lets a program post messages into a messenger channel) cover that. This is a generalized version of a script that has been running hourly on a real personal server.

What to Collect, and From Where

CPU usage comes from the summary line of top -bn1, memory from free -m, and disk from df -h. All three ship with any Linux box, so there is no agent (a resident program that collects and exports stats) to install. Discord, Slack, Mattermost, and most other messengers accept JSON via incoming webhooks, so a single curl command delivers the report.

The script below posts an hourly summary. Never write the webhook URL directly into a script (hardcoding) that might reach a repository - read it from an environment file with restricted read permissions instead.

#!/bin/bash
# Save WEBHOOK_URL="https://..." in /etc/server-report.env (chmod 600)
source /etc/server-report.env

CPU=$(top -bn1 | awk '/Cpu\(s\)/{print $2}' | cut -d'%' -f1)
RAM_USED=$(free -m | awk '/^Mem:/{print $3}')
RAM_TOTAL=$(free -m | awk '/^Mem:/{print $2}')
RAM_PCT=$(awk "BEGIN {printf \"%.1f\", ($RAM_USED/$RAM_TOTAL)*100}")
DISK=$(df -h / | awk 'NR==2{print $3" / "$2" ("$5")"}')
UP=$(uptime -p | sed 's/up //')

MSG="Server status report
CPU: ${CPU}%
RAM: ${RAM_USED}MB / ${RAM_TOTAL}MB (${RAM_PCT}%)
DISK: ${DISK}
UPTIME: ${UP}"

curl -s -H "Content-Type: application/json" \
     -d "{\"content\": \"${MSG}\"}" \
     "$WEBHOOK_URL" > /dev/null

Operation Tips

The blind spot of this approach: if the server dies completely, the alerts die with it. Treat it as a heartbeat report - when the hourly message stops arriving, that silence itself is the incident signal. For stronger coverage, add a free external uptime service (one that checks from outside whether your site still responds) watching your HTTP endpoint.

Prefer cron (the scheduler built into Linux) or a systemd timer over a while/sleep infinite loop. A looping script that dies silently stays dead, while cron starts fresh each time so one failure never affects the next run. Adding threshold-only alerts - for example, only when disk usage passes 90% - also cuts noise.

Get the full script (GitHub) Open the crontab explainer View operation notes