Home / Alt manpages / certbot(1)

  • certbot(1)
  • User command
  • linux

Issue and Safely Renew a Let's Encrypt Certificate with Certbot

You will finish with an HTTPS certificate issued by the installed Certbot 2.9.0, a renewal test that does not save a certificate, and a way to check which files and domains Certbot manages. Allow about 20 minutes for an existing web server, DNS that already points at this host, and a short maintenance window if you must use standalone mode.

These examples use example.com and www.example.com as placeholders. Replace them before running anything. You need control of the domain, inbound HTTP access on port 80 for an HTTP-01 challenge, and root privileges for the commands that read or write /etc/letsencrypt or change a web server.

1. Check the installed Certbot

Start with read-only checks. They do not need sudo and prevent a common distraction: copying commands for a different package or version.

$ command -v certbot
/usr/bin/certbot
$ certbot --version
certbot 2.9.0
$ certbot plugins

The last command lists available authenticators and installers. The local package is Debian's certbot 2.9.0-1 in this guide. Plugin availability is installation-specific, so do not assume that an Apache, Nginx or DNS plugin exists just because the option appears in general documentation.

Checkpoint

Continue only when the binary is the one you intend to run and the plugin you need appears in the plugin list.

2. Choose how Certbot will prove domain control

For Apache or Nginx already serving the site, the matching plugin can authenticate and install the certificate:

$ sudo certbot --apache -d example.com -d www.example.com
$ sudo certbot --nginx -d example.com -d www.example.com

Run only the command for your server. These modes can edit the server configuration. Certbot's normal install and run behaviour enables an HTTP to HTTPS redirect unless you select --no-redirect; inspect the proposed changes and keep a configuration backup before accepting them.

If the web server should remain running and you know its document root, use webroot mode. Certbot writes a temporary token below .well-known/acme-challenge/; your server must serve that path publicly.

$ sudo certbot certonly --webroot -w /var/www/example -d example.com -d www.example.com

Here certonly obtains or renews the certificate but does not install it in Apache or Nginx. Confirm that /var/www/example is the actual public webroot, not merely a source directory.

Standalone mode is for a host where Certbot can listen on port 80 itself. It cannot share that port with another service, so this is a service-disrupting choice:

$ sudo systemctl stop nginx
$ sudo certbot certonly --standalone -d example.com -d www.example.com
$ sudo systemctl start nginx

Before using this form, confirm the service name and have a recovery plan. If Certbot fails, start the service before investigating. The ACME server still connects to port 80 even if you change Certbot's local --http-01-port value; changing that option alone does not move the public challenge port.

3. Use staging when testing a new setup

Repeated failed attempts can hit the production CA's rate limits. Add --test-cert while testing a command, or use --dry-run for an existing renewal configuration:

$ sudo certbot certonly --webroot -w /var/www/example \
    --test-cert -d example.com -d www.example.com
$ sudo certbot renew --dry-run

A staging certificate is intentionally not trusted by browsers. It is useful for checking challenge routing, but do not deploy it as the site's live certificate. --dry-run is limited to certonly and renew; the local manual says it obtains a temporary test certificate without saving certificates to disk, although it may reload a web server and run pre or post hooks.

Checkpoint

Do not move to production until the challenge path is reachable from the public internet and the dry run succeeds. A successful dry run is evidence that the renewal procedure worked, not proof that an unrelated virtual host is configured correctly.

4. Inspect the certificate and its managed paths

After a real issuance, list Certbot's view of the certificate:

$ sudo certbot certificates

The output includes the certificate name, domains, expiry date, certificate path and private key path. The first domain normally becomes the certificate name, but a name conflict can add a suffix such as -0001. Use the displayed certificate name rather than guessing a directory name.

$ sudo ls -l /etc/letsencrypt/live/example.com/
$ sudo openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem \
    -noout -subject -issuer -dates -ext subjectAltName

The default configuration directory is /etc/letsencrypt. A typical live directory contains cert.pem, chain.pem, fullchain.pem and privkey.pem. Treat the private key as secret material. Do not paste it into a ticket, commit it to source control or loosen its permissions to make a service start.

5. Test and automate renewal

renew checks all previously obtained certificates and attempts those close to expiry. It reuses the plugins and options recorded for each certificate, so it normally needs no domain or authenticator flags:

$ sudo certbot renew --dry-run
$ sudo certbot renew

Run the first command now. Run the second only when you intend a real renewal. A normal renewal run may say that a certificate is not yet due; that is a successful no-op, not a failure.

Check how this installation schedules the command instead of creating a duplicate job:

$ systemctl list-timers --all | grep -i certbot
$ sudo grep -R "certbot renew" /etc/crontab /etc/cron.* 2>/dev/null

The official Certbot guidance says packages may provide a systemd timer or cron entry. Choose one existing mechanism and verify its logs. If your web server reads certificate files only at startup, add a carefully tested deploy hook to reload it after a successful renewal. A hook is a shell command with operational privileges, so use an absolute executable path and test its reload command separately.

6. Recover from the usual failures

A webroot challenge failure usually means DNS, port 80, the virtual host or the .well-known path is wrong. Test the public route with a harmless file in the real webroot, then remove that file after checking it:

$ printf '%s\n' certbot-check | sudo tee /var/www/example/.well-known/acme-challenge/certbot-check
$ curl -fsS http://example.com/.well-known/acme-challenge/certbot-check
certbot-check
$ sudo rm /var/www/example/.well-known/acme-challenge/certbot-check

Removal is deliberate: the check file is no longer needed. If standalone mode reports that port 80 is busy, identify the listener with sudo ss -ltnp 'sport = :80', then either use webroot mode or stop the correct service with a recovery command ready.

To replace a mistaken certificate configuration, inspect first with sudo certbot certificates. Do not use certbot delete casually: it cleans up all files related to the named certificate. Revocation is also irreversible in practice for that certificate. Use revoke only for a genuine compromise or other confirmed reason, and take a backup of any configuration you are about to edit.

Done means

  • The installed version and required plugin were checked.
  • The chosen challenge can be reached for every requested domain.
  • A production certificate was issued or an existing one was inspected with certbot certificates.
  • sudo certbot renew --dry-run completed successfully.
  • An existing timer or cron entry, rather than a duplicate job, will run renewal.
  • The web server reload path is tested, and private keys and destructive commands remain protected.