1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let cfg = config.system.autoUpgrade;
6
7in {
8
9 options = {
10
11 system.autoUpgrade = {
12
13 enable = mkOption {
14 type = types.bool;
15 default = false;
16 description = ''
17 Whether to periodically upgrade NixOS to the latest
18 version. If enabled, a systemd timer will run
19 <literal>nixos-rebuild switch --upgrade</literal> once a
20 day.
21 '';
22 };
23
24 flake = mkOption {
25 type = types.nullOr types.str;
26 default = null;
27 example = "github:kloenk/nix";
28 description = ''
29 The Flake URI of the NixOS configuration to build.
30 Disables the option <option>system.autoUpgrade.channel</option>.
31 '';
32 };
33
34 channel = mkOption {
35 type = types.nullOr types.str;
36 default = null;
37 example = "https://nixos.org/channels/nixos-14.12-small";
38 description = ''
39 The URI of the NixOS channel to use for automatic
40 upgrades. By default, this is the channel set using
41 <command>nix-channel</command> (run <literal>nix-channel
42 --list</literal> to see the current value).
43 '';
44 };
45
46 flags = mkOption {
47 type = types.listOf types.str;
48 default = [ ];
49 example = [
50 "-I"
51 "stuff=/home/alice/nixos-stuff"
52 "--option"
53 "extra-binary-caches"
54 "http://my-cache.example.org/"
55 ];
56 description = ''
57 Any additional flags passed to <command>nixos-rebuild</command>.
58
59 If you are using flakes and use a local repo you can add
60 <command>[ "--update-input" "nixpkgs" "--commit-lock-file" ]</command>
61 to update nixpkgs.
62 '';
63 };
64
65 dates = mkOption {
66 default = "04:40";
67 type = types.str;
68 description = ''
69 Specification (in the format described by
70 <citerefentry><refentrytitle>systemd.time</refentrytitle>
71 <manvolnum>7</manvolnum></citerefentry>) of the time at
72 which the update will occur.
73 '';
74 };
75
76 allowReboot = mkOption {
77 default = false;
78 type = types.bool;
79 description = ''
80 Reboot the system into the new generation instead of a switch
81 if the new generation uses a different kernel, kernel modules
82 or initrd than the booted system.
83 '';
84 };
85
86 randomizedDelaySec = mkOption {
87 default = "0";
88 type = types.str;
89 example = "45min";
90 description = ''
91 Add a randomized delay before each automatic upgrade.
92 The delay will be chozen between zero and this value.
93 This value must be a time span in the format specified by
94 <citerefentry><refentrytitle>systemd.time</refentrytitle>
95 <manvolnum>7</manvolnum></citerefentry>
96 '';
97 };
98
99 };
100
101 };
102
103 config = lib.mkIf cfg.enable {
104
105 assertions = [{
106 assertion = !((cfg.channel != null) && (cfg.flake != null));
107 message = ''
108 The options 'system.autoUpgrade.channels' and 'system.autoUpgrade.flake' cannot both be set.
109 '';
110 }];
111
112 system.autoUpgrade.flags = (if cfg.flake == null then
113 [ "--no-build-output" ] ++ (if cfg.channel == null then
114 [ "--upgrade" ]
115 else [
116 "-I"
117 "nixpkgs=${cfg.channel}/nixexprs.tar.xz"
118 ])
119 else
120 [ "--flake ${cfg.flake}" ]);
121
122 systemd.services.nixos-upgrade = {
123 description = "NixOS Upgrade";
124
125 restartIfChanged = false;
126 unitConfig.X-StopOnRemoval = false;
127
128 serviceConfig.Type = "oneshot";
129
130 environment = config.nix.envVars // {
131 inherit (config.environment.sessionVariables) NIX_PATH;
132 HOME = "/root";
133 } // config.networking.proxy.envVars;
134
135 path = with pkgs; [
136 coreutils
137 gnutar
138 xz.bin
139 gzip
140 gitMinimal
141 config.nix.package.out
142 ];
143
144 script = let
145 nixos-rebuild =
146 "${config.system.build.nixos-rebuild}/bin/nixos-rebuild";
147 in if cfg.allowReboot then ''
148 ${nixos-rebuild} boot ${toString cfg.flags}
149 booted="$(readlink /run/booted-system/{initrd,kernel,kernel-modules})"
150 built="$(readlink /nix/var/nix/profiles/system/{initrd,kernel,kernel-modules})"
151 if [ "$booted" = "$built" ]; then
152 ${nixos-rebuild} switch ${toString cfg.flags}
153 else
154 /run/current-system/sw/bin/shutdown -r +1
155 fi
156 '' else ''
157 ${nixos-rebuild} switch ${toString cfg.flags}
158 '';
159
160 startAt = cfg.dates;
161 };
162
163 systemd.timers.nixos-upgrade.timerConfig.RandomizedDelaySec =
164 cfg.randomizedDelaySec;
165
166 };
167
168}