Overview of Deployment of a Node API Server

Overview of Deployment of a Node API Server

by John Vincent


Posted on May 2, 2020


The Node API Server supports various APIs that represent functionality that is used by a number of different applications.

Node API Server Technologies

Server

Production Deployment

Add Subdomain

Add subdomain, please see Configuring Google Domains

Add

Type: A
TTL: 1h
Data: 104.236.194.244

for each of

www.apis
apis

Verify subdomains

dig www.apis.johnvincent.io
dig apis.johnvincent.io

Configure HTTP Nginx

For details, please see Configure non-SSL Nginx

cd /var/www
sudo mkdir -p apis/html/.well-known

Create index.html

sudo vi /var/www/apis/html/index.html
<html>
    <head>
        <title>Welcome to apis!</title>
    </head>
    <body>
        <h1>Success! The server block is working!</h1>
    </body>
</html>

Permissions

sudo chown -R jv:jv /var/www/apis/html
cd /var/www/apis/html
find . -type d -print0 | xargs -0 chmod 0755
find . -type f -print0 | xargs -0 chmod 0644

Server block

sudo vi /etc/nginx/sites-available/http/apis
server {
  listen 80;
  listen [::]:80;

  server_name apis.johnvincent.io www.apis.johnvincent.io;
  root /var/www/apis/html;
  index index.html;

  location / {
    try_files $uri $uri/ =404;
  }
  location ~ /.well-known {
    allow all;
  }
}

Enable Server Block

Add to bin/enable-http and bin/enable-https

enable-http

Restart Nginx

nginx-restart

Test from browser

http://www.apis.johnvincent.io
http://apis.johnvincent.io

SSL Certificates

sudo letsencrypt certonly -a webroot --webroot-path=/var/www/apis/html -d apis.johnvincent.io -d www.apis.johnvincent.io

Create

sudo vi /etc/nginx/snippets/ssl-apis-johnvincent.io.conf

ssl_certificate /etc/letsencrypt/live/apis.johnvincent.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/apis.johnvincent.io/privkey.pem;

Configure HTTPS Nginx

For details, please see Configure SSL Nginx

cd /etc/nginx/sites-available/https
sudo vi apis
server {
    listen 80;
    listen [::]:80;
    server_name apis.johnvincent.io www.apis.johnvincent.io;
    return 301 https://www.apis.johnvincent.io$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
        include snippets/ssl-apis-johnvincent.io.conf;
    include snippets/ssl-params.conf;

    server_name apis.johnvincent.io;
    return 301 https://www.apis.johnvincent.io$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    include snippets/ssl-apis-johnvincent.io.conf;
    include snippets/ssl-params.conf;
    include h5bp/basic.conf;

    server_name www.apis.johnvincent.io;

        location / {
            proxy_pass http://localhost:3101;
        }
}

Notice proxying all through to the Node Server listening at http://localhost:3101

Enable Https

cd bin
./enable-https

Test from Browser

http://www.apis.johnvincent.io
http://apis.johnvincent.io

https://www.apis.johnvincent.io
https://apis.johnvincent.io
https://www.apis.johnvincent.io/api/word/random

Test SSL Certificates

Ensure all scores are A+

https://www.ssllabs.com/ssltest/analyze.html?d=apis.johnvincent.io
https://www.ssllabs.com/ssltest/analyze.html?d=www.apis.johnvincent.io

Create .env files

Development

Create .env

PORT=9444

LOG_LEVEL=debug
LOG_ENV=dev
# LOG_ENV=heroku
# LOG_ENV=prod

...

Production

Create /save-env/server-project/server.env

PORT=3101

LOG_LEVEL=debug
# LOG_ENV=dev
# LOG_ENV=heroku
LOG_ENV=prod

CLIENT_SERVER=https://www.hangman.johnvincent.io

...

Note that https://www.hangman.johnvincent.io is CORS enabled.

Create Server Directory

cd /var/www
sudo mkdir -p server-project/server

Permissions

sudo chown -R jv:jv /var/www/server-project/server
cd /var/www/server-project/server
find . -type d -print0 | xargs -0 chmod 0755
find . -type f -print0 | xargs -0 chmod 0644

PM2

Add to handle-pm2

echo "Check status of server-project"
pm2 describe server-project > /dev/null
RUNNING=$? 
if [ "${RUNNING}" -ne 0 ]; then
  echo "Adding server-project to PM2"
  cd /var/www/server-project/server
  pm2 start server.js --name "server-project"
else
  echo "Restarting server-project"
  pm2 restart server-project
fi;

Deployment Script

bin/deploy-server-project

#!/bin/sh
#
#  script to get, build and deploy the Node Server
#
# setup ssh to github
#
echo "setup ssh to github"
eval "$(ssh-agent)"
ssh-add -k ~/.ssh/id_github
#
cd
cd tmp

#
echo "Removing Logfile"
rm /home/jv/tmp/logfile.txt

#
CLONES_DIR="/home/jv/clones/server-project"
SERVER_ROOT_DIR="/var/www/server-project/server"
SAVE_ENV_DIR="/home/jv/save-env/server-project"
#
echo "Removing clones directory $CLONES_DIR"
rm -rf $CLONES_DIR
#
echo "Creating clones directory $CLONES_DIR"
mkdir $CLONES_DIR
cd $CLONES_DIR
#
echo "Git clone desired repositories to $CLONES_DIR"
git clone git@github.com:johnvincentio/server-project $CLONES_DIR

#
#  Make Node Server
#
# copy .env file
#
echo "Copy Node Server .env file to $CLONES_DIR"
cp -r $SAVE_ENV_DIR/server.env $CLONES_DIR/.env

#
echo "Make the Node Server"
cd $CLONES_DIR

#
echo "Npm install the Node Server $CLONES_DIR"
npm install
#

#
# Delete files in nginx server-root
#
echo "Delete files in Nginx server root $SERVER_ROOT_DIR"
rm -rf $SERVER_ROOT_DIR/*


#
# Copy server files to nginx
#
echo "Copy server files to Nginx $SERVER_ROOT_DIR"
cp -r $CLONES_DIR/* $SERVER_ROOT_DIR
cp -r $CLONES_DIR/.env $SERVER_ROOT_DIR


#
# set permissions
#
echo "Setting permissions on $SERVER_ROOT_DIR"
sudo chown -R jv:jv $SERVER_ROOT_DIR
sudo chmod 0755 $SERVER_ROOT_DIR
find $SERVER_ROOT_DIR -type d -print0 | xargs -0 chmod 0755 # For directories
find $SERVER_ROOT_DIR -type f -print0 | xargs -0 chmod 0644 # For files
#

echo "Handle PM2"
cd $SERVER_ROOT_DIR
handle-pm2
#
echo "Restarting Nginx"
nginx-restart
#
echo "Mongo Status"
mongo-status
#
echo "Completed"

Deploy

cd
cd bin
./deploy-server-project