diff --git a/nixos/modules/tasks/filesystems/envfs.nix b/nixos/modules/tasks/filesystems/envfs.nix index 1e821277b614..4b1846f5c1a8 100644 --- a/nixos/modules/tasks/filesystems/envfs.nix +++ b/nixos/modules/tasks/filesystems/envfs.nix @@ -74,5 +74,39 @@ in # We no longer need those when using envfs system.activationScripts.usrbinenv = lib.mkForce ""; system.activationScripts.binsh = lib.mkForce ""; + + # Disabling the activation scripts above prevents the creation of 2 + # directories, which would normally be created just before switch-root at + # stage1. This causes problems when systemd is used in the initrd. + # + # This only affects fresh installations or systems using impermanence/tmpfs + # root, where these directories don't persist from a previous activation. + boot.initrd.systemd.tmpfiles.settings = lib.mkIf config.boot.initrd.systemd.enable { + "50-envfs" = { + # During switch-root, systemd's base_filesystem_create_fd() creates an + # empty /usr. Later at stage2, systemd initialize_runtime() checks + # dir_is_empty("/usr/"), which returns 1 for an empty but existing + # directory causing a fatal boot failure: "Refusing to run in + # unsupported environment where /usr/ is not populated." + "/sysroot/usr/bin" = { + d = { + group = "root"; + mode = "0755"; + user = "root"; + }; + }; + # During switch-root, base_filesystem_create_fd() creates a symlink + # /bin -> /usr/bin if /bin does not exist. systemd-fstab-generator then + # canonicalizes the /bin fstab entry through this symlink, producing a + # duplicate usr-bin.mount. Create /bin to avoid this behaviour. + "/sysroot/bin" = { + d = { + group = "root"; + mode = "0755"; + user = "root"; + }; + }; + }; + }; }; } diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 7892274095aa..99c1d26f6f34 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -518,7 +518,14 @@ in enlightenment = runTest ./enlightenment.nix; ente = runTest ./ente; env = runTest ./env.nix; - envfs = runTest ./envfs.nix; + envfs = runTest { + imports = [ ./envfs.nix ]; + _module.args.systemdStage1 = false; + }; + envfs-systemd-stage-1 = runTest { + imports = [ ./envfs.nix ]; + _module.args.systemdStage1 = true; + }; envoy = runTest { imports = [ ./envoy.nix ]; _module.args.envoyPackage = pkgs.envoy; diff --git a/nixos/tests/envfs.nix b/nixos/tests/envfs.nix index 6e8ee7e55aea..78946285ed68 100644 --- a/nixos/tests/envfs.nix +++ b/nixos/tests/envfs.nix @@ -1,4 +1,9 @@ -{ lib, pkgs, ... }: +{ + pkgs, + systemdStage1 ? false, + ... +}: + let pythonShebang = pkgs.writeScript "python-shebang" '' #!/usr/bin/python @@ -12,7 +17,11 @@ let in { name = "envfs"; - nodes.machine.services.envfs.enable = true; + + nodes.machine = { + services.envfs.enable = true; + boot.initrd.systemd.enable = systemdStage1; + }; testScript = '' start_all() diff --git a/pkgs/by-name/en/envfs/package.nix b/pkgs/by-name/en/envfs/package.nix index 7e2fbd3127d3..f1601aa562bc 100644 --- a/pkgs/by-name/en/envfs/package.nix +++ b/pkgs/by-name/en/envfs/package.nix @@ -25,7 +25,7 @@ rustPlatform.buildRustPackage (finalAttrs: { passthru = { tests = { - envfs = nixosTests.envfs; + inherit (nixosTests) envfs envfs-systemd-stage-1; }; updateScript = nix-update-script { };