SSL Certificate creation and setup Guide for Pull Request Environments
This guide outlines the process for creating and setting up SSL certificates for pull request environments using Let’s Encrypt and AWS Route 53.
This also is the process we currently apply upon expiration in order to generate new valid ones.
Generating the Certificate
Run the following command to start the certificate generation process:
certbot certonly --manual --preferred-challenges dns \
--cert-name <the-domain> \
-d "*.<the-domain>" \
-d "<the-domain>"
Both -d flags are required. A wildcard matches exactly one label and
does not cover the bare domain it is derived from, so a certificate
issued only for *.<the-domain> is valid for 1234.<the-domain>
but not for <the-domain> itself. Browsers reject the latter with
ERR_CERT_COMMON_NAME_INVALID.
--cert-name keeps the certificate lineage at a stable path across
renewals. Without it, certbot may create a new <the-domain>-0001
directory and the paths further down this guide stop matching.
The command prompts to create a DNS TXT record for domain verification and it waits for action to proceed:
Please deploy a DNS TXT record under the name _acme-challenge.<the-domain>. with the following value: <very_long_and_random_string> Before continuing, verify the TXT record has been deployed.
The two names are validated separately, but both challenges use the
same record name, _acme-challenge.<the-domain>, with different
values. Certbot prints them one at a time:
-
If it prompts twice, the second value must be added alongside the first, not replace it. Certbot says so explicitly: "do not remove, replace, or undo the previous challenge tasks yet". A TXT record set holds multiple values, and Let’s Encrypt looks for the one it expects among them. Overwriting the first value is the most common way this run fails.
-
If it prompts once, that is also correct. Let’s Encrypt caches successful authorizations for 30 days, so a name validated by a recent run is not challenged again.
Updating DNS Records in AWS Route 53
-
Log in to the AWS Management Console
-
Navigate to the Route 53 service
-
Select the hosted zone containing
<the-domain> -
Find the TXT record for
_acme-challenge.<the-domain> -
Set its value to the
<very_long_and_random_string>provided by certbot, quoted. When certbot prompts a second time, add that value as an additional line in the same record set - keep both. -
Wait a few moments for DNS propagation to complete
-
Return to the terminal and press Enter to continue the certificate generation process
Certificate Files
After successful verification, the certificates and keys will be available at:
/etc/letsencrypt/live/<the-domain>/
Verifying the Certificate
Before deploying, confirm the certificate actually covers both names:
openssl x509 -in /etc/letsencrypt/live/<the-domain>/fullchain.pem \
-noout -ext subjectAltName -dates
The output must list both entries:
X509v3 Subject Alternative Name:
DNS:*.<the-domain>, DNS:<the-domain>
If only the wildcard is present, the bare domain was not included in the order and the certificate needs to be reissued.
Updating GitHub Action Secrets
The final step is to update the CI secrets in GitHub:
-
Navigate to Web’s Actions secrets and variables
-
Update the
PR_ENV_SSL_CERTsecret:cat /etc/letsencrypt/live/<the-domain>/fullchain.pem | base64Copy the output and paste it as the value for
PR_ENV_SSL_CERT -
Update the
PR_ENV_SSL_CERT_KEYsecret:cat /etc/letsencrypt/live/<the-domain>/privkey.pem | base64Copy the output and paste it as the value for
PR_ENV_SSL_CERT_KEY
Once completed, the pull request environments will use the new SSL certificate.