1{ config, lib, pkgs, utils, ... }:
2
3with lib;
4
5let
6 cfg = config.systemd.tmpfiles;
7 systemd = config.systemd.package;
8in
9{
10 options = {
11 systemd.tmpfiles.rules = mkOption {
12 type = types.listOf types.str;
13 default = [];
14 example = [ "d /tmp 1777 root root 10d" ];
15 description = lib.mdDoc ''
16 Rules for creation, deletion and cleaning of volatile and temporary files
17 automatically. See
18 {manpage}`tmpfiles.d(5)`
19 for the exact format.
20 '';
21 };
22
23 systemd.tmpfiles.packages = mkOption {
24 type = types.listOf types.package;
25 default = [];
26 example = literalExpression "[ pkgs.lvm2 ]";
27 apply = map getLib;
28 description = lib.mdDoc ''
29 List of packages containing {command}`systemd-tmpfiles` rules.
30
31 All files ending in .conf found in
32 {file}`«pkg»/lib/tmpfiles.d`
33 will be included.
34 If this folder does not exist or does not contain any files an error will be returned instead.
35
36 If a {file}`lib` output is available, rules are searched there and only there.
37 If there is no {file}`lib` output it will fall back to {file}`out`
38 and if that does not exist either, the default output will be used.
39 '';
40 };
41 };
42
43 config = {
44 systemd.additionalUpstreamSystemUnits = [
45 "systemd-tmpfiles-clean.service"
46 "systemd-tmpfiles-clean.timer"
47 "systemd-tmpfiles-setup.service"
48 "systemd-tmpfiles-setup-dev.service"
49 ];
50
51 systemd.additionalUpstreamUserUnits = [
52 "systemd-tmpfiles-clean.service"
53 "systemd-tmpfiles-clean.timer"
54 "systemd-tmpfiles-setup.service"
55 ];
56
57 environment.etc = {
58 "tmpfiles.d".source = (pkgs.symlinkJoin {
59 name = "tmpfiles.d";
60 paths = map (p: p + "/lib/tmpfiles.d") cfg.packages;
61 postBuild = ''
62 for i in $(cat $pathsPath); do
63 (test -d "$i" && test $(ls "$i"/*.conf | wc -l) -ge 1) || (
64 echo "ERROR: The path '$i' from systemd.tmpfiles.packages contains no *.conf files."
65 exit 1
66 )
67 done
68 '' + concatMapStrings (name: optionalString (hasPrefix "tmpfiles.d/" name) ''
69 rm -f $out/${removePrefix "tmpfiles.d/" name}
70 '') config.system.build.etc.passthru.targets;
71 }) + "/*";
72 };
73
74 systemd.tmpfiles.packages = [
75 # Default tmpfiles rules provided by systemd
76 (pkgs.runCommand "systemd-default-tmpfiles" {} ''
77 mkdir -p $out/lib/tmpfiles.d
78 cd $out/lib/tmpfiles.d
79
80 ln -s "${systemd}/example/tmpfiles.d/home.conf"
81 ln -s "${systemd}/example/tmpfiles.d/journal-nocow.conf"
82 ln -s "${systemd}/example/tmpfiles.d/portables.conf"
83 ln -s "${systemd}/example/tmpfiles.d/static-nodes-permissions.conf"
84 ln -s "${systemd}/example/tmpfiles.d/systemd.conf"
85 ln -s "${systemd}/example/tmpfiles.d/systemd-nologin.conf"
86 ln -s "${systemd}/example/tmpfiles.d/systemd-nspawn.conf"
87 ln -s "${systemd}/example/tmpfiles.d/systemd-tmp.conf"
88 ln -s "${systemd}/example/tmpfiles.d/tmp.conf"
89 ln -s "${systemd}/example/tmpfiles.d/var.conf"
90 ln -s "${systemd}/example/tmpfiles.d/x11.conf"
91 '')
92 # User-specified tmpfiles rules
93 (pkgs.writeTextFile {
94 name = "nixos-tmpfiles.d";
95 destination = "/lib/tmpfiles.d/00-nixos.conf";
96 text = ''
97 # This file is created automatically and should not be modified.
98 # Please change the option ‘systemd.tmpfiles.rules’ instead.
99
100 ${concatStringsSep "\n" cfg.rules}
101 '';
102 })
103 ];
104
105 systemd.tmpfiles.rules = [
106 "d /nix/var 0755 root root - -"
107 "L+ /nix/var/nix/gcroots/booted-system 0755 root root - /run/booted-system"
108 "d /run/lock 0755 root root - -"
109 "d /var/db 0755 root root - -"
110 "L /etc/mtab - - - - ../proc/mounts"
111 "L /var/lock - - - - ../run/lock"
112 # Boot-time cleanup
113 "R! /etc/group.lock - - - - -"
114 "R! /etc/passwd.lock - - - - -"
115 "R! /etc/shadow.lock - - - - -"
116 "R! /etc/mtab* - - - - -"
117 "R! /nix/var/nix/gcroots/tmp - - - - -"
118 "R! /nix/var/nix/temproots - - - - -"
119 ];
120 };
121}