Introduction

This tutorial shows how to deploy a Jekyll blog to a GNU/Linux server with the help of builds.sr.ht

Prerequisites

  1. GNU/Linux Server - hosts your blog
  2. Jekyll blog - hosted on any git server provider; Sourcehut, GitHub, GitLab etc.
  3. A builds.sr.ht account.

Public repositories

The following section details how to achieve this with a public repo.

Defining the build manifest

  image: archlinux
  sources:
    - 'https://github.com/<username>/<repo>'
  secrets:
    - <secret-uuid-1>
    - <secret-uuid-2>
  packages:
    - ruby
    - nodejs-lts-fermium
  tasks:
    - setup: |
        ruby -v
        gem -v
        export PATH=$(ruby -e 'puts Gem.user_dir')/bin:$PATH
        gem install --user-install bundler
        cd blog
        sudo chown -R $(whoami) ~/.gem/*
        bundle install 
    - build: |
        cd blog
        export PATH=$(ruby -e 'puts Gem.user_dir')/bin:$PATH
        bundle exec jekyll build
    - deploy: |
        cd blog
        DEPLOY_HOST=168.119.234.216
        DEPLOY_USER=ken
        eval `ssh-agent`
        ssh-add ~/.ssh/<secret-uuid-1>
        ln -s ~/.ssh/<secret-uuid-2> ~/.ssh/id_rsa.pub
        scp -o StrictHostKeyChecking=no -rv _site/* [email protected]$DEPLOY_HOST:/var/www/html/blog

Although a general description of the build manifest schema can be found here, I’ll continue by detailing the Jekyll specific configuration options below.

Image

builds.sr.ht offers a ton of images to choose from. This tutorial went witharchlinux.

image: archlinux

Sources

Specify what repo to clone. The https schema is used to define the repo URL.

sources:
  - 'https://github.com/<username>/<repo>.git'

Secrets

Public repos just need 2 uuids i.e. the deploy server key pair.

secrets:
  - <secret-uuid-1>
  - <secret-uuid-2>

Packages

Install any packages needed as dependencies.

packages:
  - ruby
  - nodejs-lts-fermium

This is the equivalent of

  sudo pacman -S ruby nodejs-lts-fermium

Tasks

This YAML list contains the actual build steps.

  tasks:
      - setup: |
          ruby -v
          gem -v
          export PATH=$(ruby -e 'puts Gem.user_dir')/bin:$PATH
          gem install --user-install bundler
          cd blog
          sudo chown -R $(whoami) ~/.gem/*
          bundle install 
      - build: |
          cd blog
          export PATH=$(ruby -e 'puts Gem.user_dir')/bin:$PATH
          bundle exec jekyll build
      - deploy: |
          cd blog
          DEPLOY_HOST=168.119.234.216
          DEPLOY_USER=ken
          eval `ssh-agent`
          ssh-add ~/.ssh/<secret-uuid-1>
          ln -s ~/.ssh/<secret-uuid-2> ~/.ssh/id_rsa.pub
          scp -o StrictHostKeyChecking=no -rv _site/* [email protected]$DEPLOY_HOST:/var/www/html/blog

Private repositories

The following section details how to achieve this goal when a private repo is involved.

Defining the build manifest

Much like travis.yml or circle.yml files, manifests describe a build. The relevant build manifest is shown below.

image: archlinux
sources:
  - '[email protected]:<username>/<repo>.git'
secrets:
    - <secret-uuid-1>
    - <secret-uuid-2>
    - <secret-uuid-3>
packages:
  - ruby
  - nodejs-lts-fermium
tasks:
  - setup: |
      if [ "$(git rev-parse origin/develop)" != "$(git rev-parse HEAD)" ]; then \
        complete-build; \
      fi
      ruby -v
      gem -v
      export PATH=$(ruby -e 'puts Gem.user_dir')/bin:$PATH
      gem install --user-install bundler
      cd blog
      sudo chown -R $(whoami) ~/.gem/*
      bundle install 
  - build: |
      cd blog
      export PATH=$(ruby -e 'puts Gem.user_dir')/bin:$PATH
      bundle exec jekyll build
  - deploy: |
      cd blog
      DEPLOY_HOST=156.116.53.2
      DEPLOY_USER=myusername
      eval `ssh-agent`
      ssh-add ~/.ssh/<secret-uuid-2>
      ln -s ~/.ssh/<secret-uuid-3> ~/.ssh/id_rsa.pub
      scp -o StrictHostKeyChecking=no -rv _site/* [email protected]$DEPLOY_HOST:/var/www/html/blog
  

Sources

Specify what repo to clone. The ssh schema is used if the repo in question is private, otherwise use the https schema.

sources:
  - '[email protected]:<username>/<repo>.git'

Secrets

A YAML list of uuids that point to secrets specified here. Secrets can be SSH, PGP keys or files.

secrets:
  - <secret-uuid-1>
  - <secret-uuid-2>
  - <secret-uuid-3>

For this build however, we are only interested in SSH secrets. In addition to GitHub’s private key, we also need the deploy server’s public and private key.

The first key on the list is linked to ~/.ssh/id_rsa. Subsequent keys can be added later in the build using ssh-add.

Generate a key pair with ssh-keygen. Do not use a passphrase when prompted.

  ssh-keygen -t rsa

Copy the public key over to the deploy server with ssh-copy-id

  ssh-copy-id -i ~/.ssh/id_rsa $DEPLOY_USER@$DEPLOY_HOST

NOTE: The private key needed for git clone should occupy the first slot.

Tasks

YAML list of command line instructions needed to successfully run the build.

  tasks:
    - setup: |
        if [ "$(git rev-parse origin/develop)" != "$(git rev-parse HEAD)" ]; then \
          complete-build; \
        fi
        ruby -v
        gem -v
        export PATH=$(ruby -e 'puts Gem.user_dir')/bin:$PATH
        gem install --user-install bundler
        cd blog
        sudo chown -R $(whoami) ~/.gem/*
        bundle install 
    - build: |
        cd blog
        export PATH=$(ruby -e 'puts Gem.user_dir')/bin:$PATH
        bundle exec jekyll build
    - deploy: |
        cd blog
        DEPLOY_HOST=156.116.53.2
        DEPLOY_USER=myusername
        eval `ssh-agent`
        ssh-add ~/.ssh/<secret-uuid-2>
        ln -s ~/.ssh/<secret-uuid-3> ~/.ssh/id_rsa.pub
        scp -o StrictHostKeyChecking=no -rv _site/* [email protected]$DEPLOY_HOST:/var/www/html/blog

Conclusion

Sourcehut is a CI/CD tool with a different take on build systems. Although it is still an early stage project, the simplicity it offers is worth a try, especially for side projects.