I was unable to find a straightforward guide to generating and automating LetsEncrypt on Amazon Linux so I have compiled the steps I used here in a hopefully straightforward guide. We will assume you’re already using nginx and Amazon Linux.

Prepare Your Server:

If you are not using docker, install docker

sudo yum update && sudo yum install -y docker

and start docker…

sudo service docker start

Modify Nginx Config:

Since we’re trying to keep our app up while the cert is generating we will use Nginx reloads to change the config without disruption to the user. Using an editor of your choice, add this location block to your Nginx site config listening on port 80. This allows LetsEncrypt / Certbot to authenticate without your users knowing anything is going on behind the scenes:

    location '/.well-known/acme-challenge' {
        default_type "text/plain";
        alias /var/www/letsencrypt;
    }

So all together it should look something like:

server {
    listen    80;
    server_name www.yoursite.com;
    location '/.well-known/acme-challenge' {
        default_type "text/plain";
        alias /var/www/temp;
    }
    location / {
        ... whatever else your config needs
    }
}

Let’s test our config to be sure:

nginx -t

If its good, reload like so:

service nginx reload

Now lets make our cert directories.

mkdir -p /var/www/certs /var/www/temp

We are ready to user docker to generate our certs. The docker image used in the command below is auto built directly from the Certbot GitHub repo. Here is the Docker Hub repo for your reference.

For reference: Certbot Documentation

docker run --rm -it -v "/var/www/temp:/var/www/temp" -v "/var/www/certs:/etc/letsencrypt" deliverous/certbot certonly -n -d www.yoursite.com --email you@example.com --webroot --webroot-path /var/www/temp

This will use the /var/www/temp directory to store files during the verification process. Nginx will serve them as directed by the config above while your users are happily browsing.

Shiny New Certs! Let’s Use Them!

Add an ssl server block to your Nginx conf file:

server {
    listen 443;
    server_name www.yoursite.com;
    ssl    on;
    ssl_certificate        /var/www/certs/live/www.yoursite.com/fullchain.pem;
    ssl_certificate_key    /var/www/certs/live/www.yoursite.com/privkey.pem;

    location / {
    ... The rest of your server block code ...
    }
}

You may also want to change your http server block to redirect to https. Use this location block in your https server block.

    location / {
        return 301 https://$server_name$request_uri;
    }

Test to make sure Nginx can read your newly generated cert files:

nginx -t

Now, go live!

service nginx reload

Automatically Renew:

Since LetsEncrypt certs are only valid for 90 days, we probably want to check often to see if today is renewal day. We will use cron to rerun our docker container command which will automatically renew our cert if it is within a given window.

Using an editor of your choice, create a script file like so:

#!/bin/bash
docker run --rm -v "/var/www/temp:/var/www/temp" -v "/var/www/certs:/etc/letsencrypt" deliverous/certbot certonly -n -d www.yoursite.com --email you@example.com --webroot --webroot-path /var/www/temp

*Please note: the -it flag in the docker command has been removed because cron is non interactive and will error if left in.

Save your file and enjoy free SSL certs that wont bring your site down when its time to renew!

Let me know if you have any questions. A huge Thank You goes out to the LetsEncrypt and Certbot teams.

-Paul