Questions about system-level flake on a multi-user setup

I’m new to Nix/NixOS and trying to get to a point where I understand how things work. Right now I’m experimenting with use of flakes for both NixOS and Home Manager, in a multi-user configuration.

Below is the flake.nix I’m currently using, which appears to work well. However I have questions, to see if I’m understanding it properly, or missing anything.

  • I’m using nixpkgs-unstable, and I have home-manager.inputs.nixpkgs.follows = "nixpkgs", which I believe means it uses the nixpkgs.url I defined, and will also use nixpkgs-unstable, right?
  • Since I’m using flakes, this means both nixos-rebuild and home-manager updates will always pull from the same set of flake packages until I update the flake.lock file right? There is no possibility of either update command pulling in updates if I haven’t run nix flake lock --update-input nixpkgs right?
  • Who should own this flake.nix file? It points to the system configuration.nix, as well as each user’s home.nix. So far, testing with a single user, I have the user owning the file. This works fine as I have to run nix-rebuild as sudo anyway, and allows home-manager to update without sudo. But as this file contains more than just the info for one user, it seems like it should be owned by root. But that could create permission issues when I try to update home manager. I know giving root ownership of flake.lock means future lock updates require sudo. How to I keep the flake.nix/flake.lock files accessible without sudo, but not tied to a particular user’s ownership?
{
  description = "Test system nix config";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";

    home-manager.url = "github:nix-community/home-manager";
    home-manager.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = { nixpkgs, home-manager, ... }@inputs: {
    # NixOS configuration entrypoint
    # Available through 'nixos-rebuild --flake .#mymachine'
    nixosConfigurations = {
      mymachine = nixpkgs.lib.nixosSystem {
        specialArgs = { inherit inputs; };

        modules = [
          ./nixos/configuration.nix
        ];
      };
    };

    # Standalone home-manager configuration entrypoint
    # Available through 'home-manager --flake .#myusername@mymachine'
    homeConfigurations = {
      "myusername@mymachine" = home-manager.lib.homeManagerConfiguration {
        pkgs = nixpkgs.legacyPackages.x86_64-linux;
        extraSpecialArgs = { inherit inputs; };

        modules = [
          ./home-manager/home.nix
        ];
      };
    };
  };
}

If you want a multi-user setup, I wouldn’t put every user’s home configuration in the system flake. Allow each user to control their own home-manager flake so they own their own files. Otherwise everyone needs sudo to update their home configs, and you have to have weird file permissions

1 Like

Yes

Yes

As @ElvishJerricco says, you should split it up into a flake for each user, and have each user maintain their own homeConfiguration.

Reading between the lines, however, you want all user configurations to also pull from the same version of nixpkgs as root. For this, set up an entry in the flake registry like so: dotfiles/default.nix at c309c95753dcf6463ea8364665b83157b2998f3b · TLATER/dotfiles · GitHub

And then ask your users to use the "nixpkgs" input. You can’t enforce this, of course, but you can’t do that anyway.

I.e., the user flakes should look something like:

inputs = {
  nixpkgs.url = "nixpkgs";
}

outputs = {
  homeConfigurations.user = ...
};

Nix will automatically resolve the input from the registry. It does require users to also rebuild whenever you pull in a new version at the system level, so that’s a bit awkward. Maybe you could fix that with a homebrew nixos-rebuild that also rebuilds each users’ configuration.

2 Likes

Interesting, I thought home manager’s home.nix had to be tied to the flake.nix file, since the CLI command references the flake location.

How would I separate them, and still have them reference the same nixpkgs? Do you know any links that show how to do this?

This is VERY helpful, thanks! I don’t entirely understand what a flake registry is or where that gets setup (configuration.nix?) but I’ll try to do more reading. Using a separate flake per user is very promising!

From your comment, I assume this is unusual? Do most people keep system and home manager separate, and just allow different versions to be used?

I assumed this would build up a waste of disk space, but maybe it’s just simpler that way.

1 Like

You want to look at nix.registry.

It’s unusual in that not many people have multi-user systems. Personally I just use home-manager’s NixOS module to install my home-manager stuff with the rest of the system; convenient for single user setups, but obviously unworkable for you.

Yes, having every user use a different nixpkgs input version will waste some disk space. Potentially quite a bit of it, if they all have mismatching glibcs and a ton of software. That’s unfortunately one of the paper cuts you have to deal with by nix’s design; being able to use mismatching software versions between different users without system updates randomly breaking an individual users’ setup is a core part of the idea.

With non-flake systems the same thing happens, though, because the home-manager generations aren’t automatically updated anyway and will go out of sync over time.

In other words, if you’ve used this with channels before, you won’t notice much of an increase.

1 Like

Great point. Sounds like the potential duplication may be worth the configuration simplicity.

I appreciate your help!!