about summary refs log tree commit diff
path: root/nixos/modules/system/etc/etc-activation.nix
blob: f47fd771c6592f2deca33426748fdea302131278 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
{ config, lib, ... }:

{

  imports = [ ./etc.nix ];

  config = lib.mkMerge [

    {
      system.activationScripts.etc =
        lib.stringAfter [ "users" "groups" ] config.system.build.etcActivationCommands;
    }

    (lib.mkIf config.system.etc.overlay.enable {

      assertions = [
        {
          assertion = config.boot.initrd.systemd.enable;
          message = "`system.etc.overlay.enable` requires `boot.initrd.systemd.enable`";
        }
        {
          assertion = (!config.system.etc.overlay.mutable) -> config.systemd.sysusers.enable;
          message = "`system.etc.overlay.mutable = false` requires `systemd.sysusers.enable`";
        }
        {
          assertion = lib.versionAtLeast config.boot.kernelPackages.kernel.version "6.6";
          message = "`system.etc.overlay.enable requires a newer kernel, at least version 6.6";
        }
        {
          assertion = config.systemd.sysusers.enable -> (config.users.mutableUsers == config.system.etc.overlay.mutable);
          message = ''
            When using systemd-sysusers and mounting `/etc` via an overlay, users
            can only be mutable when `/etc` is mutable and vice versa.
          '';
        }
      ];

      boot.initrd.availableKernelModules = [ "loop" "erofs" "overlay" ];

      boot.initrd.systemd = {
        mounts = [
          {
            where = "/run/etc-metadata";
            what = "/sysroot${config.system.build.etcMetadataImage}";
            type = "erofs";
            options = "loop";
            unitConfig.RequiresMountsFor = [
              "/sysroot/nix/store"
            ];
          }
          {
            where = "/sysroot/etc";
            what = "overlay";
            type = "overlay";
            options = lib.concatStringsSep "," ([
              "relatime"
              "redirect_dir=on"
              "metacopy=on"
              "lowerdir=/run/etc-metadata::/sysroot${config.system.build.etcBasedir}"
            ] ++ lib.optionals config.system.etc.overlay.mutable [
              "rw"
              "upperdir=/sysroot/.rw-etc/upper"
              "workdir=/sysroot/.rw-etc/work"
            ] ++ lib.optionals (!config.system.etc.overlay.mutable) [
              "ro"
            ]);
            wantedBy = [ "initrd-fs.target" ];
            before = [ "initrd-fs.target" ];
            requires = lib.mkIf config.system.etc.overlay.mutable [ "rw-etc.service" ];
            after = lib.mkIf config.system.etc.overlay.mutable [ "rw-etc.service" ];
            unitConfig.RequiresMountsFor = [
              "/sysroot/nix/store"
              "/run/etc-metadata"
            ];
          }
        ];
        services = lib.mkIf config.system.etc.overlay.mutable {
          rw-etc = {
            unitConfig = {
              DefaultDependencies = false;
              RequiresMountsFor = "/sysroot";
            };
            serviceConfig = {
              Type = "oneshot";
              ExecStart = ''
                /bin/mkdir -p -m 0755 /sysroot/.rw-etc/upper /sysroot/.rw-etc/work
              '';
            };
          };
        };
      };

    })

  ];
}