Skip to content

Instantly share code, notes, and snippets.

@MagnusOxlund
Last active December 9, 2024 11:35
Show Gist options
  • Save MagnusOxlund/088ca6d5630609d537e84e344ed25d8e to your computer and use it in GitHub Desktop.
Save MagnusOxlund/088ca6d5630609d537e84e344ed25d8e to your computer and use it in GitHub Desktop.
How to renew Let's Encrypt certificates with Certbot

How to renew Let's Encrypt certificates with Certbot

Acquire a certificate (certbot certonly)

Certificates are initially acquired with the certbot certonly command.

Certificates expire 90 days after being issued and need to be renewed (or replaced).

When acquiring a certificate, a list of options is specificed. These include domain names and an authentication method. The official manual refers to authentication methods as "plugins". The term "plugins" also refers to "installation plugins", which are optional components used to install certificates on webservers.

example description
certbot certonly --standalone acquire certificate using Certbot's standalone webserver
certbot certonly --webroot acquire certificate by serving files from the filesystem
certbot certonly --nginx acquire certificate while keeping NGINX running

Renewal (certbot renew)

Certificates are renewed with the certbot renew command.

The command attempts to renew all acquired certificates by default. Individual certificates can be selected with the --cert-name <cert name> option.

The options used when acquiring a certificate are automatically saved. Certbot reuses those options when renewing a certificate. The options are stored in each certificate's individual renewal configuration located at /etc/letsencrypt/renewal/<cert name>.conf. Instead of editing the file directly, the manual recommends using a separate command: certbot reconfigure.

Although not documented, it's possible to change renewal options directly with certbot renew. The --dry-run option can be used to test changes before performing a renewal. If the dry run is successful, the changes are automatically saved.

One of the certbot renew command's documented features are the three renewal hooks:

certbot renew --pre-hook <command> --post-hook <command> --deploy-hook <command>

Read more about renewal hooks below.

The certbot renew command only renews certificates when they're within 30 days of expiration. Running the command frequently does not trigger rate limits. To renew certificates immediately, use the --force-renewal option.

example description
certbot renew renew all certificates listed in /etc/letsencrypt/renewal
certbot renew --cert-name <cert name> only renew the specified certificate(s)
certbot renew --force-renewal renew even if outside 30-day renewal window
certbot renew --dry-run simulate renewal (skips deploy hook)
certbot renew --dry-run --run-deploy-hooks simulate renewal with deploy hook
certbot renew --pre-hook code to run before renewal process
certbot renew --post-hook code to run after renewal process
certbot renew --deploy-hook code to run for each successfully renewed certificate

Change renewal options (certbot reconfigure)

Certificate renewal options are changed with the certbot reconfigure command.

Renewal options are changed by passing the same options used to acquire a certiciate. Once options are changed, they're saved in each certificate's renewal configuration located at /etc/letsencrypt/renewal/<cert name.conf. It's discouraged to edit the file directly.

It's not fully documented how the command works. Instead, the manual refers to the certbot help reconfigure command. Its output is brief and its terminology is not entirely consistent with the manual. Although not documented, the certbot reconfigure command is currently implemented by calling certbot renew --dry-run.

Once reconfiguration is done, Certbot will report any changes made to the renewal options.

example description
cerbot reconfigure change certificate renewal options
--cert-name <cert name> certificate to reconfigure (required)
--authenticator webroot authenticator method (webroot selected)
--webroot-path <path to webroot> webroot path (if authenticating with webroot)
--domains example.com www.example.com domain list
--pre-hook pre hook (read more below)
--post-hook post hook (read more below)
--deploy-hook deploy hook (read more below)
certbot help reconfigure command line documentation
/etc/letsencrypt/renewals/<cert name>.conf certificate renewal configuration filepath

Renewal hooks (--pre-hook, --post-hook, --deploy-hook)

Three renewal hooks are used to schedule tasks before and after the renewal process as well as for each successful renewal.

hook description
--pre-hook <command> runs before renewal process begins (once)
--post-hook <command> runs after renewal process ends (once)
--deploy-hook <command> runs during renewal process (once for each successful certificate renewal)

A typical use case is to stop and restart a webserver before and after the renewal process and to install any succesfully renewed certificates.

Renewal hooks can be set in four different ways:

  1. As command line options
  2. As global configuration options
  3. As certificate renewal configuration options
  4. As executables in the global renewal hook directories

Command line option hooks override most other hooks. If used with a successful certbot renew command (including dry runs) or with certbot reconfigure, the hooks are saved in the certificate renewal configuration. Existing hooks in the configuration will be overwritten.

Hooks set in the global configuration located at /etc/letsencrypt/cli.ini apply to all certificates and will override options set in each certificate's renewal configuration. The global configuration uses hyphens in option names, e.g., pre-hook=<command>.

Hooks set in certificate renewal configurations only apply to individual certificates. Each certificate has its own renewal configuration located at /etc/letsencrypt/renewal/<cert name>.conf. Underscores are used in option names here, e.g., pre_hook=<command>.

Executables in the renewal hook directories behave uniquely. The hooks are global, they're not overridden, they always execute before other hooks, and the executables only run once, even if referenced by other hooks. Use the command line option --no-directory-hooks to skip them.

The following order describes how the non-directory hooks are overridden:

command line options > global configuration > certificate renewal configuration

Certbot provides environment variables to hooks, which include domain names and certificate file paths.

example description
certbot renew --pre-hook <command> command line option hook
certbot reconfigure --cert-name <cert name> --pre-hook <command> set a certificate configuration hook
cat /etc/letsencrypt/renewals/<cert name>.conf | grep pre_hook view a certificate configuration option (note the underscore)
cat /etc/letsencrypt/cli.ini | grep pre-hook global configuration option (note the hyphen)
/etc/letsencrypt/renewal-hooks/pre/ global renewal hook directory
certbot renew --no-directory-hooks skip renewal hook directories
$RENEWED_DOMAINS list of domains
$RENEWED_LINEAGE absolute filepath to renewed certificates (contains the certificate name)

Reacquiring vs. renewing

Under the hood, a renewal is just a replacement. By renewing an existing certificate, a new certificate with an identical list of domains is issued in place of the existing one.

Certbot's implementation reflects this. The commands certbot renew and certbot reconfigure are implemented as wrappers around certbot certonly. Although not documented, it's possible to pass renewal-specific command line options like --dry-run to certbot certonly.

There are benefits to using Certbot's two renew and reconfigure commands, such as rate limit checks, expiration reminders, and the convenience of renewal hooks. If more granular control is needed, reacquiring a certificate is a viable approach.


© Magnus Lind Oxlund 2024. This work is openly licensed via CC BY 4.0. Attribution required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment