Setting up an HTTPS site using Nodejs, AWS EC2, Nginx, Let’s Encrypt, and Namecheap

1. Create an AWS EC2 instance

Log into AWS and create an account if you don’t have one already. Log in and you should see your dashboard, or a list of services

Select EC2. Then select Launch Instance.

If you are just prototyping a simple website then choosing the latest Ubuntu Server image is fine. Make sure to save your private key somewhere safe.

2. Connecting to your EC2 instance

Test your new EC2 instance by connecting to it.

ssh -i keyname.pem user@your-ec2-address

Or press the Connect button while on your EC2 console for exact instructions.

Your ec2 address looks something like ec2-55-55-555-55.xx-yyyy-5.compute.amazonaws.com

Success? Great good to go!

3. Setup your Security Groups

Let’s open up some ports so requests can make it to our VM. At the AWS Dashboard, find the link to “Security Groups” on the left

Then click “Create”

Make the following rules

Click the “Create” button in the bottom right. Next, go back to “Instances” and under “Actions” select “Networking”->”Change Security Groups” and select your newly created security group. Mine was called something like launch-wizard-1. Remember to click “Assign Security Groups” after you check the box.

4. Create your Elastic IP

This allows for better DNS.

Click the blue “Allocate new address” button, then select “Allocate”. Next, select the created Elastic IP and select “Actions”->”Associate”. Then select your EC2 Instance. It’s that easy.

5. Create and configure a Hosted Zone

We will use the Route 53 service for this. Select it from the Services menu.

Select “Create Hosted Zone”

Hit “Create”. Back at the Route 53 Dashboard, select the created Hosted Zone and click “Go to Record Sets”.Click “Create Record Set”, leave the Name field blank, and place your Elastic IP into the Value field. Then, hit Create.

Hit “Create Record Set” again. Put “www” in the Name field, and place your Elastic IP into the Value field. Then, hit Create.

Next, click the Go to Record Sets button. Take the dns servers in the Values column of your NS record…

And set your Namecheap DNS servers to them (without the period at the end). Yours may be different than mine. These may take up to a few hours to propogate.

6. Set up Nginx

Right. Now lets ssh into our EC2 instance and setup the Nginx webserver.

sudo apt-get install nginx

Navigating to your Elastic IP, you will see the default Nginx page.

Next, let’s setup Let’s Encrypt using Certbot.

cd /etc/nginx/sites-available
sudo nano default

Edit the lines near the top specifying the server name

server {
      listen 80 default_server;
      listen [::]:80 default_server;

Replace both the two “listen” lines with the following. Ues your domain instead of “example.com”

listen 80 example.com www.example.com

Let’s install certbot and build our certificate.

sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx

And make it!

sudo certbot --nginx -d example.com -d www.example.com

It may prompt you for some things. Follow the instructions. Now lets configure Nginx to be a reverse proxy to our application.

cd /etc/nginx/sites-available
cp default default.bak
sudo nano default

Here is a popular reverse proxy https config that you can replace the server block with. Remember to replace example.com with your domain.

server {
     listen 80;
     listen [::]:80;
     server_name example.com www.example.com;
     return 301 https://$server_name$request_uri;
}
server {
     listen 443 ssl http2 default_server;
     listen [::]:443 ssl http2 default_server;
     server_name example.com www.example.com;
     location / {
          proxy_pass http://localhost:3000;
     }
     ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
     ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
     ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
     ssl_prefer_server_ciphers on;
     ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
     ssl_session_cache shared:SSL:5m;
     ssl_session_timeout 1h;
     add_header Strict-Transport-Security “max-age=15768000” always;
}

And now just restart Nginx

sudo service nginx restart

7. Run your App!

The reverse proxy is set to forward everything to port 3000 which is the default Express port!

cd ~/yourapp
npm start

Visit your domain name to see all the https goodness!

Leave a Reply

Your email address will not be published. Required fields are marked *