bucur/modules/services/webhook-deploy.nix

86 lines
3 KiB
Nix

{ config, pkgs, lib, ... }:
let
sites = [
{ name = "sublunar"; input = "sublunar"; }
{ name = "tobias-raayoni-last"; input = "flux_vision"; }
{ name = "nmns"; input = "nfc_web"; }
{ name = "zonetoast"; input = "zonetoast"; }
];
# Template hooks.json with a placeholder secret — real secret injected at
# service start time from the sops-managed file.
hooksTemplate = pkgs.writeText "webhook-hooks-template.json" (builtins.toJSON
(map (site: {
id = "rebuild-${site.name}";
execute-command = "/run/current-system/sw/bin/systemctl";
pass-arguments-to-command = [
{ source = "string"; name = "start"; }
{ source = "string"; name = "--no-block"; }
{ source = "string"; name = "update-${site.name}"; }
];
response-message = "Queued rebuild of ${site.name}";
trigger-rule.match = {
type = "payload-hmac-sha256";
secret = "placeholder";
parameter = { source = "header"; name = "X-Gitea-Signature"; };
};
}) sites)
);
# Writes /run/webhook-deploy/hooks.json with the real secret at startup.
makeHooks = pkgs.writeShellScript "make-webhook-hooks" ''
set -euo pipefail
${pkgs.jq}/bin/jq \
--arg s "$(cat ${config.sops.secrets.webhook_secret.path})" \
'map(.["trigger-rule"].match.secret = $s)' \
${hooksTemplate} > /run/webhook-deploy/hooks.json
'';
updateScript = site: pkgs.writeShellScript "do-update-${site.name}" ''
set -euo pipefail
export PATH=/run/current-system/sw/bin:$PATH
cd /etc/nixos
OLD=$(${pkgs.jq}/bin/jq -r '.nodes.${site.input}.locked.rev' flake.lock)
nix flake update ${site.input}
NEW=$(${pkgs.jq}/bin/jq -r '.nodes.${site.input}.locked.rev' flake.lock)
if [ "$OLD" = "$NEW" ]; then
echo "${site.name}: no change, skipping rebuild"
exit 0
fi
echo "${site.name}: updated $OLD -> $NEW, rebuilding"
nixos-rebuild switch --flake /etc/nixos#bucur
systemctl start deploy-${site.name}
'';
in
{
sops.secrets.webhook_secret = {
owner = "root";
mode = "0400";
};
# All flake inputs pulled here now live on code.randogoth.com; the SSH
# client config for that host (same deploy key) is set up in forgejo.nix.
systemd.services = lib.listToAttrs
(map (site: lib.nameValuePair "update-${site.name}" {
description = "Pull and rebuild ${site.name}";
serviceConfig = {
Type = "oneshot";
ExecStart = updateScript site;
};
}) sites)
// {
webhook-deploy = {
description = "Webhook server for Pelican site rebuilds";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" "sops-nix.service" ];
serviceConfig = {
Type = "simple";
RuntimeDirectory = "webhook-deploy";
ExecStartPre = "+${makeHooks}";
ExecStart = "${pkgs.webhook}/bin/webhook -hooks /run/webhook-deploy/hooks.json -port 9000";
Restart = "on-failure";
};
};
};
}