8 cfg = config.system.autoUpgrade;
15 system.autoUpgrade = {
17 enable = lib.mkOption {
18 type = lib.types.bool;
21 Whether to periodically upgrade NixOS to the latest
22 version. If enabled, a systemd timer will run
23 `nixos-rebuild switch --upgrade` once a
28 operation = lib.mkOption {
29 type = lib.types.enum [
37 `nixos-rebuild switch --upgrade` or run
38 `nixos-rebuild boot --upgrade`
42 flake = lib.mkOption {
43 type = lib.types.nullOr lib.types.str;
45 example = "github:kloenk/nix";
47 The Flake URI of the NixOS configuration to build.
48 Disables the option {option}`system.autoUpgrade.channel`.
52 channel = lib.mkOption {
53 type = lib.types.nullOr lib.types.str;
55 example = "https://nixos.org/channels/nixos-14.12-small";
57 The URI of the NixOS channel to use for automatic
58 upgrades. By default, this is the channel set using
59 {command}`nix-channel` (run `nix-channel --list`
60 to see the current value).
64 flags = lib.mkOption {
65 type = lib.types.listOf lib.types.str;
69 "stuff=/home/alice/nixos-stuff"
72 "http://my-cache.example.org/"
75 Any additional flags passed to {command}`nixos-rebuild`.
77 If you are using flakes and use a local repo you can add
78 {command}`[ "--update-input" "nixpkgs" "--commit-lock-file" ]`
83 dates = lib.mkOption {
88 How often or when upgrade occurs. For most desktop and server systems
89 a sufficient upgrade frequency is once a day.
91 The format is described in
92 {manpage}`systemd.time(7)`.
96 allowReboot = lib.mkOption {
98 type = lib.types.bool;
100 Reboot the system into the new generation instead of a switch
101 if the new generation uses a different kernel, kernel modules
102 or initrd than the booted system.
103 See {option}`rebootWindow` for configuring the times at which a reboot is allowed.
107 randomizedDelaySec = lib.mkOption {
109 type = lib.types.str;
112 Add a randomized delay before each automatic upgrade.
113 The delay will be chosen between zero and this value.
114 This value must be a time span in the format specified by
115 {manpage}`systemd.time(7)`
119 fixedRandomDelay = lib.mkOption {
121 type = lib.types.bool;
124 Make the randomized delay consistent between runs.
125 This reduces the jitter between automatic upgrades.
126 See {option}`randomizedDelaySec` for configuring the randomized delay.
130 rebootWindow = lib.mkOption {
132 Define a lower and upper time value (in HH:MM format) which
133 constitute a time window during which reboots are allowed after an upgrade.
134 This option only has an effect when {option}`allowReboot` is enabled.
135 The default value of `null` means that reboots are allowed at any time.
146 lower = lib.mkOption {
147 description = "Lower limit of the reboot window";
148 type = lib.types.strMatching "[[:digit:]]{2}:[[:digit:]]{2}";
152 upper = lib.mkOption {
153 description = "Upper limit of the reboot window";
154 type = lib.types.strMatching "[[:digit:]]{2}:[[:digit:]]{2}";
161 persistent = lib.mkOption {
163 type = lib.types.bool;
166 Takes a boolean argument. If true, the time when the service
167 unit was last triggered is stored on disk. When the timer is
168 activated, the service unit is triggered immediately if it
169 would have been triggered at least once during the time when
170 the timer was inactive. Such triggering is nonetheless
171 subject to the delay imposed by RandomizedDelaySec=. This is
172 useful to catch up on missed runs of the service when the
173 system was powered down.
181 config = lib.mkIf cfg.enable {
185 assertion = !((cfg.channel != null) && (cfg.flake != null));
187 The options 'system.autoUpgrade.channel' and 'system.autoUpgrade.flake' cannot both be set.
192 system.autoUpgrade.flags = (
193 if cfg.flake == null then
194 [ "--no-build-output" ]
195 ++ lib.optionals (cfg.channel != null) [
197 "nixpkgs=${cfg.channel}/nixexprs.tar.xz"
202 "--flake ${cfg.flake}"
206 systemd.services.nixos-upgrade = {
207 description = "NixOS Upgrade";
209 restartIfChanged = false;
210 unitConfig.X-StopOnRemoval = false;
212 serviceConfig.Type = "oneshot";
217 inherit (config.environment.sessionVariables) NIX_PATH;
220 // config.networking.proxy.envVars;
228 config.nix.package.out
229 config.programs.ssh.package
234 nixos-rebuild = "${config.system.build.nixos-rebuild}/bin/nixos-rebuild";
235 date = "${pkgs.coreutils}/bin/date";
236 readlink = "${pkgs.coreutils}/bin/readlink";
237 shutdown = "${config.systemd.package}/bin/shutdown";
238 upgradeFlag = lib.optional (cfg.channel == null) "--upgrade";
240 if cfg.allowReboot then
242 ${nixos-rebuild} boot ${toString (cfg.flags ++ upgradeFlag)}
243 booted="$(${readlink} /run/booted-system/{initrd,kernel,kernel-modules})"
244 built="$(${readlink} /nix/var/nix/profiles/system/{initrd,kernel,kernel-modules})"
246 ${lib.optionalString (cfg.rebootWindow != null) ''
247 current_time="$(${date} +%H:%M)"
249 lower="${cfg.rebootWindow.lower}"
250 upper="${cfg.rebootWindow.upper}"
252 if [[ "''${lower}" < "''${upper}" ]]; then
253 if [[ "''${current_time}" > "''${lower}" ]] && \
254 [[ "''${current_time}" < "''${upper}" ]]; then
260 # lower > upper, so we are crossing midnight (e.g. lower=23h, upper=6h)
261 # we want to reboot if cur > 23h or cur < 6h
262 if [[ "''${current_time}" < "''${upper}" ]] || \
263 [[ "''${current_time}" > "''${lower}" ]]; then
271 if [ "''${booted}" = "''${built}" ]; then
272 ${nixos-rebuild} ${cfg.operation} ${toString cfg.flags}
273 ${lib.optionalString (cfg.rebootWindow != null) ''
274 elif [ "''${do_reboot}" != true ]; then
275 echo "Outside of configured reboot window, skipping."
283 ${nixos-rebuild} ${cfg.operation} ${toString (cfg.flags ++ upgradeFlag)}
288 after = [ "network-online.target" ];
289 wants = [ "network-online.target" ];
292 systemd.timers.nixos-upgrade = {
294 RandomizedDelaySec = cfg.randomizedDelaySec;
295 FixedRandomDelay = cfg.fixedRandomDelay;
296 Persistent = cfg.persistent;