Push to GitHub Triggers Push to Remote

Hi. Today I would like to go over how I changed things up a bit and am now able to push my site updates to GitHub, which then pushes the updates to the live production server. This should allow me to add checks within GitHub to ensure my site it updated only if everything is correct. Though I won’t go into that here today. I will be focusing on the GitHub Action.

The Idea

Again the basic idea is pretty simple. I will push updates to my GitHub repo. This will then cause GitHub to trigger an action that will push the updates to my live production site server. In this case I will be using the actions/checkout instead of pushing directly to the production server. Less risk of mistakes, if you have checks in place on GitHub.

Requirements

  • Actions must be done by unprivileged users.
  • Connect over SSH

Getting Everything we Need

SSH

  1. We need to generate a new ssh key pair. For simplicity I went with the standard rsa with 4096.
ssh-keygen -t rsa -b 4096 -C "[identifier]@linode" -f linode

This creates two files. linode the private key. The one we need to keep really safe. And linode.pub the public key that we usually share.
Things are going to be a little different here since we are actually going to put the private key into GitHub as a repository secret. And add the public key to the remote, linode, server.

Before we do that we also need to get some information about the destination server. We need the information that would normally be stored in the known_hosts file when we connect to a remote server using standard ssh

We can get this information with:

ssh-keyscan -t rsa [host address/IP address]

You should see that I used -t rsa here because my ssh keys are also rsa.


  1. Add these ssh details to our GitHub repo. We have to open our repo on GitHub and add our secrets to the repo we will be pushing to.

Access Settings -> Secrets and create the following two secrets. Using the New Respository Secret button.

Name: LINODE_KEY
Contents:

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn
--snip--
-----END OPENSSH PRIVATE KEY-----

I know this looks odd but, Github will keep this safe. And I would use a unique key anyway. Just in case you need to burn it in the future.

Next we need to add the second secret.

Name: LINODE_KNOWN_HOSTS
Contents: This will be the output you get from the ssh-keyscan command listed earlier.


  1. We next need to add the contents of linode.pub to the remote server’s authorized_keys under .ssh for the user we plan to connect as. There are lots of guides online for this.

GitHub Action

At this point we can start putting the GitHub Action together. We do this under .github/workflows/

name: Linode Push Update

on:
  push:
    branches:
      - master

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
    - name: Prepare ssh keys
      uses: shimataro/ssh-key-action@v2
      with:
        key: ${{ secrets.LINODE_KEY }}
        known_hosts: ${{ secrets.LINODE_KNOWN_HOSTS }}
        
    - name: Checkout the Repo
      uses: actions/checkout@v2
      with:
        ssh-key: ${{ secrets.LINODE_KEY }}
        fetch-depth: 0
        ref: master
    - name: Push to Linode
      run: |
        git config user.name github-actions
        git config user.email github-actions@github.com
        git remote add prod ssh://[username]@[host]:/var/repos/[remote-repo-name].git
        git push prod        

Most of this is pretty straight forward. But I was missing an important step initially. That is the use to of the shimataro/ssh-key-action. This action is needed as it will add our secret ssh data so that we authenticate when we connect to the remote server. It adds the LINODE_KEY and the LINODE_KNOWN_HOSTS information.

If you are wondering about the remote-repo-name.git this is because it should be created as a bare git repo. If you want to know more about how I created it and the post-receive script that is eventually triggered. Take a look at my previous post here

Using this approach I was able to reuse my previously written post-receieve hook script on the remote server to update the live site. So I didn’t need to change anything on the remote server.

Closing

I hope that was interesting and helps others.


See also