nixos/envfs: fix compatibility with systemd in initrd
This module disables the activation scripts that would normally create `/usr/bin/env` and `/bin/sh` (and their parent directories). When systemd is used in the initrd, the absence of these directories causes 2 problems: - During switch-root, base_filesystem_create_fd() creates an empty /usr directory. Later at stage2, systemd's initialize_runtime() aborts booting with "Refusing to run in unsupported environment where /usr/ is not populated." - Once /usr/bin is restored (by the fix above), base_filesystem_create_fd() creates a symlink /bin -> /usr/bin. systemd-fstab-generator then canonicalizes the /bin fstab entry through this symlink, producing a duplicate usr-bin.mount. We create both /sysroot/usr/bin and /sysroot/bin via initrd tmpfiles to prevent both issues. Resolves NixOS#462556 Co-authored-by: Lin Yinfeng <lin.yinfeng@outlook.com>
This commit is contained in:
co-authored by
Lin Yinfeng
parent
73bbf0dc60
commit
3a6f7a60ac
@@ -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";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
+11
-2
@@ -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()
|
||||
|
||||
@@ -25,7 +25,7 @@ rustPlatform.buildRustPackage (finalAttrs: {
|
||||
|
||||
passthru = {
|
||||
tests = {
|
||||
envfs = nixosTests.envfs;
|
||||
inherit (nixosTests) envfs envfs-systemd-stage-1;
|
||||
};
|
||||
|
||||
updateScript = nix-update-script { };
|
||||
|
||||
Reference in New Issue
Block a user