Skip to content

fix bug: use numeric UID/GID for directory ownership in initrd where usernames don't resolve#316

Open
mihakrumpestar wants to merge 1 commit intonix-community:masterfrom
mihakrumpestar:fix-initrd-user-permissions
Open

fix bug: use numeric UID/GID for directory ownership in initrd where usernames don't resolve#316
mihakrumpestar wants to merge 1 commit intonix-community:masterfrom
mihakrumpestar:fix-initrd-user-permissions

Conversation

@mihakrumpestar
Copy link
Copy Markdown

@mihakrumpestar mihakrumpestar commented Mar 22, 2026

Problem

When using boot.initrd.systemd.enable = true, activation scripts run in the initrd environment where /etc/passwd doesn't contain regular users. This causes create-directories.bash to fail when trying to set ownership with usernames like chown user:group /path, resulting in directories being created with root:root ownership instead of the correct user ownership.

This is particularly problematic for persistent home directories which are bind-mounted early in boot and need correct ownership for the user to access their files.

Note that this happens with both home-manager and nixos module, for all non-root users, when initrd.systemd is enabled.

Relevant sections in nix config:

{
  # Core disks - enables initrd systemd for encrypted root
  boot.initrd.systemd = {
    enable = true;  # Required for LUKS + TPM2/FIDO2
    fido2.enable = true;  # or tpm2.enable
  };

  fileSystems."/persistent-root".neededForBoot = true;
  fileSystems."/persistent-home".neededForBoot = true;
  fileSystems."/home".neededForBoot = true;

  boot.initrd = {
    supportedFilesystems = ["btrfs"];
    postResumeCommands = mkIf (!systemdInitrd) (mkAfter wipeScript);
    systemd = mkIf systemdInitrd {
      services.impermanence-wipe = {
        description = "Wipe root and home btrfs subvolumes for impermanence";
        wantedBy = ["initrd.target"];
        after = ["cryptsetup.target"];
        before = ["sysroot.mount"];
        unitConfig.DefaultDependencies = false;
        serviceConfig.Type = "oneshot";
        script = wipeScript;
      };
    };
  };

  environment.persistence."/persistent-root" = {
    hideMounts = true;
    allowTrash = true;
    files = defaultFiles ++ cfg.files;
    directories = defaultDirectories ++ cfg.directories;
  };

  home-manager.sharedModules = [
    ({config, ...}: {
      home.persistence."/persistent-home" = {
        enable = true;
        files = defaultUserFiles ++ cfg.userFiles;
        directories = defaultUserDirectories ++ cfg.userDirectories;
      };
    })
  ];

  # User management with userborn
  services.userborn.enable = true; 
  
  users.users.krumpy-miha = {
    isNormalUser = true;
    uid = 1000;  # Now required with systemd initrd + persistent home
  };
  users.groups."users".gid = 100;
}

I discovered the issue when I tried to make the directory creation script automatically fix the wrong user:group ownership.

journalctl-default.log

The relevant section from journalctl clearly shows that it tries to chown without the users even being available (they are created/available later in boot process).

Solution

Pass numeric UID/GID to the directory creation script and use them for chown operations when usernames cannot be resolved:

  1. Pass UID/GID to create-directories.bash: The script now accepts optional uid and gid arguments
  2. Ownership handling:
    • In initrd: Use numeric chown uid:gid when the user doesn't exist
    • In main system: Use chown user:group when the user database is available
  3. Fix existing directories: On subsequent boots, correct ownership using numeric ID comparison
  4. Build-time assertion: When boot.initrd.systemd.enable = true, require that users with persistent home directories have explicit uid/gid set

Relevant section in journalctl that shows that the solution is working:

journalctl-with-solution.log

Changes

  • nixos.nix: Pass uid/gid to create-directories.bash, add assertion for initrd systemd users
  • create-directories.bash: Accept uid/gid args, use numeric IDs when usernames don't resolve
  • Skip activation during nixos-install (users don't exist in chroot anyway)

Requirements for users

When using boot.initrd.systemd.enable = true with persistent home directories, users must now set explicit uid/gid:

users.users.myuser.uid = 1000;
users.groups.mygroup.gid = 1000;

An assertion error is shown if this is forgotten.

Additional notes

While I did search the issues and pull request, none seem to mention this specific problem. If this fix is unnecessary, and I simply did something wrong in the config, please correct me.

I also added code that will fix the permissions if they got set wrong, but it is not really necessary, unless they got set wrong before.

Both journalctl logs are from first boot on completely fresh nixos system (used disko and nixos-install). I did not test with initrd.systemd disabled, since I currently use all system drives encrypted only (initrd.systemd has to be enabled therefore).

@mihakrumpestar mihakrumpestar changed the title fix: use numeric UID/GID for directory ownership in initrd where usernames don't resolve fix bug: use numeric UID/GID for directory ownership in initrd where usernames don't resolve Mar 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant