diff options
Diffstat (limited to 'ops')
-rw-r--r-- | ops/modules/auto-deploy.nix | 92 | ||||
-rw-r--r-- | ops/modules/default-imports.nix | 1 | ||||
-rw-r--r-- | ops/nixos.nix | 8 |
3 files changed, 98 insertions, 3 deletions
diff --git a/ops/modules/auto-deploy.nix b/ops/modules/auto-deploy.nix new file mode 100644 index 000000000000..8ffc0afbc695 --- /dev/null +++ b/ops/modules/auto-deploy.nix @@ -0,0 +1,92 @@ +# Defines a service for automatically and periodically calling depot's +# rebuild-system on a NixOS machine. +{ depot, config, lib, pkgs, ... }: + +let + cfg = config.services.depot.auto-deploy; + description = "to automatically rebuild the current system's NixOS config from the latest checkout of depot"; + + rebuild-system = depot.ops.nixos.rebuildSystemWith "$STATE_DIRECTORY/deploy"; + deployScript = pkgs.writeShellScript "auto-deploy" '' + set -ueo pipefail + + if [[ $EUID -ne 0 ]]; then + echo "Oh no! Only root is allowed to run auto-deploy!" >&2 + exit 1 + fi + + readonly depot=$STATE_DIRECTORY/depot.git + readonly deploy=$STATE_DIRECTORY/deploy + readonly git="git -C $depot" + + # find-or-create depot + if [ ! -d $depot ]; then + # cannot use $git here because $depot doesn't exist + git clone --bare ${cfg.git-remote} $depot + fi + + function cleanup() { + $git worktree remove $deploy + } + trap cleanup EXIT + + $git fetch origin + $git worktree add --force $deploy FETCH_HEAD + # unsure why, but without this switch-to-configuration attempts to install + # NixOS in $STATE_DIRECTORY + (cd / && ${rebuild-system}/bin/rebuild-system) + ''; +in { + options.services.depot.auto-deploy = { + enable = lib.mkEnableOption description; + + git-remote = lib.mkOption { + type = lib.types.str; + default = "https://cl.tvl.fyi/depot.git"; + description = '' + The (possibly remote) repository from which to clone as specified by the + GIT URLS section of `man git-clone`. + ''; + }; + + interval = lib.mkOption { + type = lib.types.str; + example = "1h"; + description = '' + Interval between Nix builds, specified in systemd.time(7) format. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.auto-deploy = { + inherit description; + script = "${deployScript}"; + path = [ + pkgs.bash + pkgs.git + ]; + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; + + # We need to prevent NixOS from interrupting us while it attempts to + # restart systemd units. + restartIfChanged = false; + + serviceConfig = { + Type = "oneshot"; + StateDirectory = "auto-deploy"; + }; + }; + + systemd.timers.auto-deploy = { + inherit description; + wantedBy = [ "multi-user.target" ]; + + timerConfig = { + OnActiveSec = "1"; + OnUnitActiveSec = cfg.interval; + }; + }; + }; +} diff --git a/ops/modules/default-imports.nix b/ops/modules/default-imports.nix index acd70bd05f01..11514a437a42 100644 --- a/ops/modules/default-imports.nix +++ b/ops/modules/default-imports.nix @@ -8,6 +8,7 @@ { imports = [ ./automatic-gc.nix + ./auto-deploy.nix ./tvl-cache.nix ]; } diff --git a/ops/nixos.nix b/ops/nixos.nix index 19ba0168c07e..66ca188c5bca 100644 --- a/ops/nixos.nix +++ b/ops/nixos.nix @@ -32,7 +32,9 @@ in rec { (throw "${hostname} is not a known NixOS host") (map nixosFor depot.ops.machines.all-systems)); - rebuild-system = pkgs.writeShellScriptBin "rebuild-system" '' + rebuild-system = rebuildSystemWith depot.path; + + rebuildSystemWith = depotPath: pkgs.writeShellScriptBin "rebuild-system" '' set -ue if [[ $EUID -ne 0 ]]; then echo "Oh no! Only root is allowed to rebuild the system!" >&2 @@ -40,9 +42,9 @@ in rec { fi echo "Rebuilding NixOS for $HOSTNAME" - system=$(nix-build -E "((import ${toString depot.path} {}).ops.nixos.findSystem \"$HOSTNAME\").system" --no-out-link --show-trace) + system=$(${pkgs.nix}/bin/nix-build -E "((import ${depotPath} {}).ops.nixos.findSystem \"$HOSTNAME\").system" --no-out-link --show-trace) - nix-env -p /nix/var/nix/profiles/system --set $system + ${pkgs.nix}/bin/nix-env -p /nix/var/nix/profiles/system --set $system $system/bin/switch-to-configuration switch ''; |