From 80ef71e9958d0effe0ea1e1fb39b7200e02eff70 Mon Sep 17 00:00:00 2001 From: William Carroll Date: Thu, 16 Dec 2021 19:49:23 -0500 Subject: feat(ops/auto-deploy): Support auto-deploy Automatically rebuild the current system's NixOS config from the latest checkout of depot. Change-Id: I23aa7af50e16e985ac34df214e0905e770316e5e Reviewed-on: https://cl.tvl.fyi/c/depot/+/4390 Reviewed-by: wpcarro Reviewed-by: zseri Reviewed-by: grfn Autosubmit: wpcarro Tested-by: BuildkiteCI --- ops/modules/auto-deploy.nix | 92 ++++++++++++++++++++++++++++++++ ops/modules/default-imports.nix | 1 + ops/nixos.nix | 8 +-- users/wpcarro/nixos/diogenes/default.nix | 5 ++ 4 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 ops/modules/auto-deploy.nix 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 ''; diff --git a/users/wpcarro/nixos/diogenes/default.nix b/users/wpcarro/nixos/diogenes/default.nix index af49f33aa1a1..fd710d804b07 100644 --- a/users/wpcarro/nixos/diogenes/default.nix +++ b/users/wpcarro/nixos/diogenes/default.nix @@ -68,6 +68,11 @@ in { ]; }; + depot.auto-deploy = { + enable = true; + interval = "1h"; + }; + journaldriver = { enable = true; logStream = "home"; -- cgit 1.4.1