There are several ways to automate blog publishing from git push. This one is mine. Mostly notes for future self. I use Gitea, Hugo, Caddy and NixOS.
Gitea basically has three options for solving the problem of deploying a hugo web page when you git push: CI, git hooks or webhooks. I don’t really like CI for this, giving the CI enviroment access to modify production. Git hooks have privileged access on the Gitea server. Webhook access depends on how one implements them.
There is a nice webhook receiver project called webhook that is packaged for NixOS. So I’ll use that.
# in configuration.nix or similar
# customize user for running hugo on git push
users.users.webhook = {
description = "Webhook daemon user";
isSystemUser = true;
group = "webhook";
createHome = true;
home = "/var/lib/webhook";
};
# docs https://search.nixos.org/options?query=services.webhook
services.webhook = {
enable = true;
hooks = {
publish-hugo-site = {
# docs https://github.com/adnanh/webhook/blob/master/docs/Hook-Definition.md
command-working-directory = "/srv/web/hugo-site/gitrepo";
# let nix handle the script with dependencies for us
execute-command = "${
pkgs.writeShellApplication {
name = "publish-hugo-site";
runtimeInputs = with pkgs; [ git hugo openssh ]; # git calls ssh
text = ''
git pull
hugo -d ../docroot
'';
}
}/bin/publish-hugo-site"; # match shell application name from above
# docs https://github.com/adnanh/webhook/blob/master/docs/Hook-Rules.md
trigger-rule = {
and = [
{
match = {
type = "payload-hmac-sha256";
secret = "<... pick a secret ...>";
parameter = {
source = "header";
name = "X-Gitea-Signature";
};
};
}
{
match = {
type = "value";
value = "refs/heads/main";
parameter = {
source = "payload";
name = "ref"; # docs https://docs.gitea.io/en-us/webhooks/
};
};
}
];
};
};
};
};
services.caddy = {
enable = true;
email = "needed@for.acme";
virtualHosts = {
"${config.networking.hostName}.${config.networking.domain}" = {
extraConfig = ''
route /hooks/* {
# no uri manipulation, path /hooks/ on webhook service as well
reverse_proxy http://localhost:9000;
}
'';
};
"hugo.site" = {
extraConfig = ''
root * /srv/web/hugo-site/docroot
file_server
'';
};
};
};
Now with those running, a few things must still be put in order:
- Pick a secret above shared by the webhook service and Gitea:
pwgen -s 64 1 - Create an SSH keypair for the webhook user so that it can git pull over SSH:
ssh-keygen -t ed25519 - Add that SSH keypair as a deploy key to the repository in Gitea
- Make an initial checkout of the repository in e.g.
/srv/web/hugo-site/gitrepo - Make sure /srv/web/hugo-site and contents is owned by user webhook
- Add a webhook in Gitea for the URL
https://host.name/hooks/publish-hugo-site, using the secret. Test & check logsjournalctl -fu webhook