Let’s Encrypt generating Wildcard SSL certificate using Certbot

Marcin Cuber
5 min readJun 8, 2020


Generate valid SSL certificates using Certbot cli and renewals


SSL Certificates are small data files that digitally bind a cryptographic key to an organisation’s details. When installed on a web server, it activates the padlock and the https protocol and allows secure connections from a web server to a browser. Commonly, SSL is used to secure credit card transactions, data transfer and logins, and more recently is becoming the norm when securing browsing of social media sites.

Note: As of August 2020 most browsers will no longer display the green padlock and address bar to indicate Extended Validation.

When a certificate is successfully installed on your server, the application protocol (also known as HTTP) will change to HTTPS, where the ‘S’ stands for ‘secure’.


Recently, I started switching all my certificates that are soon expiring to Amazon issued ones which are automatically stored in AWS ACM. Limitation of that approach is that you can’t export such certificates. For that reason, I started using Let’s encrypt which allows me to use and store SSL certificates locally.

Since I am using AWS and cert manager I have a need to install following CLIs:

  • AWS
  • Certbot

To install them on your Macbook, you can simply use brew :

brew install awscli
brew install certbot

At the time of writing this article I am using following versions:

$ sudo certbot --version
certbot 1.4.0
$ aws --version
aws-cli/2.0.10 Python/3.8.3 Darwin/19.5.0 botocore/2.0.0dev14

In this story, I am aiming to cover the generation of a wildcard SSL certificate for domain.com using Certbot. Also, I will provide information how to import such certificate into AWS ACM.

The wildcard certificate is marked as demonstrated in the image and covers all possible subdomain under domain.com .

Generating The Wildcard SSL Certificate using certbot cli

At this stage you should have your certbot cli installed.

certbot certonly --manual \
--preferred-challenges=dns \
--email marcin@hotmail.com \
--server https://acme-v02.api.letsencrypt.org/directory \
--agree-tos \
--manual-public-ip-logging-ok \
-d “*.domain.com”

expected output:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for domain.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.domain.com with the following value:
SiPbTUGdqp37WnMNnG17N4qoZEVIiuO_MivrrhYmW-YBefore continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
Waiting for verification...
Cleaning up challenges
- Congratulations! Your certificate and chain have been saved at:
Your key file has been saved at:
Your cert will expire on 2020-09-06. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"

During the execution you will be prompt to create TXT record inside Route53 which you can see demonstrated below:

Once you have that record in place, press enter to continue and you will get a desired output presented above.

Find the SSL Certificate

After your certificate is successfully generated. You can find them in the default location:


So certificates for domain.com will be available in /etc/letsencrypt/live/domain.com/

More above folder structure and naming

All generated keys and issued certificates can be found in /etc/letsencrypt/live/${domain}. In the case of creating a SAN certificate with multiple alternative names, ${domain} is the first domain passed in via -d parameter. Rather than copying, please point your (web) server configuration directly to those files (or create symlinks). During the renewal, /etc/letsencrypt/live is updated with the latest necessary files.

For historical reasons, the containing directories are created with permissions of 0700 meaning that certificates are accessible only to servers that run as the root user. If you will never downgrade to an older version of Certbot, then you can safely fix this using chmod 0755 /etc/letsencrypt/{live,archive}.

For servers that drop root privileges before attempting to read the private key file, you will also need to use chgrp and chmod 0640 to allow the server to read /etc/letsencrypt/live/$domain/privkey.pem.

Available files for each certificate

Inside that folder you will find following files:

privkey.pem — private key for the certificate.

fullchain.pem — All certificates, including server certificate (aka leaf certificate or end-entity certificate). The server certificate is the first one in this file, followed by any intermediates.

cert.pem and chain.pemcert.pem contains the server certificate by itself, and chain.pem contains the additional intermediate certificate or certificates that web browsers will need in order to validate the server certificate. If you provide one of these files to your web server, you must provide both of them, or some browsers will show “This Connection is Untrusted” errors for your site, some of the time.

Verify validity of SSL Certificates generated by Certbot

To do that you can run the following command:

sudo certbot certificates

which will generate following output:

Found the following certs:
Certificate Name: domain.com
Serial Number: 4c006834c40af115ed6336331bc93034c97
Domains: *.domain.com
Expiry Date: 2020-09-06 07:51:47+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/domain.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/domain.com/privkey.pem
Certificate Name: domain.io
Serial Number: 318d565040c512614e31c77e938f024d256
Domains: *.domain.io
Expiry Date: 2020-09-06 06:28:59+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/domain.io/fullchain.pem
Private Key Path: /etc/letsencrypt/live/domain.io/privkey.pem
Certificate Name: domain.net
Serial Number: 31a5f3ecf68387f2a023758f2a7cac58b93
Domains: *.domain.net
Expiry Date: 2020-09-06 07:47:34+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/domain.net/fullchain.pem
Private Key Path: /etc/letsencrypt/live/domain.net/privkey.pem

Note that in my output above, I have three wildcard SSL certificates for three different domains.

Uploading certs to AWS ACM

Assuming you have all the files available for your generated SSL certificate, you can make use of AWS CLI to import your certificate to ACM.

aws --region eu-west-1 acm import-certificate \
--certificate "/etc/letsencrypt/live/domain.com/cert.pem" \
--private-key "/etc/letsencrypt/live/domain.com/privkey.pem" \
--certificate-chain "/etc/letsencrypt/live/domain.com/fullchain.pem"


I have demonstrated how to generate and upload SSL certificates to AWS ACM. Personally, I find Certbot very easy to use. I have not hit any issues so far.

Important note, each Certificate is valid for 90 days so it is recommended to renew them every 60 day as per docs.

Hope this is going to help others and speed up their learning.



Marcin Cuber

Technical Lead/Principal Devops Engineer and AWS Community Builder