Github Self-Hosted Runner Setup[update]
Tags: aws, github, node, npm
Published: 2021-04-13 04:42:54


A funny request came recently from a friend of mine who needed a local server to deploy his code from for clients.  For whatever reason, his clients want him to deploy to not cloud or web services.  Most code pipelines run through cloud services like AWS, Heroku, or Digital Oceans so this would be a novel issue.

I decided to try and make an Ubuntu Server VM to host these changes.  The settings for Ubuntu and Github can be found below.

Prerequisites:
Github account
VMWare Workstation
Ubuntu Server:
-https://ubuntu.com/download/server
A way to push code in VS Code or Github CLI

The first thing you'll want to do setup an Ubuntu Server as a VM to host the deployment.  Go on over and download that that and Choose the Manual Server Installation option and we will for this tutorial be using the 20.0.4 version.
![ubuntuDL2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y28ljnk0kxuh691qe3ie.png)
![ubuntuDL](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h9wdqf2n12n6sj9cw598.PNG)
Now you got the iso you need so go ahead and start installing a new VM.  Along the way, you will need a couple of choices to add. 
1. Do add the OpenSSH.  We will need it later
![opensshInstall](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0rxtbggcjk7bo0j9ac4w.PNG)
2. Pick up a couple of apps in the menu on the way.  Docker and maybe a Kubernetes app is good depending on what your deployment calls for.
![installApps](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aa1hqbkbz3tcdie6hll9.PNG)
The cloud cli you see might be useful to you but likely it won't since this is a self runner and we want to keep bloat to a minimum.
When the Installation process is done, you will probably want to update your router to let outside senders contact your server via SSH.  Details can be found here: https://portforward.com/
This will probably include the server's IP and SSH port(probably 22).  The next parts involve a lot of communication between Github and your new server.

This part of the install and configuring is actually best followed on Github docs about self hosted runners.  I will make a few small suggestions along the way but please visit and bookmark this page:
https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners

Now we need to setup Github Actions to set up the process.  But first you will need to set up Secrets.  

![Secrets](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2i0abiwa9dlkocmi8kxh.PNG)
Under Settings-> Secrets, you will find where to put details that are safely stored so no one can read them after you enter them.  Just go to New Repository Secret and enter a simple name and the detail you are making(Server Host Address, Username, Password, etc.)  You can do this with a PKI key but for the sake of simplicity this tutorial uses a User/Password configuration.

Also in Actions you will need to set up a Self Runner.  Go to Settings tab and Actions, choose Add runner at the bottom under Self Hosted Runner.
![setupRunner](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7tbqf7c6xeouaqg454y6.PNG)
Follow the directions on this page to configure your server for doing runner work. 

To set up the work flow in Git Hub you will go to Actions Tab and New Workflow.  It follows a yaml file setup.
Here you will make sure to enter the info that you supplied in Secrets:
```
        host: ${{ secrets.HOST }}
        username: ${{ secrets.USERNAME }}
        password: ${{ secrets.PASSWORD }}
        port: ${{ secrets.PORT }}
```
After that you will enter the script to be executed on the server.  For now you can just enter commands to output here in Github for testing connection like "ls" or "whoami".

In the script you will also change the runs on to:
```
runs-on: self-hosted
```
This indicates it is for a Self Hosted Runner.


The Final workflow script I ended up with is below:
```

name: remote ssh command
on: [push]
jobs:

  build:
    name: Build
    runs-on: self-hosted
    steps:
    - name: executing remote ssh commands using password
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.HOST }}
        username: ${{ secrets.USERNAME }}
        password: ${{ secrets.PASSWORD }}
        port: ${{ secrets.PORT }}
        script: |
          cd /home/<USER NAME>/actions-runner/_work/samplenodejs/samplenodejs
          git pull
          npm install
          npm build
          ls -la
```
To see the Github Action take place, simply do a Git Push and the process should start automatically.
Head over to your Actions tab to see if it was successful:
![Actions Tab](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4o6ydvbf9ejlam9gkqc4.PNG)
 
And if done correctly, you should be able to see the output in a web browser if that was the final destination of your app.

UPDATE:
I will add some info regarding workflow in the jobs.


```
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: self-hosted      
    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - name: Runs code deploy
        uses: actions/checkout@v2
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USERNAME }}
          password: ${{ secrets.PASSWORD }}
          port: ${{ secrets.PORT }}
      - name: Build npm
        uses: actions/setup-node@v2
        with:
          node-version: "16"    
      - run: cd /home/..../<appname>/
      - run: pwd
      - run: npm ci
      - run: npm test --if-present
      - run: npm run build
      - run: pm2 restart npm
```
You will notice that ***uses: actions/checkout@v2*** line is different from before.  [This one](https://github.com/actions/checkout) is an improvement over appleboy's ssh-action repository.   You will also notice it is listed under ***- name: Runs code deploy*** The name tag separates the different tasks.
```
- name: Build npm
  uses: actions/setup-node@v2
  with:
  node-version: "16"
```
This part is separated and sets up a named task and a different repo to use.  This task involves npm so we need the ***setup-node@v2*** and specify we are talking about node version 16 as that is what is on the target machine.
```
      - run: cd /home/appname/
      - run: pwd
      - run: npm ci
      - run: npm test --if-present
      - run: npm run build
      - run: pm2 restart npm 
```
This part has the actual steps listed out.  The first part with ***cd*** and ***pwd*** commands is a sanity check for myself.  This will return values in the Actions area and we will know we are connected and things are happening.

The ***npm*** commands can run in the folder we ***cd*** to and they test and build the app respectively.   I commented out the ***npm run start*** as we do not need it.  It's already previously setup in ***pm2***.  [PM2](https://pm2.keymetrics.io/) is a daemon process manager made for Node.js projects and makes it easier to use those processes in the background of your server.  
I will probably do a post on PM2 at some point as it is a handy service.
We can see the results in the Actions tab and go to the successful run.
![successfulRun](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pdz828kgcs52plg9rip2.PNG)
As you can see, the script runs and the ***Run*** steps come out below one at a time.
![successfulRun2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/koa53rqgo8ow10stodyc.PNG)
It even gives you the return that PM2 would from the terminal.  
Not too shabby.