{ config, pkgs, lib, ... }: let sites = [ { name = "sublunar"; input = "sublunar"; } { name = "tobias-raayoni-last"; input = "flux_vision"; } { name = "nmns"; input = "nfc_web"; } ]; # 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 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 ''; in { sops.secrets.webhook_secret = { owner = "root"; mode = "0400"; }; # System-wide SSH client config so root can reach Codeberg via the deploy key. programs.ssh.extraConfig = '' Host codeberg.org IdentityFile /etc/ssh/codeberg_id_ed25519 StrictHostKeyChecking accept-new ''; 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"; }; }; }; }