If you are still paying for SSL certificates on AWS, or setting calendar reminders to renew them, you can stop. Free SSL on AWS ACM (AWS Certificate Manager) issues public TLS certificates at no cost, and as long as you use DNS validation they renew automatically with no action from you. I have run production fleets where a cert quietly rolled over for years and nobody touched it. The one thing that bites everyone, including me on my first ALB, is WHERE an ACM cert can actually be attached. Get that wrong and you spend an afternoon wondering why your EC2 box still serves a self-signed warning.
What does ACM actually give you for free?
ACM issues public certificates signed by Amazon's trusted CA. They cost nothing, they support wildcards and multiple subject alternative names, and the part that earns its keep is managed renewal: ACM renews an in-use, DNS-validated certificate well before expiry and reinstalls it on the attached resource for you. No Certbot timer, no cron, no 2am page because a cert expired. The only place free does not apply is ACM Private CA, a separate paid service for issuing internal certs. For public HTTPS on a real domain, you pay zero.
There is one condition for hands-off renewal: the DNS validation record ACM gave you has to stay in place. Delete that CNAME and the next renewal fails. I treat that record as load-bearing infrastructure and never garbage-collect it.
How do I request a certificate with DNS validation?
DNS validation beats email validation on the things that matter: it is what makes renewal hands-off, and it does not depend on someone clicking a link in an inbox nobody monitors. You request the cert, ACM hands you a CNAME record, you add that record to your zone, and ACM flips the cert to ISSUED once it sees the record resolve. Here is the request itself with AWS CLI v2.
aws acm request-certificate \
--domain-name example.com \
--subject-alternative-names "*.example.com" \
--validation-method DNS \
--idempotency-token deploy2026 \
--region ap-southeast-2That returns a CertificateArn. Describe the cert to pull the CNAME name and value ACM wants you to publish. The record only appears once ACM has finished creating the certificate, so if the ResourceRecord block is empty, wait a few seconds and describe again.
aws acm describe-certificate \
--certificate-arn arn:aws:acm:ap-southeast-2:111122223333:certificate/abcd-1234 \
--region ap-southeast-2 \
--query 'Certificate.DomainValidationOptions[].ResourceRecord'If your domain is hosted in Route 53, the console gives you a 'Create records in Route 53' button that writes the CNAME for you in one click, which is the path I take every time. Validation usually completes within a few minutes once the record propagates. The slow cases I have hit were always the record landing in the wrong hosted zone, so double-check you edited the public zone and not a private one.
Why can't I attach an ACM cert directly to my EC2 instance?
This is the gotcha that costs people an afternoon. ACM public certificates do not export a usable private key, so you cannot copy the cert and key onto an EC2 box and point Nginx at them. ACM certs are designed to attach to AWS-managed endpoints that terminate TLS for you. In practice that means a short list of integration points.
- Application Load Balancer - the cert lives on an HTTPS listener; the ALB terminates TLS and forwards plain HTTP to your instances.
- Network Load Balancer - same idea, but the cert lives on a TLS listener rather than an HTTPS one.
- CloudFront - the cert sits on the distribution; good for static sites and as a CDN in front of an origin.
- API Gateway - for custom domains on your APIs.
- NOT a standalone EC2 instance - there is no ACM integration that installs the cert onto the OS.
So if your architecture is 'one EC2 instance serving HTTPS directly', ACM does not slot in. You have two real choices. Put an Application Load Balancer in front of the instance and attach the ACM cert to its HTTPS listener; this is the clean, AWS-native answer and what I reach for on anything that will grow. I covered the listener and security-group wiring in detail in my ALB HTTPS guide. The alternative, for a single box where an ALB's hourly cost is not justified, is to terminate TLS on the instance itself with Let's Encrypt and Certbot.
ACM is free and renews itself, but it only terminates TLS where AWS controls the endpoint. The moment TLS has to terminate on your own box, ACM is the wrong tool and Certbot is the right one.
When should I use Certbot instead?
Use Certbot when TLS must terminate on the EC2 instance itself and you do not want a load balancer in the path. Let's Encrypt issues free, trusted certs too, and Certbot installs them directly into Nginx and sets up auto-renewal via a systemd timer. On Ubuntu 22.04 or 24.04 the snap package is the supported install path.
sudo snap install --classic certbot
sudo ln -sf /snap/bin/certbot /usr/bin/certbot
# Issue and install into Nginx in one step:
sudo certbot --nginx -d example.com -d www.example.com
# Confirm the renewal timer is armed and will work:
sudo certbot renew --dry-run
systemctl list-timers snap.certbot.renew.timerCertbot rewrites your server block to add the certificate paths and a port 443 listener. That edit is also where it can clobber an existing config; if your renewals start failing or HTTPS breaks after a Certbot run, I wrote up the exact conflicts and fixes in Nginx and Certbot SSL conflicts. The trade-off versus ACM: you own the renewal mechanism, so if that systemd timer dies, your cert expires. ACM removes that failure mode, which is why I keep anything fronted by an ALB or CloudFront on ACM and reserve Certbot for the bare single-instance case.
The CloudFront region trap
One rule catches people every time: a certificate you want to use with CloudFront must be requested in the us-east-1 region, no matter where your application, your bucket, or your users live. CloudFront is a global service and only reads certs from us-east-1. If your app runs in ap-southeast-2 and you request the cert there, it will not appear in the CloudFront distribution's certificate dropdown, and the UI does not tell you why. Request a separate cert in us-east-1 for CloudFront; ALB certs stay in your app's region. If you are fronting an S3 site, my S3 static site with CloudFront walkthrough uses exactly this us-east-1 cert.
# CloudFront only reads certs from us-east-1 - region is not optional here.
aws acm request-certificate \
--domain-name cdn.example.com \
--validation-method DNS \
--region us-east-1What should I actually do?
Stop buying certs and stop renewing them by hand on AWS. If your traffic flows through an ALB, CloudFront, or API Gateway, request a free ACM cert with DNS validation, add the CNAME, and leave it alone. If TLS has to terminate on a lone EC2 instance, either front it with an ALB and attach the ACM cert there, or run Certbot on the box and own the renewal timer. And before your next CloudFront deploy, remember the cert goes in us-east-1 regardless of where everything else runs. The full reference lives in the AWS ACM documentation, but those three decisions cover most of what you hit in production.

