Free Wildcard Certificates with Certbot

Certbot is a package on many different distributions which simplifies the task of registering and managing Lets Encrypt certificates.

In this post, you will setup a scheduled task to automate this process for your domain name.

0 . Latest updates and prerequisites.

2023.09.25 – First draft, Ubuntu 22.04 Server.

Check back for updates, if you run into trouble. Leave a comment if the post is missing some detail.

You need enough permission to install a package and setup a cron job. There are some optional steps to setup notifications. This post instructions will work on just about any Linux distribution that has a certbot package.

The authentication method requires the DNS of the domain is in good order and you need access to create a record.

1 . Install and setup certbot.

This is a small package. There are many arguments to dockerise this package and process, however, it is small enough that dockerisation would maybe be more trouble than just running the package once a week.

First, install certbot:

sudo apt install certbot -y

Once the package is installed, use this step to generate a certificate request for your domain, in this case, it is done with the domain aardvark.systems, replace the values as necessary for your domain and email address. Notice the domain name starts with ‘*.’, indicating this is a wildcard domain:

sudo /usr/bin/certbot certonly --manual \
  --preferred-challenges=dns \
  --email=info@aardvark.systems \
  --server https://acme-v02.api.letsencrypt.org/directory \
  --agree-tos -d *.aardvark.systems

The first time you run certbot, you will be asked to add your email address to a list, you can say no. You will also be asked if you wish for your IP to be recorded. For the purpose of wildcard cert, this is required. You are then given a DNS challenge:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for *.aardvark.systems
-----------------------------------------------
Please deploy a DNS TXT record under the name:

_acme-challenge.aardvark.systems.

with the following value:

FQ3bQIiaJGCNSr2yOPyRAwZdti8qjvbxWcfH1wcPaAo

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.aardvark.systems.
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

Create the DNS TXT record and set it to the text string given.

Wait a few minutes before hitting Enter so there is time for the DNS records to update. Certbot will check your DNS records for that string to confirm you manage the domain, then download the certificate:

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/aardvark.systems/fullchain.pem
Key is saved at: /etc/letsencrypt/live/aardvark.systems/privkey.pem
This certificate expires on 2023-12-24.
These files will be updated when the certificate renews.

A folder structure has been created in /etc/letsencrypt/live and this is where the domain certificates will be maintained by certbot.

The TXT record can be deleted.

When certbot runs, it checks if any domain is a few weeks to expiry and tries to renew the certificate if so. Otherwise it does nothing. For this reason, it is safe to run this script daily to check for new updates without fear of overwhelming the service:

sudo certbot renew
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/aardvark.systems.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Certificate not yet due for renewal

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The following certificates are not due for renewal yet:
  /etc/letsencrypt/live/aardvark.systems/fullchain.pem expires on 2023-12-24 (skipped)
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

You can repeat the above steps for every domain you wish to create a certificate for.

2 . Automate the process.

Add certbot to the scheduler so it can check for a new certificate to update every week. Certbot checks for all the domains, by default:

sudo crontab -e

And at 1 am every Tuesday:

0 1 * * 2 /usr/bin/certbot renew

If you manually run certbot, you can see some output as to what it is trying to do. The certificate files are now kept in the folder structure described above.

3 . Optionally distribute the certificates as needed.

This is more about knowing what format a certificate is required and where it needs to be, as well as the permissions to apply. In many cases, it is enough to point the application to the certificates in the /etc/letsencrypt/live/ folder structure however many applications will not re-read a certificate automatically and need to be restarted.

For certificates which are on remote hosts, key based authentication allows a script to run without manual intervention and it is possible to copy certificate files to remote hosts for further processing.

The script below, for example, first checks for a mountpoint, in this case, a Windows share, where certificates are stored. If the mount is there, the script executes. For some applications, you may create a third certificate type (combined.pem). Then copies everything out to a share other applications have read permissions to. Beware that this share should be secure.

The advantage of using a script is that, for example, a service can be restarted, to read the new certificate, or some other action can be added, such as notification:

sudo mkdir -p /opt/sslupdate/
sudo nano /opt/sslupdate/sslupdate.sh
#!/bin/bash
# remove the readme file
rm /etc/letsencrypt/live/README
# Create PEM certificates for each domain type
for domain in $(ls /etc/letsencrypt/live/); do
  cd /etc/letsencrypt/live/
  cat ./$domain/privkey.pem ./$domain/cert.pem > ./$domain/combined.pem
  done
# Copy certificates to a windows share if mounted
if [[ $(findmnt -m "/mnt/certificates") ]]; then
  echo "Cert share mounted"
  cp -LRv /etc/letsencrypt/live/* /mnt/certificates/
  else echo "Certificates share not mounted"
  fi
# Send certificates to a linux system over ssh
  # Update online hosting services
  scp /etc/letsencrypt/live/aardvark.systems/fullchain.pem \
  root@domainname.com:/usr/local/ispconfig/interface/ssl/ispserver.crt
  scp /etc/letsencrypt/live/domainname.com/privkey.pem \
  root@domainname.com:/usr/local/ispconfig/interface/ssl/ispserver.key
# Restart services that need to re-read certificate updates
  # Restart lighttpd which hosts pihole on this server
  systemctl restart lighttpd.service
# Send a Discord notification
  /opt/discord/discord.sh "server40" "Certbot processed a renewal, please test it."  

This script can be run automatically when certbot runs only if certbot finds a renewal to process and successfully processes it. This is built in functionality. To run the script like this, create a scheduled job for certbot:

sudo crontab -e

Make a line like this:

0 1 * * 3 /usr/bin/certbot renew --deploy-hook /opt/sslupdate/sslupdate.sh

Check the script is executable and you can manually run it to make sure it works:

sudo chmod +x /opt/sslupdate/sslupdate.sh

Be sure to have adjusted the paths to suit your environment. You now have a repository of up to date wildcard certificates for any number of domains you run.

To setup the Discord notification called in the script, check out this post.

4 . Supporting this blog.

This type of content takes a lot of effort to write. Each post is drafted, researched, then tested multiple times, even a simple step or detail might take more than a few hours to go from the idea to a published blog post.

If you feel I have saved you some time, you can support me by;

  • buying me a beer through PayPal – PayPal.

© HorseFreeGlue, 2025. Unauthorized use and/or duplication of this material without express and written permission from this site’s author and/or owner is strictly prohibited