Let op: Tweakers stopt per 2023 met Tweakblogs. In
dit artikel
leggen we uit waarom we hiervoor hebben gekozen.
Let’s Encrypt - En waarom het renewen maar niet werkte…
Even een klein verhaaltje over mijn ervaringen met certbot, het automagische tooltje om Let's Encrypt te installeren op je server. Ik heb best prima ervaringen met certbot. Even uitvoeren, en na een seconde of 10 zijn de SSL certificaten volledig automatisch geinstalleerd op je Apache of Nginx installatie. So far so good...
Omdat je certificaten niet eeuwig geldig zijn, wil je ze af en toe verversen. Dit wil je natuurlijk niet met de hand doen. Dus zoals je in vrijwel elke guide terug zal kunnen vinden, is dat je het certbot renew commando eenvoudig als cronjob in kunt stellen.
Crontab instellen
Dus, ik crontab -e gebruiken om in mijn favoriete editor een regel aan te maken:
Zo. Klaar is kees. Iedere nacht, om 3.15u wordt dit commando uitgevoerd, en zal er heel stilletjes een renewal worden uitgevoerd. Nooit meer naar omkijken dacht ik...
Nope nope nope
Helaas kwamen we er op een zekere dag achter dat de certificaten verliepen. Natuurlijk kwam de klant er net iets eerder achter dan wijzelf en waren alle browsers in rep en roer. Snel inloggen met SSH, en even certbot renew uitvoeren. Hoppa. Gefixt. Alles werkte weer. Maar automatisch via de cronjob vernieuwen, ho maar...
Debuggen
Ok, dan maar even wat langer uitzoeken waarom de certificaten niet automatisch werden ververst. Eerst even checken of de cron-regel juist was. Met https://crontab.guru even gekeken, en dat leek in orde.
Vervolgens gecheckt of de cron-regels uitgevoerd werden. Daarvoor heb ik een regel aangemaakt die elke minuut een bestandje 'aanraakt'. Middels de timestamp is dan snel af te leiden of het werkte. En ja, dat werkte wel.
Logboeken
Next step, logs checken. Eerst maar eens in /var/log/cron kijken:
En voila, hij wordt wel uitgevoerd. Maar hij doet het niet?!
Op internet lees ik dat de output van de cronregels niet worden gelogd, maar standaard aan de uitvoerende gebruiker worden 'gemailt'. In de inbox /var/spool/mail/root van de root gebruiker las ik toen:
Het nginx commando kon niet worden gevonden... Nginx is natuurlijk wel geinstalleerd, en wel hier: /usr/sbin/nginx, dus het zou waarschijnlijk iets met het PATH te maken hebben.
Terug naar de crontab
Toen ik in /etc/crontab keek, de algemene system-wide crontab, stonden daar bovenin de file daar wel het juiste pad!
Ik leerde uiteindelijk dat wanneer je via crontab -e een cronjob insteld, je deze als user instelt. Zelfs al ben je root. Dus crontab -e zal alleen voor de ingelogde gebruiker een cronjob instellen.
Het blijkt dat de user cronjobs worden opgeslagen in de /var/spool/cron/ map. Toen ik uiteindelijk er achter kwam dat wanneer er geen settings worden opgegeven, de user-cronjobs een standaard PATH van /usr/bin:/bin hebben, had ik eindelijk mijn antwoord...
Conclusie
Kortom: Stel je cronjobs in via crontab -e check dan ook even of je gewenste commando - of het commando die daaruit voortvloeit, zoals in een script als certbot - wel vanuit het default PATH bereikt kunnen worden. Zo niet, stel dan het gewenste PATH in bovenaan in je user crontab.
Ps: Ik kwam erachter dat --post-hook "systemctl reload nginx" ook wel handig is, zodat je webserver de nieuwe certificaten ook daadwerkelijk reload
Ps2: Bovengenoemde voorbeelden komen van een CentOS 7 distro.
Omdat je certificaten niet eeuwig geldig zijn, wil je ze af en toe verversen. Dit wil je natuurlijk niet met de hand doen. Dus zoals je in vrijwel elke guide terug zal kunnen vinden, is dat je het certbot renew commando eenvoudig als cronjob in kunt stellen.
Crontab instellen
Dus, ik crontab -e gebruiken om in mijn favoriete editor een regel aan te maken:
15 3 * * * /usr/bin/certbot renew --quiet
Zo. Klaar is kees. Iedere nacht, om 3.15u wordt dit commando uitgevoerd, en zal er heel stilletjes een renewal worden uitgevoerd. Nooit meer naar omkijken dacht ik...
Nope nope nope
Helaas kwamen we er op een zekere dag achter dat de certificaten verliepen. Natuurlijk kwam de klant er net iets eerder achter dan wijzelf en waren alle browsers in rep en roer. Snel inloggen met SSH, en even certbot renew uitvoeren. Hoppa. Gefixt. Alles werkte weer. Maar automatisch via de cronjob vernieuwen, ho maar...
Debuggen
Ok, dan maar even wat langer uitzoeken waarom de certificaten niet automatisch werden ververst. Eerst even checken of de cron-regel juist was. Met https://crontab.guru even gekeken, en dat leek in orde.
Vervolgens gecheckt of de cron-regels uitgevoerd werden. Daarvoor heb ik een regel aangemaakt die elke minuut een bestandje 'aanraakt'. Middels de timestamp is dan snel af te leiden of het werkte. En ja, dat werkte wel.
* * * * * touch /root/crony-to-my-pony
Logboeken
Next step, logs checken. Eerst maar eens in /var/log/cron kijken:
Aug 20 03:01:01 lb1 run-parts(/etc/cron.hourly)[2870]: finished 0anacro Aug 20 03:15:01 lb1 CROND[3008]: (root) CMD (/usr/bin/certbot renew --quiet) Aug 20 03:43:01 lb1 anacron[2868]: Job `cron.daily' startedn
En voila, hij wordt wel uitgevoerd. Maar hij doet het niet?!
Op internet lees ik dat de output van de cronregels niet worden gelogd, maar standaard aan de uitvoerende gebruiker worden 'gemailt'. In de inbox /var/spool/mail/root van de root gebruiker las ik toen:
Attempting to renew cert (domein-van-onze-klant.nl) from /etc/letsencrypt/renewal/domein-van-onze-klant.nl.conf produced an unexpected error: The nginx plugin is not working; there may be problems with your existing configuration
The error was: NoInstallationError("Could not find a usable 'nginx' binary. Ensure nginx exists, the binary is executable, and your PATH is set correctly.",). Skipping.
All renewal attempts failed. The following certs could not be renewed:
/etc/letsencrypt/live/domein-van-onze-klant.nl/fullchain.pem (failure)
1 renew failure(s), 0 parse failure(s).
Het nginx commando kon niet worden gevonden... Nginx is natuurlijk wel geinstalleerd, en wel hier: /usr/sbin/nginx, dus het zou waarschijnlijk iets met het PATH te maken hebben.
Terug naar de crontab
Toen ik in /etc/crontab keek, de algemene system-wide crontab, stonden daar bovenin de file daar wel het juiste pad!
SHELL=/bin/bash PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root
Ik leerde uiteindelijk dat wanneer je via crontab -e een cronjob insteld, je deze als user instelt. Zelfs al ben je root. Dus crontab -e zal alleen voor de ingelogde gebruiker een cronjob instellen.
Het blijkt dat de user cronjobs worden opgeslagen in de /var/spool/cron/ map. Toen ik uiteindelijk er achter kwam dat wanneer er geen settings worden opgegeven, de user-cronjobs een standaard PATH van /usr/bin:/bin hebben, had ik eindelijk mijn antwoord...
Conclusie
Kortom: Stel je cronjobs in via crontab -e check dan ook even of je gewenste commando - of het commando die daaruit voortvloeit, zoals in een script als certbot - wel vanuit het default PATH bereikt kunnen worden. Zo niet, stel dan het gewenste PATH in bovenaan in je user crontab.
PATH=/sbin:/bin:/usr/sbin:/usr/bin 15 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
Ps: Ik kwam erachter dat --post-hook "systemctl reload nginx" ook wel handig is, zodat je webserver de nieuwe certificaten ook daadwerkelijk reload
Ps2: Bovengenoemde voorbeelden komen van een CentOS 7 distro.