Files
athenix/docs/USER_CONFIGURATION.md
UGA Innovation Factory 0ba0e854cf
All checks were successful
CI / Flake Check (push) Successful in 1m33s
CI / Format Check (push) Successful in 2s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 10s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 11s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 8s
CI / Build Artifacts (installer-iso-nix-laptop1) (push) Successful in 3m33s
CI / Build Artifacts (lxc-nix-builder) (push) Successful in 57s
migrate CI to gitea
2025-12-18 12:35:35 -05:00

12 KiB

User Configuration Guide

Complete guide to managing user accounts in nixos-systems.

Table of Contents

Overview

Users are defined in users.nix but are not enabled by default on all systems. Each system must explicitly enable users in inventory.nix.

Default enabled users:

  • root - System administrator
  • engr-ugaif - Innovation Factory default account

Quick Start

1. Define User in users.nix

athenix.users = {
  # Option 1: Inline definition
  myuser = {
    description = "My Full Name";
    extraGroups = [ "wheel" "networkmanager" ];
    shell = pkgs.zsh;
    hashedPassword = "$6$...";  # Generate with: mkpasswd -m sha-512
    opensshKeys = [
      "ssh-ed25519 AAAA... user@machine"
    ];
  };
  
  # Option 2: External configuration (recommended for personalization)
  myuser.external = builtins.fetchGit {
    url = "https://git.factory.uga.edu/username/dotfiles";
    rev = "abc123...";  # Pin to specific commit
  };
};

2. Enable User on Hosts

In inventory.nix:

nix-laptop = {
  devices = 2;
  overrides.athenix.users.myuser.enable = true;  # Enables on all nix-laptop hosts
};

# Or for specific devices
nix-desktop = {
  devices = {
    "1".athenix.users.myuser.enable = true;
    "2".athenix.users.otheruser.enable = true;
  };
};

# Or use convenience option
nix-wsl = {
  devices."alice".athenix.forUser = "alice-user";  # Automatically enables user
};

User Account Options

Each user in users.nix can have the following options:

username = {
  # === Identity ===
  description = "Full Name";              # User's full name
  
  # === System Access ===
  isNormalUser = true;                    # Default: true (false for root)
  extraGroups = [                         # Additional Unix groups
    "wheel"                               # Sudo access
    "networkmanager"                      # Network configuration
    "docker"                              # Docker access
    "video"                               # Video device access
    "audio"                               # Audio device access
  ];
  shell = pkgs.zsh;                       # Login shell (default: pkgs.bash)
  hashedPassword = "$6$...";              # Hashed password (see below)
  
  # === SSH Access ===
  opensshKeys = [                         # SSH public keys
    "ssh-ed25519 AAAA... user@host"
    "ssh-rsa AAAA... user@otherhost"
  ];
  
  # === External Configuration ===
  external = builtins.fetchGit { ... };   # External user module (see below)
  
  # === Theme Integration ===
  useZshTheme = true;                     # Apply system Zsh theme (default: true)
  useNvimPlugins = true;                  # Apply system Neovim config (default: true)
  
  # === System Enablement ===
  enable = false;                         # Enable on this system (set in inventory.nix)
};

External User Configurations

Users can maintain their dotfiles and home-manager configuration in separate Git repositories.

Basic External Configuration

In users.nix:

myuser = {
  # Basic options can be set here OR in the external module's user.nix
  description = "My Name";
  extraGroups = [ "wheel" ];
  hashedPassword = "$6$...";
  
  # Point to external configuration repository
  external = builtins.fetchGit {
    url = "https://git.factory.uga.edu/username/dotfiles";
    rev = "abc123...";  # Pin to specific commit
  };
};

External Repository Structure

dotfiles/
├── user.nix     # Required: User options AND home-manager config
├── nixos.nix    # Optional: System-level configuration
└── config/      # Optional: Your dotfiles
    ├── bashrc
    ├── vimrc
    └── ...

At least user.nix should be present for a functional user module.

user.nix (required):

{ inputs, ... }:
{ config, lib, pkgs, osConfig ? null, ... }:
{
  # ========== User Account Configuration ==========
  # These options define the user account itself
  athenix.users.myuser = {
    description = "My Full Name";
    extraGroups = [ "wheel" "docker" ];
    shell = pkgs.zsh;
    hashedPassword = "!";
    opensshKeys = [
      "ssh-ed25519 AAAA... user@host"
    ];
    useZshTheme = true;
    useNvimPlugins = true;
  };

  # ========== Home Manager Configuration ==========
  # User environment, packages, and dotfiles
  
  home.packages = with pkgs; [
    vim
    ripgrep
  ] ++ lib.optional (osConfig.athenix.sw.type or null == "desktop") firefox;

  programs.git = {
    enable = true;
    userName = "My Name";
    userEmail = "me@example.com";
    extraConfig = {
      init.defaultBranch = "main";
    };
  };
  
  home.file.".bashrc".source = ./config/bashrc;
}

nixos.nix (optional):

{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
  # System-level configuration
  users.users.myusername.extraGroups = [ "docker" ];
  environment.systemPackages = [ pkgs.docker ];
}

What External Modules Receive

In user.nix:

  • inputs - Flake inputs (nixpkgs, home-manager, etc.)
  • config - Configuration (NixOS or home-manager depending on import context)
  • lib - Nixpkgs library functions
  • pkgs - Package set
  • osConfig - (home-manager context only) OS-level configuration

How External Modules Are Loaded

The user.nix module serves a dual purpose and is imported in two contexts:

  1. NixOS Module Context (User Options): The module is imported as a NixOS module where athenix.users.<username> options are read to define the user account (description, shell, groups, SSH keys, etc.). These options override any defaults set in users.nix.

  2. Home-Manager Context: The same module is imported into home-manager where home.*, programs.*, and services.* options configure the user's environment, packages, and dotfiles.

Key insight: A single user.nix file contains both account configuration AND home environment configuration. The system automatically imports it in the appropriate contexts.

Example: The user account options (like shell, extraGroups) are read during NixOS evaluation, while home-manager options (like home.packages, programs.git) are used when building the user's home environment.

In nixos.nix:

  • inputs - Flake inputs
  • config - NixOS configuration
  • lib - Nixpkgs library functions
  • pkgs - Package set

Alternative Configuration Methods

Local path (for testing):

external = /home/username/dev/dotfiles;

Note: User options can be set in users.nix OR in the external module's user.nix file. For custom packages and environment configuration without external modules, create a local module and reference it with extraImports.

Create User Template

nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#user

See templates/user/README.md for complete template.

Enabling Users on Hosts

Users must be explicitly enabled on each host in inventory.nix.

Method 1: Enable in Overrides (All Devices)

nix-laptop = {
  devices = 5;
  overrides = {
    athenix.users.student.enable = true;  # All 5 laptops get this user
  };
};

Method 2: Enable per Device

nix-desktop = {
  devices = {
    "1".athenix.users.alice.enable = true;
    "2".athenix.users.bob.enable = true;
    "3" = {
      athenix.users.alice.enable = true;
      athenix.users.bob.enable = true;
    };
  };
};

Method 3: Convenience Option (athenix.forUser)

Quick setup for single-user systems:

nix-wsl = {
  devices = {
    "alice".athenix.forUser = "alice-user";  # Automatically enables alice-user
    "bob".athenix.forUser = "bob-user";
  };
};

This is equivalent to athenix.users.alice-user.enable = true.

Password Management

Generate Hashed Password

mkpasswd -m sha-512
# Enter password when prompted
# Copy the output hash

In users.nix

myuser = {
  hashedPassword = "$6$rounds=656000$...";  # Paste hash here
};

Disable Password Login

myuser = {
  hashedPassword = "!";  # Locks password, SSH key only
  opensshKeys = [ "ssh-ed25519 ..." ];
};

Change Password Later

On the system:

sudo passwd myuser

Or regenerate hash and update users.nix.

SSH Keys

Adding SSH Keys

myuser = {
  opensshKeys = [
    "ssh-ed25519 AAAAC3Nza... user@laptop"
    "ssh-rsa AAAAB3NzaC1... user@desktop"
  ];
};

Generate SSH Key

ssh-keygen -t ed25519 -C "user@hostname"
cat ~/.ssh/id_ed25519.pub  # Copy this

Multiple Keys

Users can have multiple SSH keys for different machines:

opensshKeys = [
  "ssh-ed25519 ... user@work-laptop"
  "ssh-ed25519 ... user@home-desktop"  
  "ssh-ed25519 ... user@tablet"
];

Examples

Basic User

student = {
  description = "Student Account";
  extraGroups = [ "networkmanager" ];
  shell = pkgs.bash;
  hashedPassword = "$6$...";
};

Admin User with SSH

admin = {
  description = "System Administrator";
  extraGroups = [ "wheel" "networkmanager" "docker" ];
  shell = pkgs.zsh;
  hashedPassword = "$6$...";
  opensshKeys = [
    "ssh-ed25519 AAAA... admin@laptop"
  ];
};

User with External Configuration

developer = {
  description = "Developer";
  extraGroups = [ "wheel" "docker" ];
  shell = pkgs.zsh;
  hashedPassword = "$6$...";
  external = builtins.fetchGit {
    url = "https://git.factory.uga.edu/username/dotfiles";
    rev = "abc123def456...";
  };
};

WSL User

wsl-user = {
  description = "WSL User";
  extraGroups = [ "wheel" ];
  shell = pkgs.zsh;
  hashedPassword = "$6$...";
  external = builtins.fetchGit {
    url = "https://git.factory.uga.edu/username/dotfiles";
    rev = "abc123...";
  };
};

Enable in inventory.nix:

nix-wsl = {
  devices."my-wsl".athenix.forUser = "wsl-user";
};

User Without System Themes

For users who want complete control over their shell/editor:

poweruser = {
  description = "Power User";
  extraGroups = [ "wheel" ];
  shell = pkgs.zsh;
  hashedPassword = "$6$...";
  useZshTheme = false;      # Don't apply system theme
  useNvimPlugins = false;   # Don't apply system nvim config
  external = builtins.fetchGit {
    url = "https://github.com/username/custom-dotfiles";
    rev = "abc123...";
  };
};

Theme Integration

System Zsh Theme

When useZshTheme = true (default), the system applies:

  • Oh My Posh with custom theme
  • History substring search
  • Vi mode (for non-root users)
  • Zsh plugins (zplug)

Disable if you want full control in your dotfiles.

System Neovim Config

When useNvimPlugins = true (default), the system applies:

  • LazyVim distribution
  • TreeSitter parsers
  • Language servers

Disable if you want to configure Neovim yourself.

Troubleshooting

User Can't Login

Check if enabled on host:

nix eval .#nixosConfigurations.nix-laptop1.config.athenix.users.myuser.enable

Check if user exists:

# On the system
id myuser

SSH Key Not Working

Check key in configuration:

nix eval .#nixosConfigurations.nix-laptop1.config.users.users.myuser.openssh.authorizedKeys.keys

Verify key format:

  • Should start with ssh-ed25519, ssh-rsa, or ssh-dss
  • Should be all on one line
  • Should end with comment (optional)

External Config Not Loading

Check repository access:

git ls-remote https://git.factory.uga.edu/username/dotfiles

Verify structure:

  • Must have user.nix at repository root
  • nixos.nix is optional
  • Check file permissions

Test with local path first:

external = /path/to/local/dotfiles;

See Also