Setup an Ubuntu NestJS API Server with Nginx in AWS EC2

Kingyinma
5 min readOct 15, 2020

--

Go to AWS Console, prepare remote ssh group

Create an EC2 instance

Better to create an elastic IP and associate to this instance

ssh to instance,

ssh ubuntu@{your_host} -i ~/.ssh/{your_instance}.pem

better change root password, change to root user

sudo -i

change root password

passwd

add new user for deployment instead of root

adduser {username}

for me, i want to create new user, deploy, then

adduser deploy

input password twice

Modify user account

usermod -aG sudo {new-username}

i.e.

usermod -aG sudo deploy

Sync user

rsync --archive --chown={new-username}:{new-username} ~/.ssh /home/{new-username}

i.e.

rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy

Install Nginx (latest)

sudo wget https://nginx.org/keys/nginx_signing.key
sudo apt-key add nginx_signing.key

update sources.list

sudo vi /etc/apt/sources.list
# add below 2 lines
deb https://nginx.org/packages/mainline/ubuntu/ bionic nginx
deb-src https://nginx.org/packages/mainline/ubuntu/ bionic nginx

then install nginx

sudo apt-get remove nginx-common
sudo apt update
sudo apt install nginx

Adjust Firewall

sudo ufw app list

Show list of app

Available applications:Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH

Enable Nginx HTTP or Nginx Full

sudo ufw allow 'Nginx Full'

if fails, since no alias application available, then we can directly use port

sudo ufw allow 80
sudo ufw allow 443

Check ufw status

sudo ufw status

It shows inactive status, to enable ufw, it prompts Command may disrupt existing ssh connections. Proceed with operation (y|n)

sudo ufw enable

Set ssh allow

sudo ufw allow ssh

Check ufw status again

Nginx Full                 ALLOW       Anywhere
Nginx HTTP ALLOW Anywhere
22/tcp ALLOW Anywhere
Nginx Full (v6) ALLOW Anywhere (v6)
Nginx HTTP (v6) ALLOW Anywhere (v6)
22/tcp (v6) ALLOW Anywhere (v6)

Check rules that are set. The rest of this tutorial covers how to use UFW in more detail, like allowing or denying different kinds of connections.

sudo ufw status verbose

it shows

Status: activeLogging: on (low)Default: deny (incoming), allow (outgoing), disabled (routed)New profiles: skip

Check status of Nginx

systemctl status nginx

Setup Security Group of EC2 (all traffic first for example)

Type ip address in browser,

If you want to remove default website in nginx

sudo rm /etc/nginx/sites-enabled/default
// reload nginx
sudo service nginx reload

Edit nginx config file

sudo vi /etc/nginx/nginx.conf

Modify, append line include sites-enable folder

include /etc/nginx/sites-enabled/*;

Install Install Chinese Fonts (optional, depends on your web app)

sudo apt-get install fonts-noto

Install nvm

Go to github to check latest version of nvm, currently it is v0.36.0

Update package first as usual

sudo apt-get update

Get essential package

sudo apt-get install build-essential libssl-dev

Install nvm

curl https://raw.githubusercontent.com/creationix/nvm/v0.36.0/install.sh | bash

Exit Terminal, then ssh to server again

Next source profile

source ~/.profile

then check nvm version

nvm --version

it shows

0.36.0

Install Node js by nvm

You can check versions supported by nvm

nvm ls-remote

Install stable latest version, e.g. v12.19.0

nvm install v12.19.0

check node version

node --version

it shows

v12.19.0

if you want to switch to another version of node later, says you install v12.18.1 before

nvm use v12.18.1

Install yarn

Refer to official website of yarn,

curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -

Result show, “OK”, then input command below again

echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list

Update package again

sudo apt update

Install yarn

sudo apt install --no-install-recommends yarn

Or

echo "==> Installing Yarn package manager"rm -rf ~/.yarncurl -o- -L https://yarnpkg.com/install.sh | bash# Yarn configurations
export PATH="$HOME/.yarn/bin:$PATH"
yarn config set prefix ~/.yarn -g

Add the following in ~/.bashrc

export PATH="$HOME/.yarn/bin:$HOME/.config/yarn/global/node_modules/.bin:$PATH"

Check yarn version

yarn --version1.22.5

Find yarn location

which yarn# result
# /home/deploy/.yarn/bin/yarn

Clean cache

yarn cache clean

As our node js application always need to upload image to s3, it would be better to Install image conversion library like imagemagick, graphicsmagick

To install imagemagick, first need to uncommenting deb-src of ubuntu /etc/apt/sources.list

sudo vi /etc/apt/sources.list

to

then install imagemagick

sudo apt build-dep imagemagick

Intall graphicsmagick

sudo apt-get install software-properties-common
sudo add-apt-repository ppa:dhor/myway
sudo apt-get update
sudo apt-get install graphicsmagick

Setup a sample website

cd /etc/nginx/sites-available
sudo vi {server_name}.conf
or
sudo vi /etc/nginx/sites-available/{server_name}.conf

here i use example-api.conf

sudo vi example-api.conforsudo vi /etc/nginx/sites-available/example-api.conf

configure this site

server {   listen 80;   server_name api.example.com;   access_log /var/log/nginx/access.log;   client_max_body_size 20M;   location / {      proxy_http_version 1.1;      proxy_set_header X-Real-IP $remote_addr;      proxy_set_header HOST $host;      proxy_set_header X-NginX-Proxy true;      proxy_set_header Upgrade $http_upgrade;      proxy_set_header Connection 'upgrade';      proxy_cache_bypass $http_upgrade;      proxy_pass http://localhost:8086;      proxy_redirect off;    }}

next, link to sites-enabled

ln -s /etc/nginx/sites-available/{server_name}.conf /etc/nginx/sites-enabled/{server_name}.conf

i.e.

ln -s /etc/nginx/sites-available/example-api.conf /etc/nginx/sites-enabled/example-api.conf

Reload nginx

service nginx reload

Create a folder to store website, for this example i use sites

mkdir sites
cd sites
mkdir example-api

Use your own deployment method to copy files to this folder

Install pm2

yarn add global pm2#add path in .bashrc
PATH="$PATH:/home/deploy/.yarn/bin"

Check pm2 version

pm2 --version4.5.0

pm2 start application to corresponding path,

{your_site_folder} is the application you locate

{env} is the environment of your application define in code

pm2 kill && pm2 start ./api/{your_site_folder}/configs/pm2/pm2.{env}.json --env {env}

e.g.

pm2 kill && pm2 start ./api/example-api/configs/pm2/pm2.production.json --env production

startup pm2

# Detect available init system, generate configuration and enable startup system
pm2 startup

You can see instruction and run script as

$ pm2 startup
[PM2] You have to run this command as root. Execute the following command:
sudo su -c "env PATH=$PATH:/home/unitech/.nvm/versions/node/v4.3/bin pm2 startup <distribution> -u <user> --hp <home-path>

save pm2 setting

pm2 save

May prompt ask you input password

Type pm2 list and you can see your application is started

Ref: https://pm2.keymetrics.io/docs/usage/startup/

Cloudflare Setup page rule

A Record, example.com, IP Address

CNAME

Page Rule

Non-www, Always HTTPS

http://example.com/*

www redirect to non-www

https://example.com/$1

--

--

No responses yet