Auto-Deploy a Node.JS application with AWS EC2 and Github Actions
Tags: node, aws, githubactions, devops
Published: 2023-02-26 21:49:37

## Introduction
As a software developer we always want to automate our daily task as much as possible. When designing software, automated deployment is another automation that can help us save a lot of extra time. 

### What is Automated Deployment ?
Automated deployment, also known as continuous deployment or continuous delivery, is the practice of automating the process of deploying software applications to production or staging environments. Automated deployment aims to accelerate the delivery of new features and bug fixes to users while streamlining the deployment process, lowering the risk of mistakes or inconsistencies.

Automated deployment involves creating a series of scripts or workflows that automate the tasks involved in deploying an application, such as building, testing, and deploying the application to a server or cloud provider. The deployment procedure becomes more repeatable, predictable, and less prone to human mistake by automating these operations.

There are many tools and platforms that can be used to implement automated deployment, such as Jenkins, Travis CI, GitHub Actions, and AWS CodeDeploy. These tools typically integrate with version control systems like Git and can be configured to trigger deployment workflows based on events such as code commits, pull requests, or scheduled builds.

Overall, automated deployment can help software teams to deliver new features and bug fixes to users faster and with greater reliability, while reducing the risk of downtime or errors during the deployment process.

### What is Github Actions ?

> GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub. Make code reviews, branch management, and issue triaging work the way you want.

[Github Actions](https://github.com/features/actions)

---


## Setting up your EC2 instance:
It's really simple to start an EC2 instance on AWS. You can follow AWS EC2 getting started [guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EC2_GetStarted.html#ec2-launch-instance). Make sure that the Firewall Network Configuration permits HTTPS and HTTP traffic. Whoa, your EC2 instance is now running!.

### NodeJS Runtime Installation
You can follow this Digital Ocean [article](https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-20-04#option-3-installing-node-using-the-node-version-manager) to setup Node.JS on ubuntu.

### PM2 Installation

> PM2 is a daemon process manager that will help you manage and keep your application online. Getting started with PM2 is straightforward, it is offered as a simple and intuitive CLI, installable via NPM.

1. `npm install pm2@latest -g`

### Project setup
As we setup an auto-deployment pipeline for our project, We need to manage our project with some version control system like git and we host our project via Github. Now we will clone our project on the EC2 instance. I will deploy one of my [project](https://github.com/nil1729/url-shortner-nodejs) on Github. Lets us now setup an ssh-key on Github, so that we can clone and pull from Github without username and password prompt every time. Refer this [gist](https://gist.github.com/xirixiz/b6b0c6f4917ce17a90e00f9b60566278) for ssh-key setup.

1. `git clone https://github.com/nil1729/url-shortner-nodejs`

### The `ecosystem.config.js` file
Lets us now setup up `ecosystem.config.js` file. This file will manage the environment variables our project needs to connect to any database or any third party service.

```
cd ~
pm2 init
sudo nano ecosystem.config.js
```
Next, replace the boilerplate content in the file, with the following:
```
module.exports = {
  apps: [
    {
      name: 'url-nodejs-app',
      cwd: '/home/ubuntu/url-shortner-nodejs',
      script: 'npm',
      args: 'start',
      env: {
        NODE_ENV: 'production',
        MONGO_URI: '',
        // put all the environment variables here
      },
    },
  ],
};

```
Now start the application by `pm2 start ecosystem.config.js`. After starting your application for the first time visit your application on browser via `http://<public_ip>:<port>`. Make sure you allow all the inbound traffic to current EC2 instance via security group.


![Hosted Application Demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3uypzmv7hm6jn2f4m2ij.png)



### The `sync.sh` file
This file is the main script which we need to run to deploy a new version of our application. This file contains all the necessary steps from installing the dependencies to running the application on desired environment. Here are the steps for my application to run, you can write your own steps

```
#!/bin/bash

# setting up the node environment
export NVM_DIR=~/.nvm
source ~/.nvm/nvm.sh

echo "starting deployment process"

# download new version of our application
cd /home/ubuntu/url-shortner-nodejs
git pull origin master

# install all the dependencies
echo "installing dependencies"
npm run setup:env

# build the application
echo "building application"
npm run build

# run the application
echo "starting the application"
cd ~
pm2 restart ecosystem.config.js

echo "deployment process completed"

```
Now, add executable permission on `sync.sh` file

```
chmod +x sync.sh
```

---


## Configuring GitHub Actions:
Now we will learn about how to configure a CI/CD workflow with Github. For this we have to create a directory `.github/workflows` on root of your project and a `yaml` file inside that directory which contain all the steps we need to deploy our application automatically. Workflow file content are pretty much boilerplate code we have to write.

```
name: Deploy

on:
  push:
    branches: [master]

jobs:
  deploy:
    name: Deploying NodeJS Application
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3
      - name: deploying application to EC2
        env:
          PRIVATE_KEY: ${{ secrets.SERVER_SSH_KEY  }}
          HOSTNAME: ${{ secrets.SERVER_HOST  }}
          USER_NAME: ${{ secrets.SERVER_USERNAME  }}

        run: |
          echo "$PRIVATE_KEY" > private_key && chmod 600 private_key
          ssh -o StrictHostKeyChecking=no -i private_key ${USER_NAME}@${HOSTNAME} bash sync.sh

```
Before commit this file to our repository, we have to setup these variables on Github Actions Secret. 
![Github Secrets Setting Demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z9mx3rw9yjo5qdj900k7.gif)

Set these three variable on Github Action Secrets
1. `SERVER_SSH_KEY` : Value will be your private key you generated when launching the EC2 instance ssh-key pair
2. `SERVER_USERNAME`: Value should the the left part of `@`. In my case `ubuntu`.
3. `SERVER_HOST`: Value will be the right part of `@`. For my case `ec2-3-7-254-17.ap-south-1.compute.amazonaws.com`.

![Github Secrets Value](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsqx2ac4h6le7pf5rbcg.png)

Now commit the changes and push your code to Github. This commit will trigger an action on Github and you will see a yellow dot right before your commit hash on Github. This indicates that your workflow file trigger an Action. If this action completed successfully it will changed to a green tick :white_check_mark: or If the action failed for any reason it will the icon changed to red icon :x:.

---

## Testing the deployment:
Let's test the deployment. We can test by simple update out code and push the changes to Github. I have updated the my page title and push the change to my Github. Here's an example: 

{% youtube https://youtu.be/V2DglsruE5E %}

---


## Conclusion
In conclusion, automating your Node.js application's deployment process using AWS EC2 and GitHub Actions will substantially streamline and ease the process. You can set up an EC2 instance on AWS, get your Node.js application ready for deployment, and build up a GitHub Actions workflow to automate the deployment process by following the instructions in this post.

Automatic deployment can help to boost the reliability and efficiency of your deployment process overall, decrease the risk of failures, and shorten the time it takes to bring new features or bug fixes into users' hands.

You have effective resources at your fingertips for automating deployment and enhancing your software development lifecycle using AWS EC2 and GitHub Actions. You may concentrate more on creating your application and less on the deployment procedure by putting these tools into practise.

---


### References
1. [AWS EC2 Guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EC2_GetStarted.html#ec2-launch-instance)
2. [Digital Ocean Community](https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-20-04#option-3-installing-node-using-the-node-version-manager)
3. [Github SSH Setup](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account)

---


### Let's Connect
:pushpin: [Github](https://github.com/nil1729)
:pushpin: [Twitter](https://twitter.com/nil1729)