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
33 ${pkgs.pinch}/bin/pinch update channels
37 in_tmpdir ${config.system.build.nixos-rebuild}/bin/nixos-rebuild build
38 as_user nix-build --no-out-link '<nixpkgs>' -A ${
39 escapeShellArg cfg.userEnvironment.package
43 ${config.system.build.nixos-rebuild}/bin/nixos-rebuild switch
44 as_user nix-env -f '<nixpkgs>' -riA ${
45 escapeShellArg cfg.userEnvironment.package
52 system.autoUpgradeWithPinch = {
58 Whether to periodically upgrade NixOS to the latest version.
59 Presumes that /etc/nixos is a git repo with a remote and
60 contains a pinch file called "channels".
68 Specification (in the format described by
69 <citerefentry><refentrytitle>systemd.time</refentrytitle>
70 <manvolnum>7</manvolnum></citerefentry>) of the time at
71 which the update will occur.
78 File containing GPG keys that sign updates. Updates are only merged
79 if the commit at the tip of the remote branch is signed with one of
89 Whether to update a user-environment as well. This update is done
90 with nix-env -riA. Note the -r! I.e., ALL OTHER PACKAGES INSTALLED
91 WITH nix-env WILL BE DELETED!
93 This presumes that you have configured an "entire user environment"
95 https://nixos.wiki/wiki/FAQ#How_can_I_manage_software_with_nix-env_like_with_configuration.nix.3F
97 To check if you're set up for this, run "nix-env --query". If it
98 only lists one package, you're good to go.
105 The username of the user whose environment should be updated.
111 example = "nixos.userPackages";
113 The name of the single package that is the user's entire environment.
121 config = lib.mkIf cfg.enable {
123 security.sudo.extraRules = lib.mkAfter [{
124 groups = [ "users" ];
126 command = "${auto-upgrade-script}";
127 options = [ "NOPASSWD" "NOSETENV" ];
130 # NOSETENV above still allows through ~17 vars, including PATH. Block those
132 security.sudo.extraConfig = ''
133 Defaults!${auto-upgrade-script} !env_check
134 Defaults!${auto-upgrade-script} !env_keep
138 (import ../overlays/keyedgit.nix)
139 (import ../overlays/pinch.nix)
140 (import ../overlays/polite-merge.nix)
142 auto-upgrade = super.writeShellScriptBin "auto-upgrade" ''
143 /run/wrappers/bin/sudo ${auto-upgrade-script}
148 environment.systemPackages = [ pkgs.auto-upgrade ];
150 systemd.services.nixos-upgrade = {
151 description = "NixOS Upgrade";
152 restartIfChanged = false;
153 unitConfig.X-StopOnRemoval = false;
154 serviceConfig.Type = "oneshot";
155 environment = config.nix.envVars // {
156 inherit (config.environment.sessionVariables) NIX_PATH;
158 } // config.networking.proxy.envVars;
161 config.nix.package.out
173 # Chill for awhile before applying updates. If applying an update
174 # badly breaks things, we want a window in which an operator can
175 # intervene either to fix the problem or disable automatic updates.
178 # Wait until outside business hours
180 day_of_week=$(date +%u)
181 business_start=$(date -d 8:00 +%s)
182 business_end=$( date -d 17:00 +%s)
183 if (( day_of_week <= 5 && now > business_start && now < business_end ));then
184 delay=$((business_end - now))
185 echo "Waiting $delay seconds so we don't upgrade during business hours" >&2
189 ${auto-upgrade-script}
196 assertion = cfg.userEnvironment.enable -> cfg.enable;
198 "User environment upgrades cannot yet be enabled separately from system upgrades.";