How to Setup a HTTPS Node JS Server on Amazon EC2

2021/3/1·10 min read

Table of Contents

  1. Introduction
  2. Requirements
  3. Setup Simple Express.js Web Server by Using Linux EC2
  4. SSH into the EC2
  5. Test the Express.js Web App
  6. Use PM2 to Run Express.js App
  7. Test PM2 App
  8. Test by Using the EC2 Public IP
  9. Create SSL/TLS Certificate via AWS ACM
  10. Hosted zones - create new hosted zone with domain name example.com
  11. Update Registered domain's name servers
  12. Request AWS Certificate
  13. Setup AWS Application Load Balancer
  14. Create Target Group for Application Load Balancer
  15. configure Route 53 with AWS Application Load Balancer
  16. Conclusion

Introduction

This blog is a guide that shows how to set up HTTPS node.js web server on EC2 from beginning to end. It'll include how to set up a simple Express.js web app on EC2, how to create an SSL/TSL certificate by using AWS Certificate Manager, how to setup AWS application load balancer and create redirect rule from non-www to www, HTTP to HTTPS, and how to use Route 53 to configure a route from your custom domain to the AWS application load balancer. This blog will assume the domain name is example.com, at the end of the blog, we'd like all the http://example.com, http://www.example.com, https://example.com traffic redirect to https://www.example.com.

Requirements

  • AWS Account
    • First of all you'll need an AWS account, if you don't have one already you can create one should be get an AWS free tier for a year.
  • Custom Domain
    • Another requirement is the domain name if you wish to walk through with this blog's steps.
    • Purchase from AWS
      • So if you don't have a domain name but you wish to get one, you could get one from AWS route 53 to register a domain. AWS has the ability to purchase a domain name similar to the Godaddy and any other domain hosting company, below is the page at AWS where you can search and purchase domain name.
      • AWS Route 53 Register Domain
      • Once purchased new domain is done, later at this blog we'll connect this domain's name server to the route 53 NS record. You'll need to create route 53 Hosted zoned with the domain you just purchased.

Below is example of domain name's name server

ns-111.awsdns-11.co.uk.
ns-234.awsdns-22.net.
ns-12312asd.awsdns-33.org.
ns-123a.awsdns-44.com.

If you already have a domain name at another domain hosting company and want to use that at AWS route 53, most likely what you have to do is use the domain name at route53 to create new public host record, once you created the hosted zone, you will get NS and SOA records, then you'll use the NS record and enter that at your domain hosting's site. (e.g. GoDaddy) In this way, the name server at your hosting site will redirect the traffic to the AWS route53 account.

For example, if you have a custom domain, example.com at Godaddy, then go to the GoDaddy DNS management and choose to enter your own nameservers for the example.com, then adding the above 4 NS records to the GoDaddy, after entering all of the name servers from AWS route 53 to Godaddy, Godaddy should be able to route the domain to your AWS route 53, but how to point Godaddy domain name to AWS Route 53 is not included for this blog.

Setup Simple Express.js Web Server by Using Linux EC2

The first step of the route53 configure is done, at here, we'll try to set up the express.js web app at the EC2 manually. Go to EC2, click Launch Instances and Choose Amazon Linux 2 AMI, choose t2.micro as Instance type, at the Configure Instance Details' User data section, paste following section.

  • enter the EC2 name
  • create key pair if don't have
  • other leave default
  • Create EC2 Instance

Put below code to the User Data section, we specific the node.js to be 14 cause at the moment create this blog that's the version which had verified it is working.

sudo yum update -y
#!/bin/bash -ex
# output user data logs into a separate place for debugging
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1 | sudo bash -
# get node into yum - with version 14.16.1
curl -fsSL https://rpm.nodesource.com/setup_14.x | sudo bash -
# install node (and npm) with yum
sudo yum install -y nodejs
# install pm2 to restart node app
npm i -g pm2@2.4.3

Click Launch Instance to create a new Instance, should be done pretty quickly.

Set Inbound Rule for port 80

After setup the EC2 instance, make sure the inbound rule has 80 , Type is HTTP and Source is 0.0.0.0/0.

  • Create EC2 Instance

At the next step, we'll Configure Security Group, make sure to open HTTP, HTTPS, and SSH, because later we'll have to ssh into this instance.

Also, once you create the instance, we'll manually SSH into the instance and install the node.js and PM2 package.

SSH into the EC2

There're few way to SSH into the instance as show below, the easiest one is EC2 Instance Connect which will be using the browser.

  • Choice to SSH into the EC2

After ssh into the EC2, let's run the following script, run the sudo su to make sure everything is easier. Then, we'll create an app folder and create app.js file to start express.js.

First, let's check the version by run following command, you should see node version is v14.21.0, npm version is 6.14.17, and pm2 is 2.4.3.

npm -v
node -v
pm2 -v

If you see some error from output that can not recognize npm command, maybe run the below command again.

sudo yum update -y
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1 | sudo bash -
curl -fsSL https://rpm.nodesource.com/setup_14.x | sudo bash -
sudo yum install -y nodejs
npm i -g pm2@2.4.3

Now, once npm or node command confirmed running, let's run the below script to install the express.

sudo su
# create app folder
mkdir -p /var/www/app && cd /var/www/app
npm init -y
npm install express --save
nano app.js

nano app.js will try to create file app.js, so next add below code to the command window.

Add code to app.js

Following code is a sample to start express.js, when you type URL will return the Hello World! message.

var express = require('express');
var app = express();
app.get('/', function (req, res) {
  res.send('Hello World!');
});
app.listen(80, function () {
  console.log('Example app listening on port 80!');
});

Test the Express.js Web App

Run the following command to test if the express.js app is able to run on the local of the Linux window. If you see this log from command window 'Example app listening on port 80!', our test is done.

node app.js

Use PM2 to Run Express.js App

Use the above command can't keep the express.js run forever, when you exist the SSH window, the node.js is close. So we'll use PM2 at here, PM2 is production process manager for nod.js and can keep application alive forever.

To run pm2 simply just run below command at the linux.

pm2 start app.js

PM2 status

Test PM2 App

Now, if the above pm2 success, the express.js should running on the Amazon Linux EC2 with port 80 even if you stop ssh into this instance. Let's run the following command to test it out inside the linux instance, If return the same message that's good.

curl http://localhost:80

Test by Using the EC2 Public IP

Another test you should test is to copy the EC2 public instance IP to the browser to make sure you see the same message Hello World! or not. If it does mean the EC2 part is finished, now we can create an HTTPS certificate, Load balancer, and Configure route 53 now.

Create Public Hosted Zone

Here we start creating public hosted zone and assume either you have registered domain name from AWS or route from other register domain host.

Create public hosted zone

Create hosted zone

Verified 2 Record created, one is NS and another is SOA **.

Create hosted zone

Create SSL/TLS Certificate via AWS ACM

Now, before creating the ACM, we assume we'll use the custom domain example.com, we would also expect to see the following URL and they should all go to the same Linux EC2 instance we created earlier.

  • http://example.com
  • http://www.example.com
  • https://example.com
  • https://www.example.com

As you can see, we'll have to create an SSL certificate and should be able to use it by https://example.com and https://www.example.com.

Here, we assume the domain is registered at AWS so we can continue with below steps.

Hosted zones - create new hosted zone with domain name example.com

Once you create a example.com, you should see 2 records, NS and SOA type, the NS should has 4 values, probably something looks like below.

......com.
......org.
......co.uk.
......net.

Now, this 2 value are important, since we use registered our domain at AWS, we need to update above 4 value to the registered domain.

Update Registered domain's name servers

go to the registered domains, click the Add or edit name servers, update the Name servers value from NS records' value. Update Name servers

name servers -> NS records Once above steps had confirmed, then we can go to ACM to create certificate, otherwise might see error during the process.

Request AWS Certificate

Go to the AWS ACM, click Request a certificate and choose Request a public certificate, at the windows of Add domain names, add *.example.com, then also add the following 2 as another name to this certificate, example.com, www.example.com. In this way, you can create one certification and will be valid for both example.com and www.example.com.

Request a public certificate

Request a Public certificate

List of domain name and validation method

Request a Public certificate

Click the Create records in Route 53

Create records in Route 53

At the validation method, choose DNS validation, and click Create a record in Route 53, so it will create an HTTPS record into route 53.

Success in ACM creation We want to create these 3 domain name, once domain created and new records add to route 53, you will see as below. Success in ACM

Setup AWS Application Load Balancer

Once the EC2 and SSL/TLS certificates are ready, we can set up an AWS Application load balancer now. The reason we use an application load balancer is the SSL certificate, if we want to use an AWS ACM certificate, you can't directly use it for the EC2 instance at this moment. You'll have to use either AWS Load Balancer or AWS CloudFront. Also, we'll use the Application load balancer to write redirect rules from HTTP to HTTPS, non-www to www.

Configure AWS Application Load Balancer

Go to EC2 and click the Load Balancers section, click to create Application Load Balancer. Enter following at the configure load balancer window.

  • Enter a name for this application load balancer
  • choose for internet-facing
  • Use IPv4
  • make sure has HTTP with port 80
  • make sure has HTTPS with port 443
  • choose your VPC and select the availability zone

At the window for the select default certificate, we'll choose the certificate we create at ACM. Choose the Choose a certificate from ACM and select the certificate we create, should be *.example.com.Leave everything else as default and choose the security group, make sure the security group has the port open for HTTP and HTTPS because we'll have our load balancer open to the public.

In summary, below is what we just setup for application load balancer, note if you didn't config ACM correctly, you won't see any choice at SSL/TLS certificate section. Application Load Balancer Summary

Create Target Group for Application Load Balancer

As part of the process of creating AWS Application Load Balancer, it will require creating a target group, you'll need to add the EC2 instance and set up health check configure, so when we launch the application load balancer it will use the EC2 instance we created before. Here, add the EC2 instance we created earlier at this blog, and leave the health check as default as well.

Test Load Balancer Access

To test load balancer setup, copy the ALB's DNS name we just created and put it to the browser, if you're able to see the Hello World!, that means we are able to setup the load balancer and underneath is using the EC2 Instance.

How to add rules for AWS application load balancer

At here, we'll add a redirect rule for AWS application load balancer to handler HTTP to HTTPS, none-www to www, so at the end, all traffic should go to https://www.example.com.

First, choose the load balancer, click Listeners and click the View/edit rules at HTTP:80. At the rule page, choose to add a new rule, and add the following for the if area.

  • Choose Host header,
  • and add example.com and www.example.com

At the Then area, add the following

  • Choose Redirect
  • Choose HTTPS, and port set as 443
  • Choose Custom host, path, query
  • Modify the Host as, www.example.com
  • Choose 301, as permanently moved

Click confirm and update button to update your change, above change is for HTTP port direct for the example.com, so http://example.com and http://www.example.com will redirect to https://www.example.com. Now, let's go to the 443 HTTPS port to modify the rule.

At the HTTPS rule's if area, add the following

  • Choose Host
  • Add example.com

At the then area, add the following

  • Choose Redirect
  • Choose HTTPS, and port set as 443
  • Choose Custom host, path, query
  • Modify the Host to, www.example.com
  • Choose 301, as permanently moved

Click confirm and update button to update your change, above change is for HTTPS port redirect for the example.com, so https://example.com will redirect to https://www.example.com. That's all the redirect rules we'll need for setup at AWS application load balancer.

Now, the last part is we'll configure route53 to route traffic to the application load balancer.

configure Route 53 with AWS Application Load Balancer

At this point, the EC2 and the application load balancer should all be running, but if you type www.example.com at your browser you still get "This site can't be reached" DNS errors. We'll fix it here, we'll configure Route 53 to route to the AWS application load balancer we just created.

Let's go to AWS Route 53 and click the Hosted zones for your custom domain, on this blog we've been using example.com, so you should see 3 records at the hosted zone. NS, SOA when first create the hosted zone, and CNAME created by the ACM certificate.

Now, create one record as following, this will route traffic for www.example.com to the application load balancer, after creating this record, if you type the http://www.example.com or https://www.example.com, you should see the same page when directly open the EC2 or application load balancer.

  • Record names, www.example.com
  • Type, A
  • Route traffic to, choose Alias
    • Choose the Application and Classic Load Balancer, then select the application we just configured
  • Routing policy, choose Simple routing

Now, we need to create the last one record, this will route traffic for example.com to the application load balancer, after creating this record, if you type the http://example.com or https://example.com, you should see it redirect to the get www.example.com.

  • Record names, leave as example.com
  • Type, A
  • Route traffic to, choose Alias
    • Choose as Alias to another record in this hosted zone
    • type, www.example.com
  • Routing policy, choose Simple routing

That's all for setting up Route 53, now, if you type http://example.com, http://www.example.com, https://example.com will all go to the https://www.example.com.

Conclusion

It requires some steps to set up HTTPS node.js on AWS EC2, with AWS Application Load Balancer and Route 53, next we'll see how we can automate this steps.