Hakyll + sourcehut = ☺
29 April 2020This blog is now automatically deployed by pushing to its source repository at sourcehut! Here are the steps I took to convert it from a manual rsync to a job run by builds.sr.ht after each push to its git repository.
The first step is to create an SSH key so that the build service can access the filesystem on the VPS hosting my blog. Obviously we can’t use a passphrase since we need it to connect without any human intervention. Easy enough with the usual command:
desktop $ ssh-keygen -t ed25519 -f srht
Then to the secrets page
on sourcehut and upload the content of the srht
file (NOT
srht.pub
) as a new secret with the type ‘SSH Key’ and a
reasonable description. We’ll need to make a note of the UUID that got
assigned; for me, it was
2959238e-ea6f-4276-9441-cdc71b933f73
.
The next step is to set up the user that we will connect as from the sourcehut builds service. We’ll also need to make sure the ownership and permissions on the webroot are properly set up.
server # WEBROOT=/srv/inv.alid.pw
server # adduser --system srht
server # chsh -s /bin/sh srht
server # chown -R srht:adm "$WEBROOT"
server # chmod -R ug=rwX,o=rX "$WEBROOT"
server # find $WEBROOT -type d -exec g+s {} +
I like to have files like this writable by an admin group so that I
can delete stuff without having to be root
myself, and the
last command sets the setgid bit on all the directories so that
newly-created files continue to belong to that group. That’s personal
preference though: in the end, as long as the srht
user can
write there (and nowhere else) then everything should work just
fine.
We’ll also need to authorise the SSH key we generated to log in as
the srht
user, and we can restrict it to only run
rsync
at the same time. Take the content of the
srht.pub
file we generated earlier, and add it to
~srht/.ssh/authorized_keys
, along with the options to lock
it down to rsync:
restrict,command="rrsync /srv/inv.alid.pw" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH4E9kTv92l1NY1DgqXTnkHJWglVW+Laz6mQELviXzGI srht deployment
rrsync
is not a typo: it’s a script that comes with the
rsync package (in Ubuntu, it’s installed to
/usr/share/doc/rsync/scripts/rrsync.gz
, so you’ll have to
decompress it and copy it somewhere that shows up in the
srht
user’s PATH
) that means logging in with
the given SSH key can only run rsync in the specified directory.
And that’s it for the server-side configuration! Now, we just have to
fill in the .build.yml
file to tell the sourcehut builders
how to do all the deployment. Here it is, all in one go:
image: archlinux
packages:
- stack
- rsync
sources:
- https://git.sr.ht/~jshholland/inv.alid.pw
environment:
user: srht
webhost: procyon.chrys.alid.pw
hostkey: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKemAh9xHg0lQBhwzVp9UemuSgaDqVC5Mwa+CmnXijP8
secrets:
- 2959238e-ea6f-4276-9441-cdc71b933f73
tasks:
- build: |
cd inv.alid.pw
stack install
$HOME/.local/bin/site build
- deploy: |
mkdir -p $HOME/.ssh
echo "$webhost $hostkey" > $HOME/.ssh/known_hosts
cd inv.alid.pw
rsync -rlptzz --delete _site/ ${user}@${webhost}:
This ties everything together in two steps: first we compile the
site
binary that generates the website structure in
_site
, then, in the deploy task, we set up SSH and rsync
the files into place. That’s it! We just have to save this into our repo
and everything will just happen automagically when we push new
commits.
One issue I have at the moment (and probably the reason I’m only finishing this now, when I first started trying to set this up back in November) is that it takes a long time for the build server to download and compile all the Haskell dependencies, particularly Pandoc. In the long term, a half-hour delay to publishing isn’t that bad, but it’s a little annoying. Next on my list is to try building this with NixOS (instead of Stack) to see if the binary caching provided there speeds things up a bit.