ring0 » blog

Automatic deployment of hugo sites

tags: hugo, drone, ci 2016-01-27 13:25 by lhw

Something I wanted to try out since I set up the blog as hugo static site was the automatic testing and deployment straight from the git to our webserver. As we are not using any of the common hosts for static sites, because why would we when we have a server at our disposal, it was a interesting to find a solution without using third-party services.

Our current setup is a VPS running a nginx and a docker environment for everything we don’t quite trust and or want to run on bare metal. Two of those docker containers are Gogs and Drone CI, which work miraculously well together.

The later has quite the list of possible deploy/publish plugins including scp, sftp and rsync. I chose the rsync plugin which I set up with the rssh shell on the server side. But the other two are also valid choices for this task but they do require direct config entries in the sshd_config to restrict user access.

The drone configuration lives in the root of the hugo-site git in the .drone.yml file and would look something like this:

build:
  image: debian:stretch
  commands:
    - apt-get update && apt-get -y install hugo python-pygments
    - hugo

publish:
  rsync:
    host: ring0.de
    user: hugo-deploy
    source: public/
    target: /blog
    delete: true
    recursive: true

drone.io internally uses docker containers for basically everything, which means images, plugins and so on are not limited to some predermined ones but can be basically anything. I am using an official drone publisher instance with drone-rsync.

On the server side I installed rssh via the usual channels then added a user for the upload. The login for the user is limited to the ssh key automatically generated by drone for every repository. A very nifty little feature.

adduser --system --group blog --home /var/lib/hugo --shell /usr/bin/rssh hugo-deploy

The rssh is configured by adding a single line to the bottom of /etc/rssh.conf

user=hugo-deploy:002:100000:/var/lib/hugo

The format for this line is not quite obvious but it is somewhat explained by the example lines: user=<user>:<umask>:<action bitfield>:<chroot>. And because it is a real chroot it needs a bit of a setup before you can use it. rssh comes with a script which adds all the necessary files to the user chroot for the programs you need. As rsync is not added by default I patched the script up little to also copy rsync.

Then execute the script, copying all the necessary files (mkchroot.sh /var/lib/hugo) and create a directory within the chroot with write permissions for the deploy user.

Set up your nginx to serve the deploy user directory and tell drone to hook into the Gogs repository and you are done. Every push to the repo should now be automatically build, tested and then deployed to the server. In case you want to commit something without it being deployed you can simply add a [ci skip] to the commit message.


Update (2016-10-14)

Removed the usage of local builder tools as drone.io now seems to to only work with registries instead of locally available images. And running an additional docker registry just for the few updates we add to this blog seems pointless.