It’s been a while since my last post! Today, let’s explore how to use Certbot’s Route53 plugin to generate SSL certificates using certbot-dns-route53. Typically, Certbot verifies domain ownership by placing files on a public web server and checking for their existence. However, this approach doesn’t work for internal services that are inaccessible from the internet.
This limitation is particularly frustrating because internal sites are a great use case for Let’s Encrypt. Paying for a certificate for something only internal users see feels unnecessary, yet manually generating a certificate every 60 to 90 days can be tedious. Thankfully, AWS Route53 provides a solution.
Step 1 Install Certbot and the Route53 Plugin
Install Certbot and the Route53 plugin using the following commands:
sudo snap install --classic certbot
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-route53Step 2 Create an AWS Route53 Subdomain and IAM User
To minimize security risks, I prefer to avoid using AWS credentials with permissions that can modify second-level DNS names—especially for internal services that don’t require access to public-facing domains. Instead, we will create a subdomain (int.yourdomain.com) in Route53.
Creating the Subdomain
- Navigate to Route53 in the AWS console.
- Click Hosted Zones → Create Hosted Zone.
- Name the zone int.yourdomain.com.
- Update the parent domain’s DNS records to include the nameservers of the newly created subdomain’s hosted zone.
Creating an IAM User with Limited Access
Now, we’ll create an IAM user with access restricted to our new hosted zone.
- In the IAM console, click Create User.
- Name the user and select Attach policies directly.
- Click Create Policy.
- Under Specify permissions, go to the JSON tab and paste the following policy (replace YOURHOSTEDZONEID with your actual Hosted Zone ID):
{
"Version": "2012-10-17",
"Id": "certbot-dns-route53 sample policy",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:ListHostedZones",
"route53:GetChange"
],
"Resource": [
"*"
]
},
{
"Effect" : "Allow",
"Action" : [
"route53:ChangeResourceRecordSets"
],
"Resource" : [
"arn:aws:route53:::hostedzone/YOURHOSTEDZONEID"
]
}
]
}- Save the policy, return to the user creation page, refresh the policy list, and attach the new policy.
- Generate an access key for the user.
- On your server, add the access keys to
~/.aws/config:
[default]
aws_access_key_id=keyid
aws_secret_access_key=keyvalueStep 3 Test and Generate the Certificate
Before proceeding with the actual certificate issuance, perform a dry run to ensure everything is set up correctly:
certbot certonly --dns-route53 -d foo.bar.net -n --agree-tos -m [email protected] --dry-run --test-certcertbot certonly --dns-route53 -d foo.bar.net -nIn my case, I had to manually export the AWS credentials for them to be recognized properly. We’ll see if they are correctly detected during renewal.
That’s it! Hopefully, this guide helps streamline the process of securing your internal services with Let’s Encrypt. 🚀