]> git.scottworley.com Git - auto-upgrade-with-pinch/blobdiff - modules/auto-upgrade.nix
Drop 22.11 support: Just use "nativeCheckInputs"
[auto-upgrade-with-pinch] / modules / auto-upgrade.nix
index 7e48c40d137bc978adffa38651f42b64f48ef41d..a80aa5cdf56fe51ebdfedee0bdcf5e0f4ab3c608 100644 (file)
@@ -1,65 +1,73 @@
+# auto-upgrade-with-pinch: Secure managed NixOS updates
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, version 3.
+
 { config, lib, pkgs, ... }:
 with lib;
 let
 { config, lib, pkgs, ... }:
 with lib;
 let
+  local-pkgs = import ../. { inherit pkgs; };
   cfg = config.system.autoUpgradeWithPinch;
   cfg = config.system.autoUpgradeWithPinch;
-  pull-repo-script =
-    pkgs.writeShellScript "pull-repo" ''
-      set -eo pipefail
-
-      path=$1
-      config=$2
-
-      prop() {
-        ${pkgs.jq}/bin/jq -r ".$1" <<< "$config"
-      }
-
-      echo Pulling in "$path" >&2
-
-      if [[ ! -e "$path" ]];then
-        d=$(mktemp -d)
-        ${pkgs.git}/bin/git init "$d"
-        ${pkgs.git}/bin/git -C "$d" checkout -b "$(prop localBranch)"
-        ${pkgs.git}/bin/git -C "$d" remote add "$(prop remoteName)" "$(prop url)"
-        ${pkgs.git}/bin/git -C "$d" branch -u "$(prop remoteBranch)"
-        mkdir -p "$(${pkgs.coreutils}/bin/dirname "$path")"
-        mv "$d" "$path"
-      fi
-
-      cd "$path"
-
-      if [[ "$(${pkgs.git}/bin/git remote get-url "$(prop remoteName)")" != "$(prop url)" ]]; then
-        echo Expected git remote "$(prop remoteName)" to point at "$(prop url)" \
-          but it points at "$(${pkgs.git}/bin/git remote get-url "$(prop remoteName)")" >&2
-        case "$(prop onRemoteURLMismatch)" in
-          abort)  exit 1;;
-          update) echo Updating it >&2
-                  ${pkgs.git}/bin/git -C "$d" remote set-url "$(prop remoteName)" "$(prop url)";;
-        esac
-      fi
-
-      ${pkgs.git}/bin/git fetch "$(prop remoteName)" "$(prop remoteBranch)"
-
-      if [[ "$(${pkgs.git}/bin/git rev-parse --abbrev-ref HEAD)" != "$(prop localBranch)" ]];then
-        echo Could not merge because currently-checked-out \
-             \""$(${pkgs.git}/bin/git rev-parse --abbrev-ref HEAD)"\" is not \
-             \""$(prop localBranch)"\"
-        case "$(prop onBranchMismatch)" in
-          abort) exit 1;;
-          continue) exit 0;;
-        esac
-      fi
-
-      if [[ "$(prop requireSignature)" == true ]]; then
-        ${pkgs.polite-merge}/bin/polite-merge \
-          -c gpg.program='${pkgs.keyedgpg} '"$(prop 'signingKeys[]' | tr \\n ' ')"' --' \
-          merge --ff-only --verify-signatures
-      else
-        ${pkgs.polite-merge}/bin/polite-merge merge --ff-only
-      fi
-    '';
+  pull-repo-script = pkgs.writeShellScript "pull-repo" ''
+    set -eo pipefail
+
+    path=$1
+    config=$2
+
+    prop() {
+      ${pkgs.jq}/bin/jq -r ".$1" <<< "$config"
+    }
+
+    echo Pulling in "$path" >&2
+
+    if [[ ! -e "$path" ]];then
+      d=$(mktemp -d)
+      ${pkgs.git}/bin/git init "$d"
+      ${pkgs.git}/bin/git -C "$d" checkout -b "$(prop localBranch)"
+      ${pkgs.git}/bin/git -C "$d" remote add "$(prop remoteName)" "$(prop url)"
+      ${pkgs.git}/bin/git -C "$d" branch -u "$(prop remoteBranch)"
+      mkdir -p "$(${pkgs.coreutils}/bin/dirname "$path")"
+      mv "$d" "$path"
+    fi
+
+    cd "$path"
+
+    if [[ "$(${pkgs.git}/bin/git remote get-url "$(prop remoteName)")" != "$(prop url)" ]]; then
+      echo Expected git remote "$(prop remoteName)" to point at "$(prop url)" \
+        but it points at "$(${pkgs.git}/bin/git remote get-url "$(prop remoteName)")" >&2
+      case "$(prop onRemoteURLMismatch)" in
+        abort)  exit 1;;
+        update) echo Updating it >&2
+                ${pkgs.git}/bin/git -C "$d" remote set-url "$(prop remoteName)" "$(prop url)";;
+      esac
+    fi
+
+    ${pkgs.git}/bin/git fetch "$(prop remoteName)" "$(prop remoteBranch)"
+
+    if [[ "$(${pkgs.git}/bin/git rev-parse --abbrev-ref HEAD)" != "$(prop localBranch)" ]];then
+      echo Could not merge because currently-checked-out \
+           \""$(${pkgs.git}/bin/git rev-parse --abbrev-ref HEAD)"\" is not \
+           \""$(prop localBranch)"\"
+      case "$(prop onBranchMismatch)" in
+        abort) exit 1;;
+        continue) exit 0;;
+      esac
+    fi
+
+    if [[ "$(prop requireSignature)" == true ]]; then
+      ${pkgs.polite-merge}/bin/polite-merge \
+        -c gpg.program=${escapeShellArg (local-pkgs.keyed-gpg cfg.signingKeys)} \
+        merge --ff-only --verify-signatures
+    else
+      ${pkgs.polite-merge}/bin/polite-merge merge --ff-only
+    fi
+  '';
 
   auto-upgrade-script = pkgs.writeShellScript "auto-upgrade" ''
 
   auto-upgrade-script = pkgs.writeShellScript "auto-upgrade" ''
-    ${pkgs.utillinux}/bin/flock /run/auto-upgrade-with-pinch ${
+    ${pkgs.coreutils}/bin/nice -n 17 \
+    ${pkgs.util-linux}/bin/ionice -c 3 \
+    ${pkgs.util-linux}/bin/flock /run/auto-upgrade-with-pinch ${
       pkgs.writeShellScript "auto-upgrade-with-lock-held" ''
         set -eo pipefail
 
       pkgs.writeShellScript "auto-upgrade-with-lock-held" ''
         set -eo pipefail
 
@@ -144,12 +152,12 @@ let
           + concatMapStringsSep "\n" (f: "verify_ownership ${escapeShellArg f}")
           cfg.upgradeConfig)}
 
           + concatMapStringsSep "\n" (f: "verify_ownership ${escapeShellArg f}")
           cfg.upgradeConfig)}
 
-        config=$(${pkgs.nix}/bin/nix eval --json -f ${../upgrade-config.nix} \
+        config=$(${pkgs.nix}/bin/nix-instantiate --eval --strict --json -A config \
           --arg upgradeConfig ${
             escapeShellArg ("["
               + lib.concatMapStringsSep " " lib.strings.escapeNixString
               cfg.upgradeConfig + "]")
           --arg upgradeConfig ${
             escapeShellArg ("["
               + lib.concatMapStringsSep " " lib.strings.escapeNixString
               cfg.upgradeConfig + "]")
-          } config)
+          } ${../upgrade-config.nix})
 
         config_query() {
           ${pkgs.jq}/bin/jq -r "$@" <<< "$config"
 
         config_query() {
           ${pkgs.jq}/bin/jq -r "$@" <<< "$config"
@@ -218,6 +226,15 @@ in {
         '';
       };
 
         '';
       };
 
+      signingKeys = mkOption {
+        type = types.listOf types.path;
+        description = ''
+          Files containing GPG keys that are authorized to sign updates.
+          Updates are only merged if the commit at the tip of the remote
+          ref is signed with one of these keys.
+        '';
+      };
+
       upgradeConfig = mkOption {
         type = types.listOf types.path;
         description = ''
       upgradeConfig = mkOption {
         type = types.listOf types.path;
         description = ''
@@ -261,7 +278,6 @@ in {
     '';
 
     nixpkgs.overlays = [
     '';
 
     nixpkgs.overlays = [
-      (import ../overlays/keyedgpg.nix)
       (import ../overlays/pinch.nix)
       (import ../overlays/polite-merge.nix)
       (self: super: {
       (import ../overlays/pinch.nix)
       (import ../overlays/polite-merge.nix)
       (self: super: {