Eind 2025 kwam ik tot de conclusie dat ik onder andere door studie te weinig tijd heb besteed aan de zaken die "eigenlijk" voor mij op de planning stonden. Dus begin 2026 ben ik begonnen om daar serieuzer mee aan de slag te gaan.
Een (mooi Nederlands woord) -gamechanger- daarbij was dat ik dacht: als ik nu zaken ga combineren, dan staat het misschien als 4 uren op de planning, maar kan ik dat in 1 uur doen. Daar is dit blog één van de voorbeelden van.
Zo staat er elke maandagavond voor mij "1 uur Zabbix" op de planning. Op vrijdagavond "1 uur zaken automatiseren", op vrijdagavond "1 uur techblog" en op zondag "1 uur code project". Op al die zaken ga ik nu een uur boeken, want ik vind dat ik ze hiermee wel combineer.
Ik heb wel eens naar "life-hacks" gekeken. Herhalende taken zou je moeten automatiseren, want als je elke dag 5 minuten met iets bezig bent, dan ben je per jaar daar iets meer dan 30 uur aan kwijt. Elke avond kijk ik op mijn wiki-pagina of er ook mensen jarig zijn. Dat kan ik (pas) bekijken als ik ingelogd ben. Dus ik zit nu al op de 2e pagina. Dan naar beneden naar de huidige datum scrollen. Vervolgens op Facebook even feliciteren, klaar.
Soms zitten er ook mensen "niet meer op Facebook", dus geen felicitatie te versturen. Of er is op een dag niemand jarig.
1. wiki inrichten voor toegang
Standaard is een wiki "open". Iedereen kan lezen wat er op staat. Maar verjaardagen van kennissen, daar heeft niemand wat mee te maken. Ik heb dat in het verleden met een "quick fix" opgelost door in het begin van een pagina de tag [GEHEIM] te zetten. In LocalSettings.php (het is een WikiMedia wiki) staat deze code:
# hide [GEHEIM] pages for non-logged-in users
$wgHooks['BeforePageDisplay'][] = 'hnp_beforePageDisplay';
function hnp_beforePageDisplay( $out ) {$user = $out->getUser();
if (strpos("_" . $out->getHTML(), "[GEHEIM]") > 0){
if ($user->mId <= 0){
header("Location: /");
exit;
}
}
else{}
return true;
}
Het is niet helemaal "fool-proof", bij het zoeken kun je volgens mij nog wel bepaalde zaken deels bekijken, maar over het algemeen geldt: "alleen als je ingelogd bent, kun je de pagina bekijken".
Daar wil ik nu aan toevoegen dat mij Zabbix-agent ook bij deze pagina moet kunnen komen. Dat doe ik door in de header een X-API-KEY header met een bepaalde waarde mee te sturen. Als die header meegestuurd wordt en de waarde is correct, dan tonen we de pagina, anders voeren we de redirect uit.
# hide [GEHEIM] pages for non-logged-in users and when trying to fetch with invalid API key
$wgHooks['BeforePageDisplay'][] = 'hnp_beforePageDisplay';
function hnp_beforePageDisplay( $out ) {
$headers = RequestContext::getMain()->getRequest()->getAllHeaders();
$validPostedApiKey = $headers["X-API-KEY"] != null && trim($headers["X-API-KEY"]."") == "RandomNietTeRadenWaarde";
$user = $out->getUser();if (strpos("_" . $out->getHTML(), "[GEHEIM]") > 0){
if ($user->mId > 0 || $validPostedApiKey){
return true;
}
header("Location: /");
exit;
}
return true;
}
Dit werkt.
2. data opvragen vanuit Zabbix
Met UserParameters kun je scripts uitvoeren bij Zabbix-items. Ik heb dit al eens gebruikt met een script om te bepalen wanneer een SLL-certificaat verloopt, nu moet ik de opvraagde data "parsen" om zo de verjaardagen eruit te filteren. Want ik zit er ook nog mee dat de Zabbix Docker container Engels is, terwijl ik de datums als Nederlandse datums noteeer (1 januari, 26 maart). Ik heb lokaal op mijn Windows-laptop WLS actief, dus ik kan daar eerst al zaken in gaan testen. Uiteindelijk is dit het script geworden:
#!/bin/bash
data=$(curl -G -H "X-API-KEY: RandomNietTeRadenWaarde" https://mijnwikidomein.nl/index.php?title=Birthday 2>/dev/null)
month=$(date +%m)
day=$(date +%-d)
if [ $month == "01" ]
then
monthName="januari"
elif [ $month == "02" ]
then
monthName="februari"
elif [ $month == "03" ]
then
monthName="maart"
elif [ $month == "04" ]
then
monthName="april"
elif [ $month == "05" ]
then
monthName="mei"
elif [ $month == "06" ]
then
monthName="juni"
elif [ $month == "07" ]
then
monthName="juli"
elif [ $month == "08" ]
then
monthName="augustus"
elif [ $month == "09" ]
then
monthName="september"
elif [ $month == "10" ]
then
monthName="oktober"
elif [ $month == "11" ]
then
monthName="november"
elif [ $month == "12" ]
then
monthName="december"
else
monthName="onbekende maand"
fi
birthdays=$( echo "$data" | grep -oE "(.*)$day $monthName(.*)" )
output=""
while read n; do
#echo "$n"
trimmed=$(echo $n | sed -e 's/<[^>]*>//g')
trimmed=$(echo $trimmed | grep -oE "^$day $monthName(.*)")
if [ ${#trimmed} -gt 0 ]; then
if [ ${#output} -gt 0 ]; then
output="$output, $trimmed"
else
output="$trimmed"
fi
fi
done <<< "$birthdays"
echo $output
Lokaal gaat het goed, op mijn VPS nog niet. Blijkt dat in de Docker-container geen cURL geïnstalleerd is. Easy fix met apk add curl
Nu moeten we het script nog toevoegen aan de User parameters.
Ik heb in /etc/zabbix/zabbix_agentd_user_parameters.conf de volgende regel toegevoegd:
UserParameter=retrieve_birthdays,/etc/zabbix/scripts/retrieve_birthdays.sh
Op de "manier zoals het zou horen om parameters te herladen", dat werkt bij mij niet, dus de container via Plesk herstart.
3. item en trigger voor notificatie
Ik voeg het domein toe als host (via Data Collection, Hosts).
Vervolgens maak ik daar een item aan:
Name: Birthdays
Type: Zabbix agent
Key: retrieve_birthdays (dat moet de naam van de User Parameter zijn)
Type of information: Text
Host interface: IP:10050 van de agent
Update interval: 4h
Custom intervals: Flexible, interval: 4h, period: 1-7,07:00-16:00
Die "custom interval" is voor mij nieuw, bij het opvragen van data doen we eigenlijk altijd "om de zoveel tijd", met deze configuratie overschrijf je dat en zeg je: elke dag (1-7), tussen 7.00 en 16.00 uur, check het elke 4 uur, wat dus zou betekenen dat om 7.00, 11.00 en 15.00 de check uitgevoerd wordt.
Dat gaat bij mij niet goed. Elke 4 uur wordt de data opgevraagd. Volgens deze pagina hebben meer mensen daar problemen mee. Ik heb de Update interval nu maar op 0 gezet...
Met de knop "Test" en in het volgende scherm Get Value and Test kun je controleren of je de goede waarde binnen krijgt.
Dat gaat bij mij goed.
Ik wil via Telegram een notificatie ontvangen, dus ik moet een trigger aanmaken. Het is even zoeken "hoe" ik die slim kan activeren, door te testen kom ik op deze configuratie uit:
Name: Birthday Today
Severity: Information
Expression:
length(last(/mijnwikidomein.nl/retrieve_birthdays,#1))>0and
change(/mijnwikidomein.nl/retrieve_birthdays)=1
Ik zal de expressie even toelichten, op het moment dat we tekst terug krijgen, zijn er mensen jarig.
Dus length(..) > 0 moet dat activeren.
Stel dat dit op 1 januari gebeurt. Dan wordt het 2 januari.
Er zijn andere mensen jarig, ook die data krijgen we binnen.
Maar omdat de trigger al in "probleem-status" staat, wordt er geen melding naar Telegram gestuurd.
Hier komt de "change"-check om de hoek kijken.
Op 1 januari gaat ie in de "probleem status".
Maar als na 4 uur de data opgevraagd wordt, krijgen we dezelfde lijst met jarigen terug.
Op dat moment is de huidige data gelijk aan de data van de vorige check (geen change) en springt de trigger dus in de "OK"-status.
Nu zal hij de volgende dag, als er data is, weer in de "probleem status" schieten en mij een bericht sturen.
Ook voeg ik nog een tweede trigger toe, namelijk als er "geen verjaardag is". Want als je geen bericht krijgt, dan is de vraag: is er niemand jarig, of ligt je Zabbix-installatie plat?
Name: No Birthday Today
Severity: Information
Expression:length(last(/wiki.durkotheek.nl/retrieve_birthdays,#1))=0
and
change(/wiki.durkotheek.nl/retrieve_birthdays)=1
4. bericht via Telegram
In Zabbix heb je bij Alerts, Media types het type "Telegram", dat wijst zich verder vanzelf.
Bij Alerts, Actions, Trigger actions voeg ik een nieuw type toe. Bij conditions selecteer ik de host-groepen en Trigger severity: Information. Bij het tabblad operations voeg ik bij operations het versturen van een bericht naar mijn account. Bij "Recovery operations" voeg ik niets toe. Als de waarde weer "leeg" geworden is, dat interesseert mij niet, dit type "alert", daar wil je alleen een bericht van op het moment dat deze getriggerd wordt.