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.