For systems using nginx, haproxy, or similar software that needs a local certificate, automating certificate management for your dns provider is crucial. Let’s take a look at how to set up Certbot with AWS’s Route53 for handling domain validation and certificate renewal.

Prerequisites

First, make sure you have the required tools installed:

wget https://bootstrap.pypa.io/get-pip.py
sudo python3 get-pip.py
pip3 install -U pyopenssl cryptography # (there is a bug in old pyopenssl and cryptography so these need to be up to date)
apt install certbot
pip3 install certbot-dns-route53
certbot plugins # Check to make sure the plugin is loaded

Note: Up-to-date versions of pyopenssl and cryptography are required due to a known bug in older versions.

Route53 Authentication

To allow Certbot to interact with Route53, we need to create a credential file with AWS access keys. Replace the placeholders with your actual keys:

mkdir /root/.aws
cat << EOF > /root/.aws/credentials
[default]
aws_access_key_id=KEYID_PLACEHOLDER
aws_secret_access_key=ACCESSKEY_PLACEHOLDER
EOF

Also, you need to create an IAM policy for the user, replacing Z064682SAMPLEYS04I0D with your actual hosted zone ID:

{
    "Version": "2012-10-17",
    "Id": "letsencrypt-policy",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "route53:GetChange",
                "route53:ListHostedZones",
                "route53:ListHostedZonesByName"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "route53:ChangeResourceRecordSets",
                "route53:ListResourceRecordSets"
            ],
            "Resource": "arn:aws:route53:::hostedzone/Z064682SAMPLEYS04I0D",
            "Condition": {
                "ForAllValues:StringLike": {
                    "route53:ChangeResourceRecordSetsNormalizedRecordNames": [
                        "_acme-challenge.*"
                    ],
                    "route53:ChangeResourceRecordSetsRecordTypes": [
                        "TXT"
                    ],
                    "route53:ChangeResourceRecordSetsActions": [
                        "UPSERT",
                        "DELETE"
                    ]
                }
            }
        }
    ]
}
  • Record Name Restriction: Only allows modifications to _acme-challenge.* records, protecting your main domain records
  • Record Type Limitation: Restricts operations to TXT records only (used for DNS challenges)
  • Action Limitation: Only permits UPSERT and DELETE operations, blocking other potentially dangerous actions
  • Principle of Least Privilege: Grants only the minimum permissions needed for certificate validation

If your AWS credentials are compromised, an attacker cannot modify your main domain records, create malicious redirects, or disrupt other services - they can only manage the temporary challenge records needed for certificate validation.

Certificate Management

Initial Certificate Creation

Run the following command to initially create the certificate for your domain:

certbot certonly -d some.domain.com -d *.some.domain.com --dns-route53 --logs-dir /var/log/letsencrypt/log/ --config-dir /etc/letsencrypt/config/ --work-dir /etc/letsencrypt/work/ -m [email protected] --agree-tos --non-interactive --server https://acme-v02.api.letsencrypt.org/directory

Important: For testing, use the staging server first to avoid hitting rate limits:

# Use staging server for testing
certbot certonly -d some.domain.com -d *.some.domain.com --dns-route53 --logs-dir /var/log/letsencrypt/log/ --config-dir /etc/letsencrypt/config/ --work-dir /etc/letsencrypt/work/ -m [email protected] --agree-tos --non-interactive --server https://acme-staging-v02.api.letsencrypt.org/directory

Renewing Certificates

Use the following command to renew certificates when needed:

certbot renew --dns-route53 --logs-dir /var/log/letsencrypt/log/ --config-dir /etc/letsencrypt/config/ --work-dir /etc/letsencrypt/work/ -m [email protected] --agree-tos --non-interactive --server https://acme-v02.api.letsencrypt.org/directory --post-hook "sudo service nginx reload"

Automating Renewals with Crontab

You can set up a cron job to automatically renew the certificates. Here’s how to create the renewal script and set up a cron job:

mkdir /root/.aws
cat << EOF > /root/renew-letsencrypt-certificates.sh
#!/bin/bash

certbot renew --dns-route53 \
 --logs-dir /var/log/letsencrypt/log/ \
 --config-dir /etc/letsencrypt/config/ \
 --work-dir /etc/letsencrypt/work/ \
 -m [email protected] \
 --agree-tos --non-interactive \
 --server https://acme-v02.api.letsencrypt.org/directory \
 --post-hook "sudo service nginx reload"
EOF

# Crontab
0 0 */89 * * /bin/bash -c "/root/renew-letsencrypt-certificates.sh

And there you go!



Buy Me a Coffee