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}