Let's Encrypt on Ubuntu 24.04 LTS: A step-by-step guide to obtaining and managing SSL certificates using Certbot


Introduction

This article discusses the process of obtaining and managing SSL/TLS certificates from Let’s Encrypt on an Ubuntu 24.04 LTS server using the Certbot tool. Certbot automates many routine tasks related to obtaining, installing, and updating certificates, significantly simplifying the process of ensuring a secure HTTPS connection for websites.

The article is divided into two main parts:

  • Brief version - provides brief, non-interactive commands for quickly obtaining certificates, allowing you to save time and effort.
  • Detailed version - describes each step of the process in detail, including configuration and troubleshooting, which will be useful for users who want to study Certbot’s operation in more detail and configure it for their specific needs.

Brief version

Update packages on the server:

sudo apt update && sudo apt upgrade -y

Install certbot:

sudo apt-get install -y certbot

Create an account:

sudo certbot register --non-interactive --agree-tos --email your.email@example.ru

Issue a certificate with HTTP validation

sudo certbot certonly --non-interactive --preferred-challenges http --standalone -d example.ru

View the list of available certificates using the command:

sudo certbot certificates

To revoke a certificate and remove it from the local Certbot database, use the command:

sudo certbot revoke --non-interactive --cert-name example.ru

To simply remove it from the local Certbot database, use the command:

sudo certbot delete --non-interactive --cert-name example.ru

Issue a domain with DNS+Cloudflare validation

Install the Cloudflare plugin for Certbot:

sudo apt-get install -y certbot python3-certbot-dns-cloudflare

Open the file in the editor nano (or the one you prefer):

sudo nano /etc/letsencrypt/dnscloudflare.ini

Add the access token for the Cloudflare API (previously created on the Cloudflare website):

# Cloudflare API token used by Certbot
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN

Set file permissions:

sudo chmod 0600 /etc/letsencrypt/dnscloudflare.ini

Issue a certificate for the domain example.ru with DNS validation:

sudo certbot certonly --non-interactive --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/dnscloudflare.ini -d example.ru

You can also issue a wildcard certificate using DNS validation:

sudo certbot certonly --non-interactive --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/dnscloudflare.ini -d example.ru -d '*.example.ru'

Note: If you only need a pure wildcard, you can omit -d example.ru.

Issue a certificate in one command with HTTP validation

sudo certbot certonly --non-interactive --preferred-challenges http --standalone -d example.ru --agree-tos --email your.email@example.ru

In this case, remember that Certbot can only work with one account, and when issuing certificates for different domains, it will bind them to the email specified for the first created domain.

Detailed version

Install certbot and issue Let’s Encrypt certificates with HTTP verification

Update packages on the server:

sudo apt update && sudo apt upgrade -y

Install certbot:

sudo apt-get install -y certbot

Register the ACME account

sudo certbot register
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel): 

Enter the email address for urgent updates and security notifications.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf. You must agree in order to register with the ACME server.
Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: 

Accept the terms of service.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about our work encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: 

Subscribe or not subscribe to the Electronic Frontier Foundation mailing list.

Issue a certificate with HTTP verification

To issue a certificate with HTTP verification without binding to web servers such as nginx and apache, use the following command:

sudo certbot certonly --preferred-challenges http -d example.ru
Saving debug log to /var/log/letsencrypt/letsencrypt.log
How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Runs an HTTP server locally which serves the necessary validation files under the /.well-known/acme-challenge/ request path. Suitable if there is no HTTP server already running. HTTP challenge only (wildcards not supported). (standalone)
2: Saves the necessary validation files to a .well-known/acme-challenge/ directory within the nominated webroot path. A seperate HTTP server must be running and serving files from the webroot path. HTTP challenge only (wildcards not supported). (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 

Choose option 1, and certbot will do everything itself. If you have a web server installed on your server, this option will not work due to a conflict listening on port 80. In this case, you need to choose option 2. Or use alternative authentication methods in the ACME CA. So we chose option 1 if everything is successful, we see a message similar to this:

Requesting a certificate for example.ru
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.ru/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.ru/privkey.pem
This certificate expires on 2024-11-12.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Let’s check for the presence and status of the certificate:

sudo certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
Certificate Name: example.ru
Serial Number: 49cdc1d31da5fbb4b445384c82ebbebc62f
Key Type: ECDSA
Domains: example.ru
Expiry Date: 2024-11-12 17:53:16+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/example.ru/fullchain.pem
Private Key Path: /etc/letsencrypt/live/example.ru/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Now we can use the certificate for third-party software.

Issue a certificate with DNS+Cloudflare verification

Install the plugin:

sudo apt-get install -y certbot python3-certbot-dns-cloudflare

Create the file /etc/letsencrypt/dnscloudflare.ini with the following content, replacing AN_API_TOKEN_HERE with your Cloudflare API token:

sudo nano /etc/letsencrypt/dnscloudflare.ini
# Cloudflare API token used by Certbot
dns_cloudflare_api_token = AN_API_TOKEN_HERE

Make the file readable only:

sudo chmod 0600 /etc/letsencrypt/dnscloudflare.ini

Issue an SSL/TLS certificate using Certbot with the Cloudflare plugin. Specify your domain and email:

sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/dnscloudflare.ini -d '*.example.ru' -d example.ru

Certbot will automatically create the necessary TXT records in Cloudflare for domain validation and issue the certificate.

Note: If you only need a pure wildcard, you can omit -d example.ru.

Check if automatic re-issuance works

If you have Debian/Ubuntu, Certbot automatically re-issues certificates using the systemd timer. You can check for the presence of the timer with the command:

sudo systemctl status certbot.timer

You can also check for the presence of a cron job:

sudo cat /etc/cron.d/certbot

The file should exist and contain a line similar to:

0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew --no-random-sleep-on-renew

To test how the automatic re-issuance mechanism works, you can run a “dry run” re-issuance with the command:

sudo certbot renew --dry-run

Troubleshooting

Cloudflare API token issued with IP restriction

Command

sudo certbot certonly --non-interactive --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/dnscloudflare.ini -d example.ru

Error

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for example.ru
Error determining zone_id: 29739
Cannot use the access token from location: 255.255.255.255. Please confirm that you have supplied valid Cloudflare API credentials. (Did you enter a valid Cloudflare Token?)
Ask for help or search for solutions at https://community.letsencrypt.org.
See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.

Solution

Go to the Cloudflare interface, find the token used on the server, and add the IP address from the error message to the allowed list.

Firewall prevents issuing a certificate with HTTP verification

Command

sudo certbot certonly --non-interactive --preferred-challenges http --standalone -d example.ru

Error

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for example.ru
Certbot failed to authenticate some domains (authenticator: standalone).
The Certificate Authority reported these problems:
Domain: example.ru
Type: connection
Detail: 255.255.255.255: Fetching http://example.ru/.well-known/acme-challenge/M3J59BZ6XVI4_7htpd4eYHYgfM3tBvHGwahiItwG0rm: Connection refused
Hint: The Certificate Authority failed to download the challenge files from the temporary standalone webserver started by Certbot on port 80. Ensure that the listed domains point to this machine and that it can accept inbound connections from the internet.
Some challenges have failed.
Ask for help or search for solutions at https://community.letsencrypt.org.
See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.

Solution

Check if ufw is installed:

sudo ufw status

If you see sudo: ufw: command not found or Status:... inactive, you need to look at your hosting provider’s firewall and the configured rules (port 80 needs to be allowed). Or dig deeper into iptables.

If you see something like:

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
To Action From
-- ------ ----
22/tcp ALLOW IN Anywhere
22/tcp (v6) ALLOW IN Anywhere (v6)

And 80/tcp ALLOW IN Anywhere is not in the list, allow access to port 80 using the following command:

sudo ufw allow http
Rule added
Rule added (v6)

Now the status sudo ufw status verbose should look like:

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
To Action From
-- ------ ----
22/tcp ALLOW IN Anywhere
80/tcp ALLOW IN Anywhere
22/tcp (v6) ALLOW IN Anywhere (v6)
80/tcp (v6) ALLOW IN Anywhere (v6)

After that, the error should disappear. If it doesn’t, you need to look at your hosting provider’s firewall settings and study iptables.