{ upgradeConfig, lib ? (import { }).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 systemd.time 7) 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 remoteBranch are only ever merged into localBranch, 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 signingKeys. ''; }; 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 repos' 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 package. 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 package. 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 = { }; }; }; }; }]; }