Jay Gould

Setting up SSL on an AWS EC2 instance with Nginx

February 29, 2020

A few months ago I published a 2 part post detailing how to run React and Node together on one AWS EC2 instance. After following that post myself recently to quickly set up another project, I noticed I’d missed a critical part of setting up a server for use - the SSL certificate. It’s not as straightforward as you’d hope to get an SSL installed for free, in my opinion anyway, so this post will list each step in a simple way.

Setup

First, you’ll want to make sure you have post 443 open on the AWS admin area. Log in, go to the “Network and Security” section, and open security groups. You should see the corresponding security group for your instance. Ensure protocol TCP is open with post 443, and this must be open twice with the following sources:

  • 0.0.0.0/0
  • ::/0

Installing the certificate(s)

Now the ports are open, we can begin the installation. Run the following:

sudo wget https://dl.eff.org/certbot-auto

This will download the certbot-auto file ready to be used. Before we can use, we must modify the file to be executed:

chmod a+x certbot-auto

You can then begin the installation of the certificate by running:

./certbot-auto --standalone -d WEBSITE_URL_HERE certonly

Be sure to change the website URL! And the “certbot-auto” refers to the file you just downloaded, so if you’re running from the same location you have downloaded the file, be sure to prefix with ”./“.

Another gotcha here is that the above command must be executed when the Nginx server has stopped, so be sure to run sudo service nginx stop beforehand, and sudo service nginx start afterwards.

After running this, you may encounter an error which says something like “Sorry, I don’t know how to bootstrap Certbot on your operating system!”. This may happen because the server may not have the pre-loaded software required, which happened to me when attempting to run on a newer EC2 instance. The fix is quite easy:

  • sudo nano certbot-auto
  • Scroll down to the line which says elif [ -f /etc/redhat-release ]; then (around line 800), and replace with elif [ -f /etc/redhat-release ] || grep 'cpe:.*:amazon_linux:2' /etc/os-release > /dev/null 2>&1; then
  • Save and quit

Continue with the process of generating the SSL from the original command - this will ask for your email address and some other questions.

Once installed, you’ll be presented with the SSL location - keep this to one side.

Adding to Nginx config

Following on from my previous post, this post assumes you already have your Nginx config in the /etc/nginx/sites-available directory. With the SSL installed, we want to:

  • Listen to SSL traffic on port 443 and reverse proxy that to our chosen port, with the SSL locations specified
  • Listen to non SSL traffic on port 80 and redirect this to https
// /etc/nginx/sites-available/my-site.com
server {

    server_name my-site.com;

    location /
    {
       	proxy_pass http://127.0.0.1:3000;
        include /etc/nginx/proxy_params;
    }
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/my-site.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/my-site.com/privkey.pem;
}

server {
    if ($host = my-site.com) {
        return 301 https://$host$request_uri;
    }

    server_name my-site.com;
    listen 80;
    return 404;
}

I like to separate my proxy params to another file at /etc/nginx/proxy_params:

// /etc/nginx/proxy_params

 proxy_buffers 16 32k;
 proxy_buffer_size 64k;
 proxy_busy_buffers_size 128k;
 proxy_cache_bypass $http_pragma $http_authorization;
 proxy_connect_timeout 59s;
 proxy_hide_header X-Powered-By;
 proxy_http_version 1.1;
 proxy_ignore_headers Cache-Control Expires;
 proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404;
 proxy_no_cache $http_pragma $http_authorization;
 proxy_pass_header Set-Cookie;
 proxy_read_timeout 600;
 proxy_redirect off;
 proxy_send_timeout 600;
 proxy_temp_file_write_size 64k;
 proxy_set_header Accept-Encoding '';
 proxy_set_header Cookie $http_cookie;
 proxy_set_header Host $host;
 proxy_set_header Proxy '';
 proxy_set_header Referer $http_referer;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Forwarded-Host $host;
 proxy_set_header X-Forwarded-Server $host;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-Forwarded-Proto $scheme;
 proxy_set_header X-Original-Request $request_uri;

Once set up, restart the server:

sudo service nginx start or sudo service nginx reload

At this point, if there are any error messages, run the following command to find out what’s causing those pesky errors:

nginx -t -c /etc/nginx/nginx.conf

In the future, if you need to re-install, just log in to the EC2 instance and run:

sudo certbot --nginx -d WEBSITE_URL_HERE

And this will prompt a re-install.

And you’re done! Thanks for reading.


Senior Engineer at Haven

© Jay Gould 2023, Built with love and tequila.