about summary refs log tree commit diff
path: root/ops
diff options
context:
space:
mode:
Diffstat (limited to 'ops')
-rw-r--r--ops/modules/auto-deploy.nix92
-rw-r--r--ops/modules/default-imports.nix1
-rw-r--r--ops/nixos.nix8
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
   '';