]> git.scottworley.com Git - auto-upgrade-with-pinch/blobdiff - upgrade-config.nix
Dynamic config
[auto-upgrade-with-pinch] / upgrade-config.nix
diff --git a/upgrade-config.nix b/upgrade-config.nix
new file mode 100644 (file)
index 0000000..e9962eb
--- /dev/null
@@ -0,0 +1,157 @@
+{ upgradeConfig, lib ? (import <nixpkgs> { }).lib, }:
+with lib;
+evalModules {
+  modules = upgradeConfig ++ [{
+    options = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to periodically upgrade NixOS to the latest version.
+          Presumes that /etc/nixos is a git repo with a remote and
+          contains a pinch file called "channels".
+        '';
+      };
+
+      dates = mkOption {
+        default = "04:40";
+        type = types.str;
+        description = ''
+          Specification (in the format described by
+          <citerefentry><refentrytitle>systemd.time</refentrytitle>
+          <manvolnum>7</manvolnum></citerefentry>) of the time at
+          which the update will occur.
+        '';
+      };
+
+      repos = mkOption {
+        description = ''
+          Git repositories to pull before running pinch.  These are maintained
+          as git checkouts at specified places in the filesystem with specified
+          ownership rather than kept read-only in the nix store so that humans
+          can use them both as points of intervention in the automation and to
+          author and push changes back up.
+        '';
+        type = types.attrsOf (types.submodule {
+          options = {
+            url = mkOption {
+              description = "Remote git repo.";
+              type = types.str;
+            };
+            remoteName = mkOption {
+              description = ''Name of the git remote.  Customarily "origin".'';
+              type = types.str;
+              default = "origin";
+            };
+            onRemoteURLMismatch = mkOption {
+              description = ''
+                What to do if the remote URL in the git repo doesn't match the
+                URL configured here.
+              '';
+              type = types.enum [ "update" "abort" ];
+              default = "update";
+            };
+            onBranchMismatch = mkOption {
+              description = ''
+                What to do if a different branch is currently checked out.
+
+                (Changes from <literal>remoteBranch</literal> are only ever
+                merged into <literal>localBranch</literal>, so if a different
+                branch is checked out, no remote changes will be merged.)
+              '';
+              type = types.enum [ "continue" "abort" ];
+              default = "continue";
+            };
+            user = mkOption {
+              description = "User as which to run 'git fetch'";
+              type = types.str;
+            };
+            localBranch = mkOption {
+              description = "";
+              type = types.str;
+              default = "master";
+            };
+            remoteBranch = mkOption {
+              type = types.str;
+              default = "master";
+            };
+            requireSignature = mkOption {
+              type = types.bool;
+              default = true;
+              description = ''
+                Only pull when the tip of the remote ref is signed by a key
+                specifed in <literal>signingKeys</literal>.
+              '';
+            };
+            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.
+              '';
+            };
+          };
+        });
+        example = {
+          "/etc/nixos" = {
+            url = "https://github.com/chkno/auto-upgrade-demo-nixos";
+            user = "root";
+            signingKeys = [ ./admins.asc ];
+          };
+          "/home/alice/.config/nixpkgs" = {
+            url = "https://github.com/chkno/auto-upgrade-demo-user-nixpkgs";
+            user = "alice";
+            signingKeys = [ ./admins.asc ./alice.asc ];
+          };
+        };
+      };
+
+      pinchFiles = mkOption {
+        description = ''
+          Pinch files to use for channel updates.  Typically these are inside
+          <literal>repos</literal>' paths.
+        '';
+        type = types.listOf types.path;
+        example = [ "/etc/nixos/channels" ];
+      };
+
+      userEnvironments = mkOption {
+        description = ''
+          User environments to update as part of an upgrade run.
+        '';
+        type = types.attrsOf (types.submodule {
+          options = {
+            package = mkOption {
+              type = types.str;
+              default = "userPackages";
+              description = ''
+                The name of the single package that will be updated.  You'll
+                want to create an 'entire user environment' package as shown in
+                https://nixos.wiki/wiki/FAQ#How_can_I_manage_software_with_nix-env_like_with_configuration.nix.3F
+              '';
+            };
+            otherPackagesAction = mkOption {
+              type = types.enum [ "remove" "keep" "abort" ];
+              default = "remove";
+              description = ''
+                What to do with packages other than <literal>package</literal>.
+
+                THIS DEFAULTS TO "remove", WHICH IS POTENTIALLY SOMEWHAT
+                DESTRUCTIVE!  This is the default because it is the recommended
+                setting -- This module recommends managing your environment
+                through your one entire-environment <literal>package</literal>.
+                This keeps your environment declarative and ensures that all
+                packages receive regular updates.
+              '';
+              # It seems like "upgrade" ought to be another choice here, powered
+              # by "nix-env --upgrade".  But when I tried this, it didn't work.
+            };
+          };
+        });
+        example = { alice = { }; };
+      };
+    };
+  }];
+}