Skip to content
Hosting Operations6 min read

Certbot Renew Cron Setup: Systemd Timer vs Cron [2026]

Compare systemd timers and cron for certbot renewal automation. Real trade-offs, failure handling, and which method fits your infrastructure.

Written by Abdul AbrorTechnical Hosting Support Engineer
Alaska airlines jet with "go dawgs!" livery on fuselage.
On this page

TL;DR — Key takeaways

  • Systemd timers offer better logging, failure tracking, and retry logic compared to cron for certbot renewal
  • Cron works on any Linux system and requires less configuration, making it the simpler choice for single-server setups
  • Deploy hooks reload services automatically after renewal; test them in staging to avoid production service disruptions
  • Both methods should run renewal checks twice daily; certbot only renews certificates within 30 days of expiration
  • Monitor renewal failures through systemd journal entries or cron email alerts to catch expired certificates before outages

Unattended certificate renewal keeps your site secure without manual intervention every 90 days. But the setup method you choose affects how you debug failures, monitor renewals, and recover from errors.

Certbot supports two automation approaches: systemd timers and cron jobs. Each has distinct trade-offs in logging, portability, and operational complexity. I'll compare both methods with real configuration examples and explain which one fits different infrastructure types.

How Certbot Renewal Actually Works

Certbot renew checks all certificates managed by Certbot and renews any expiring within 30 days. The renewal process contacts Let's Encrypt, completes the same challenge type used during initial issuance (HTTP-01 or DNS-01), and writes new certificate files to /etc/letsencrypt/live/.

A typical renewal check completes in 2-5 seconds when no renewal is needed. Actual renewal takes 10-30 seconds depending on challenge type and DNS propagation. Certbot includes built-in retry logic and exponential backoff for transient failures.

After writing new certificates, Certbot executes deploy hooks if configured. These hooks typically reload web servers (nginx, Apache) to pick up the new certificates without downtime.

Systemd Timer Method: Configuration and Trade-offs

Modern distributions ship with certbot-timer.service and certbot-timer.timer units pre-installed. Check if they exist with systemctl list-timers certbot.timer. If present, enable them with systemctl enable --now certbot.timer.

The default timer runs twice daily at randomized times. View the exact schedule with systemctl status certbot.timer. Check recent renewal attempts with journalctl -u certbot.service.

Systemd timers track the last run time, next scheduled run, and failure count. If renewal fails, systemd marks the service as failed and you can inspect logs with journalctl -u certbot.service -n 50. Failed units appear in systemctl --failed output.

Deploy hooks go in /etc/letsencrypt/renewal-hooks/deploy/. Here's a basic nginx reload hook:

  • Create /etc/letsencrypt/renewal-hooks/deploy/reload-nginx with: #!/bin/bash\nsystemctl reload nginx
  • Make it executable: chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx
  • Test with: certbot renew --dry-run --deploy-hook /etc/letsencrypt/renewal-hooks/deploy/reload-nginx
  • Deploy hooks only execute when certificates actually renew, not on every check

Cron Method: Configuration and Trade-offs

Cron works on any Linux distribution without additional dependencies. Add a renewal job to root's crontab with crontab -e:

0 3,15 * * * /usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx"

This runs at 3:00 AM and 3:00 PM daily. The --quiet flag suppresses output unless renewal fails. Without it, cron emails full output on every run, flooding your inbox with success messages.

Cron sends email to the MAILTO address defined in the crontab. Configure it at the top of your crontab: [email protected]. Check /var/log/syslog or /var/log/cron for execution records, though these only show that the job ran, not whether renewal succeeded.

The --deploy-hook flag executes commands after successful renewal. Quote the command if it contains spaces. For multiple services, chain commands: --deploy-hook "systemctl reload nginx && systemctl reload postfix".

Testing and Validation Before Production

Always test renewal automation in staging mode first. Run certbot renew --dry-run to validate your entire renewal chain without touching production certificates or hitting rate limits.

Staging mode tests challenge completion, hook execution, and service reloads. Fix any errors before enabling the production timer or cron job. Common staging failures include:

Firewall rules blocking HTTP/.well-known/acme-challenge/ paths. Incorrect file permissions on renewal hooks (must be executable). Web server config syntax errors preventing reload. DNS issues if using DNS-01 challenges.

After staging passes, verify the production schedule is active. For systemd: systemctl list-timers certbot.timer shows next run time. For cron: grep certbot /var/spool/cron/crontabs/root confirms the entry exists.

Monitoring Renewal Failures

Silent renewal failures are the biggest operational risk. Your first indication of a problem should not be an expired certificate taking down your site.

With systemd timers, monitor with systemctl status certbot.timer daily or integrate with monitoring tools that check systemd unit states. Failed renewals appear in journalctl -u certbot.service with ERROR or FAILED markers.

With cron, configure MAILTO so renewal failures trigger email alerts. Test email delivery by temporarily breaking renewal (move /usr/bin/certbot aside, run cron manually, restore it). If email doesn't arrive, fix your MTA configuration before relying on cron notifications.

Check certificate expiration independently of renewal automation. Use openssl s_client -connect yourdomain.com:443 -servername yourdomain.com | openssl x509 -noout -dates to see expiration dates. Set up external monitoring that alerts 14 days before expiration.

Which Method Should You Choose?

Use systemd timers if you run Ubuntu 16.04+, Debian 8+, CentOS 7+, or any modern distribution with systemd. The superior logging, failure tracking, and integration with monitoring tools outweigh the minor increase in complexity. Operations teams with centralized logging benefit most from structured journal entries.

Use cron if you manage mixed infrastructure with older distributions, need portable automation scripts that work everywhere, or prefer explicit configuration you can read in one file. Single-server setups where you check logs manually work fine with cron.

I've debugged both in production. Systemd timers catch more failures early because failed renewals are visible in system status checks. Cron failures hide until you actively check email or logs. That delay cost us an expired certificate on a low-traffic staging server once.

Whichever method you choose, document it in your runbooks with the exact commands to check status, view logs, and manually trigger renewal. Future you—or your replacement—will appreciate the clarity at 2 AM during an incident.

Quick troubleshooting checklist

  • Test renewal in staging mode first: certbot renew --dry-run
  • Set up twice-daily renewal checks with randomized timing
  • Configure deploy hooks to reload web server after renewal
  • Enable failure notifications via email or logging
  • Verify certificate expiration dates after initial setup
  • Document your chosen method in runbooks
  • Test rollback procedure for failed renewals

FAQ

Should I use systemd timers or cron for certbot renewal?

Use systemd timers on modern distributions (Ubuntu 16.04+, CentOS 7+, Debian 8+) for better logging and failure handling. Use cron if you need maximum portability across legacy systems or prefer simpler configuration. Both methods are officially supported by Certbot and work reliably for automated renewal.

How often should certbot renewal checks run?

Run certbot renew twice daily with randomized timing to spread load across Let's Encrypt infrastructure. Certbot only attempts actual renewal when certificates are within 30 days of expiration, so frequent checks do not cause unnecessary API calls or rate limiting.

What happens if certbot renewal fails?

Failed renewals leave existing certificates in place until they expire. With systemd timers, failures appear in systemctl status and journalctl logs. With cron, failures trigger email alerts if MAILTO is configured. Monitor both methods actively because a silent failure means an expired certificate and site downtime.