···2828- [LACT](https://github.com/ilya-zlobintsev/LACT), a GPU monitoring and configuration tool, can now be enabled through [services.lact.enable](#opt-services.lact.enable).
2929 Note that for LACT to work properly on AMD GPU systems, you need to enable [hardware.amdgpu.overdrive.enable](#opt-hardware.amdgpu.overdrive.enable).
30303131+- Auto-scrub support for Bcachefs filesystems can now be enabled through [services.bcachefs.autoScrub.enable](#opt-services.bcachefs.autoScrub.enable) to periodically check for data corruption. If there's a correct copy available, it will automatically repair corrupted blocks.
3232+3133- [tlsrpt-reporter], an application suite to generate and deliver TLSRPT reports. Available as [services.tlsrpt](#opt-services.tlsrpt.enable).
32343335- [Broadcast Box](https://github.com/Glimesh/broadcast-box), a WebRTC broadcast server. Available as [services.broadcast-box](options.html#opt-services.broadcast-box.enable).
+2-2
nixos/modules/services/networking/atticd.nix
···86868787 user = lib.mkOption {
8888 description = ''
8989- The group under which attic runs.
8989+ The user under which attic runs.
9090 '';
9191 type = types.str;
9292 default = "atticd";
···94949595 group = lib.mkOption {
9696 description = ''
9797- The user under which attic runs.
9797+ The group under which attic runs.
9898 '';
9999 type = types.str;
100100 default = "atticd";
+120
nixos/modules/tasks/filesystems/bcachefs.nix
···77}:
8899let
1010+ cfgScrub = config.services.bcachefs.autoScrub;
10111112 bootFs = lib.filterAttrs (
1213 n: fs: (fs.fsType == "bcachefs") && (utils.fsNeededForBoot fs)
···159160in
160161161162{
163163+ options.services.bcachefs.autoScrub = {
164164+ enable = lib.mkEnableOption "regular bcachefs scrub";
165165+166166+ fileSystems = lib.mkOption {
167167+ type = lib.types.listOf lib.types.path;
168168+ example = [ "/" ];
169169+ description = ''
170170+ List of paths to bcachefs filesystems to regularly call {command}`bcachefs scrub` on.
171171+ Defaults to all mount points with bcachefs filesystems.
172172+ '';
173173+ };
174174+175175+ interval = lib.mkOption {
176176+ default = "monthly";
177177+ type = lib.types.str;
178178+ example = "weekly";
179179+ description = ''
180180+ Systemd calendar expression for when to scrub bcachefs filesystems.
181181+ The recommended period is a month but could be less.
182182+ See
183183+ {manpage}`systemd.time(7)`
184184+ for more information on the syntax.
185185+ '';
186186+ };
187187+ };
188188+162189 config = lib.mkIf (config.boot.supportedFilesystems.bcachefs or false) (
163190 lib.mkMerge [
164191 {
···205232206233 boot.initrd.systemd.services = lib.mapAttrs' (mkUnits "/sysroot") bootFs;
207234 })
235235+236236+ (lib.mkIf (cfgScrub.enable) {
237237+ assertions = [
238238+ {
239239+ assertion = lib.versionAtLeast config.boot.kernelPackages.kernel.version "6.14";
240240+ message = "Bcachefs scrubbing is supported from kernel version 6.14 or later.";
241241+ }
242242+ {
243243+ assertion = cfgScrub.enable -> (cfgScrub.fileSystems != [ ]);
244244+ message = ''
245245+ If 'services.bcachefs.autoScrub' is enabled, you need to have at least one
246246+ bcachefs file system mounted via 'fileSystems' or specify a list manually
247247+ in 'services.bcachefs.autoScrub.fileSystems'.
248248+ '';
249249+ }
250250+ ];
251251+252252+ # This will remove duplicated units from either having a filesystem mounted multiple
253253+ # time, or additionally mounted subvolumes, as well as having a filesystem span
254254+ # multiple devices (provided the same device is used to mount said filesystem).
255255+ services.bcachefs.autoScrub.fileSystems =
256256+ let
257257+ isDeviceInList = list: device: builtins.filter (e: e.device == device) list != [ ];
258258+259259+ uniqueDeviceList = lib.foldl' (
260260+ acc: e: if isDeviceInList acc e.device then acc else acc ++ [ e ]
261261+ ) [ ];
262262+ in
263263+ lib.mkDefault (
264264+ map (e: e.mountPoint) (
265265+ uniqueDeviceList (
266266+ lib.mapAttrsToList (name: fs: {
267267+ mountPoint = fs.mountPoint;
268268+ device = fs.device;
269269+ }) (lib.filterAttrs (name: fs: fs.fsType == "bcachefs") config.fileSystems)
270270+ )
271271+ )
272272+ );
273273+274274+ systemd.timers =
275275+ let
276276+ scrubTimer =
277277+ fs:
278278+ let
279279+ fs' = utils.escapeSystemdPath fs;
280280+ in
281281+ lib.nameValuePair "bcachefs-scrub-${fs'}" {
282282+ description = "regular bcachefs scrub timer on ${fs}";
283283+284284+ wantedBy = [ "timers.target" ];
285285+ timerConfig = {
286286+ OnCalendar = cfgScrub.interval;
287287+ AccuracySec = "1d";
288288+ Persistent = true;
289289+ };
290290+ };
291291+ in
292292+ lib.listToAttrs (map scrubTimer cfgScrub.fileSystems);
293293+294294+ systemd.services =
295295+ let
296296+ scrubService =
297297+ fs:
298298+ let
299299+ fs' = utils.escapeSystemdPath fs;
300300+ in
301301+ lib.nameValuePair "bcachefs-scrub-${fs'}" {
302302+ description = "bcachefs scrub on ${fs}";
303303+ # scrub prevents suspend2ram or proper shutdown
304304+ conflicts = [
305305+ "shutdown.target"
306306+ "sleep.target"
307307+ ];
308308+ before = [
309309+ "shutdown.target"
310310+ "sleep.target"
311311+ ];
312312+313313+ script = "${lib.getExe pkgs.bcachefs-tools} data scrub ${fs}";
314314+315315+ serviceConfig = {
316316+ Type = "oneshot";
317317+ Nice = 19;
318318+ IOSchedulingClass = "idle";
319319+ };
320320+ };
321321+ in
322322+ lib.listToAttrs (map scrubService cfgScrub.fileSystems);
323323+ })
208324 ]
209325 );
326326+327327+ meta = {
328328+ inherit (pkgs.bcachefs-tools.meta) maintainers;
329329+ };
210330}