1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8{
9
10 imports = [ ./etc.nix ];
11
12 config = lib.mkMerge [
13
14 {
15 system.activationScripts.etc = lib.stringAfter [
16 "users"
17 "groups"
18 "specialfs"
19 ] config.system.build.etcActivationCommands;
20 }
21
22 (lib.mkIf config.system.etc.overlay.enable {
23
24 assertions = [
25 {
26 assertion = config.boot.initrd.systemd.enable;
27 message = "`system.etc.overlay.enable` requires `boot.initrd.systemd.enable`";
28 }
29 {
30 assertion =
31 (!config.system.etc.overlay.mutable)
32 -> (config.systemd.sysusers.enable || config.services.userborn.enable);
33 message = "`!system.etc.overlay.mutable` requires `systemd.sysusers.enable` or `services.userborn.enable`";
34 }
35 {
36 assertion =
37 (config.system.switch.enable)
38 -> (lib.versionAtLeast config.boot.kernelPackages.kernel.version "6.6");
39 message = "switchable systems with `system.etc.overlay.enable` require a newer kernel, at least version 6.6";
40 }
41 ];
42
43 boot.initrd.availableKernelModules = [
44 "loop"
45 "erofs"
46 "overlay"
47 ];
48
49 system.requiredKernelConfig = with config.lib.kernelConfig; [
50 (isEnabled "EROFS_FS")
51 ];
52
53 boot.initrd.systemd = {
54 mounts = [
55 {
56 where = "/run/nixos-etc-metadata";
57 what = "/etc-metadata-image";
58 type = "erofs";
59 options = "loop,ro,nodev,nosuid";
60 unitConfig = {
61 # Since this unit depends on the nix store being mounted, it cannot
62 # be a dependency of local-fs.target, because if it did, we'd have
63 # local-fs.target ordered after the nix store mount which would cause
64 # things like network.target to only become active after the nix store
65 # has been mounted.
66 # This breaks for instance setups where sshd needs to be up before
67 # any encrypted disks can be mounted.
68 DefaultDependencies = false;
69 RequiresMountsFor = [
70 "/sysroot/nix/store"
71 ];
72 };
73 requires = [
74 config.boot.initrd.systemd.services.initrd-find-etc.name
75 ];
76 after = [
77 config.boot.initrd.systemd.services.initrd-find-etc.name
78 ];
79 requiredBy = [ "initrd-fs.target" ];
80 before = [ "initrd-fs.target" ];
81 }
82 {
83 where = "/sysroot/etc";
84 what = "overlay";
85 type = "overlay";
86 options = lib.concatStringsSep "," (
87 [
88 "nodev"
89 "nosuid"
90 "relatime"
91 "redirect_dir=on"
92 "metacopy=on"
93 "lowerdir=/run/nixos-etc-metadata::/etc-basedir"
94 ]
95 ++ lib.optionals config.system.etc.overlay.mutable [
96 "rw"
97 "upperdir=/sysroot/.rw-etc/upper"
98 "workdir=/sysroot/.rw-etc/work"
99 ]
100 ++ lib.optionals (!config.system.etc.overlay.mutable) [
101 "ro"
102 ]
103 );
104 requiredBy = [ "initrd-fs.target" ];
105 before = [ "initrd-fs.target" ];
106 requires = [
107 config.boot.initrd.systemd.services.initrd-find-etc.name
108 ]
109 ++ lib.optionals config.system.etc.overlay.mutable [
110 config.boot.initrd.systemd.services."rw-etc".name
111 ];
112 after = [
113 config.boot.initrd.systemd.services.initrd-find-etc.name
114 ]
115 ++ lib.optionals config.system.etc.overlay.mutable [
116 config.boot.initrd.systemd.services."rw-etc".name
117 ];
118 unitConfig = {
119 RequiresMountsFor = [
120 "/sysroot/nix/store"
121 "/run/nixos-etc-metadata"
122 ];
123 DefaultDependencies = false;
124 };
125 }
126 ];
127 services = lib.mkMerge [
128 (lib.mkIf config.system.etc.overlay.mutable {
129 rw-etc = {
130 requiredBy = [ "initrd-fs.target" ];
131 before = [ "initrd-fs.target" ];
132 unitConfig = {
133 DefaultDependencies = false;
134 RequiresMountsFor = "/sysroot";
135 };
136 serviceConfig = {
137 Type = "oneshot";
138 ExecStart = ''
139 /bin/mkdir -p -m 0755 /sysroot/.rw-etc/upper /sysroot/.rw-etc/work
140 '';
141 };
142 };
143 })
144 {
145 initrd-find-etc = {
146 description = "Find the path to the etc metadata image and based dir";
147 before = [ "shutdown.target" ];
148 conflicts = [ "shutdown.target" ];
149 requiredBy = [ "initrd.target" ];
150 path = [ config.system.nixos-init.package ];
151 unitConfig = {
152 DefaultDependencies = false;
153 RequiresMountsFor = "/sysroot/nix/store";
154 };
155 serviceConfig = {
156 Type = "oneshot";
157 RemainAfterExit = true;
158 ExecStart = "${config.system.nixos-init.package}/bin/find-etc";
159 };
160 };
161 }
162 ];
163 };
164
165 })
166
167 ];
168}