{ config, pkgs, ... }: let updateCommand = "/run/current-system/sw/bin/systemctl start updater.service"; in { # Build user users = { groups.updater = {}; users.updater = { isSystemUser = true; group = "updater"; home = "/var/lib/updater"; }; }; systemd = { # Timer-triggered service that updates flake.lock and pushes to a branch to be picked up by Hydra. services.updater = { wantedBy = [ "multi-user.target" ]; path = with pkgs; [ git nix curl openssh ]; script = '' git config --global user.email "astro@spaceboyz.net" git config --global user.name "Astrobot" TEMP=$(mktemp -d) cd $TEMP git clone --depth=1 --single-branch gitea@gitea.c3d2.de:C3D2/nix-config.git cd nix-config nix flake update --commit-lock-file git push -f origin HEAD:flake-update ''; serviceConfig = { User = "updater"; Group = config.users.users.updater.group; PrivateTmp = true; ProtectSystem = "full"; }; }; timers.updater = { partOf = [ "updater.service" ]; wantedBy = [ "timers.target" ]; # update flake.lock daily at 10am so that systems are freshly # built by afternoon timerConfig.OnCalendar = "10:00"; }; tmpfiles.rules = [ # needs to be provisioned with ssh privkey "d ${config.users.users.updater.home} 0700 updater ${config.users.users.updater.group} -" ]; }; # make webhook service accessible thru reverse proxy services.nginx .virtualHosts."hydra.serv.zentralwerk.org" .locations."/hooks/" .proxyPass = "http://localhost:9000/hooks/"; # webhook trigger for gitea systemd.services.webhook = let hooksJson = pkgs.writeText "hooks.json" (builtins.toJSON [ { # https://hydra.serv.zentralwerk.org/hooks/updater id = "updater"; execute-command = pkgs.writeShellScript "updater" '' # Start updater.service if not already running exec /run/wrappers/bin/sudo ${updateCommand} ''; } ]); in { wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = "${pkgs.webhook}/bin/webhook -hooks ${hooksJson} -verbose -ip 127.0.0.1"; User = "updater"; Group = config.users.users.updater.group; PrivateTmp = true; ProtectSystem = "full"; }; }; security.sudo.extraRules = [ { users = [ "updater" ]; commands = [ { command = updateCommand; options = [ "NOPASSWD" ]; } ]; } ]; }