1 { config, lib, pkgs, ... }:
4 cfg = config.system.autoUpgradeWithPinch;
5 auto-upgrade-script = pkgs.writeShellScript "auto-upgrade" ''
6 ${pkgs.utillinux}/bin/flock /run/auto-upgrade-with-pinch ${
7 pkgs.writeShellScript "auto-upgrade-with-lock-held" ''
20 if cfg.userEnvironment.enable then ''
21 /run/wrappers/bin/sudo -u ${escapeShellArg cfg.userEnvironment.user} "$@"
31 ${pkgs.git}/bin/git fetch
32 PATH="${pkgs.keyedgit cfg.keys}/bin:$PATH" ${pkgs.polite-merge}/bin/polite-merge --ff-only --verify-signatures
36 ${pkgs.pinch}/bin/pinch update /etc/nixos/channels
39 in_tmpdir ${config.system.build.nixos-rebuild}/bin/nixos-rebuild build
40 as_user nix-build --no-out-link '<nixpkgs>' -A ${
41 escapeShellArg cfg.userEnvironment.package
45 ${config.system.build.nixos-rebuild}/bin/nixos-rebuild switch
46 as_user nix-env -f '<nixpkgs>' -riA ${
47 escapeShellArg cfg.userEnvironment.package
54 system.autoUpgradeWithPinch = {
60 Whether to periodically upgrade NixOS to the latest version.
61 Presumes that /etc/nixos is a git repo with a remote and
62 contains a pinch file called "channels".
70 Specification (in the format described by
71 <citerefentry><refentrytitle>systemd.time</refentrytitle>
72 <manvolnum>7</manvolnum></citerefentry>) of the time at
73 which the update will occur.
80 File containing GPG keys that sign updates. Updates are only merged
81 if the commit at the tip of the remote branch is signed with one of
91 Whether to update a user-environment as well. This update is done
92 with nix-env -riA. Note the -r! I.e., ALL OTHER PACKAGES INSTALLED
93 WITH nix-env WILL BE DELETED!
95 This presumes that you have configured an "entire user environment"
97 https://nixos.wiki/wiki/FAQ#How_can_I_manage_software_with_nix-env_like_with_configuration.nix.3F
99 To check if you're set up for this, run "nix-env --query". If it
100 only lists one package, you're good to go.
107 The username of the user whose environment should be updated.
113 example = "nixos.userPackages";
115 The name of the single package that is the user's entire environment.
123 config = lib.mkIf cfg.enable {
125 security.sudo.extraRules = lib.mkAfter [{
126 groups = [ "users" ];
128 command = "${auto-upgrade-script}";
129 options = [ "NOPASSWD" "NOSETENV" ];
132 # NOSETENV above still allows through ~17 vars, including PATH. Block those
134 security.sudo.extraConfig = ''
135 Defaults!${auto-upgrade-script} !env_check
136 Defaults!${auto-upgrade-script} !env_keep
140 (import ../overlays/keyedgit.nix)
141 (import ../overlays/pinch.nix)
142 (import ../overlays/polite-merge.nix)
144 auto-upgrade = super.writeShellScriptBin "auto-upgrade" ''
145 /run/wrappers/bin/sudo ${auto-upgrade-script}
150 environment.systemPackages = [ pkgs.auto-upgrade ];
152 systemd.services.nixos-upgrade = {
153 description = "NixOS Upgrade";
154 restartIfChanged = false;
155 unitConfig.X-StopOnRemoval = false;
156 serviceConfig.Type = "oneshot";
157 environment = config.nix.envVars // {
158 inherit (config.environment.sessionVariables) NIX_PATH;
160 } // config.networking.proxy.envVars;
163 config.nix.package.out
175 # Chill for awhile before applying updates. If applying an update
176 # badly breaks things, we want a window in which an operator can
177 # intervene either to fix the problem or disable automatic updates.
180 # Wait until outside business hours
182 day_of_week=$(date +%u)
183 business_start=$(date -d 8:00 +%s)
184 business_end=$( date -d 17:00 +%s)
185 if (( day_of_week <= 5 && now > business_start && now < business_end ));then
186 delay=$((business_end - now))
187 echo "Waiting $delay seconds so we don't upgrade during business hours" >&2
191 ${auto-upgrade-script}
198 assertion = cfg.userEnvironment.enable -> cfg.enable;
200 "User environment upgrades cannot yet be enabled separately from system upgrades.";