45-day certificates: automating renewal and alerts before expiry
Guide with certbot commands on Ubuntu 24.04 + Nginx and independent expiry check scripts, calibrated to Let's Encrypt's 45-day timeline.
UptimeMag editorial team · 15 October 2026 · 4 min read

As of 15 October 2026, certificates issued by Let's Encrypt are still valid for 90 days. But the countdown to 45 days is already marked on the official calendar, and anyone managing servers needs to tune automatic renewal and alerts to that deadline, not the current one. This guide covers certbot on Ubuntu 24.04 LTS with Nginx: system timers, verification, and an expiry check that doesn't depend on the ACME client.\n\n## The calendar that matters\n\nAccording to the official Let's Encrypt blog, Let's Encrypt is reducing certificate validity: currently 90 days, which will be halved to 45 days by 2028.\n\n| Date | Change | Authorisation reuse |\n|---|---|---|\n| 13 May 2026 | tlsserver profile opt-in to 45 days (early adopter) | unchanged, 30 days |\n| 10 February 2027 | classic profile default to 64 days | 10 days |\n| 16 February 2028 | classic profile default to 45 days | 7 hours |\n\nThe dates are confirmed by the official post: on 13 May 2026 Let's Encrypt will move the ACME tlsserver profile to 45-day certificates, an opt-in profile for those who want to test automation early; on 16 February 2028 the classic profile will issue 45-day certificates with an authorisation reuse period of 7 hours. Those currently using the shortlived profile already work with 6-day certificates: the move to 64 days will affect all users who haven't chosen the tlsserver or shortlived profiles (6 days).\n\nThe practical reason: over the next two years, the shift from 90 to 64 and then to 45 days will double the number of renewal requests per day; today renewal is expected around day 60 of a 90-day certificate, in future around day 30 of a 45-day one. With an ACME client that supports ARI this happens automatically.\n\n## Automatic renewal with certbot on Ubuntu 24.04 + Nginx\n\nThe certbot package installed from repository or snap creates the renewal mechanism by itself. Verify it like this:\n\n\nsystemctl list-timers --all | grep certbot\nsystemctl status certbot.timer\n\n\nOn RHEL and derivatives, though the scheme applies to Ubuntu as well, the system timer runs twice a day and on each execution certbot checks all managed certificates and renews those within 30 days of expiry.\n\nBefore trusting the automation, test without touching production certificates:\n\n\nsudo certbot renew --dry-run\n\n\nThe command simulates the entire renewal process, including configured hooks, and connects to Let's Encrypt's staging environment, not production, so it doesn't consume real rate limits.\n\nIf you want a dedicated timer instead of the package one, add a RandomizedDelaySec in the [Timer] section: randomisation distributes the load across Let's Encrypt infrastructure, correct practice and recommended. To reload Nginx after each renewal, place a script in /etc/letsencrypt/renewal-hooks/deploy/ that runs systemctl reload nginx.\n\n## An expiry check independent of the ACME client\n\nThe certbot timer can fail silently (port 80 closed, rate limit, broken hook). A second check is needed, one that reads the actual expiry from the certificate, not from client configuration:\n\nbash\n#!/bin/bash\nCERT=/etc/letsencrypt/live/example.com/cert.pem\nWARN_THRESHOLD=20\nCRIT_THRESHOLD=7\n\nEXPIRY=$(openssl x509 -enddate -noout -in \"$CERT\" | cut -d= -f2)\nEXPIRY_EPOCH=$(date -d \"$EXPIRY\" +%s)\nTODAY_EPOCH=$(date +%s)\nDAYS_LEFT=$(( (EXPIRY_EPOCH - TODAY_EPOCH) / 86400 ))\n\nif [ \"$DAYS_LEFT\" -le \"$CRIT_THRESHOLD\" ]; then\n LEVEL=\"CRITICAL\"\nelif [ \"$DAYS_LEFT\" -le \"$WARN_THRESHOLD\" ]; then\n LEVEL=\"WARNING\"\nelse\n exit 0\nfi\n\nMSG=\"Certificate $CERT: $DAYS_LEFT days remaining ($LEVEL)\"\necho \"$MSG\" | mail -s \"[$LEVEL] Certificate expiry\" ops@example.com\ncurl -s -X POST -H 'Content-Type: application/json' \\\n -d \"{\\\"text\\\":\\\"$MSG\\\"}\" https://hooks.example.com/webhook\n\n\nPut it in cron once a day, separate from the certbot timer:\n\n\n0 7 * * * /usr/local/bin/check-cert-expiry.sh\n\n\n## How to calibrate thresholds for each lifecycle\n\nLet's Encrypt's official criterion for those not yet using ARI: if your client doesn't yet support ARI, you must ensure it works on a schedule compatible with 45-day certificates; renewing at a fixed interval of 60 days will no longer be sufficient, but renewing at roughly two-thirds of the certificate lifetime works well.\n\nApplying the two-thirds criterion:\n\n| Profile | Certificate lifetime | Expected renewal (2/3 lifetime) | WARNING threshold | CRITICAL threshold |\n|---|---|---|---|---|\n| classic (today) | 90 days | day 60 (30 days left) | 20 days left | 7 days left |\n| classic (from 10/02/2027) | 64 days | day 43 (21 days left) | 14 days left | 5 days left |\n| tlsserver / classic (from 16/02/2028) | 45 days | day 30 (15 days left) | 10 days left | 3 days left |\n| shortlived | 6 days | day 4 (2 days left) | 2 days left | 12 hours |\n\nWith the shortlived profile the check should run in cron every hour, not every day: a 2-day margin runs out quickly if automatic renewal gets stuck.\n\n## ARI and the next step: DNS-PERSIST-01\n\nThose using a client with ARI support (ACME Renewal Information) don't need to recalculate thresholds manually: it's the Let's Encrypt server that tells the client when to renew. For those automating via DNS-01, a new validation type is coming, DNS-PERSIST-01, which reduces reliance on authorisation reuse because the DNS record can remain unchanged without further ACME client intervention; Let's Encrypt expects to roll it out in the course of 2026.\n\nThe full text of the plan is on the official blog, letsencrypt.org/2025/12/02/from-90-to-45; certbot commands are documented at eff-certbot.readthedocs.io/en/stable/using.html.
Written with the help of artificial intelligence and checked by the editors (EU AI Act, art. 50).