Introduction

I have written a Long and Detailed Article about deploying a Node.js application using AWS. This is a brief cheatsheet for quick lookups.

Creating a Ubuntu Linux Instance using AWS EC2

Creation of Instance - On the EC2 Dashboard, select the Launch Instance option.

Choose Amazon Machine Image (AMI) - Choose the Amazon Machine Image, this post is written in context of Ubuntu 20.04

Choose the Instance Type - t2.micro qualifies for free-tier, also this is sufficient for small web apps.

Instance Configuration - Leave the defaults, basically this section asks for no of instances (for scaling up the application), custom virtual private cloud (VPC) settings, IAM roles etc.

Storage - The defaults should suffice.

Security Groups - Add rules to allow traffic from HTTP and HTTPS.

Reviewing the Instance - In this step, we can see our AMI, instance type, security groups, storage and other info. Hit Launch to create the instance.

Upon Launch, we have to create a key-pair which is to be used as a private key for SSHing into our created instance. Create and store this key-pair safely.

A GIF walkthrough of the creation process

Connecting to the Instance

Go to EC2 > Instances > Instance-ID > Connect to Instance -> SSH Client

  • chmod 400 - To protect a file against accidental overwriting.
chmod 400 "your-key.pem"
ssh -i /path/my-key-pair.pem my-instance-user-name@my-instance-public-dns-name
# Example
ssh -i "you-key.pem" ubuntu@ec2-xx-xx-xxx-xx.region.compute.amazonaws.com

Installing Node/NPM

curl -fsSL https://deb.nodesource.com/setup_15.x | sudo -E bash -
sudo apt-get install -y nodejs
node --version

Check out the NodeSource link for detailed installation instructions on other platforms/versions.

Link to NodeSource for Node.js Binary Distributions: https://github.com/nodesource/distributions/blob/master/README.md

Cloning your project from Github/Bitbucket/Gitlab

Connect your account via SSH and clone your repository.

Links for connecting SSH via Github/Gitlab/Bitbucket

Provider Links
Github https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh
Gitlab https://docs.gitlab.com/ee/ssh/
Bitbucket https://support.atlassian.com/bitbucket-cloud/docs/set-up-an-ssh-key

Install all the associated Dependencies

Go to your folder containing package.json and run,

# If using yarn, install yarn too.
# npm i -g yarn
yarn install

# Tests if any
yarn test

Setting up PM2 for Node.js

# Install PM2 using NPM or Yarn

sudo npm i pm2 -g
# or
sudo yarn add global pm2

# Go to your app's entry file
pm2 start app.js # (or whatever your file name)

PM2 Commands for Reference

Note: Refer to my longer article

You can use the below command to use your npm/yarn start script via PM2.

For running your npm.yarn start script in package.json
pm2 start yarn -- start
pm2 start npm -- start

Setting up NGINX

sudo apt install nginx

Now, we need to change the default configuration.

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

Add the following snippet to the server block.

    server_name yourdomain.com www.yourdomain.com;

    location / {
        proxy_pass http://localhost:8000; # Whatever port your app runs on
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

Note: Explanation of the above Code Snippet listed on my longer article

After adding the above code snippet, check NGINX config for errors and restart nginx.

Run this to check NGINX config
sudo nginx -t

#output nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful

Restart NGINX service

sudo service nginx restart

Now to check NGINX status,

sudo systemctl status nginx
# If you get this output then success!

● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since DAY YYYY-MM-DD HH:M:SS UTC; X days ago
Docs: man:nginx(8)
Main PID: xxxx (nginx)
Tasks: 2 (limit: 1160)
Memory: X M
CGroup: /system.slice/nginx.service
├─ xxxx nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
└─xxxx nginx: worker process

You should now be able to visit your IP with no port (port 80) and see your app.

Setting up Custom Domain for our EC2 Instance

Note: For detailed explanation check out my longer article

Setting up and managing DNS for a Custom Domain using domain name provider’s basic DNS

All you have to do is create two A records in the DNS records section.

That’s it process complete, depending on your provider. It might take some time for the actual DNS propagation.

Setting up a Hosted zone and Managing DNS for a Custom Domain using Route53

Note: Hosted Zone doesn’t come under a free-tier, hosted zone is paid.

Refer: https://aws.amazon.com/route53/pricing/

Create a hosted zone

Add your domain, description, type (public here) and hit Create hosted zone

In the Hosted Zone dashboard, we can see the Record, Type, Value/Route traffic to options.

We need to create two A records, to route all traffic hitting yourdomain.com and www.yourdomain.com to the public ip of the created EC2 Instance.

Creating @ record

Creating WWW record

Now, the hosted zone dashboard should look like this.

Updating Name Server Records (NS)

We need to add the NS Record values to our custom domain provider’s nameserver section.

Find the name server records associated with your domain.

  • ns-xxx.awsdns-xx.org
  • ns-xxx.awsdns-xx.com
  • ns-xxx.awsdns-xx.co.uk
  • ns-xxx.awsdns-xx.net

Add them to your domain name provider’s Nameserver section.

Refer to my Long and Detailed Article

Name.com

  • You will need to remove all nsx.name.com records and add the above aws nsrecords associated with your domain.

Refer: https://www.name.com/support/articles/205934547-Changing-nameservers-for-DNS-management

Namecheap

Similarly, add the nameservers to your domain name provider’s nameserver section.

Now, nameserver & DNS progression will take some time. You might have to wait up to 24 or above hours depending on your provider.

Mostly it happens in 1 hour or so, do check every hour. You can use nslookup or dig to check dns response. Sample nslookup and dig output given below.

Add SSL with LetsEncrypt for HTTPs

SSL, or Secure Sockets Layer, is an encryption based Internet security protocol. A website that implements SSL/TLS has “HTTPS” in its URL instead of “HTTP.”

sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Certbot can automatically configure SSL for Nginx.

Check NGINX Configuration
sudo nginx -t
Restart NGINX
sudo systemctl reload nginx
Certificate is only valid for 90 days. Test the renewal process with
certbot renew --dry-run

Now visit https://yourdomain.com and you would see your app.

Cheers!

Pic Credits: Photo by Long Phan