Hakyll + sourcehut = ☺
This 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.