Setting up automatic deployment for blog

Posted on Jul 15, 2024

In theory its pretty easy to setup automatic deployment of a static site.

  1. Build the site
  2. 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

  1. 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.
  1. 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.
  2. 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.