Using the Let’s Encrypt Certbot to get HTTPS on your Amazon EC2 NGINX box

Karan Thakkar
We’ve moved to freeCodeCamp.org/news
3 min readJun 1, 2016

Let’s Encrypt is a new Certificate Authority which provides free SSL certificates (up to a certain limit per week). It came out of beta around a month back and is supported by a wide array of browsers.

Certbot is the official Let’s Encrypt client, developed by the Electronic Frontier Foundation. It makes automatically fetching and deploying SSL/TLS certificates for your web server a relatively straight forward process.

Lets get started.

Step #1

Make sure that you have opened up ports 80 (HTTP) and 443 (HTTPS) in your instance Security Group to public. Certbot will use this to establish connections while generating your certificates.

Note that I spent far too much time to figure out why I couldn’t generate a certificate, while the only issue was that I hadn’t opened up port 443 in my EC2 instance Security Group.

Inbound settings in EC2 Security Group

Step #2

Setup your domain’s CNAME Record to point to the public DNS of your EC2 instance.

Public DNS value in your EC2 instance description
This setting would point api.mydomain.com to my EC2 instance

Step #3

Install Certbot on your instance. Based on your operating system and server, you can find out how to install it on Certbot’s homepage. For NGINX on Ubuntu 14.04, use this.

wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto

Run this command in your home directory:

/home/ubtuntu

Step #4

Stop any existing servers running on the port 80 and 443, since those are used by Certbot to verify your domain and generate certificates.

You can restart those servers once you have finished generating the certificates.

Step #5

Run the following command to generate certificates for your domain:

./certbot-auto certonly --standalone -d xyz.yourdomain.com

You can generate certificates for multiple domains using this approach.

Step #6

Change your NGINX configuration in /etc/nginx/nginx.conf to enable SSL:

http {  ##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
server {
listen 80;
server_name xyz.yourdomain.com;
location / {
# Redirect any http requests to https
return 301 https://$server_name$request_uri;
}
}
server {
listen 443 ssl;
server_name xyz.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/xyz.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xyz.yourdomain.com/privkey.pem;
add_header Strict-Transport-Security “max-age=31536000”;

location / {
proxy_pass http://127.0.0.1:3000;
}
}
}

The Strict-Transport-Security (HSTS) header ensures that any internal links that are not HTTPS will automatically be routed to the HTTPS version during a HTTPS session.

Step #7

Lastly, reload your NGINX configuration:

sudo service nginx reload

Congratulations! Your site xyz.example.com is now successfully running on HTTPS.

NOTE: Let’s Encrypt certificates are only valid for 3 months after issue. So every 3 months, renewal is required. Here’s how you can automate this using a cron job.

If this post helped you, hit the heart button below. 😄 And if it didn’t, please leave a comment to tell me how I can make it better.

PS: Thanks to Narendra N Shetty for proofreading and giving suggestions.

--

--

Karan Thakkar
We’ve moved to freeCodeCamp.org/news

he/him 💖 staff engineer @Transferwise ⚛️ prev: @Skyscanner, @Crowdfire 👨‍💻