Gitlab CI automation für Jekyll

I use Jekyll for my blog and the posts are pushed into a Gitlab-repository. To make life easier I decided to use CI/CD to publish new posts easier. As soon as a new blog post is commited to the main branch, it will be deployed on my webserver.

The website resides on a different server and is accessible through SSH. The deploy script uses rsync over SSH to copy the files over. In order for that to work, the Gitlab CI needs a way to authenticate to the other server. A good way is to use SSH keys. Since the gitlab-ci.yaml-file is visible in the repository, you should avoid putting sensitive data in there.

The CI file I use requires two variables to be set: SSH_KNOWN_HOSTS, which should contain the ssh fingerprint of the remote host and SSH_PRIVATE_KEY, which contains the private key. To generate a new key you can use ssh-keygen -t ed25519 -C "<comment>" (Copy the contents of the private key into the variable and copy the public key to the machine that runs the webserver (either with ssh-copy-id or manually). In order to the the ssh fingerprint you can use ssh-keyscan <host>, which prints the fingerprint of your host. (Simply copy the output of ssh-keyscan)

Add variables to the settings of your project and add the folowing file to your repository: .gitlab-ci.yaml:

The script requires a webserver running on the target host which serves from /var/www/html and an SSH user, which is allowed to write to the directory.

The script runs bundler to build the jekyll-page and exports the site as an artefact (which you can download if you want) and then copies the files to the webserver.

# This file is a template, and might need editing before it works on your project.
# Template project: https://gitlab.com/pages/jekyll
# Docs: https://docs.gitlab.com/ce/pages/
image: ruby:2.6

variables:
  JEKYLL_ENV: production
  LC_ALL: C.UTF-8

before_script:
  - gem install bundler
  - bundle install
  - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
  ## Run ssh-agent (inside the build environment)
  - eval $(ssh-agent -s)

  ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
  - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -

  ## Create the SSH directory and give it the right permissions
  - mkdir -p ~/.ssh
  - chmod 700 ~/.ssh
  - echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
  - chmod 644 ~/.ssh/known_hosts
test:
  stage: test
  script:
    - bundle exec jekyll build -d test
  artifacts:
    paths:
      - test
  except:
    - master
# Deploy using rsync
rsync_prod:
  stage: deploy
  script:
    - bundle exec jekyll build -d public
    - apt-get update
    - apt-get install rsync -y
    - rsync -v -a -O --no-perms -essh public/ my_user@host_or_ip:/var/www/html/
  artifacts:
    paths:
      - public
  only:
    - master

Use this as a base line. It would make sense to add variable for the username/hostname and path, so you can use the same ci-file for different websites and adjust the settings for each project.

Comments

Currently Deactivated - Contact me on Twitter, Mastodon or email if you have questions or suggestions.