dustinlyons / nixos-config

General purpose Nix configuration for macOS / NixOS with starter templates + step-by-step guides ✨
BSD 3-Clause "New" or "Revised" License
1.78k stars 113 forks source link

Single Admin user & multiple non-admin users #119

Open lougreenwood opened 1 month ago

lougreenwood commented 1 month ago

I've been watching this project for some time now, looks very cool & interesting!

Currently I have my own custom blueprint system which is based on homebrew, mackup, dotbot & transcrypt as well as many custom scripts.

As part of my system setup I always create a separate admin user and then all of my day-to-day users are non-admin.

This means that I always need to install things with homebrew as an admin user.

❓ So my question is...

I tried searching the repo, I see that there is a trusted_user thing and it seems that there is other stuff related to user info etc... but without diving into the setup I figured it might be easier to ask it here and then there is some documentation for future users.

Thanks!!

dustinlyons commented 3 weeks ago

Hi @lougreenwood

Thanks for the kind words on the project!

Here is where I setup the user: https://github.com/dustinlyons/nixos-config/blob/d94dff06e0926266a50ff6cc2e727e865dd902bd/modules/darwin/home-manager.nix#L19

The trusted-users setting is only used to specify some additional permissions on the Nix daemon, such as the ability to specify additional binary caches, or import unsigned code. It doesn't manage sudo.

You could do something like this (I haven't tested it):

{
  # Define the "admin" user with root-like privileges
  users.users.admin = {
    isNormalUser = true;
    home = "/home/admin";
    extraGroups = [ "wheel" ]; # wheel group allows sudo access
    hashedPassword = "<hashed-password>"; # You can set a hashed password here or use `passwordFile` or `password` directly for simplicity
    shell = pkgs.bashInteractive; # You can specify any shell here
  };

  # Define a less privileged user, "standard"
  users.users.standard = {
    isNormalUser = true;
    home = "/home/standard";
    hashedPassword = "<hashed-password>";
    shell = pkgs.bashInteractive;
  };

  # Ensure sudo privileges for members of the "wheel" group
  security.sudo = {
    enable = true;
    wheelNeedsPassword = true; # Members of the wheel group must provide a password for sudo
  };

  # Setup user packages, programs, and nix settings
  nix = {
    package = pkgs.nix;
    configureBuildUsers = true;

    settings = {
      trusted-users = [ "@admin" "root" "standard" ];
      substituters = [ "https://nix-community.cachix.org" "https://cache.nixos.org" ];
      trusted-public-keys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ];
    };

    gc = {
      user = "root";
      automatic = true;
      interval = { Weekday = 0; Hour = 2; Minute = 0; };
      options = "--delete-older-than 30d";
    };

    extraOptions = ''
      experimental-features = nix-command flakes
    '';
  };
}

For managing different software for different users, I'd look into breaking out home-manager a bit more. You would have multiple lines here:

https://github.com/dustinlyons/nixos-config/blob/d94dff06e0926266a50ff6cc2e727e865dd902bd/flake.nix#L124

Don't get confused by the ${user}, that just gets replaced with dustin, my user. I could just as easily have written users.dustin.

For how to break it out, I asked ChatGPT how to do it and here's what it said:

To ensure different users on a macOS system receive distinct packages and settings declaratively with nix-darwin and home-manager, we can set up separate configurations for each user. Let’s walk through how this setup works and how each user would get a tailored environment upon logging in.

1. Organize User-Specific Configuration Files

First, you need separate files for each user’s configuration, specifying packages and any custom settings they need. For example:

Each of these files will define the packages and settings unique to that user. Here’s an example structure for dustin.nix:

   { config, pkgs, ... }:

   {
     home-manager.users.dustin = { pkgs, ... }: {
       # Packages specific to user "dustin"
       home.packages = with pkgs; [
         emacs
         git
         tmux
       ];

       # Additional user-specific settings go here
     };
   }

For otheruser.nix, you’d specify the configuration specific to otheruser:

   { config, pkgs, ... }:

   {
     home-manager.users.otheruser = { pkgs, ... }: {
       # Packages specific to "otheruser"
       home.packages = with pkgs; [
         nano
         htop
         wget
       ];

       # Additional user-specific settings go here
     };
   }

2. Integrate User Modules into darwinConfigurations

In your main flake configuration, reference these user modules within darwinConfigurations. This setup will link each user’s configuration to their profile in a declarative manner.

Here’s how you’d adjust the darwinConfigurations section to incorporate the different user-specific modules:

   darwinConfigurations = nixpkgs.lib.genAttrs darwinSystems (system:
     darwin.lib.darwinSystem {
       inherit system;
       specialArgs = inputs;
       modules = [
         # Load the home-manager module for macOS
         home-manager.darwinModules.home-manager

         # Load nix-homebrew for macOS
         nix-homebrew.darwinModules.nix-homebrew

         # Homebrew settings (applicable to all users on macOS)
         {
           nix-homebrew = {
             inherit user;
             enable = true;
             taps = {
               "homebrew/homebrew-core" = homebrew-core;
               "homebrew/homebrew-cask" = homebrew-cask;
               "homebrew/homebrew-bundle" = homebrew-bundle;
             };
             mutableTaps = false;
             autoMigrate = true;
           };
         }

         # Base macOS host configurations
         ./hosts/darwin

         # User-specific modules
         ./users/dustin.nix
         ./users/otheruser.nix
       ];
     }
   );

3. Login and Home-Manager Activation for Each User

Once this setup is applied, here’s what will happen for each user:

4. Home-Manager Execution and Profile Activation

For each user:

Summary of the Flow

  1. Configure: Each user has a dedicated .nix file (dustin.nix, otheruser.nix) with their packages and settings.
  2. Integrate: The main flake config includes all user configurations under darwinConfigurations.
  3. Activate: Upon login, home-manager activates the configuration for each user, linking packages into their environment.

Notes

This setup maintains a clear, declarative, and reproducible environment for each user on macOS with Nix flakes, nix-darwin, and home-manager.