The goal here is to deploy our jekyll blog after a push to the master branch. In this example we are deploying to a host running nginx and will need to transfer files after building the site on our gitlab runner. There are quite a few variations of Gitlab Runners, but we will be using a Docker Runner in which we will start with one with ruby already installed and then use the before_script to install anything else we will need.

Our runner will need ssh access to transfer files, so we will generate a key, add the public key to the authorized_keys on our “production” host, and add paste the private key as a secret variable called SSH_PRIVATE_KEY. Remember our runner is ephemeral and we are basically creating a new machine for every deploy.

Side note, we could use a SSH runner to simplify this since we would only have to set it up once, which in turn would be faster. But I do prefer the docker method, even with the speed penalty, since the deploy host’s recipe is all contained in the gitlab-ci file.

Note the use of the tr -d '\r' exists because the forms used to enter the secret variables can inject carriage returns for multiline values such as a private key.

Also the when: on_success is the default, but there as a reminder you can change its value. For example to manual if you want to add an additional step before it deploys.

image: ruby:2.4

stages:
  - deploy

before_script:
# install ssh-agent
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- 'which rsync || ( apt-get update -y && apt-get install rsync -y )'

# run ssh-agent
- eval $(ssh-agent -s)

# disable host key checking (NOTE: makes you susceptible to man-in-the-middle attacks)
# WARNING: use only in docker container, if you use it with shell you will overwrite your user's ssh config
# add ssh key stored in SSH_PRIVATE_KEY variable to the agent store
- mkdir -p ~/.ssh
- ssh-add <(echo "$SSH_PRIVATE_KEY" | tr -d '\r')
- echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
- gem install bundler
- gem install jekyll
- bundle install

deploy_prod:
  stage: deploy
  script:
  - JEKYLL_ENV=production bundle exec jekyll build
  - rsync -avz --delete _site/ ubuntu@seantemple.com:/var/www/seantemple.com
  environment:
    name: production
    url: https://seantemple.com
  when: on_success
  only:
  - master