Last Updated: September 30, 2021
·
61.3K
· aeas44

HTTPS with Certbot for Nginx on Amazon Linux

Here's how you can configure Certbot for Nginx on Amazon Linux.

Create an EC2 instance on AWS

Make sure that the port 443 (SSL) and 22 (SSH) is open. In this tips, let's assume that we chose to use Amazon Linux.

Install Certbot

$ ssh -i ~/.ssh/my-aws.pem ec2-user@52.193.111.xxx
$ curl -O https://dl.eff.org/certbot-auto
$ chmod +x certbot-auto 
$ sudo mv certbot-auto /usr/local/bin/certbot-auto

Install Nginx

$ sudo yum install nginx -y

(Nginx must be stopped during Certbot installation)
$ sudo service nginx stop

Configure your domain to point to the EC2 instance

You can do it with Route53 or any other domain registrars.

Run Certbot

ec2-user on Amazon Linux sets /usr/local/bin as a part of $PATH so let's simply run following command:

(become a root user)
$ sudo su -

(Amazon Linux support is currently experimental, so don't forget to add "--debug" option. This will update the script itself when you run it for the first time)
# certbot-auto certonly --standalone -d example.com

(You'll be asked to enter your email address)

(Finally, you'll get a message like following)

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.com/fullchain.pem. Your cert will
   expire on 2016-mm-dd. To obtain a new version of the certificate in
   the future, simply run Certbot again.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Modify Nginx Configuration

Assuming that following commands are executed as root.

# cd /etc/nginx/
# cp nginx.conf nginx.conf.org

(Modify nginx.conf)
# vi nginx.conf

(The diff will be followings)
# diff nginx.conf nginx.conf.org
85,89c85,117
<     server {
<         listen       443 ssl;
<         listen       [::]:443 ssl;
<         server_name  localhost;
<         root         /usr/share/nginx/html;
---
> # Settings for a TLS enabled server.
> #
> #    server {
> #        listen       443 ssl;
> #        listen       [::]:443 ssl;
> #        server_name  localhost;
> #        root         /usr/share/nginx/html;
> #
> #        ssl_certificate "/etc/pki/nginx/server.crt";
> #        ssl_certificate_key "/etc/pki/nginx/private/server.key";
> #        # It is *strongly* recommended to generate unique DH parameters
> #        # Generate them with: openssl dhparam -out /etc/pki/nginx/dhparams.pem 2048
> #        #ssl_dhparam "/etc/pki/nginx/dhparams.pem";
> #        ssl_session_cache shared:SSL:1m;
> #        ssl_session_timeout  10m;
> #        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
> #        ssl_ciphers HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP;
> #        ssl_prefer_server_ciphers on;
> #
> #        # Load configuration files for the default server block.
> #        include /etc/nginx/default.d/*.conf;
> #
> #        location / {
> #        }
> #
> #        error_page 404 /404.html;
> #            location = /40x.html {
> #        }
> #
> #        error_page 500 502 503 504 /50x.html;
> #            location = /50x.html {
> #        }
> #    }
91,115d118
<         ssl_certificate "/etc/letsencrypt/live/example.com/fullchain.pem";
<         ssl_certificate_key "/etc/letsencrypt/live/example.com/privkey.pem";
<         # It is *strongly* recommended to generate unique DH parameters
<         # Generate them with: openssl dhparam -out /etc/pki/nginx/dhparams.pem 2048
<         #ssl_dhparam "/etc/pki/nginx/dhparams.pem";
<         ssl_session_cache shared:SSL:1m;
<         ssl_session_timeout  10m;
<         ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
<         ssl_ciphers HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP;
<         ssl_prefer_server_ciphers on;
< 
<         # Load configuration files for the default server block.
<         include /etc/nginx/default.d/*.conf;
< 
<         location / {
<         }
< 
<         error_page 404 /404.html;
<             location = /40x.html {
<         }
< 
<         error_page 500 502 503 504 /50x.html;
<             location = /50x.html {
<         }
<     }

Let's restart nginx after the change:

# service nginx start

HTTPS is available now!

Let's open https://example.com and check that it's actually working!

4 Responses
Add your response

When I run certbot-auto certonly -standalone --debug -d mydomain.com
as root using my domain, I get the following error:

Creating virtual environment... Installing Python packages... Installation succeeded. Traceback (most recent call last): File "/root/.local/share/letsencrypt/bin/letsencrypt", line 7, in <module> from certbot.main import main File "/root/.local/share/letsencrypt/local/lib/python2.7/dist-packages/certbot/main.py", line 12, in <module> import zope.component File "/root/.local/share/letsencrypt/local/lib/python2.7/dist-packages/zope/component/init.py", line 16, in <module> from zope.interface import Interface </code>

Do you have any tips as to what I can try in order to diagnose the problem?

over 1 year ago ·

@pstaight I just had the problem you mention when following the above. I didn't have virtualenv on my system...but I did have virtualenv-2.7 one quick ln -s /usr/bin/virtualenv-2.7 /usr/bin/virtualenv later and everything else worked beautifully.

over 1 year ago ·

Another thing that might be useful to mention is that since letsencrypt certs are only valid for 90 days we will want to auto renew. I played around with certbot-auto renew and it suggested I use certonly instead.

So I added the following to root's crontab:
* 3 15 * * /usr/local/bin/certbot-auto certonly -n --debug --pre-hook="service nginx stop" --post-hook="service nginx start" --standalone -d my.domain.example.com

  • --debug was a requirement for using this on Amazon linux (so certbot-auto told me).
  • -n runs it non-interactively
  • the entry runs once a month, at 3AM on the 15th of each month. If I was concerned that there might be some outage and the jobs get missed (and I end up with an expired cert) then I could up the frequency. certbot won't do anything until the cert is due for renewal (after 60 days).
  • I'm running nginx as a reverse proxy/SSL termination. It was easiest to bounce it so that certbot could authenticate in standalone mode (hence the --pre-hook and --post-hook).
over 1 year ago ·

So what happens if we need to tear down the instance and create a new one. Are we just able to copy over the generated certs to a new instance? I assume creating new certs on a new instance would make browsers suspicious.

over 1 year ago ·