I tend to suffer from the “if you have a hammer, everything starts to look like a nail” syndrome. So I started off with an Ansible deployment for this blog site.

That works just fine (I build the site locally, zip it, transfer it to my webserver, unzip and do an update of the site using rsync between 2 local directories). It’s included in my nginx deployment playbook.

But it’s a little complicated at the moment, since I have to manually run the Ansible playbook when I’m done editing the blog.

Enter Github actions!

Github nowadays allows you to run simple sites based on markdown documents as Github Pages, and these are also Jekyll-based. But some of the plugins I use are not compatible with Github Pages, so that is not an option for me.

Github actions will execute every time a push is done to the main branch, and deploy the changes to my nginx site.

I’ve mostly followed this blog entry : https://christianspecht.de/2020/05/03/building-and-deploying-a-jekyll-site-via-github-actions/.

I’ve moved all commands directly into the Github Action workflow, and I changed some of the actual commands.

This is the resulting Workflow Action.

name: build my Jekyll blog

on:
  push:
    branches:
      - main

jobs:
  build_job:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Build site
      run: |
        docker run \
        -v $:/srv/jekyll -v $/_site:/srv/jekyll/_site \
        jekyll/builder:latest /bin/bash -c "chmod -R 777 /srv/jekyll && JEKYLL_ENV=production jekyll build --config _config.yml,_config_prod.yml&& mkdir build && tar -czvf build/build.tar.gz -C _site ."
    - name: Upload artifact
      uses: actions/upload-artifact@v1
      with:
        name: build
        path: build
        
  deploy:
    runs-on: ubuntu-latest
    needs: build_job
    steps:
    - uses: actions/download-artifact@v1
      with:
        name: build
    - name: Prepare SSH key and known hosts
      run: |
        mkdir -p ~/.ssh
        echo "$" > ~/.ssh/id_rsa
        chmod 600 ~/.ssh/id_rsa
        ssh-keyscan $ >> ~/.ssh/known_hosts
    - name: Copy the compressed file to webserver
      run: |
        rsync -rSlh --stats build/ $@$:/tmp
    - name: Extract the zip and deploy
      run: |
        export GW_RND=${RANDOM}
        echo " random directory: ${GW_RND} "
        ssh -o StrictHostKeyChecking=yes ${{ secrets.SSH_USERNAME }}@${{ secrets.WEBHOST }} "mkdir /home/${{ secrets.SSH_USERNAME }}/$GW_RND; tar -xzf /tmp/build.tar.gz -C /home/${{ secrets.SSH_USERNAME }}/$GW_RND/"
        ssh -o StrictHostKeyChecking=yes ${{ secrets.SSH_USERNAME }}@${{ secrets.WEBHOST }} "rsync -r --delete --chown=nginx:nginx /home/${{ secrets.SSH_USERNAME }}/$GW_RND/ /usr/share/nginx/gwbasics/_site"
        ssh -o StrictHostKeyChecking=yes ${{ secrets.SSH_USERNAME }}@${{ secrets.WEBHOST }} "rm -rf /home/${{ secrets.SSH_USERNAME }}/$GW_RND/"

This depends on a couple of secrets to have been set in the repository settings.

I also modified some things on my webserver:

  • set the setguid bit on the directory
  • created a deploy user (referenced as ${{ secrets.SSH_USERNAME }})
  • prepared the ssh keys and added the public key for ${{ secrets.SSH_PRIVATE_KEY }} to the authorized_keys of my deploy user
  • added my deploy user to the nginx group

Image:github actions running

I’m sure there’s better ways of doing certain things in Github Actions, but for a first exploration I’m happy with the result.