Mike Slinn
Mike Slinn

Creating and Renewing Letsencrypt Wildcard SSL Certificates

Published 2022-06-15. Last modified 2022-09-14.
Time to read: 2 minutes.

This site is categorized under Internet, Security.

The process of making wildcard SSL certificates can be hard to get right at first. However, I use wildcard SSL certificates for most of my internet domains, so it is important to me. This blog post distills the essence of what I have found to be important when creating these certificates.

Making a Free Wildcard SSL Certificate

Certbot powers EFF’s Letsencrypt capability. Source code is on GitHub. Install certbot on Debian distros such as Ubuntu as follows:

Shell
$ sudo apt install certbot
Preparing to unpack .../06-python3-zope.event_4.4-3_all.deb ...
  Unpacking python3-zope.event (4.4-3) ...
  Selecting previously unselected package python3-zope.component.
  Preparing to unpack .../07-python3-zope.component_4.3.0-3_all.deb ...
  Unpacking python3-zope.component (4.3.0-3) ...
  Selecting previously unselected package python3-certbot.
  Preparing to unpack .../08-python3-certbot_1.21.0-1build1_all.deb ...
  Unpacking python3-certbot (1.21.0-1build1) ...
  Selecting previously unselected package python3-icu.
  Preparing to unpack .../09-python3-icu_2.8.1-0ubuntu2_amd64.deb ...
  Unpacking python3-icu (2.8.1-0ubuntu2) ...
  Selecting previously unselected package certbot.
  Preparing to unpack .../10-certbot_1.21.0-1build1_all.deb ...
  Unpacking certbot (1.21.0-1build1) ...
  Setting up python3-configargparse (1.5.3-1) ...
  Setting up python3-requests-toolbelt (0.9.1-1) ...
  Setting up python3-parsedatetime (2.6-2) ...
  Setting up python3-icu (2.8.1-0ubuntu2) ...
  Setting up python3-zope.event (4.4-3) ...
  Setting up python3-zope.hookable (5.1.0-1build1) ...
  Setting up python3-josepy (1.10.0-1) ...
  Setting up python3-zope.component (4.3.0-3) ...
  Setting up python3-acme (1.21.0-1) ...
  Setting up python3-certbot (1.21.0-1build1) ...
  Setting up certbot (1.21.0-1build1) ...
  Created symlink /etc/systemd/system/timers.target.wants/certbot.timer → /lib/systemd/system/certbot.timer.
  Processing triggers for man-db (2.10.2-1) ...
  Scanning processes...
  Scanning processor microcode...
  Scanning linux images...

  Failed to retrieve available kernel versions.

  Failed to check for processor microcode upgrades.

  No services need to be restarted.

  No containers need to be restarted.

  No user sessions are running outdated binaries.

  No VM guests are running outdated hypervisor (qemu) binaries on this host. 

certbot has 2 subcommands of interest: certonly (used when creating a certificate for the first time), and renew (used when updating a pre-existing certificate). The creation process requires the user to do things before it can complete, so it can only be run interactively.

The files and directories creating by the process of creating a new SSL certificate should not be deleted. Contrary to what the Letsencrypt certbot documentation says, I have found that these files and directories allow the renewal process to proceed without requiring user interaction, so it can be scripted.

Certbot Help Messages

Here is the help message for the certbot certonly subcommand:

Shell
$ certbot certonly --help
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  certbot [SUBCOMMAND] [options] [-d DOMAIN] [-d DOMAIN] ...
Certbot can obtain and install HTTPS/TLS/SSL certificates. By default, it will attempt to use a webserver both for obtaining and installing the certificate. The most common SUBCOMMANDS and flags are:
obtain, install, and renew certificates: (default) run Obtain & install a certificate in your current webserver certonly Obtain or renew a certificate, but do not install it renew Renew all previously obtained certificates that are near expiry enhance Add security enhancements to your existing configuration -d DOMAINS Comma-separated list of domains to obtain a certificate for
(the certbot apache plugin is not installed) --standalone Run a standalone webserver for authentication (the certbot nginx plugin is not installed) --webroot Place files in a server's webroot folder for authentication --manual Obtain certificates interactively, or using shell script hooks
-n Run non-interactively --test-cert Obtain a test certificate from a staging server --dry-run Test "renew" or "certonly" without saving any certificates to disk
manage certificates: certificates Display information about certificates you have from Certbot revoke Revoke a certificate (supply --cert-name or --cert-path) delete Delete a certificate (supply --cert-name)
manage your account: register Create an ACME account unregister Deactivate an ACME account update_account Update an ACME account --agree-tos Agree to the ACME server's Subscriber Agreement -m EMAIL Email address for important account notifications
More detailed help:
-h, --help [TOPIC] print this message, or detailed help on a topic; the available TOPICS are:
all, automation, commands, paths, security, testing, or any of the subcommands or plugins (certonly, renew, install, register, nginx, apache, standalone, webroot, etc.) -h all print a detailed help page including all topics --version print the version number - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Here is the help message for the certbot certonly subcommand:

Shell
$ certbot renew --help
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
certbot [SUBCOMMAND] [options] [-d DOMAIN] [-d DOMAIN] ...
Certbot can obtain and install HTTPS/TLS/SSL certificates. By default, it will attempt to use a webserver both for obtaining and installing the certificate. The most common SUBCOMMANDS and flags are:
obtain, install, and renew certificates: (default) run Obtain & install a certificate in your current webserver certonly Obtain or renew a certificate, but do not install it renew Renew all previously obtained certificates that are near expiry enhance Add security enhancements to your existing configuration -d DOMAINS Comma-separated list of domains to obtain a certificate for
(the certbot apache plugin is not installed) --standalone Run a standalone webserver for authentication (the certbot nginx plugin is not installed) --webroot Place files in a server's webroot folder for authentication --manual Obtain certificates interactively, or using shell script hooks
-n Run non-interactively --test-cert Obtain a test certificate from a staging server --dry-run Test "renew" or "certonly" without saving any certificates to disk
manage certificates: certificates Display information about certificates you have from Certbot revoke Revoke a certificate (supply --cert-name or --cert-path) delete Delete a certificate (supply --cert-name)
manage your account: register Create an ACME account unregister Deactivate an ACME account update_account Update an ACME account show_account Display account details --agree-tos Agree to the ACME server's Subscriber Agreement -m EMAIL Email address for important account notifications
More detailed help:
-h, --help [TOPIC] print this message, or detailed help on a topic; the available TOPICS are:
all, automation, commands, paths, security, testing, or any of the subcommands or plugins (certonly, renew, install, register, nginx, apache, standalone, webroot, etc.) -h all print a detailed help page including all topics --version print the version number - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Complete documentation for certbot is here.

Generic DNS Authentication

I used certbot to create a special file within the website as follows, without using sudo. I want a wildcard SSL certificate, which requires certbot to use DNS authentication.

BTW, the following options include two -d options, one for the domain apex (mslinn.com) and one for the subdomains (*.mslinn.com)

Shell
$ certbot certonly \
  --manual \
  --agree-tos \
  --preferred-challenges dns-01 \
  --rsa-key-size 4096 \
  -d mslinn.com -d *.mslinn.com \
  --config-dir ~/.certbot/mslinn.com/config \
  --logs-dir ~/.certbot/mslinn.com/logs \
  --work-dir ~/.certbot/mslinn.com/work
Saving debug log to /home/mslinn/.certbot/mslinn.com/logs/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel):  mslinn@mslinn.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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: n Account registered. Requesting a certificate for mslinn.com and *.mslinn.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Please deploy a DNS TXT record under the name:
_acme-challenge.mslinn.com.
with the following value:
n6o3qMw5N7qxAzV4uNQePKxJjaw0f-Bo32CybWr-lhE
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Press Enter to Continue (This must be set up in addition to the previous challenges; do not remove, replace, or undo the previous challenge tasks yet. Note that you might be asked to create multiple distinct TXT records with the same name. This is permitted by DNS standards.) Before continuing, verify the TXT record has been deployed. Depending on the DNS provider, this may take some time, from a few seconds to multiple minutes. You can check if it has finished deploying with aid of online tools, such as the Google Admin Toolbox: https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.mslinn.com. Look for one or more bolded line(s) below the line ';ANSWER'. It should show the value(s) you’ve just added. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Press Enter to Continue Successfully received certificate. Certificate is saved at: /home/mslinn/.certbot/mslinn.com/config/live/mslinn.com/fullchain.pem Key is saved at: /home/mslinn/.certbot/mslinn.com/config/live/mslinn.com/privkey.pem This certificate expires on 2022-09-29. These files will be updated when the certificate renews. NEXT STEPS: - This certificate will not be renewed automatically. Autorenewal of --manual certificates requires the use of an authentication hook script (--manual-auth-hook) but one was not provided. To renew this certificate, repeat this same certbot command before the certificate’s expiry date. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

I made a bash script (~/.local/bin/sslCert) to create SSL certificates, which performs the same steps as the above, but it works for any site, and can renew certificates as well as create them:

#!/bin/bash

function help {
  echo "Creates or updates an wildcard SSL certificate

Usage: $(basename $0) DOMAIN

Example: $(basename $0) scalacourses.com

The relevant files are stored in ~/.certbot/DOMAIN/

Creating a new certificate requires an interactive user session;
updating a certificate can be done in a cron job.

Currently, the renew verb is capable of either renewing all installed 
certificates that are due to be renewed or renewing a single certificate 
specified by its name. If you would like to renew specific certificates 
by their domains, use the certonly command instead. 

The renew verb may provide other options for selecting certificates to 
renew in the future.

Ask for help or search for solutions at https://community.letsencrypt.org 
See the logfile /home/mslinn/.certbot/ancientwarmth.com/logs/letsencrypt.log 
or re-run Certbot with -v for more details.
"
  exit 1
}

if [ -z "$1" ]; then help; fi

DOMAIN="$1"
if [ -d "$HOME/.certbot/$DOMAIN" ]; then # Renew existing certificate
  CMD=certonly # renew
  OPTIONS=--force-renew
else # Make new certificate (interactively)
  CMD=certonly
  unset OPTIONS
fi
certbot "$CMD" $OPTIONS \
  --agree-tos \
  --config-dir "$HOME/.certbot/$DOMAIN/config" \
  -d "$DOMAIN" -d "*.$DOMAIN" \
  --email mslinn@mslinn.com \
  --logs-dir "$HOME/.certbot/$DOMAIN/logs" \
  --manual \
  --preferred-challenges dns-01 \
  --rsa-key-size 4096 \
  --work-dir "$HOME/.certbot/$DOMAIN/work"

Here is the help message for the script:

Shell
$ sslCert
Creates or updates an wildcard SSL certificate

Usage: sslCert DOMAIN

Example: sslCert scalacourses.com

The relevant files are stored in ~/.certbot/DOMAIN/

Creating a new certificate requires an interactive user session;
updating a certificate can be done in a cron job. 

The following crontab entry causes the script to run every 60 days.

crontab
0 0 1 */2 * .local/bin/sslCert mslinn.com

The next time the script was run, output looked like:

Shell
$ sslCert mslinn.com
Saving debug log to /home/mslinn/.certbot/mslinn.com/logs/letsencrypt.log
Renewing an existing certificate for mslinn.com and *.mslinn.com
Successfully received certificate. Certificate is saved at: /home/mslinn/.certbot/mslinn.com/config/live/mslinn.com/fullchain.pem Key is saved at: /home/mslinn/.certbot/mslinn.com/config/live/mslinn.com/privkey.pem This certificate expires on 2022-12-13. These files will be updated when the certificate renews.
NEXT STEPS: - This certificate will not be renewed automatically. Autorenewal of --manual certificates requires the use of an authentication hook script (--manual-auth-hook) but one was not provided. To renew this certificate, repeat this same certbot command before the certificate's expiry date.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
😁

Subsequent blog posts will discuss how to install the new wildcard SSL certificate for various scenarios.