For wildcard TLS/SSL certificates, the only challenge method Let’s Encrypt accepts is the DNS challenge to authenticate the domain ownership. Therefore, we need to Route53 AWS DNS API to add/modify DNS for our domain. This tutorial explains how to generate a wildcard TLS/SSL certificate using Let’s Encrypt client called acme.sh running on Linux or Unix-like systems.
Tutorial requirements | |
---|---|
Operating system/app | Linux or Unix with AWS Route 53 DNS account |
Root privileges required | Yes |
Difficulty | Intermediate (rss) |
Estimated completion time | 20m |
Prerequisite to set up Route 53 Let’s Encrypt wildcard certificate with acme.sh
Make sure Nginx server installed and running. For example:
$ sudo apt install nginx
$ sudo yum install nginx
Apache users can run the following command::
$ sudo apt install apache2
$ sudo yum install httpd
Step 1 – Creating a new AWS user and get API access keys for Route 53
You can add user and create policy for Route53 using console. In this example, I will create a new IAM user for my AWS account, attach, and assign the policy using the aws cli.
Get the of hosted zones associated with the current AWS account
First we need to find out DNS zone ID. Run the aws command as follows to list hosted zone:
$ aws route53 list-hosted-zones
Note down your hosted zone Id. For example:
{
"HostedZones": [
{
"Id": "/hostedzone/RANDOM_ID_HERE_1",
"Name": "nixcraft.org.",
"CallerReference": "RISWorkflow-RD:473d5c18-2ca9-421b-b217-c40f9d90b976",
"Config": {
"Comment": "HostedZone created by Route53 Registrar",
"PrivateZone": false
},
"ResourceRecordSetCount": 2
},
{
"Id": "/hostedzone/RANDOM_ID_HERE_2",
"Name": "nixcraft.com.",
"CallerReference": "2BC89E0B-FB84-7FA0-8EA6-5A2D46189415",
"Config": {
"Comment": "nixCraft forum DNS",
"PrivateZone": false
},
"ResourceRecordSetCount": 16
}
]
}
Create a new customer managed policy file named route53.txt
Use your favorite text editor such as vim to create a strict policy to update your Route53 DNS zone:
$ vim route53.txt
Append the following text replacing RANDOM_ID_HERE_2 as per your set up:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "vim0",
"Effect": "Allow",
"Action": [
"route53:GetHostedZone",
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets"
],
"Resource": "arn:aws:route53:::hostedzone/RANDOM_ID_HERE_2"
},
{
"Sid": "vim1",
"Effect": "Allow",
"Action": "route53:ListHostedZones",
"Resource": "*"
}
]
}
Creates police in AWS
The file route53.txt is a JSON document in the current folder (or /path/to/route53.txt) that grants read/write only access to the DNS zone in an Amazon Route 53 DNS ID named RANDOM_ID_HERE_2:
$ aws iam create-policy --policy-name le-route53-wildcard-dns-verification --policy-document file:///path/to/route53.txt
{
"Policy": {
"PolicyName": "le-route53-wildcard-dns-verification",
"PolicyId": "AQPAZ4PKKZL7RYIBYM6YI",
"Arn": "arn:aws:iam::791914887124:policy/le-route53-wildcard-dns-verification",
"Path": "/",
"DefaultVersionId": "v1",
"AttachmentCount": 0,
"PermissionsBoundaryUsageCount": 0,
"IsAttachable": true,
"CreateDate": "2020-08-03T08:14:25+00:00",
"UpdateDate": "2020-08-03T08:14:25+00:00"
}
}
Please note down the Arn.
Create an AWS IAM account called “route53-dns-verification”
Type:
$ aws iam create-user --user-name route53-dns-verification
Assign AWS policy named “arn:aws:iam::791914887124:policy/le-route53-wildcard-dns-verification” to “route53-dns-verification” user account
Run:
$ aws iam attach-user-policy \
--policy-arn 'arn:aws:iam::791914887124:policy/le-route53-wildcard-dns-verification' \
--user-name route53-dns-verification
Create an access key for an IAM user named “route53-dns-verification”
You need to note down the AccessKeyId and SecretAccessKey after typing the following command. To ensure the security of your AWS account, the secret access key is accessible only during key and user creation. You must save the key if you want to be able to access it again. If a secret key is lost, you can delete the access keys for the associated user and then create new keys. Hence save them to a text file:
$ aws iam create-access-key --user-name route53-dns-verification
{ "AccessKey": { "UserName": "route53-dns-verification", "AccessKeyId": "AKIZY3PTTYXXXXXXXXXX", "Status": "Active", "SecretAccessKey": "58XYYYYYYYYYYYYYYYYYYYYYYYYgmdS", "CreateDate": "2020-08-03T08:47:29+00:00" } }
Step 2 – Installing acme.sh client
After getting Route53 API keys, now set up the acme.sh client. Hence, clone the acme.sh repo using the git command and then install the client using su command/sudo command
$ cd /tmp/
$ git clone https://github.com/Neilpang/acme.sh.git
$ sudo -i
# touch /root/.bashrc
# cd /tmp/acme.sh/
# acme.sh --install --accountemail your-email-id@domain-here
Step 3 – Requesting new wildcard TLS certificate for domain using Route53 DNS
So far we set up Nginx/Apache, obtained Route54 API/access keys, and now it is time to use acme.sh to get a wildcard certificate for nixcraft.com domain. First set up the AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY using export command as follows:
# export AWS_ACCESS_KEY_ID="AKIZY3PTTYXXXXXXXXXX"
# export AWS_SECRET_ACCESS_KEY="58XYYYYYYYYYYYYYYYYYYYYYYYYgmdS"
Finally, request the wildcard based TLS/SSL certificate using Route53 dns as validator for your domain. Make sure you replace nixcraft.com with your domain name:
# acme.sh --issue --dns dns_aws --ocsp-must-staple --keylength 4096 -d nixcraft.com -d '*.nixcraft.com'
Grab Elliptic-curve cryptography (ECC/ECDSA) instead of RSA certificate:
# acme.sh --issue --dns dns_aws --ocsp-must-staple --keylength ec-384 -d nixcraft.com -d '*.nixcraft.com'
Where,
- --issue : Issue a certificate
- --dns dns_aws : Use dns mode. In this case use AWS dns api.
- -ocsp-must-staple : Generate ocsp must Staple extension.
- --keylength ec-384 : Set the domain key length for ECC/ECDSA to ec-384. Please note that ec-521 currently not supported by the Let’s Encrypt.
- --keylength 4096 : Set the domain key length for RSA.
- -d nixcraft.com -d '*.nixcraft.com' : Your domain name to issue, renew or revoke certificate.
Your Route 53 DNS API/access key is stored in /root/.acme.sh/account.conf file and we can see it using the cat command or grep command:
# cat /root/.acme.sh/account.conf
# grep '_AWS_' /root/.acme.sh/account.conf
Hence, do not share the /root/.acme.sh/account.conf file with anyone.
Step 4 – Configuring Nginx HTTPS
Make sure you create a Diffie-Hellman key exchange file as follows using the openssl command:
# DOMAIN="www.nixcraft.com"
# mkdir -pv /etc/nginx/letsencrypt/${DOMAIN}/
# cd /etc/nginx/letsencrypt/${DOMAIN}/
# openssl dhparam -out dhparams.pem -dsaparam 4096
Then edit your Nginx config file or virtual domain file:
# vi /etc/nginx/vhosts.d/www.nixcraft.com.conf
Update/edit the file as follows:
# Port 80 config server { listen 80 default_server; # IPv4 listen [::]:80 default_server; # IPv6 server_name www.nixcraft.com; access_log off; error_log off; root /var/www/html; return 301 https://$host$request_uri; } # Port 443 config server { listen 443 ssl http2; # IPv4 listen [::]:443 ssl http2; # HTTP/2 TLS IPv6 server_name www.nixcraft.com; # domain name root /var/www/html; index index.html; # Set access and error log for this vhos access_log /var/log/nginx/www.nixcraft.com_access.log; error_log /var/log/nginx/www.nixcraft.com_error.log; # TLS/SSL CONFIG ssl_certificate /etc/nginx/ssl/letsencrypt/www.nixcraft.com/www.nixcraft.com.fullchain.cer; ssl_certificate_key /etc/nginx/ssl/letsencrypt/www.nixcraft.com/www.nixcraft.com.key; # ECC/ECDSA certificates (dual config) #ssl_certificate /etc/nginx/ssl/letsencrypt/www.nixcraft.com/www.nixcraft.com.fullchain.cer.ecc; #ssl_certificate_key /etc/nginx/ssl/letsencrypt/www.nixcraft.com/www.nixcraft.com.key.ecc; ssl_dhparam /etc/nginx/ssl/letsencrypt/www.nixcraft.com/dhparams.pem; # A little bit of optimization ssl_session_timeout 1d; ssl_session_cache shared:NixCraftSSL:10m; # TLS version 1.2 and 1.3 only ssl_session_tickets off; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; # HSTS (ngx_http_headers_module is required) # ************************************************************************* # WARNING - Wrong headers can create serious problems. Read docs otherwise # all 3rd party scripts/ads won't load and in some case # browser won't work. Read docs @ https://developer.mozilla.org # ************************************************************************* add_header Strict-Transport-Security "max-age=63072000" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Xss-Protection "1; mode=block" always; add_header Referrer-Policy strict-origin-when-cross-origin always; add_header Feature-policy "accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'" always; # *************************************************************************************************** # WARNING: The HTTP Content-Security-Policy response header allows sysadmin/developers # to control resources the user agent is allowed to load for a given page. # Wrong config can create problems for third party scripts/ad networks. Hence read the following url: # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy # **************************************************************************************************** add_header content-security-policy "default-src https://www.nixcraft.com:443" always; # OCSP stapling # Verify chain of trust of OCSP response using Root CA and Intermediate certs ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/nginx/ssl/letsencrypt/www.nixcraft.com/www.nixcraft.com.fullchain.cer; # Replace with the IP address of your resolver resolver 8.8.8.8; }
Step 5 – Installing certificate
Install the issued certificate to apache/nginx or any other server as per your set up. Make sure you replace the “/bin/systemctl reload nginx” as per your Linux/Unix distro:
# DOMAIN="www.nixcraft.com"
# CONFIG_ROOT="/etc/nginx/ssl/letsencrypt/$DOMAIN"
# acme.sh -d "$DOMAIN" \
--install-cert \
--reloadcmd "/bin/systemctl reload nginx" \
--fullchain-file "${CONFIG_ROOT}/$DOMAIN.fullchain.cer" \
--key-file "${CONFIG_ROOT}/$DOMAIN.key" \
--cert-file "${CONFIG_ROOT}/$DOMAIN.cer"
Install the ECC cert if you are using them too:
# acme.sh -d "$DOMAIN" \
--ecc \
--install-cert \
--reloadcmd "/bin/systemctl reload nginx" \
--fullchain-file "${CONFIG_ROOT}/$DOMAIN.fullchain.cer.ecc" \
--key-file "${CONFIG_ROOT}/$DOMAIN.key.ecc" \
--cert-file "${CONFIG_ROOT}/$DOMAIN.cer.ecc"
Step 6 – Testing your nginx set up
Make sure you open Nginx server tcp port # 443 if not already opened. For example, here is how we can open it on Ubuntu or Debian Linux:
$ sudo ufw allow https comment 'Open all to access Nginx port 443'
Fire a web browser and type the url:
https://www.nixcraft.com/
Of course we can visit SSL labs to test our TLS/SSL config page. Another option is to run the testssl.sh command as follows:
$ testssl.sh --fast --parallel https://www.nixcraft.com/
Wildcard SSL certs from Let’s Encrypt issued using acme.sh and Route53 DNS.
Conclusion
There you have it, and we used acme.sh and Route53 DNS to use the DNS challenge verification to obtain the certificates. You learned how to make a wildcard TLS/SSL certificate for your domain using acme.sh and AWS Route53 DNS API for domain verification. Please note that acme.sh automatically configure a cron jobs to renew our wildcard based certificate. You can now install certificates to ISP load balancer, Apache, Postfix smtpd, mysqld server or even use on LAN that are not open from the internet.
- Set up Lets Encrypt on Debian/Ubuntu Linux
- Secure Lighttpd with Lets Encrypt certificate on Debian/Ubuntu
- Configure Nginx with Lets Encrypt certificate on Alpine Linux
- Nginx with Lets Encrypt on CentOS 7
- Apache with Lets Encrypt Certificates on RHEL 8
- CentOS 8 and Apache with Lets Encrypt Certificates
- Install Lets Encrypt certificates on CentOS 8 for Nginx
- Forcefully renew Let's Encrypt certificate
- OpenSUSE Linux and Nginx with Let's Encrypt Certificates
- Configure Nginx to use TLS 1.2 / 1.3 only
- Let's Encrypt wildcard certificate with acme.sh and Cloudflare DNS
- Nginx with Let's Encrypt on Ubuntu 18.04 with DNS Validation
- AWS Route 53 Let's Encrypt wildcard certificate with acme.sh
🐧 Get the latest tutorials on Linux, Open Source & DevOps via:
- RSS feed or Weekly email newsletter
- Share on Twitter • Facebook • 8 comments... add one ↓
Category | List of Unix and Linux commands |
---|---|
File Management | cat |
Firewall | Alpine Awall • CentOS 8 • OpenSUSE • RHEL 8 • Ubuntu 16.04 • Ubuntu 18.04 • Ubuntu 20.04 |
Network Utilities | dig • host • ip • nmap |
OpenVPN | CentOS 7 • CentOS 8 • Debian 10 • Debian 8/9 • Ubuntu 18.04 • Ubuntu 20.04 |
Package Manager | apk • apt |
Processes Management | bg • chroot • cron • disown • fg • jobs • killall • kill • pidof • pstree • pwdx • time |
Searching | grep • whereis • which |
User Information | groups • id • lastcomm • last • lid/libuser-lid • logname • members • users • whoami • who • w |
WireGuard VPN | Alpine • CentOS 8 • Debian 10 • Firewall • Ubuntu 20.04 |
Hi,
Nice write up. Is it possible to restrict AWS custom policy to web server IPv4 address 1.2.3.4?
Not tested it but it is doable with Condition https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html
Jesus. Way too complicated with JSON crap. AWS overestimated and costly. I like using Digitalocean. Simple and easy to use. AWS bad. No wonder Linux people and developer think they are god with all this commands.
Why bother commenting when you don’t have any knowledge about AWS? It is industry leader in cloud computing.
Why acme.sh? Certbot is much better client. Am I missing something?
“acme.sh” is POSIX shell script based AMCE client. Perfect for Docker or any other Linux containers tech. No need to install Python which is needed for Certbot.
I made an example using Traefik and docker here: https://github.com/Praqma/traefik-bitbucker-docker-demo
Which, I think, is a bit easier.
But you also state in the conclusion “or even use on LAN that are not open from the internet.”
I don’t understand this. With DNS-01 challenge LetsEncrypt verifies you are who you say you are with the DNS provider (route53 here). But the client (acme.sh in this case) has to retrieve it. So how could that be on a lan behind a firewall with no internet access?
Also I am quite sure LetsEncrypt does NOT publish I.P. ranges which you can whitelist in your firewall.
I mean port 80/443 not opened or forwarded at the firewall level at the home server or dev workstation. I Will update the wording to make it clear. HTH