1{ 2 config, 3 lib, 4 pkgs, 5 utils, 6 ... 7}: 8 9let 10 cfg = config.systemd.sysupdate; 11 12 format = pkgs.formats.ini { listToValue = toString; }; 13 14 # TODO: Switch back to using utils.systemdUtils.lib.definitions once 15 # https://github.com/systemd/systemd/pull/38187 is resolved. Also ensure 16 # utils.systemdUtils.lib.definitions is capable of setting a custom file 17 # suffix. 18 sysupdateTransfers = lib.mapAttrs' (name: value: { 19 name = "sysupdate.d/${name}.transfer"; 20 value.source = format.generate "${name}.transfer" value; 21 }) cfg.transfers; 22in 23{ 24 options.systemd.sysupdate = { 25 26 enable = lib.mkEnableOption "systemd-sysupdate" // { 27 description = '' 28 Atomically update the host OS, container images, portable service 29 images or other sources. 30 31 If enabled, updates are triggered in regular intervals via a 32 `systemd.timer` unit. 33 34 Please see {manpage}`systemd-sysupdate(8)` for more details. 35 ''; 36 }; 37 38 timerConfig = utils.systemdUtils.unitOptions.timerOptions.options.timerConfig // { 39 default = { }; 40 description = '' 41 The timer configuration for performing the update. 42 43 By default, the upstream configuration is used: 44 <https://github.com/systemd/systemd/blob/main/units/systemd-sysupdate.timer> 45 ''; 46 }; 47 48 reboot = { 49 enable = lib.mkEnableOption "automatically rebooting after an update" // { 50 description = '' 51 Whether to automatically reboot after an update. 52 53 If set to `true`, the system will automatically reboot via a 54 `systemd.timer` unit but only after a new version was installed. 55 56 This uses a unit completely separate from the one performing the 57 update because it is typically advisable to download updates 58 regularly while the system is up, but delay reboots until the 59 appropriate time (i.e. typically at night). 60 61 Set this to `false` if you do not want to reboot after an update. This 62 is useful when you update a container image or another source where 63 rebooting is not necessary in order to finalize the update. 64 ''; 65 }; 66 67 timerConfig = utils.systemdUtils.unitOptions.timerOptions.options.timerConfig // { 68 default = { }; 69 description = '' 70 The timer configuration for rebooting after an update. 71 72 By default, the upstream configuration is used: 73 <https://github.com/systemd/systemd/blob/main/units/systemd-sysupdate-reboot.timer> 74 ''; 75 }; 76 }; 77 78 transfers = lib.mkOption { 79 type = with lib.types; attrsOf format.type; 80 default = { }; 81 example = { 82 "10-uki" = { 83 Transfer = { 84 ProtectVersion = "%A"; 85 }; 86 87 Source = { 88 Type = "url-file"; 89 Path = "https://download.example.com/"; 90 MatchPattern = [ 91 "nixos_@v+@l-@d.efi" 92 "nixos_@v+@l.efi" 93 "nixos_@v.efi" 94 ]; 95 }; 96 97 Target = { 98 Type = "regular-file"; 99 Path = "/EFI/Linux"; 100 PathRelativeTo = "boot"; 101 MatchPattern = '' 102 nixos_@v+@l-@d.efi"; \ 103 nixos_@v+@l.efi \ 104 nixos_@v.efi 105 ''; 106 Mode = "0444"; 107 TriesLeft = 3; 108 TriesDone = 0; 109 InstancesMax = 2; 110 }; 111 }; 112 }; 113 description = '' 114 Specify transfers as a set of the names of the transfer files as the 115 key and the configuration as its value. The configuration can use all 116 upstream options. See {manpage}`sysupdate.d(5)` 117 for all available options. 118 ''; 119 }; 120 121 }; 122 123 config = lib.mkIf cfg.enable { 124 assertions = [ 125 { 126 assertion = config.systemd.package.withSysupdate; 127 message = "Cannot enable systemd-sysupdate with systemd package not built with sysupdate support"; 128 } 129 ]; 130 131 systemd.additionalUpstreamSystemUnits = [ 132 "systemd-sysupdate.service" 133 "systemd-sysupdate.timer" 134 "systemd-sysupdate-reboot.service" 135 "systemd-sysupdate-reboot.timer" 136 "systemd-sysupdated.service" 137 ]; 138 139 systemd.services.systemd-sysupdated.aliases = [ "dbus-org.freedesktop.sysupdate1.service" ]; 140 141 systemd.timers = { 142 "systemd-sysupdate" = { 143 wantedBy = [ "timers.target" ]; 144 timerConfig = cfg.timerConfig; 145 }; 146 "systemd-sysupdate-reboot" = lib.mkIf cfg.reboot.enable { 147 wantedBy = [ "timers.target" ]; 148 timerConfig = cfg.reboot.timerConfig; 149 }; 150 }; 151 152 environment.etc = sysupdateTransfers; 153 }; 154 155 meta.maintainers = with lib.maintainers; [ 156 nikstur 157 jmbaur 158 ]; 159}