Eenvoudige servermonitoring inrichten zonder extra software

Gepubliceerd op 19 min leestijd

Een controlescript, een systemd-timer en een getest meldingskanaal volstaan voor één enkele rootserver. Deze handleiding laat zien wat u moet bewaken, hoe u elke stap controleert en vanaf wanneer de grote gereedschapskist loont.

Een server meldt zich niet uit zichzelf wanneer er iets misgaat. Hij draait door tot hij niet meer doordraait, en het eerste signaal komt van een klant of van uzelf, wanneer u toevallig kijkt. Deze handleiding bouwt de kleinst mogelijke monitoring die daar een eind aan maakt: een controlescript, een systemd-timer en een meldingskanaal. Geen tijdreeksdatabase, geen dashboard, geen extra open poort.

Als referentiesystemen dienen Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS en Ubuntu 22.04 LTS. Waar de vier van elkaar afwijken, staat dat er uitdrukkelijk bij. Alle commando's zijn geschreven voor gebruik als root; als gewone gebruiker zet u voor elk commando een sudo. Deze handleiding werkt stap 8 uit van de checklist voor een nieuwe rootserver.

Wat u eigenlijk zou moeten bewaken

De meest gemaakte fout bij een eerste monitoringopzet is niet te weinig meten, maar te veel. Wie 40 meetwaarden verzamelt, kijkt naar geen enkele daarvan om. Zinvol is alleen wat de werking kan stilleggen en waarop u ook echt kunt reageren. Er blijven zeven punten over.

MeetwaardeWaarom die op de lijst hoortWaar de waarde vandaan komtZinvolle drempel
SchijfruimteMeest voorkomende storingsoorzaak die niemand ziet aankomendf --output=pcent,targetvanaf 85 procent
InodesSchijf ogenschijnlijk leeg, toch "No space left on device"df --output=ipcent,targetvanaf 85 procent
Vrij werkgeheugenDe OOM-killer treft zelden het proces dat u zou opofferenMemAvailable in /proc/meminfoonder 200 MB
SysteembelastingLaat opstopping zien, ongeacht of de CPU of de schijf de oorzaak isderde veld in /proc/loadavg15-minutengemiddelde boven tweemaal het aantal cores
Mislukte dienstenEen dienst die 's nachts omvalt, blijft anders tot de ochtend doodsystemctl is-system-runningalles behalve running
Verlopen certificaatSluit in één klap elke bezoeker buiten, niet slechts een deelopenssl x509 -checkendminder dan 21 dagen resterend
Bereikbaarheid van buitenafBeantwoordt als enige controle of de server er nog istweede host, curltwee mislukkingen op rij

Niet op de lijst staat het CPU-gebruik in procenten: een server die 100 procent trekt omdat er een videocodeerder draait, doet precies wat de bedoeling is. Netwerkdoorvoer en het aantal processen ontbreken om dezelfde reden. Allebei helpen ze bij het zoeken naar de oorzaak, maar als alarm deugen ze niet, omdat er geen waarde bestaat waarboven u wel moet ingrijpen.

De terugweg, voordat het eerste bestand bestaat

Monitoring is een lezende bezigheid en kan normaal gesproken niets stukmaken. Drie dingen kunnen dat toch.

Een script dat repareert in plaats van meldt. De gedachte is verleidelijk: als nginx dood is, moet het script hem gewoon opnieuw starten. Daar komt een dienst uit voort die elke tien minuten start, een halve seconde draait en de oorzaak toedekt. En een script dat bij een volle schijf zelfstandig wist, wist vroeg of laat iets wat nog nodig was. De eerste versie leest uitsluitend en roept noch systemctl restart, noch rm, noch kill aan.

Open netwerkinterfaces. Metrics-exporters die op alle adressen luisteren, vormen een van de meest voorkomende onbedoelde datalekken op losstaande servers. De aanpak in dit artikel opent geen poort en heeft geen firewallregel nodig.

Het alarmkanaal zelf. Monitoring waarvan de melding nooit is getest, is geen monitoring maar een prettig gevoel. De bijbehorende test staat verderop en is niet optioneel.

Hoe u zonder SSH bij de server komt

KVM-rootservers en dedicated servers hebben geen IPMI en geen iDRAC. De toegang wanneer SSH niet meer antwoordt, is de VNC-console in het klantenpaneel. Die hangt niet aan de netwerkstack van het gastsysteem, dus een firewallregel of een overbelaste SSH-dienst kan hem niet blokkeren. Log daar vooraf één keer in en overtuig uzelf ervan dat u het rootwachtwoord kent.

De uitschakelaar

Mocht de monitoring zelf het probleem worden, bijvoorbeeld doordat ze elke minuut alarmen verstuurt, dan hebt u twee commando's nodig. Onthoud die voordat u begint:

systemctl disable --now kh-monitor.timer
systemctl mask kh-monitor.service

Het eerste stopt de timer onmiddellijk en verhindert dat hij bij de volgende start terugkomt. Het tweede is de noodrem: een gemaskeerde dienst laat zich ook niet meer per ongeluk met de hand starten, ongedaan te maken met systemctl unmask kh-monitor.service. De aanpak is vooral daarom risicoarm omdat er uitsluitend nieuwe bestanden bij komen; het terugdraaien bestaat uit het verwijderen van die bestanden. Houd desondanks een tweede SSH-sessie open zolang u aan het systeem werkt.

De meetwaarden eerst met de hand controleren

Voordat een script iets gaat beoordelen, hoort u elke waarde één keer zelf te hebben gezien. Anders weet u later niet of een alarm terecht is of dat uw drempel nergens op slaat.

Schijfruimte en inodes

df -h
df --output=pcent,target -x tmpfs -x devtmpfs -x squashfs -x overlay
df -i

De uitsluitingen zijn noodzakelijk. Onder Ubuntu 22.04 en 24.04 koppelt snap zijn pakketten aan als alleen-lezen squashfs-images, en die staan permanent op 100 procent. Zonder -x squashfs meldt uw monitoring vanaf de allereerste run een volle schijf, elke dag, voor altijd. Voor de overlay-mountpoints van Docker geldt hetzelfde.

Twee eigenaardigheden moet u kennen. df accepteert -P en --output niet samen en breekt af met een melding over elkaar uitsluitende opties. En op ext4 is standaard vijf procent voor root gereserveerd, waardoor df al 100 procent meldt terwijl root nog kan schrijven. Wat u na het alarm moet doen, leest u in Schijf vol onder Linux opruimen.

De inodecontrole is geen randverschijnsel. Een map met miljoenen minieme sessie- of cachebestanden kan alle inodes opsouperen terwijl df -h volop vrije ruimte laat zien. Schrijfacties mislukken dan met No space left on device, en de voor de hand liggende verklaring is de verkeerde.

Werkgeheugen

free -m
awk '/^MemAvailable:/ { printf "%d MB\n", $2 / 1024 }' /proc/meminfo

De kolom free is op een gezond Linux-systeem bijna altijd klein, omdat de kernel ongebruikt geheugen als bestandscache inzet. Betrouwbaar is alleen available oftewel MemAvailable: de hoeveelheid geheugen die een nieuwe toepassing kan krijgen zonder dat er iets naar swap wordt geschreven. Alarmeer op die waarde, nooit op free.

Of het eerder al krap was, verraadt het kernellogboek:

journalctl -k -b --grep "Out of memory"

Elke treffer is een proces dat de kernel heeft afgebroken omdat het geheugen op was. Hoe u daarop reageert zonder blindelings swap aan te maken, leest u in Swap inrichten en out of memory voorkomen.

Systeembelasting

nproc
cat /proc/loadavg
uptime

De eerste drie velden in /proc/loadavg zijn de gemiddelden over één, vijf en vijftien minuten. Twee dingen worden geregeld verkeerd begrepen. Ten eerste is de belasting onder Linux geen zuivere CPU-grootheid: processen die op schijftoegang wachten, tellen mee. Een belasting van 20 op vier cores kan betekenen dat de CPU gloeit, maar net zo goed dat een schijf klem zit. Ten tweede deugt de waarde over één minuut niet voor alarmen, omdat elke back-uprun hem even omhoogjaagt. Neem het 15-minutengemiddelde en zet de drempel in verhouding tot het aantal cores.

Heeft uw kernel de drukstatistiek aan boord, dan is die veelzeggender, want ze splitst CPU, invoer en uitvoer en geheugen apart uit. Aanwezig is ze niet overal:

test -d /proc/pressure && cat /proc/pressure/io || echo "geen drukstatistiek in deze kernel"

Diensten

systemctl is-system-running
systemctl --failed --no-pager
systemctl is-active nginx

systemctl is-system-running is de kortste zinvolle totaalcontrole. Het geeft running terug wanneer geen enkele unit in de foutstatus staat, en degraded zodra er één in staat. De exitcode is navenant 0 of ongelijk aan 0.

Twee valkuilen. De status degraded blijft staan tot u hem na de reparatie met systemctl reset-failed terugzet; een taak die één keer is mislukt, houdt de melding anders wekenlang overeind. En bij het controleren van losse diensten lopen de referentiesystemen uiteen: onder Ubuntu 24.04 wordt SSH via socketactivering gestart, ssh.service staat daar in rust op inactive terwijl SSH prima bereikbaar is. Wie daar ssh.service bewaakt, krijgt een permanent vals alarm. Te bewaken is op Ubuntu 24.04 ssh.socket, op Debian 12, Debian 13 en Ubuntu 22.04 juist ssh.service.

Verlopen van certificaten

openssl x509 -enddate -noout -in /etc/letsencrypt/live/example.com/fullchain.pem
openssl x509 -checkend 1814400 -noout -in /etc/letsencrypt/live/example.com/fullchain.pem

Het tweede commando is het interessante. -checkend verwacht een aantal seconden, 1814400 staat voor 21 dagen. Verloopt het certificaat binnen die termijn, dan geeft het commando Certificate will expire en exitcode 1, anders Certificate will not expire en 0. /etc/letsencrypt/live en /etc/letsencrypt/archive zijn alleen voor root leesbaar.

De controle heeft een gat dat veel handleidingen verzwijgen: ze controleert het bestand op de schijf, niet het certificaat dat uw webserver uitlevert. Loopt de verlenging door maar mislukt de reload van de webserver, dan is het bestand nieuw en de uitgeleverde sleutel oud. De bestandscontrole meldt niets terwijl bezoekers al een certificaatwaarschuwing zien. Alleen de blik van buitenaf vangt dat geval op:

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddate

-servername is niet optioneel zodra er meerdere certificaten op één IP-adres liggen. Zonder die toevoeging krijgt u het standaardcertificaat van de server en controleert u het verkeerde domein.

Het controlescript

Alle controles bij elkaar leveren een script op dat niets anders doet dan lezen, vergelijken en bij een fout melden. Het heeft curl nodig en, voor de webhookroute, jq. Op minimale Debian-installaties ontbreken ze allebei:

apt update
apt install -y curl jq
cat > /usr/local/sbin/kh-monitor <<'EOF'
#!/bin/bash
set -u

DISK_WARN="${DISK_WARN:-85}"
INODE_WARN="${INODE_WARN:-85}"
MEM_MIN_MB="${MEM_MIN_MB:-200}"
LOAD_FACTOR="${LOAD_FACTOR:-2}"
CERT_DAYS="${CERT_DAYS:-21}"
UNITS="${UNITS:-ssh nginx}"
STATE_DIR="${STATE_DIRECTORY:-/var/lib/kh-monitor}"

problems=""
add() { problems+="- ${1}"$'\n'; }

notify() {
  printf '%s | %s\n' "$1" "$(printf '%s' "$2" | tr '\n' ' ')"
  if [ -n "${WEBHOOK_URL:-}" ]; then
    printf '%s\n%s' "$1" "$2" | jq -Rs '{text: .}' \
      | curl -fsS -m 10 -o /dev/null -H 'Content-Type: application/json' \
             --data-binary @- "$WEBHOOK_URL"
  fi
  if [ -n "${MAILTO:-}" ]; then
    printf '%s\n' "$2" | mail -s "$1" "$MAILTO"
  fi
}

while read -r pcent target; do
  pcent="${pcent%\%}"
  case "$pcent" in ''|*[!0-9]*) continue ;; esac
  [ "$pcent" -ge "$DISK_WARN" ] && add "Schijf ${target} voor ${pcent} procent vol"
done < <(df --output=pcent,target -x tmpfs -x devtmpfs -x squashfs -x overlay | tail -n +2)

while read -r ipcent target; do
  ipcent="${ipcent%\%}"
  case "$ipcent" in ''|*[!0-9]*) continue ;; esac
  [ "$ipcent" -ge "$INODE_WARN" ] && add "Inodes op ${target} voor ${ipcent} procent gebruikt"
done < <(df --output=ipcent,target -x tmpfs -x devtmpfs -x squashfs -x overlay | tail -n +2)

mem_avail=$(awk '/^MemAvailable:/ { printf "%d", $2 / 1024 }' /proc/meminfo)
[ "${mem_avail:-0}" -lt "$MEM_MIN_MB" ] && add "nog maar ${mem_avail} MB werkgeheugen beschikbaar"

cores=$(nproc)
load15=$(awk '{ print $3 }' /proc/loadavg)
awk -v l="$load15" -v c="$cores" -v f="$LOAD_FACTOR" 'BEGIN { exit !(l > c * f) }' \
  && add "Belasting over 15 minuten ${load15} bij ${cores} cores"

sysstate=$(systemctl is-system-running)
[ "$sysstate" = "running" ] || add "systemd meldt status ${sysstate}"

for unit in $UNITS; do
  systemctl is-active --quiet "$unit" || add "Dienst ${unit} is $(systemctl is-active "$unit")"
done

for cert in /etc/letsencrypt/live/*/fullchain.pem; do
  [ -r "$cert" ] || continue
  openssl x509 -checkend $(( CERT_DAYS * 86400 )) -noout -in "$cert" >/dev/null 2>&1 \
    || add "Certificaat ${cert} verloopt binnen minder dan ${CERT_DAYS} dagen"
done

mkdir -p "$STATE_DIR"
now=$(printf '%s' "$problems" | sha256sum | cut -d' ' -f1)
before=$(cat "${STATE_DIR}/last" 2>/dev/null || true)
printf '%s' "$now" > "${STATE_DIR}/last"

if [ -z "$problems" ]; then
  [ -n "${HEARTBEAT_URL:-}" ] && curl -fsS -m 10 -o /dev/null "$HEARTBEAT_URL"
  [ -n "$before" ] && [ "$now" != "$before" ] \
    && notify "Alles in orde $(hostname -s)" "Alle controles zijn weer zonder bevindingen."
  exit 0
fi

[ "$now" = "$before" ] && exit 0
notify "Waarschuwing $(hostname -s)" "$problems"
EOF

Vier plekken verdienen een toelichting.

  • De lussen lezen uit < <( ... ) en niet uit een pipe. Een pipe verplaatst de lus naar een subshell, en de daar verzamelde meldingen zouden na de done verdwenen zijn. Die fout is verraderlijk, want het script loopt foutloos door en meldt alleen nooit iets.
  • De drempels komen uit de omgeving. U kunt elke grens voor één enkele aanroep overschrijven. Daarop berust de alarmtest verderop.
  • De status wordt als checksum opgeslagen. Er komt alleen een melding wanneer de lijst met problemen is veranderd. Anders stuurt een volle schijf u elke tien minuten hetzelfde bericht, en zet u de monitoring na twee dagen uit.
  • De certificaatlus loopt leeg wanneer er geen Let's Encrypt-map bestaat. Het patroon blijft onopgelost, [ -r "$cert" ] mislukt en de doorloop wordt overgeslagen.

Controleer nu, voordat systemd in beeld komt:

chmod 700 /usr/local/sbin/kh-monitor
bash -n /usr/local/sbin/kh-monitor && echo "syntaxis ok"
/usr/local/sbin/kh-monitor; echo "Exitcode $?"

Op een gezonde server geeft het derde commando niets terug behalve Exitcode 0. Ziet u een melding, dan is er ofwel iets niet in orde, ofwel klopt een drempel niet, bijvoorbeeld doordat in UNITS een dienst staat die hier niet bestaat.

De systemd-timer

Een cronjob zou het ook doen. Een timer heeft echter vier concrete voordelen: hij start geen tweede exemplaar zolang het eerste draait, hij haalt een gemiste run na een herstart alsnog in, zijn uitvoer belandt in het journal, en hij is met één commando uit te schakelen. De dienst-unit heeft geen [Install]-sectie nodig, omdat ze niet bij de systeemstart maar door de timer wordt geactiveerd.

cat > /etc/systemd/system/kh-monitor.service <<'EOF'
[Unit]
Description=Korte statuscontrole van de server
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/kh-monitor
EnvironmentFile=-/etc/default/kh-monitor
StateDirectory=kh-monitor
SyslogIdentifier=kh-monitor
Nice=10
IOSchedulingClass=idle
EOF
cat > /etc/systemd/system/kh-monitor.timer <<'EOF'
[Unit]
Description=Voert kh-monitor regelmatig uit

[Timer]
OnCalendar=*:0/10
RandomizedDelaySec=60
Persistent=true

[Install]
WantedBy=timers.target
EOF

StateDirectory=kh-monitor maakt /var/lib/kh-monitor met de juiste rechten aan en zet de variabele STATE_DIRECTORY waar het script op teruggrijpt. Het minteken vooraan in EnvironmentFile=-/etc/default/kh-monitor betekent dat een ontbrekend bestand geen fout is. RandomizedDelaySec=60 spreidt het starttijdstip, en Persistent=true haalt een run die tijdens een uitschakeling is gemist bij het opstarten alsnog in.

De timer activeert de gelijknamige dienst automatisch, een Unit=-regel is niet nodig:

systemd-analyze verify /etc/systemd/system/kh-monitor.service
systemd-analyze calendar '*:0/10'
systemctl daemon-reload
systemctl start kh-monitor.service
systemctl enable --now kh-monitor.timer

Controle:

systemctl list-timers kh-monitor.timer --no-pager
journalctl -u kh-monitor.service -n 20 --no-pager

De lijst moet een regel met het volgende uitvoertijdstip tonen. Blijft ze leeg, dan is de timer niet actief. systemd-analyze calendar vindt typefouten in de tijdsuitdrukking: het rekent die om naar een normaalvorm en noemt de eerstvolgende keer. Details over unit-bestanden en hun foutbeelden staan in systemd-service aanmaken.

Het meldingskanaal

Hier lopen de meeste zelfgebouwde monitoringopzetten vast. De melder draait op de server die hij bewaakt en valt dus met die server uit. Daarmee meldt hij alles betrouwbaar, behalve dat ene geval dat werkelijk telt.

Het antwoord heet dodemansknop: de server meldt zich na elke geslaagde run bij een externe dienst, en blijft die melding uit, dan slaat die dienst alarm. Het script hierboven doet dat wanneer HEARTBEAT_URL is ingesteld. Een netwerkstoring, een vastgelopen bestandssysteem en een gecrasht systeem zien er voor die dienst hetzelfde uit, en over alle drie wilt u bericht krijgen.

De toegangsgegevens horen in een eigen bestand en niet in het script. Een webhookadres is een geheim: wie het heeft, kan in uw naam berichten versturen:

cat > /etc/default/kh-monitor <<'EOF'
WEBHOOK_URL=https://voorbeeld.example/hooks/xxxxxxxx
HEARTBEAT_URL=https://voorbeeld.example/heartbeat/xxxxxxxx
UNITS="ssh nginx"
EOF
chmod 600 /etc/default/kh-monitor

De aanhalingstekens om UNITS zijn belangrijk: systemd zou het ook zonder redden, maar bij de testrun verderop wordt het bestand door de shell ingelezen, en daar zou nginx zonder aanhalingstekens als commando worden opgevat. Vul alleen units in die op dit systeem bestaan, op Ubuntu 24.04 dus ssh.socket in plaats van ssh.

Wie e-mail verkiest, heeft een verzendroute nodig. Een volwaardige mailserver is overdreven, een eenvoudige doorstuurder volstaat:

apt install -y msmtp msmtp-mta bsd-mailx

Configureren doet u dat in /etc/msmtprc met de inloggegevens van een bestaande mailbox. Dat bestand bevat een wachtwoord en hoort op chmod 600 te staan, anders weigert msmtp dienst met een verwijzing naar de bestandsrechten. Twee eerlijke beperkingen: e-mail vanaf een net toegewezen IP-adres van een server belandt vaak in de spammap of wordt geweigerd, en een bericht dat u pas ziet bij de volgende blik in uw mailbox, is bij een storing te traag. Voor alarmen is pushbezorging de praktischere keuze.

Het alarm één keer laten afgaan

Deze stap is niet optioneel. Forceer een melding door een drempel voor één enkele aanroep onzinnig te zetten:

set -a; . /etc/default/kh-monitor; set +a
DISK_WARN=0 /usr/local/sbin/kh-monitor
rm -f /var/lib/kh-monitor/last

Het bericht moet nu daadwerkelijk bij u aankomen en niet alleen in het journal staan. De derde regel wist de opgeslagen status, zodat het testalarm de eerstvolgende echte run niet onderdrukt. Eén bijwerking is opzet: mislukt de bezorging, dan eindigt kh-monitor.service met een fout en duikt hij op in systemctl --failed. Een stil meldingskanaal zou de ergst denkbare fout in een monitoringopzet zijn.

Het beeld van buitenaf

De dodemansknop vertelt u dat de server leeft. Hij vertelt niet dat uw website antwoordt. Daarvoor is een controle vanaf een andere locatie nodig, met hetzelfde patroon van script en timer, alleen op een tweede host:

curl -fsS -m 10 -o /dev/null -w '%{http_code} %{time_total}\n' https://example.com/

Vier punten bepalen de waarde van deze controle. Ten eerste: controleer de echte dienst, niet alleen ICMP. Een server die op ping antwoordt terwijl de webserver in een oneindige lus hangt, geldt bij een pingcontrole als gezond. Ten tweede: -f laat curl mislukken bij HTTP-foutcodes, zonder die schakelaar telt ook een foutpagina als succes. Ten derde: alarmeer pas na twee mislukkingen op rij, anders meldt elke korte netwerkhapering een uitval. Ten vierde: een aanroep die elke minuut vanaf hetzelfde adres komt, kan in een rate limiting belanden of door blokkeersoftware als aanval worden gezien; zet het adres van de controlerende host daarom als uitzondering in de lijst.

Zonder tweede server blijft een gehoste controledienst over. Gratis aanbieders controleren meestal om de vijf minuten, dus verneemt u een uitval met evenveel vertraging. Voor één enkele server volstaat dat, en het is beter dan het alternatief: het helemaal niet te weten komen.

Veelvoorkomende fouten en oplossingen

Failed to start kh-monitor.service: Unit kh-monitor.service not found.: na het aanmaken of wijzigen van een unit ontbreekt systemctl daemon-reload. Op één na meest voorkomende oorzaak is een verkeerde map; eigen units horen in /etc/systemd/system/.

The unit files have no installation config: u hebt systemctl enable kh-monitor.service aangeroepen in plaats van kh-monitor.timer. De dienst heeft bewust geen [Install]-sectie, geactiveerd wordt de timer.

code=exited, status=203/EXEC: systemd kon het bestand niet uitvoeren. Of het pad in ExecStart klopt niet, of chmod 700 ontbreekt, of het bestand is onder Windows bewerkt en draagt regeleindes met een regelterugloopteken. Daartegen helpt sed -i 's/\r$//' /usr/local/sbin/kh-monitor.

Syntax error: redirection unexpected: het script is met sh in plaats van bash gestart. Onder Debian en Ubuntu is /bin/sh de shell dash, en die kent noch < <( ... ) noch += bij tekenreeksen. De eerste regel moet #!/bin/bash zijn.

bash: mail: command not found: er is geen mailprogramma geïnstalleerd. Het commando mail komt afhankelijk van het systeem uit bsd-mailx of mailutils, en die twee verschillen in hun schakelaars. Houd het op -s voor het onderwerp.

curl: (22) The requested URL returned error: 404: het webhookadres klopt niet of is aan de andere kant verwijderd. Zonder -f had curl die fout stilzwijgend ingeslikt.

curl: (60) SSL certificate problem: certificate has expired: bij de controle van buitenaf geen gereedschapsfout, maar precies de bevinding die u zocht. Tegen de eigen webhook wijst dezelfde melding op een verkeerde klok van de controlerende server.

Certificate will expire: normale uitvoer van openssl x509 -checkend met exitcode 1. Controleer of de verlenging nog loopt en of de webserver daarna opnieuw wordt geladen.

Failed to parse calendar specification: de uitdrukking achter OnCalendar= is ongeldig. Test die apart met systemd-analyze calendar voordat hij in de unit belandt.

Warning: Stopping kh-monitor.service, but it can still be activated by: kh-monitor.timer: u hebt de dienst gestopt in plaats van de timer. De dienst draait toch al maar enkele seconden, uit te schakelen is de timer.

Alarm bij elke run, terwijl er niets is veranderd: de status wordt niet opgeslagen. Controleer of StateDirectory=kh-monitor in de unit staat en of /var/lib/kh-monitor/last bestaat en beschrijfbaar is.

Geen alarm, terwijl er duidelijk iets kapot is: laat de geforceerde melding van hierboven afgaan. Blijft ook die uit, dan ligt het aan het bezorgkanaal en niet aan de controles.

Verschillen tussen de vier systemen

SysteemSSH-unit die u moet bewakensquashfs-mountpointsWaar de meldingen belanden
Debian 13 (trixie)ssh.service, losse images gebruiken ssh.socketin de regel geenalleen journal, rsyslog ontbreekt in minimale installaties
Debian 12 (bookworm)ssh.servicein de regel geenjournal, rsyslog afhankelijk van de installatievariant
Ubuntu 24.04 LTSssh.socketmeestal aanwezig, uitsluiten nodigjournal en rsyslog
Ubuntu 22.04 LTSssh.servicemeestal aanwezig, uitsluiten nodigjournal en rsyslog

Op alle vier de systemen gelijk: systemd-analyze, StateDirectory= en RandomizedDelaySec= zijn aanwezig, en het script en de unit-bestanden draaien ongewijzigd.

Wanneer de grote gereedschapskist de moeite waard is

Wat u nu hebt, kent duidelijke grenzen. Het bewaart geen historie, dus u kunt niet nakijken of het geheugengebruik al drie weken stijgt. Het kent geen correlatie over meerdere hosts. En het heeft geen escalatie, geen regels voor de wachtdienst en geen mogelijkheid om een bekend alarm twee uur lang te dempen.

Precies die punten beantwoorden de vraag naar de overstap. Een opzet met metrics en dashboard loont zodra een van deze punten opgaat:

  • U beheert meer dan een handvol servers en wilt ze naast elkaar zien.
  • U hebt historie en trends nodig, bijvoorbeeld voor capaciteitsplanning of om een klacht over traagheid met cijfers te pareren.
  • Meerdere mensen delen de wachtdienst, dus zijn er escalatieniveaus en een dempfunctie nodig.
  • U moet de beschikbaarheid tegenover derden aantonen.

Gaat niets daarvan op, dan is die opzet voor één enkele server meestal een slechte deal. Het verzamelpunt, de database, het dashboard en de exporter nemen samen al gauw enkele honderden megabytes werkgeheugen in beslag, en wel op precies de machine waarvan ze het vrije geheugen moeten bewaken. Daar komen nog een extra open poort bij en een tweede stuk software dat bijgewerkt wil worden. Het beslissende punt blijft hetzelfde: draait het verzamelpunt op dezelfde server, dan meldt het de uitval daarvan net zomin als een script. Bij een overstap hoort het verzamelpunt op een andere host, en de exporter bindt zich aan 127.0.0.1 of is via de firewall beperkt tot het adres van dat verzamelpunt.

De tussenweg werkt goed: de timer en het script blijven staan omdat ze het alarmgeval afdekken, en de opzet met metrics komt erbij zodra u historie nodig hebt. Het een sluit het ander niet uit.

Terugdraaien

Wilt u de hele opzet weer kwijt, dan zijn het vijf regels:

systemctl disable --now kh-monitor.timer
rm -f /etc/systemd/system/kh-monitor.timer /etc/systemd/system/kh-monitor.service
rm -f /usr/local/sbin/kh-monitor /etc/default/kh-monitor
rm -rf /var/lib/kh-monitor
systemctl daemon-reload

De eindcontrole

Zes controles die de werkelijke toestand laten zien en niet de gehoopte:

  1. systemctl list-timers kh-monitor.timer --no-pager noemt een volgend uitvoertijdstip.
  2. journalctl -u kh-monitor.service --since "1 hour ago" --no-pager toont runs met de verwachte tussenpozen.
  3. Een geforceerd alarm via DISK_WARN=0 komt bij u aan, niet alleen in het journal.
  4. Na een reboot draait de timer gewoon door, zonder dat u er iets voor hoeft te doen.
  5. De dodemansknop laat van zich horen: stop de timer en wacht af of de externe dienst alarm slaat.
  6. systemctl --failed --no-pager somt niets op, en zeker niet kh-monitor.service.

Punt vijf is het lastigste en het belangrijkste. Monitoring waarvan het alarmgeval zich nooit heeft voorgedaan, is een aanname. Pas wanneer u de uitval bewust hebt veroorzaakt en het bericht hebt ontvangen, is de keten van de server tot aan uw telefoon aantoonbaar compleet.

Veelgestelde vragen

Heb ik voor één enkele rootserver echt een metrics-server met dashboard nodig?
In de meeste gevallen niet. Het verzamelpunt, de database, het dashboard en de exporter nemen samen al gauw enkele honderden megabytes werkgeheugen in beslag op precies de machine waarvan ze het vrije geheugen moeten bewaken, en ze brengen een extra open poort mee plus een tweede stuk software dat bijgewerkt moet worden. Een controlescript met systemd-timer dekt het alarmgeval volledig af. De grote opzet wordt zinvol zodra u meerdere servers naast elkaar wilt zien, historie nodig hebt voor capaciteitsplanning, meerdere mensen de wachtdienst delen of u de beschikbaarheid tegenover derden moet aantonen.
Waarom een systemd-timer en geen cronjob?
Allebei werken ze. De timer heeft vier praktische voordelen: hij start geen tweede exemplaar zolang het eerste nog draait, hij haalt met Persistent=true een run die tijdens een uitschakeling is gemist bij het opstarten alsnog in, zijn uitvoer belandt via SyslogIdentifier automatisch in het journal, en hij is met systemctl disable --now kh-monitor.timer in één commando uit te schakelen. Geactiveerd wordt altijd de timer en niet de dienst: de dienst-unit heeft bewust geen [Install]-sectie.
Mijn monitoring meldt permanent een volle schijf, terwijl er genoeg vrij is. Hoe komt dat?
Bijna altijd door de mountpoints van snap. Onder Ubuntu 22.04 en 24.04 worden snap-pakketten aangekoppeld als alleen-lezen squashfs-images, en die staan uit hun aard permanent op 100 procent. Sluit ze uit, dus df --output=pcent,target -x tmpfs -x devtmpfs -x squashfs -x overlay. Hetzelfde geldt voor de overlay-mountpoints van Docker. Tweede mogelijke oorzaak: op ext4 is standaard vijf procent voor root gereserveerd, waardoor df al 100 procent kan melden terwijl root nog kan schrijven.
Hoe kom ik te weten dat de server helemaal is uitgevallen?
Niet via een script op die server, want dat valt mee uit. Daarvoor zijn er twee wegen die elkaar aanvullen. De dodemansknop: de server meldt zich na elke geslaagde run bij een externe dienst, en blijft die melding uit, dan slaat die dienst alarm. En de controle van buitenaf: een tweede host of een gehoste controledienst die de echte dienst opvraagt en niet alleen ICMP. Gratis controlediensten werken meestal om de vijf minuten, dus verneemt u een uitval met evenveel vertraging.
Welke SSH-unit moet ik bewaken?
Dat verschilt per distributie. Onder Ubuntu 24.04 wordt SSH via socketactivering gestart, daar staat ssh.service in rust op inactive terwijl SSH prima bereikbaar is. Wie daar ssh.service bewaakt, krijgt een permanent vals alarm; te bewaken is ssh.socket. Op Debian 12, Debian 13 en Ubuntu 22.04 is het andersom, daar geldt ssh.service. Losse Debian 13-images hebben echter eveneens ssh.socket actief, controleer dat met systemctl is-enabled ssh.socket.
Hoe voorkom ik dat ik elke tien minuten dezelfde waarschuwing krijg?
Met een statusbestand. Het script maakt van de lijst met gevonden problemen een checksum, legt die neer in /var/lib/kh-monitor/last en meldt alleen wanneer die checksum ten opzichte van de vorige run is veranderd. Verdwijnt een probleem, dan komt er eenmalig een bericht dat alles weer in orde is. Krijgt u toch bij elke run een bericht, dan ontbreekt in de unit de regel StateDirectory=kh-monitor, of het bestand is niet beschrijfbaar.
Het certificaat op de schijf is geldig, toch zien bezoekers een waarschuwing. Hoe kan dat?
Omdat de bestandscontrole en het uitgeleverde certificaat twee verschillende dingen zijn. Loopt de automatische verlenging door maar mislukt de reload van de webserver, dan is het bestand nieuw en de uitgeleverde sleutel oud. openssl x509 -checkend meldt dan niets. Controleer daarom aanvullend van buitenaf met openssl s_client -connect example.com:443 -servername example.com. De toevoeging -servername is niet optioneel zodra er meerdere certificaten op één IP-adres liggen.
Hoe schakel ik de monitoring snel weer uit als ze stoort?
Met systemctl disable --now kh-monitor.timer: dat stopt de timer onmiddellijk en verhindert dat hij bij de volgende start terugkomt. Als noodrem verhindert systemctl mask kh-monitor.service daarnaast elke start met de hand, ongedaan te maken met systemctl unmask. Volledig verwijderen doet u door de twee unit-bestanden, het script in /usr/local/sbin/, het bestand /etc/default/kh-monitor en de map /var/lib/kh-monitor te wissen, gevolgd door systemctl daemon-reload. Bestaande configuratie blijft daarbij onaangeroerd, omdat er uitsluitend nieuwe bestanden zijn aangemaakt.

Monitoring systemd Linux Debian Ubuntu Rootserver Serverbewaking Bash