1 { config, lib, pkgs, ... }:
4 cfg = config.system.autoUpgradeWithPinch;
8 ${pkgs.git}/bin/git fetch
9 PATH="${pkgs.keyedgit cfg.keys}/bin:$PATH" \
10 ${pkgs.polite-merge}/bin/polite-merge --ff-only --verify-signatures
14 auto-upgrade-script = pkgs.writeShellScript "auto-upgrade" ''
15 ${pkgs.utillinux}/bin/flock /run/auto-upgrade-with-pinch ${
16 pkgs.writeShellScript "auto-upgrade-with-lock-held" ''
29 if cfg.userEnvironment.enable then ''
30 /run/wrappers/bin/sudo -u ${escapeShellArg cfg.userEnvironment.user} "$@"
41 ${pkgs.pinch}/bin/pinch update /etc/nixos/channels
44 in_tmpdir ${config.system.build.nixos-rebuild}/bin/nixos-rebuild build
45 as_user nix-build --no-out-link '<nixpkgs>' -A ${
46 escapeShellArg cfg.userEnvironment.package
50 ${config.system.build.nixos-rebuild}/bin/nixos-rebuild switch
51 as_user nix-env -f '<nixpkgs>' -riA ${
52 escapeShellArg cfg.userEnvironment.package
59 system.autoUpgradeWithPinch = {
65 Whether to periodically upgrade NixOS to the latest version.
66 Presumes that /etc/nixos is a git repo with a remote and
67 contains a pinch file called "channels".
75 Specification (in the format described by
76 <citerefentry><refentrytitle>systemd.time</refentrytitle>
77 <manvolnum>7</manvolnum></citerefentry>) of the time at
78 which the update will occur.
85 File containing GPG keys that sign updates. Updates are only merged
86 if the commit at the tip of the remote branch is signed with one of
96 Whether to update a user-environment as well. This update is done
97 with nix-env -riA. Note the -r! I.e., ALL OTHER PACKAGES INSTALLED
98 WITH nix-env WILL BE DELETED!
100 This presumes that you have configured an "entire user environment"
102 https://nixos.wiki/wiki/FAQ#How_can_I_manage_software_with_nix-env_like_with_configuration.nix.3F
104 To check if you're set up for this, run "nix-env --query". If it
105 only lists one package, you're good to go.
112 The username of the user whose environment should be updated.
118 example = "nixos.userPackages";
120 The name of the single package that is the user's entire environment.
128 config = lib.mkIf cfg.enable {
130 security.sudo.extraRules = lib.mkAfter [{
131 groups = [ "users" ];
133 command = "${auto-upgrade-script}";
134 options = [ "NOPASSWD" "NOSETENV" ];
137 # NOSETENV above still allows through ~17 vars, including PATH. Block those
139 security.sudo.extraConfig = ''
140 Defaults!${auto-upgrade-script} !env_check
141 Defaults!${auto-upgrade-script} !env_keep
145 (import ../overlays/keyedgit.nix)
146 (import ../overlays/pinch.nix)
147 (import ../overlays/polite-merge.nix)
149 auto-upgrade = super.writeShellScriptBin "auto-upgrade" ''
150 /run/wrappers/bin/sudo ${auto-upgrade-script}
155 environment.systemPackages = [ pkgs.auto-upgrade ];
157 systemd.services.nixos-upgrade = {
158 description = "NixOS Upgrade";
159 restartIfChanged = false;
160 unitConfig.X-StopOnRemoval = false;
161 serviceConfig.Type = "oneshot";
162 environment = config.nix.envVars // {
163 inherit (config.environment.sessionVariables) NIX_PATH;
165 } // config.networking.proxy.envVars;
168 config.nix.package.out
180 # Chill for awhile before applying updates. If applying an update
181 # badly breaks things, we want a window in which an operator can
182 # intervene either to fix the problem or disable automatic updates.
185 # Wait until outside business hours
187 day_of_week=$(date +%u)
188 business_start=$(date -d 8:00 +%s)
189 business_end=$( date -d 17:00 +%s)
190 if (( day_of_week <= 5 && now > business_start && now < business_end ));then
191 delay=$((business_end - now))
192 echo "Waiting $delay seconds so we don't upgrade during business hours" >&2
196 ${auto-upgrade-script}
203 assertion = cfg.userEnvironment.enable -> cfg.enable;
205 "User environment upgrades cannot yet be enabled separately from system upgrades.";