Setting up automatic deployment for blog
In theory its pretty easy to setup automatic deployment of a static site.
- Build the site
- Copy the contents to server
In reality, there are some things that makes it a little more difficult, and got me in trouble.
- It must all be run automatically (no interaction)
- Security must be considered so that you don’t leak secrets
- Copying from a server to another is more complicated than copying a file on your hard drive
The fact that this post is published is evidence that it works – because it was all built and deployed automatically, two days after writing this.
Step-by-step
- Start by creating an SSH key pair. This can be done on any computer, using
ssh-keygen
; see Configuring password-less SSH.
- Take the private key and save it as a file variable on Gitlab.
- Take the public key and add it to the server.
- You will probably need to add the deployment server as a known SSH host. Do this by running
ssh-keyscan <your-server>
and copy the contents to a file variable on Gitlab. - Update your
.gitlab-ci.yml
:
- Configure the shell and SSH to use the generated key
- Use
rsync
to copy the files.
The .gitlab-ci.yml
can look something like this. (Actual building of site omitted)
Tip: Scheduled posts You can setup scheduled builds in Gitlab, under Build / Pipeline schedules. If you setup nightly builds you can schedule posts by setting the
date
variable in frontmatter.
deploy:
# Instructions:
# https://docs.gitlab.com/ee/ci/ssh_keys/
stage: deploy
before_script:
# Make sure there is an SSH client
- 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
# Install rsync
- apt-get install -y rsync
# Configure SSH to use the private key and known hosts by copying the
# CI variable files
- eval $(ssh-agent -s)
- chmod 400 "$SSH_PRIVATE_KEY"
- ssh-add "$SSH_PRIVATE_KEY"
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- cp "$SSH_KNOWN_HOSTS" ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
# Actual copying of built site
# -avz: archive, verbose and compress
# -e: use the specified SSH options (needed if specific port is used)
- rsync -avz -e "ssh -p $SSH_PORT" public/ $DEPLOY_DEST
Troubleshooting
I got stuck a long time with rsync
returning “Bad port”. It was because I used single-quotes instead of double-quotes. ('ssh -p $SSH_PORT'
vs. "ssh -p $SSH_PORT"
)
I then got stuck with “Host key verification failed.”, which was because it failed to verify my servers key. This was fixed using the SSH_KNOWN_HOSTS
.