about summary refs log tree commit diff
path: root/ops/modules
diff options
context:
space:
mode:
authorWilliam Carroll <wpcarro@gmail.com>2021-12-17T00·49-0500
committerclbot <clbot@tvl.fyi>2021-12-26T14·55+0000
commit80ef71e9958d0effe0ea1e1fb39b7200e02eff70 (patch)
tree8b47e0210cb8fcaf255aafb27ffe6faac0dd2f5e /ops/modules
parent1d10adb67ccf87cc7461be71905b1ee2378b7c73 (diff)
feat(ops/auto-deploy): Support auto-deploy r/3414
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 <wpcarro@gmail.com>
Reviewed-by: zseri <zseri.devel@ytrizja.de>
Reviewed-by: grfn <grfn@gws.fyi>
Autosubmit: wpcarro <wpcarro@gmail.com>
Tested-by: BuildkiteCI
Diffstat (limited to 'ops/modules')
-rw-r--r--ops/modules/auto-deploy.nix92
-rw-r--r--ops/modules/default-imports.nix1
2 files changed, 93 insertions, 0 deletions
diff --git a/ops/modules/auto-deploy.nix b/ops/modules/auto-deploy.nix
new file mode 100644
index 0000000000..8ffc0afbc6
--- /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 acd70bd05f..11514a437a 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
   ];
 }