Skip to content

Instantly share code, notes, and snippets.

@danielwetan
Last active April 30, 2024 07:36
Show Gist options
  • Save danielwetan/4f4db933531db5dd1af2e69ec8d54d8a to your computer and use it in GitHub Desktop.
Save danielwetan/4f4db933531db5dd1af2e69ec8d54d8a to your computer and use it in GitHub Desktop.
Deploy Node.js to VPS using Github Actions

Deploy Node.js to VPS using Github Actions

Steps to deploy Node.js to VPS using PM2 and Github Actions

1. Clone repo to VPS folder

git clone https://github.com/danielwetan/node1.git

2. Setup CI workflows

location: node1/.github/workflows/ci.yml

example: https://github.com/danielwetan/node1/blob/master/.github/workflows/ci.yml

# This workflow will do a clean install of node dependencies, 
# build the source code and run tests across different versions of node
# For more information see: 
# https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: Node.js CI

on:
  pull_request:
    branches: [ master ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js 12
      uses: actions/setup-node@v2
      with:
        node-version: 12.x
    - run: npm i
    - run: npm run build --if-present
    - run: npm test

3. Setup CD workflows

location: node1/.github/workflows/cd.yml

example: https://github.com/danielwetan/node1/blob/master/.github/workflows/cd.yml

# This is a basic workflow to help you get started with Actions

name: Node.js CD

# Controls when the action will run. 
on:
  # Triggers the workflow on push or pull request events but only for the master branch
  push:
    branches: [ master ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
    - name: Deploy using ssh
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.HOST }}
        username: ${{ secrets.USERNAME }}
        key: ${{ secrets.PRIVATE_KEY }}
        port: 22
        script: |
          cd ~/home/danielwetan/apps/node1
          git pull origin master
          git status
          npm install --only=prod
          pm2 restart node1

4. Setup Private Key and Public Key

ssh-keygen -t rsa -b 4096 -m PEM -C "github-actions-node1"

# view the key value
cat id_rsa-github-node1.pub # Public Key
cat id_rsa-github-node1 # Private Key

5. Copy Public Key to authorized key

cat id_rsa-github-node1.pub

# Copy the output to
vi ~/.ssh/authorized_keys

6. Copy Private Key

# Type and copy the output
cat ~/.ssh/id_rsa

7. Setup Github Secret keys

# Github Secret location
Settings -> Secrets -> Actions -> New repository secret

PRIVATE_KEY = "Copy generated private key from vps to github secret"
HOST = "YOUR SERVER ADDRESS, example: 172.41.91.123" 
USERNAME = "YOUR SERVER USERNAME, example: daniel"

Reference:

https://www.youtube.com/watch?v=pvPJARjqAa8

https://github.com/appleboy/ssh-action

@v-maxson
Copy link

v-maxson commented Aug 2, 2022

Errors with "pm2: command not found" even though PM2 is properly installed and working on my VPS. How can I fix this?

@Fempter
Copy link

Fempter commented Aug 16, 2022

Update master to main as of 2022

what is wrong with "master"?

@MattKeeley
Copy link

MattKeeley commented Aug 16, 2022

Update master to main as of 2022

what is wrong with "master"?

New repositories use main as the default branch name now. More info here

@Fempter
Copy link

Fempter commented Aug 17, 2022

Update master to main as of 2022

what is wrong with "master"?

New repositories use main as the default branch name now. More info here

It is neither recommended nor required. I don’t see the need to adjust all current branches to this politically-correct convention.

@riveleus
Copy link

riveleus commented Sep 1, 2022

err: git@github.com: Permission denied (publickey).
err: fatal: Could not read from remote repository.
err:
err: Please make sure you have the correct access rights
err: and the repository exists.

error while executing git pull origin main. but everything else, git status, npm install, pm2 restart app is working

@bsa7
Copy link

bsa7 commented Oct 17, 2022

Excellent explanation. It is very helpfull for me. I'm got an understanding of this process. Big thank you! After reading this gist, I implements this deploy action for our students project. But, instead using pm2 server, I realise docker-compose runned variant for our urposes.
Again, thank you very much!

@BobLamarley
Copy link

BobLamarley commented Jan 18, 2023

err: git@github.com: Permission denied (publickey). err: fatal: Could not read from remote repository. err: err: Please make sure you have the correct access rights err: and the repository exists.

error while executing git pull origin main. but everything else, git status, npm install, pm2 restart app is working

Hey @riveleus, did you get rid of this ?

@danLeBrown
Copy link

err: git@github.com: Permission denied (publickey). err: fatal: Could not read from remote repository. err: err: Please make sure you have the correct access rights err: and the repository exists.
error while executing git pull origin main. but everything else, git status, npm install, pm2 restart app is working

Hey @riveleus, did you get rid of this ?

@BobLamarley did you solve this yet? I might be able to help if you haven't

@BobLamarley
Copy link

@Ayomide-Daniel Unfortunately not, when I'm on the VPS i can do the git pull but when this is my GitHub action who do the git pull, it seems to be like the ssh key isn't used properly

@danLeBrown
Copy link

@BobLamarley I wouldn't want to bore you with too much information, so I will assume that you have done all that is necessary such as generating the ssh key on your server and adding it to your GitHub account, etc...

The last step would be to run this command on your server and trigger another workflow/ deployment.

sudo cp ~/.ssh/* /root/.ssh/

What this does is that it adds the SSH Keys you've created for specific users to the root user as well.

Let me know if it works!

@BobLamarley
Copy link

Yes I've previously generated a key and added it to my GitHub account
This was a good try but it doesn't work,
I think I'm not as root when I'm in the GitHub action, I can't ls /root/.ssh from the action
image
But the keys was successfully copied to /root/.ssh
image

@danLeBrown
Copy link

danLeBrown commented Jan 24, 2023

@BobLamarley as expected, you might not be able to use ls /root... without sudo in front from your Github action.

Let me give this more thoughts instead of blurting out random ideas that may/may not work.

In meantime, I'd advise you to try this:
(Assuming you don't have something similar going)

Clone a repo on your VPS but do it via its SSH link, it should look like git.github.com... instead of https://. This method will require you to authenticate with an SSH key. If you can successfully solve for this, then you might be able to translate your learnings into getting the GitHub workflow to work properly

@BobLamarley
Copy link

BobLamarley commented Jan 25, 2023

I used git clone git@github.com:BobLamarley/myproject.git when I've cloned my repo
If you have others things I can try even if you are not sure they might work let me know :)

@danLeBrown
Copy link

Yeah, I do, actually.

So forget what I said earlier about authenticating with your SSH key, I found a new way today that might improve your situation.

Change your remote links to their https:// variants

git remote remove origin && git remote add origin {REPO_LINK}

By switching to this variant, you'll be required to enter your Username and Password each time you want to pull or push (maybe).

Next, run this before you push/pull next to store your credentials on the server (ie.)

git config credential.helper store 
git pull origin {BRANCH_NAME}

Your last step should be you triggering/ re-running a github workflow

Let me know if this helps!

@BobLamarley
Copy link

Using password seems deprecated
Capture d’écran 2023-01-25 à 23 24 17

@danLeBrown
Copy link

Yes, it is. I had assumed...never mind

Go to your GitHub Profile at https://github.com/settings/tokens

Generate a new classic token and use it as your password instead

@danLeBrown
Copy link

@BobLamarley did it work 👀 ?

@BobLamarley
Copy link

Hey @Ayomide-Daniel, I've just tried now, It is working with this method 🥳
Thanks a lot for the help, you helped me a lot :)

@danLeBrown
Copy link

@BobLamarley yayyyy! 🎉 I'm really glad to hear

Do enjoy the rest of the day, Bob 🙌

@sistematico
Copy link

Please bump versions do actions/checkout@v3, actions/setup-node@v3 and node-version: 16.

@rkdevstack
Copy link

err: bash: line 3: npm: command not found
37
err: bash: line 4: pm2: command not found
2023/05/24 13:53:39 Process exited with status 127

I ak getting this issue can you please update

@albertgeorge56
Copy link

Thanks! It worked. I was using shared hosting with ssh access. Also I needed to add use_insecure_cipher: true in my case.

@danLeBrown
Copy link

@rkdevstack it looks like you're having an issue caused by not having NodeJS on that server. Did you get it fixed?

@danLeBrown
Copy link

danLeBrown commented Jun 6, 2023

@albertgeorge56 Glad to hear 🙌

@yavda1
Copy link

yavda1 commented Jun 8, 2023

I'm getting this error err: fatal: not a git repository (or any of the parent directories): .git

@danLeBrown
Copy link

@yavda1 looks like you're trying to carry out a git pull action or any similar git action in a folder that is not a GitHub repo. I hope you got it fixed!

@yavda1
Copy link

yavda1 commented Jun 10, 2023

@Ayomide-Daniel Yep, I forgot the .git when cloning it. Thanks!

@danLeBrown
Copy link

Nice @yavda1 💪

@danilkazp
Copy link

Thank you very much! It works with Digital Ocean VPS!

@brian-kiplagat
Copy link

Build container for action use: '/usr/share/nginx/actions-runner/_work/_actions/brian-kiplagat/portfolio/main/Dockerfile'.
Error: Docker build failed with exit code 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment