From 93ba3d8fc41c5fef8ddf79fb4ab5a6dc708a87c4 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 28 Nov 2025 02:06:09 -0300 Subject: [PATCH] Switch from sysusers to new "baked" userborn usage Avoid spending ~100ms of userspace boot time on unnecessary regeneration of entirely static /etc/{passwd,group,shadow}. This will be proposed to nixpkgs. --- nixosModules/default.nix | 46 ++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/nixosModules/default.nix b/nixosModules/default.nix index 9012eac..d3763a5 100644 --- a/nixosModules/default.nix +++ b/nixosModules/default.nix @@ -7,6 +7,29 @@ StandardError = "tty"; }; runtimeDir = "/run/vm-user"; + userbornConfig = { + groups = lib.mapAttrsToList (username: opts: { + inherit (opts) name gid members; + }) config.users.groups; + users = lib.mapAttrsToList (username: opts: { + inherit (opts) + name + uid + group + description + home + password + hashedPassword + hashedPasswordFile + initialPassword + initialHashedPassword + ; + isNormal = opts.isNormalUser; + shell = utils.toShellPath opts.shell; + }) (lib.filterAttrs (_: u: u.enable) config.users.users); + }; + userbornConfigJson = pkgs.writeText "userborn.json" (builtins.toJSON userbornConfig); + userbornResults = pkgs.runCommand "baked userborn" {} "mkdir -p $out; ${lib.getExe pkgs.userborn} ${userbornConfigJson} $out"; in { boot.isContainer = true; fileSystems."/".device = lib.mkDefault "/dev/sda"; # dummy @@ -34,8 +57,6 @@ in { boot.initrd.systemd.enable = true; # for etc.overlay, but we don't have initrd system.etc.overlay.enable = true; # erofs system.etc.overlay.mutable = false; - systemd.sysusers.enable = true; - services.userborn.enable = false; services.udev.enable = lib.mkDefault true; services.udev.packages = lib.mkDefault []; environment.etc."resolv.conf".source = "/run/resolv.conf"; @@ -57,7 +78,6 @@ in { "systemd-journald-audit.socket" "systemd-journald-dev-log.socket" "systemd-journald.service" - "systemd-sysusers.service" "systemd-udevd-kernel.socket" "systemd-udevd-control.socket" "systemd-udevd.service" @@ -67,7 +87,7 @@ in { upstreamWants = ["multi-user.target.wants"]; }); - # systemd.package = pkgs.systemdMinimal; # no sysusers + # systemd.package = pkgs.systemdMinimal; # no analyze systemd.defaultUnit = "microvm.target"; systemd.targets.microvm = { description = "Minimal microVM system"; @@ -78,16 +98,12 @@ in { systemd.services.systemd-pstore.enable = lib.mkForce false; systemd.services.lastlog2-import.enable = lib.mkForce false; systemd.services.suid-sgid-wrappers.enable = lib.mkForce false; - systemd.services.systemd-sysusers.serviceConfig = { - ExecStartPre = lib.mkForce []; - ExecStartPost = lib.mkForce []; - }; systemd.services.microvm-nixos-activation = { enable = true; description = "NixOS Activation"; wantedBy = ["local-fs.target"]; - before = ["systemd-tmpfiles-setup.service" "systemd-sysusers.service"]; - requires = ["systemd-tmpfiles-setup.service" "systemd-sysusers.service"]; + before = ["systemd-tmpfiles-setup.service"]; + requires = ["systemd-tmpfiles-setup.service"]; unitConfig.DefaultDependencies = false; serviceConfig = { Type = "oneshot"; @@ -101,7 +117,15 @@ in { ''; }; - # Configure user account + # Configure user accounts + # The immutable overlay wants userborn or sysusers.. we just want baked-in files w/o running a service. + # So we can just run userborn at system closure build time! + systemd.sysusers.enable = false; + services.userborn.enable = true; + systemd.services.userborn.enable = false; + environment.etc."passwd" = lib.mkForce { source = "${userbornResults}/passwd"; mode = "0444"; }; + environment.etc."group" = lib.mkForce { source = "${userbornResults}/group"; mode = "0444"; }; + environment.etc."shadow" = lib.mkForce { source = "${userbornResults}/shadow"; mode = "0440"; }; users.mutableUsers = false; users.users.appvm = { uid = 1337;