DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Node.js app continuous deployment with AWS, PM2, and Github Actions.
Lukas Borawski
Lukas Borawski

Posted on • Updated on

Node.js app continuous deployment with AWS, PM2, and Github Actions.

So you have this node.js app. It's not static, it's in Vue, React, Angular, whatever... It's ready and steady to publish and deploy. But where, how? In this article, I'll cover some steps on how to automatically deploy your app and keep it delivered continually.

Here is a quick summary:

  1. Runing EC2 instance on AWS
  2. PM2 setup
  3. Deployment script
  4. GitHub Action

Digression: If your app does not have any backend-related functionalities I'm almost sure that it can be built with static mode. So for that, you can use ie Netlify and skip this thread. πŸ™ƒ

Static apps generate a smaller carbon footprint.

OK, let's back to the main topic.


1. Runing EC2 instance on AWS.

For that case, we will use EC2 on AWS. If you're not familiar with the installation process all you need to do is:

Don't worry, it's super simple and we don't need to move through. Just watch the guidelines and you'll be fine. However, maybe for you, the Digital Ocean Droplet will be the best solution; or any other. Use what you like the most, we just need a regular Ubuntu instance. However, note that paths in the below configs are AWS specific.

Now, log in to your newly created instance.

ssh -i key.pem ubuntu@12.345.67.891
Enter fullscreen mode Exit fullscreen mode

For sure - for the new machine - you’ll need to configure the webserver, most likely Nginx. More about this you can find here or just use this predefined one.

$ sudo vim /etc/nginx/conf.d/nodejs-basic.conf
Enter fullscreen mode Exit fullscreen mode
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen 80;

    server_name your-server-name.com;

    location / {
         proxy_pass http://localhost:3000;
         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;
    }
}
Enter fullscreen mode Exit fullscreen mode

2. PM2 setup.

PM2, what the heck? PM2 is a daemon process manager that will help you manage and keep your application online 24/7. So it will help keep our app live and running. Let’s install it.

npm install pm2 -g
Enter fullscreen mode Exit fullscreen mode

Then, in your home folder create a simple configuration file (eccosystem.json).

{
  "apps" : [
     {
        "name"          : "App Name",
        "script"        : "npm",
        "args"          : "run start",
        "watch"         : false,
        "cwd"           : "/home/ubuntu/app-name/",
        "out_file"      : "/home/ubuntu/hooker.out.log",
        "err_file"      : "/home/ubuntu/hooker.err.log",
        "merge_logs"    : true,
        "instances"     : 1,
        "exec_mode"     : "cluster"
     }
  ]
}
Enter fullscreen mode Exit fullscreen mode

3. Deployment script.

Therefore we need some simple bash script (deploy.sh) that will run the app build and invoke PM2 process after that.

echo "Kill all the running PM2 actions"
sudo pm2 kill

echo "Jump to app folder"
cd /home/ubuntu/app-name

echo "Update app from Git"
git pull

echo "Install app dependencies"
sudo rm -rf node_modules package-lock.json
sudo npm install

echo "Build your app"
sudo npm run build

echo "Run new PM2 action"
sudo cp /home/ubuntu/ecosystem.json ecosystem.json
sudo pm2 start ecosystem.json
Enter fullscreen mode Exit fullscreen mode

You can test it by using sh deploy.sh command.

Great, we're almost there. Server configuration is relatively simple and you can make it almost effortless. If your daily environment is MacOS or Linux it will be very straightforward.

Now - just for the test - we can run the whole process manually. To do this follow the below steps.

  • configure webserver
  • clone/fetch your app on the instance
  • build the app
  • install PM2 manager
  • run sudo pm2 start npm --name "process" -- start

Or set it as a simple checklist for the instance setup.

4. GitHub action.

Finally, we can create a GitHub action that will run our deployment process. Just for our case, we will create an action that will be called for each merge to the develop branch.

In your main app directory create the .github folder inside which the workflows one. Then create a deploy.yaml file.

name: Deploying

on:
  push:
    branches:
      - develop

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest

    steps:
      - name: executing remote ssh commands using ssh key
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.AWS_HOST }}
          username: ${{ secrets.AWS_USER }}
          key: ${{ secrets.AWS_KEY }}
          script: sh deploy.sh
Enter fullscreen mode Exit fullscreen mode

As you can see we have some variables here. These are GitHub specific secrets. You can define them in your account settings. Values for AWS-related credentials can be found in the console. Here you have some detailed instructions.

Remember! Always keep sensitive data outside the repository.

And that's it. Push the workflow into your repo and wait for your first automatic deployment. It will take circa a couple of minutes (max). Done.

Cheers, Lukas.

Buy Me A Coffee

Top comments (11)

Collapse
 
fazi profile image
Muhammad Abdul Rehman

Hello Lukas
Where I need to add
eccosystem.json
and deployment scrpit
on my local machine or on my digitel ocean droplet?

Collapse
 
lukasborawski profile image
Lukas Borawski

Hi there. So you should put the ecosystem file in the root folder of your machine. A deployment script can be placed inside the app folder. You can see that inside of it the ecosystem file is copied and used as local. Cheers.

Collapse
 
fazi profile image
Muhammad Abdul Rehman

So i make the ecosystem file in my root foler anywhere or probably /etc folder

and the deployment script in the app folder and that app is on my digital ocean droplet

right?

Thread Thread
 
lukasborawski profile image
Lukas Borawski

No, not in the etc, in your Ubuntu user root folder. Typically it’s the place when you’re legged in on start.

Thread Thread
 
fazi profile image
Muhammad Abdul Rehman

Well sir i am doing it for the first time there are multiple things i dont understand I wish i could share my scree and ask you help to learn it

Thread Thread
 
fazi profile image
Muhammad Abdul Rehman

I am trying to comprehend it

Collapse
 
miachrist profile image
Mia Christ

Hey Lukas! this is definitely informative but honestly, I am not a fan big of Node.js deployment through AWS. These guys start charging your credit card whenever your resources increase or app expand. I found Heroku is better option here.

By the way, Heroku has turned itself into a paid platform and nowadays, I am considering this way to deploy my Node.js app. You can also give your comments on this method of app deployment.

Collapse
 
jitunayak profile image
Jitu Nayak

Very nice tutorial.

Collapse
 
faysal515 profile image
Faysal Ahmed

github.com/marketplace/actions/ssh...

The root Github Action says that it only supports Linux docker container, I was wondering if it can be used in plain ubuntu 16/18 instance

Collapse
 
lukasborawski profile image
Lukas Borawski

To be honest, I don't know. But supposed to ... I guess.

Collapse
 
fazi profile image
Muhammad Abdul Rehman

Sir are you on discord?

Thank you.

Thanks for visiting DEV, we’ve worked really hard to cultivate this great community and would love to have you join us. If you’d like to create an account, you can sign up here.