diff --git a/Building.md b/Building.md new file mode 100644 index 0000000..46d09ff --- /dev/null +++ b/Building.md @@ -0,0 +1,387 @@ +# Building Installation Media and Artifacts + +Guide to building installer ISOs, live images, and container artifacts. + +## Table of Contents + +- [Quick Start](#quick-start) +- [Available Artifacts](#available-artifacts) +- [Building Locally](#building-locally) +- [Building from Remote](#building-from-remote) +- [Installer ISOs](#installer-isos) +- [Live ISOs](#live-isos) +- [Container Images](#container-images) +- [Remote Builders](#remote-builders) +- [Troubleshooting](#troubleshooting) + +## Quick Start + +```bash +# List all available artifacts +nix flake show + +# Build installer ISO for a specific host +nix build .#installer-iso-nix-laptop1 + +# Result is in result/iso/ +ls -lh result/iso/ +``` + +## Available Artifacts + +Athenix can build multiple artifact types for deployment: + +| Type | Description | Location | Use Case | +|------|-------------|----------|----------| +| `installer-iso-*` | Auto-install ISO | `result/iso/` | Install NixOS to disk | +| `iso-*` | Live ISO | `result/iso/` | Boot without installing | +| `ipxe-*` | PXE netboot | `result/` | Diskless netboot systems | +| `lxc-*` | LXC container | `result/tarball/` | LXC/Proxmox containers | +| `proxmox-*` | Proxmox VMA | `result/` | Proxmox VM templates | + +Set artifact types per-host via `athenix.host.buildMethods` in `inventory.nix`: + +```nix +nix-laptop = { + devices = 5; + overrides.athenix.host.buildMethods = [ "installer-iso" ]; +}; + +nix-lxc = { + devices.builder = { + athenix.host.buildMethods = [ "lxc" "proxmox" ]; + }; +}; +``` + +## Building Locally + +Build artifacts on your local machine: + +```bash +# Build installer ISO +nix build .#installer-iso-nix-laptop1 + +# Build live ISO +nix build .#iso-nix-ephemeral1 + +# Build LXC container +nix build .#lxc-nix-builder + +# Build all available outputs +nix build .# +``` + +**Result locations:** +- ISOs: `result/iso/nixos-*.iso` +- LXC: `result/tarball/nixos-*.tar.xz` +- Proxmox: `result/` +- iPXE: `result/` (kernel, initrd, script) + +### Build Specific Host + +```bash +# Get list of all hosts +nix eval .#nixosConfigurations --apply builtins.attrNames + +# Build specific host +nix build .#nixosConfigurations.nix-laptop1.config.system.build.toplevel +``` + +## Building from Remote + +Build from the Gitea repository without cloning: + +```bash +# Build installer ISO +nix build git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#installer-iso-nix-laptop1 + +# Build LXC container +nix build git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#lxc-nix-builder + +# Use specific branch or revision +nix build git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git?ref=develop#installer-iso-nix-laptop1 +``` + +## Installer ISOs + +Installer ISOs automatically partition and install NixOS on first boot. + +### Building + +```bash +nix build .#installer-iso-nix-laptop1 +ls -lh result/iso/ +``` + +### Burning to USB + +```bash +# Find USB device (be careful!) +lsblk + +# Burn ISO to USB (replace sdX with your device) +sudo dd if=result/iso/nixos-*.iso of=/dev/sdX bs=4M status=progress + +# Sync and eject +sudo sync && sudo eject /dev/sdX +``` + +### Installation Process + +1. Boot from the USB drive +2. System automatically boots into installer +3. Installer partitions disk according to `athenix.host.filesystem` +4. NixOS is installed and configured +5. System reboots automatically +6. Log in with configured user + +**Note:** Installer will erase all data on the target disk specified in `athenix.host.filesystem.device`. + +### Installer Configuration + +Customize installer via host configuration: + +```nix +nix-laptop = { + devices = 5; + overrides = { + athenix.host.filesystem.device = "/dev/nvme0n1"; + athenix.host.filesystem.swapSize = "32G"; + athenix.host.buildMethods = [ "installer-iso" ]; + }; +}; +``` + +## Live ISOs + +Live ISOs boot into a temporary system without installing to disk. + +### Building + +```bash +nix build .#iso-nix-ephemeral1 +``` + +### Usage + +Live ISOs are useful for: +- Testing configurations before installation +- Recovery operations +- Ephemeral/stateless systems +- Booting in kiosk mode + +### Customizing Live ISO + +```nix +nix-ephemeral = { + devices.live = { + athenix.sw.type = "stateless-kiosk"; + athenix.sw.kioskUrl = "https://dashboard.example.com"; + athenix.host.buildMethods = [ "iso" ]; + }; +}; +``` + +## Container Images + +### LXC Containers + +Build LXC container tarballs for Proxmox or standalone LXC: + +```bash +nix build .#lxc-nix-builder +ls -lh result/tarball/ +``` + +#### Importing to Proxmox + +1. Copy tarball to Proxmox host: + +```bash +scp result/tarball/nixos-*.tar.xz root@proxmox:/var/lib/vz/template/cache/ +``` + +2. Create container: + +```bash +pct create 100 local:vztmpl/nixos-*.tar.xz \ + --hostname nix-builder \ + --memory 4096 \ + --cores 4 \ + --net0 name=eth0,bridge=vmbr0,ip=dhcp +``` + +3. Start and log in: + +```bash +pct start 100 +pct shell 100 +``` + +#### Proxmox Integration + +For detailed Proxmox deployment instructions, see [installer/PROXMOX_LXC.md](../installer/PROXMOX_LXC.md). + +### Proxmox VMA + +Build Proxmox-specific VMA archives: + +```bash +nix build .#proxmox-nix-builder +ls -lh result/ +``` + +VMA files can be imported directly into Proxmox for rapid VM creation. + +## iPXE / Network Boot + +Build iPXE artifacts for diskless PXE boot systems: + +```bash +nix build .#ipxe-nix-ephemeral1 +ls -lh result/ +``` + +Artifacts include: +- `bzImage` - Linux kernel +- `initrd` - Initial ramdisk +- `netboot.ipxe` - iPXE boot script + +### iPXE Setup + +Configure your PXE server to boot from these artifacts: + +```ipxe +kernel tftp://server/bzImage +initrd tftp://server/initrd +boot +``` + +See [installer/PROXMOX_LXC.md](../installer/PROXMOX_LXC.md) for detailed network boot setup. + +## Remote Builders + +Speed up builds by offloading to build servers. + +### One-Time Build + +```bash +nix build .#installer-iso-nix-laptop1 \ + --builders "ssh://engr-ugaif@nix-builder x86_64-linux" +``` + +### Persistent Configuration + +Add to `~/.config/nix/nix.conf`: + +```conf +builders = ssh://engr-ugaif@nix-builder x86_64-linux +``` + +Then build normally: + +```bash +nix build .#installer-iso-nix-laptop1 +``` + +### SSH Setup + +Ensure SSH is configured for the builder: + +```bash +# Generate key if needed +ssh-keygen -t ed25519 + +# Copy to builder +ssh-copy-id engr-ugaif@nix-builder + +# Test connection +ssh engr-ugaif@nix-builder +``` + +### Multiple Builders + +```conf +builders = ssh://engr-ugaif@nix-builder1 x86_64-linux ; ssh://engr-ugaif@nix-builder2 x86_64-linux +``` + +### Automatic Remote Build (Tablets) + +Surface tablets are configured to automatically use remote builders: + +```nix +athenix.sw.remoteBuild = { + enable = true; + hosts = [ "nix-builder" ]; +}; +``` + +This speeds up builds on resource-constrained devices. + +## Troubleshooting + +### Build Errors + +Get detailed error information: + +```bash +# Verbose error traces +nix build .#installer-iso-nix-laptop1 --show-trace + +# Check all configurations first +nix flake check --show-trace +``` + +### Out of Disk Space + +```bash +# Clean up Nix store +nix-collect-garbage -d + +# Optimize store +nix store optimise +``` + +### Build Hangs + +```bash +# List processes +ps aux | grep nix + +# Cancel build +Ctrl+C +``` + +### Finding Artifact Outputs + +```bash +# List all buildable outputs +nix flake show + +# Check specific output exists +nix flake show | grep installer-iso-nix-laptop1 + +# Get path to output +nix build .#installer-iso-nix-laptop1 --no-link +``` + +### Build Not Creating Expected File + +```bash +# Check build log +nix build .#installer-iso-nix-laptop1 -L + +# Check what's in result +ls -la result/ + +# Inspect NixOS build structure +nix build .#nixosConfigurations.nix-laptop1.config.system.build.toplevel -L +``` + +## See Also + +- [DEVELOPMENT.md](DEVELOPMENT.md) - Development workflow +- [INVENTORY.md](INVENTORY.md) - Host configuration +- [installer/PROXMOX_LXC.md](../installer/PROXMOX_LXC.md) - Proxmox deployment +- [README.md](../README.md) - Main documentation diff --git a/Configuration-Options.md b/Configuration-Options.md new file mode 100644 index 0000000..01505c1 --- /dev/null +++ b/Configuration-Options.md @@ -0,0 +1,40 @@ +# Configuration Options + +This document describes all available configuration options in the Athenix namespace. + +## Quick Reference + +- **athenix.sw** - Software configuration (desktop, headless, kiosk modes) +- **athenix.users** - User account management +- **athenix.host** - Host-specific settings (filesystem, build methods) +- **athenix.fleet** - Fleet inventory definitions +- **athenix.forUser** - Convenience option to enable a user +- **athenix.system.gc** - Garbage collection settings + +## Detailed Options + +For detailed option information, use: +```bash +# View all athenix options +nix eval .#nixosConfigurations.nix-desktop1.options.athenix --apply builtins.attrNames + +# View specific option description +nix eval .#nixosConfigurations.nix-desktop1.options.athenix.sw.desktop.enable.description + +# Export all options to JSON +nix build .#athenix-options +cat result | jq +``` + +## Software Types + +Enable different system configurations: + +- **desktop** - Full KDE Plasma desktop environment +- **headless** - Server/container configuration +- **tablet-kiosk** - Touch-optimized kiosk for tablets +- **stateless-kiosk** - Diskless PXE boot kiosk +- **builders** - Build server with optional Gitea Actions runner + +See the individual option descriptions for detailed information. + diff --git a/Development.md b/Development.md new file mode 100644 index 0000000..316b3ae --- /dev/null +++ b/Development.md @@ -0,0 +1,456 @@ +# Development Guide + +Comprehensive guide for maintaining and extending Athenix. + +## Table of Contents + +- [Prerequisites](#prerequisites) +- [Development Workflow](#development-workflow) +- [Testing Changes](#testing-changes) +- [Continuous Integration](#continuous-integration) +- [Common Tasks](#common-tasks) +- [Debugging](#debugging) +- [Troubleshooting](#troubleshooting) + +## Prerequisites + +### Install Nix with Flakes + +```bash +# Recommended: Determinate Systems installer +curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install + +# Or official installer +sh <(curl -L https://nixos.org/nix/install) --daemon + +# Enable flakes in existing installation +mkdir -p ~/.config/nix +echo 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf +``` + +### Clone Repository + +```bash +git clone https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git +cd athenix + +# Optional: enable direnv for automatic Nix environment +direnv allow +``` + +## Development Workflow + +### Making Changes + +1. **Edit configuration files** - Modify `inventory.nix`, `users.nix`, or host/software config + +2. **Validate** - Check syntax and configuration + +```bash +nix flake check +``` + +3. **Format code** - Apply consistent formatting + +```bash +nix fmt +``` + +4. **Test** - Build specific artifacts or configurations + +```bash +# Test specific host +nix build .#nixosConfigurations.nix-laptop1.config.system.build.toplevel + +# Or build an artifact +nix build .#installer-iso-nix-laptop1 +``` + +5. **Commit and push** + +```bash +git add . +git commit -m "Brief description of changes" +git push +``` + +### Example: Adding a New User + +1. Define user in `users.nix`: + +```nix +athenix.users.newuser = { + description = "New User"; + extraGroups = [ "wheel" "networkmanager" ]; + shell = pkgs.zsh; + hashedPassword = "..."; # mkpasswd -m sha-512 +}; +``` + +2. Enable on fleet in `inventory.nix`: + +```nix +nix-laptop = { + devices = 5; + overrides.athenix.users.newuser.enable = true; +}; +``` + +3. Validate and commit: + +```bash +nix flake check +nix fmt +git add . && git commit -m "Add newuser account" +git push +``` + +## Testing Changes + +### Validate Configuration Syntax + +Always run before committing: + +```bash +nix flake check +``` + +Shows any configuration errors across all ~50+ hosts. Output: + +``` +checking 50 configurations... +✓ All checks passed +``` + +### Test Specific Host Build + +```bash +# Build specific host (shows if config actually compiles) +nix build .#nixosConfigurations.nix-laptop1.config.system.build.toplevel + +# Shorter form +nix build .#nixosConfigurations.nix-laptop1.config.system.build.toplevel -L +``` + +### Test Installer Build + +```bash +# Test that installer ISO builds +nix build .#installer-iso-nix-laptop1 -L +``` + +### Test on Running NixOS System + +If you're on a NixOS system managed by Athenix: + +```bash +# Test changes temporarily (won't survive reboot) +sudo nixos-rebuild test --flake . + +# Apply and switch (persistent) +sudo nixos-rebuild switch --flake . + +# Build without switching +sudo nixos-rebuild build --flake . + +# Show what will change +sudo nixos-rebuild dry-activate --flake . +``` + +### Rollback + +If a build breaks your system: + +```bash +# List recent generations +nix-env --list-generations + +# Rollback to previous generation +nix-env --rollback + +# Or switch to specific generation +nix-env --switch-generation 42 +``` + +## Continuous Integration + +### CI Pipeline + +All pushes and pull requests trigger automated tests on the self-hosted `nix-builder`: + +1. **Flake Check** - `nix flake check` validates all 50+ configurations +2. **Format Check** - Verifies code formatted with `nix fmt` +3. **Build Key Hosts** - Builds `nix-builder`, `nix-laptop1`, `nix-desktop1` +4. **Build Artifacts** - Tests `lxc-nix-builder` and `installer-iso-nix-laptop1` + +### Viewing CI Status + +```bash +# Web interface +https://git.factory.uga.edu/UGA-Innovation-Factory/athenix/actions + +# Or check locally +git log --oneline -n 5 +# Look for ✓ or ✗ next to commits +``` + +### Running CI Checks Locally + +Test before pushing: + +```bash +# Flake check +nix flake check --show-trace + +# Format check +nix fmt --check + +# Format code +nix fmt **/*.nix + +# Build key configurations +nix build .#nixosConfigurations.nix-builder.config.system.build.toplevel -L +nix build .#nixosConfigurations.nix-laptop1.config.system.build.toplevel -L +``` + +## Common Tasks + +### Adding a New Host + +Edit `inventory.nix`: + +```nix +nix-surface = { + devices = 3; # Creates nix-surface1, nix-surface2, nix-surface3 + overrides = { + athenix.sw.type = "tablet-kiosk"; + athenix.sw.kioskUrl = "https://dashboard.example.com"; + }; +}; +``` + +Test: + +```bash +nix flake check +nix build .#installer-iso-nix-surface1 -L +``` + +### Modifying Software Configuration + +Edit appropriate file in `sw/`: + +```bash +# Desktop software +vim sw/desktop/programs.nix + +# Or for all systems +vim sw/default.nix +``` + +Use `athenix.sw.extraPackages` for host-specific additions: + +```nix +nix-laptop = { + devices = 5; + overrides.athenix.sw.extraPackages = with pkgs; [ special-tool ]; +}; +``` + +### Adding a System Type + +Create new type in `sw/`: + +```bash +mkdir -p sw/my-type +touch sw/my-type/{default.nix,programs.nix,services.nix} +``` + +Then reference in `sw/default.nix`: + +```nix +{ + imports = [ + ./my-type/default.nix + # ... other types + ]; +} +``` + +### Using External Configurations + +For user dotfiles: + +```nix +# users.nix +athenix.users.myuser.external = builtins.fetchGit { + url = "https://git.factory.uga.edu/username/dotfiles"; + rev = "abc123..."; # Pin to commit +}; +``` + +For system config: + +```nix +# inventory.nix +nix-lxc = { + devices."server".external = builtins.fetchGit { + url = "https://git.factory.uga.edu/org/server-config"; + rev = "abc123..."; + }; +}; +``` + +### Updating Dependencies + +```bash +# Update all flake inputs +nix flake update + +# Update specific input +nix flake update nixpkgs + +# Show what changed +git diff flake.lock + +# Test after update +nix flake check --show-trace + +# If tests pass, commit +git add flake.lock && git commit -m "Update dependencies" +``` + +## Debugging + +### Verbose Output + +Get detailed error messages: + +```bash +# Show full error traces +nix flake check --show-trace + +# With maximum verbosity +nix build .#installer-iso-nix-laptop1 -vvv + +# Show build log +nix build .#installer-iso-nix-laptop1 -L +``` + +### Inspect Configuration + +```bash +# Evaluate configuration for specific host +nix eval .#nixosConfigurations.nix-laptop1.config.athenix.sw --json + +# Get all host names +nix eval .#nixosConfigurations --apply builtins.attrNames + +# Check specific option +nix eval .#nixosConfigurations.nix-laptop1.config.users.users +``` + +### Test Module Loading + +```bash +# Evaluate specific module +nix-build -A nixosConfigurations.nix-laptop1.config.system.build.toplevel + +# Or with flakes +nix build .#nixosConfigurations.nix-laptop1.config.system.build.toplevel --verbose +``` + +### Check Derivation Dependencies + +```bash +# Show what dependencies a build needs +nix show-derivation .#installer-iso-nix-laptop1 + +# Or human-readable +nix build .#installer-iso-nix-laptop1 --dry-run +``` + +## Troubleshooting + +### Common Errors + +#### "Evaluation error" + +``` +error: evaluation aborted with the following error message: '...' +``` + +**Solution:** Check syntax in modified files. Use `nix fmt` and `nix flake check --show-trace`. + +#### "Unknown variable" or "Option does not exist" + +``` +error: The option `athenix.xyz' does not exist. +``` + +**Solution:** Check NAMESPACE.md for available options. Options must be in `athenix.*` namespace. + +#### "Hash mismatch" (for external modules) + +``` +error: Hash mismatch in fetched input +``` + +**Solution:** Update the pin. For `builtins.fetchGit`, use actual commit hash. Or: + +```bash +nix flake update +``` + +#### Build runs out of memory + +```bash +# Reduce parallel jobs +nix build . --max-jobs 1 +``` + +#### "No such file or directory" in build + +```bash +# Check path exists +ls -la /path/to/file + +# Or check relative to repo +ls -la sw/my-file.nix +``` + +### Helpful Diagnostics + +```bash +# List all hosts +nix eval .#nixosConfigurations --apply builtins.attrNames + +# Show flake structure +nix flake show | head -50 + +# Check Nix store size +du -sh /nix/store + +# List top space users in store +nix store du --human-readable | head -20 + +# Find store paths for a package +nix store path-info -rS $(which some-package) +``` + +### Getting Help + +1. **Check documentation** - Review relevant doc file +2. **Look at existing examples** - Check `inventory.nix` or `users.nix` +3. **Search for similar patterns** - `grep -r "athenix.option" .` +4. **Run tests locally** - `nix flake check --show-trace` with full output +5. **Review git history** - `git log --patch -- filename.nix` + +## See Also + +- [BUILDING.md](BUILDING.md) - Building artifacts +- [INVENTORY.md](INVENTORY.md) - Host configuration +- [NAMESPACE.md](NAMESPACE.md) - Configuration options +- [USER_CONFIGURATION.md](USER_CONFIGURATION.md) - User management +- [EXTERNAL_MODULES.md](EXTERNAL_MODULES.md) - External modules +- [README.md](../README.md) - Main documentation diff --git a/External-Modules.md b/External-Modules.md new file mode 100644 index 0000000..4ba7299 --- /dev/null +++ b/External-Modules.md @@ -0,0 +1,483 @@ +# External Configuration Modules + +Guide to using external modules for system and user configurations. + +## Table of Contents + +- [Overview](#overview) +- [System Modules](#system-modules) +- [User Modules](#user-modules) +- [Fetch Methods](#fetch-methods) +- [Creating External Modules](#creating-external-modules) +- [Best Practices](#best-practices) + +## Overview + +External modules allow you to maintain configurations in separate Git repositories and reference them from Athenix. + +**Benefits:** +- **Separation** - Keep complex configs in separate repositories +- **Reproducibility** - Pin specific commits for deterministic builds +- **Reusability** - Share configurations across multiple deployments +- **Flexibility** - Mix external modules with local configuration +- **Ownership** - Users maintain their own dotfiles + +## System Modules + +External system modules provide host-specific NixOS configurations. + +### Usage + +In `inventory.nix`, reference an external module using the `external` field: + +```nix +nix-lxc = { + devices = { + # Inline configuration (traditional method) + "local-server" = { + athenix.sw.type = "headless"; + services.nginx.enable = true; + }; + + # External module (lazy evaluation - fetched only when building this host) + "remote-server".external = builtins.fetchGit { + url = "https://git.factory.uga.edu/org/server-config"; + rev = "abc123def456..."; # Must pin to specific commit + }; + + # External module with additional local config + "mixed-server" = { + external = builtins.fetchGit { + url = "https://git.factory.uga.edu/org/server-config"; + rev = "abc123def456..."; + }; + # Additional local overrides + athenix.users.admin.enable = true; + services.openssh.permitRootLogin = "no"; + }; + }; +}; +``` + +**Key Features:** +- **Lazy Evaluation**: External modules are only fetched when building the specific host +- **Efficient Rebuilds**: Other hosts can be rebuilt without fetching unrelated external modules +- **Submodule Support**: Works with Git submodules without affecting other hosts + +### Repository Structure + +``` +server-config/ +├── default.nix # Required: NixOS module +├── README.md # Recommended: Documentation +└── optional/ + ├── config/ # Optional: Configuration files + └── scripts/ # Optional: Helper scripts +``` + +### Module Content (default.nix) + +```nix +# The module receives inputs and standard NixOS module parameters +{ inputs, ... }: +{ config, lib, pkgs, ... }: +{ + # Your NixOS configuration + # Use any standard NixOS option or athenix.* options + + services.nginx = { + enable = true; + virtualHosts."example.com" = { + root = "/var/www"; + forceSSL = true; + enableACME = true; + }; + }; + + # Use athenix options + athenix.sw.type = "headless"; + athenix.sw.extraPackages = with pkgs; [ git htop ]; + + # Standard NixOS configuration + networking.firewall.allowedTCPPorts = [ 80 443 ]; + services.openssh.enable = true; +} +``` + +### What System Modules Receive + +- **`inputs`** - All flake inputs (nixpkgs, home-manager, disko, etc.) +- **`config`** - Current NixOS configuration (read/write) +- **`lib`** - Nixpkgs library functions +- **`pkgs`** - Package set + +### Configuration Order + +When a host is built, modules load in this order: + +1. Hardware type module (from `hw/nix-*.nix`) +2. Common system configuration (from `fleet/common.nix`) +3. Software type module (from `sw/{type}/`) +4. User NixOS modules (from `users.nix` - `nixos.nix` files) +5. Device-specific overrides (from `inventory.nix`) +6. External system module (if present) + +Each later module can override earlier ones using standard NixOS precedence rules. + +## User Modules + +External user modules provide home-manager configurations (dotfiles, environment setup). + +### Usage + +In `users.nix`, reference an external user module: + +```nix +athenix.users = { + # External user module + myuser.external = builtins.fetchGit { + url = "https://git.factory.uga.edu/username/dotfiles"; + rev = "abc123def456..."; # Pin to specific commit + }; + + # Inline user definition + otheruser = { + description = "Other User"; + extraGroups = [ "wheel" ]; + shell = pkgs.zsh; + hashedPassword = "$6$..."; + }; +}; +``` + +Then enable on hosts in `inventory.nix`: + +```nix +nix-laptop = { + devices = 5; + overrides.athenix.users.myuser.enable = true; +}; +``` + +### Repository Structure + +``` +my-dotfiles/ +├── user.nix # Required: User options + home-manager config +├── nixos.nix # Optional: System-level configuration +├── README.md # Recommended: Documentation +└── config/ # Optional: Your actual dotfiles + ├── zshrc + ├── vimrc + ├── nvim/ + └── ... +``` + +### user.nix (Required) + +Provides both user account settings AND home-manager configuration: + +```nix +# Receives { inputs } and standard home-manager module parameters +{ inputs, ... }: +{ config, lib, pkgs, osConfig ? null, ... }: +{ + # ========== User Account Configuration ========== + # These options define the user account itself + + athenix.users.myusername = { + description = "My Full Name"; + extraGroups = [ "wheel" "docker" ]; + shell = pkgs.zsh; + hashedPassword = "!"; # SSH keys only + opensshKeys = [ + "ssh-ed25519 AAAA... user@laptop" + ]; + useZshTheme = true; + useNvimPlugins = true; + }; + + # ========== Home Manager Configuration ========== + # User environment, packages, and dotfiles + + # Packages + home.packages = with pkgs; [ + vim + git + ripgrep + fzf + ] ++ lib.optional (osConfig.athenix.sw.type or null == "desktop") firefox; + + # Programs + programs.git = { + enable = true; + userName = "My Name"; + userEmail = "me@example.com"; + extraConfig = { + init.defaultBranch = "main"; + core.editor = "vim"; + }; + }; + + programs.zsh = { + enable = true; + initExtra = '' + # Your Zsh configuration + export EDITOR=vim + ''; + }; + + # Manage dotfiles + home.file.".zshrc".source = ./config/zshrc; + home.file.".vimrc".source = ./config/vimrc; + home.file.".config/nvim".source = ./config/nvim; + + # Services + services.gpg-agent.enable = true; +} +``` + +### nixos.nix (Optional) + +System-level configuration for this user (rarely needed): + +```nix +{ inputs, ... }: +{ config, lib, pkgs, ... }: +{ + # System-level configuration + # Only needed if the user requires specific system-wide settings + + users.users.myusername.extraGroups = [ "docker" ]; + environment.systemPackages = [ pkgs.docker ]; + + # Security settings + security.sudo.extraRules = [{ + users = [ "myusername" ]; + commands = [{ + command = "/usr/bin/something"; + options = [ "NOPASSWD" ]; + }]; + }]; +} +``` + +### What User Modules Receive + +**In user.nix:** +- **`inputs`** - All flake inputs (nixpkgs, home-manager, etc.) +- **`config`** - Home-manager configuration (read/write) +- **`lib`** - Nixpkgs library functions +- **`pkgs`** - Package set +- **`osConfig`** - OS configuration (read-only) - useful for conditional setup + +**In nixos.nix:** +- **`inputs`** - Flake inputs +- **`config`** - NixOS configuration (read/write) +- **`lib`** - Nixpkgs library functions +- **`pkgs`** - Package set + +### Conditional Setup Example + +Use `osConfig` to conditionally set up dotfiles based on the system type: + +```nix +# In user.nix +{ inputs, ... }: +{ config, lib, pkgs, osConfig ? null, ... }: +{ + athenix.users.myuser = { /* ... */ }; + + # Install Firefox only on desktop systems + home.packages = with pkgs; [ + ripgrep + ] ++ lib.optional (osConfig.athenix.sw.type or null == "desktop") firefox; + + # Different shell config per system + programs.zsh.initExtra = '' + ${lib.optionalString (osConfig.athenix.sw.type or null == "headless") " + # Headless-only settings + "} + ''; +} +``` + +## Fetch Methods + +### builtins.fetchGit (Recommended) + +Pin to a specific Git revision: + +```nix +builtins.fetchGit { + url = "https://git.factory.uga.edu/username/dotfiles"; + rev = "abc123def456..."; # Required: specific commit hash +} +``` + +**Advantages:** +- Reproducible (pinned to exact commit) +- Works with any Git repository +- Supports SSH or HTTPS URLs + +**Important:** Always specify `rev` (commit hash) for reproducibility. Don't use branches which can change. + +### builtins.fetchTarball + +Download specific release archives: + +```nix +builtins.fetchTarball { + url = "https://github.com/user/repo/archive/v1.0.0.tar.gz"; + sha256 = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; +} +``` + +**Get the hash:** +```bash +nix-prefetch-url --unpack https://github.com/user/repo/archive/v1.0.0.tar.gz +``` + +### Local Path (For Testing) + +Use local directories during development: + +```nix +# users.nix +athenix.users.myuser.external = /home/user/my-dotfiles; + +# inventory.nix +nix-laptop = { + devices = { + "dev".athenix.users.myuser.enable = true; + }; +}; +``` + +**Note:** Only works if the path exists on the machine running `nix flake check` or `nix build`. + +## Creating External Modules + +### System Module Template + +Create a new system module repository from the template: + +```bash +nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#system +``` + +This creates: + +``` +my-system-config/ +├── flake.nix # Optional: for testing standalone +├── default.nix # Your NixOS module +└── README.md # Documentation +``` + +### User Module Template + +Create a new user module repository: + +```bash +nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#user +``` + +This creates: + +``` +my-dotfiles/ +├── flake.nix # Optional: for testing standalone +├── user.nix # User options + home-manager config +├── nixos.nix # Optional: system-level config +└── README.md # Documentation +``` + +### Testing External Modules + +Test your external module locally before pushing: + +```bash +# In your module repository +cd /path/to/my-module + +# Test the Nix syntax +nix flake check +``` + +## Best Practices + +### 1. Always Pin to Specific Commits + +❌ Wrong - using branch names: +```nix +builtins.fetchGit { + url = "https://git.factory.uga.edu/username/dotfiles"; + # No rev specified or using "main" +} +``` + +✅ Correct - using commit hash: +```nix +builtins.fetchGit { + url = "https://git.factory.uga.edu/username/dotfiles"; + rev = "abc123def456789..."; +} +``` + +### 2. Keep External Modules Focused + +Each external module should have a clear purpose: +- User dotfiles (one repo per user) +- System service configuration (one repo per service/cluster) +- Hardware-specific config (one repo per hardware setup) + +### 3. Document Your Modules + +Include a README with: +- What the module configures +- Required dependencies +- Usage examples +- Configuration options + +### 4. Use Semantic Versioning + +Tag releases in Git: + +```bash +git tag v1.0.0 +git push origin v1.0.0 +``` + +Reference specific versions: + +```nix +builtins.fetchGit { + url = "https://git.factory.uga.edu/org/server-config"; + rev = "v1.0.0"; # Can use tags too +} +``` + +### 5. Test Before Updating Pins + +When updating commit hashes: + +```bash +# Test new revision locally +nix flake update + +# Validate all configurations +nix flake check --show-trace + +# Only commit after validation +git add . && git commit -m "Update module versions" +``` + +## See Also + +- [USER_CONFIGURATION.md](USER_CONFIGURATION.md) - User management +- [INVENTORY.md](INVENTORY.md) - Host configuration +- [NAMESPACE.md](NAMESPACE.md) - Configuration options +- [README.md](../README.md) - Main documentation +- [templates/user/](../templates/user/) - User module template +- [templates/system/](../templates/system/) - System module template diff --git a/Home.md b/Home.md new file mode 100644 index 0000000..743b37d --- /dev/null +++ b/Home.md @@ -0,0 +1,47 @@ +# Athenix - NixOS Fleet Management + +Athenix is a NixOS configuration system for managing the UGA Innovation Factory's fleet of devices using Nix flakes and a custom configuration framework. + +## Quick Start + +- [Configuration Options](Configuration-Options) - All available `athenix.*` options +- [User Guide](User-Configuration) - Setting up user accounts and dotfiles +- [Building](Building) - Creating installers and system images +- [Development](Development) - Contributing to Athenix + +## Features + +- **Inventory-based fleet management** - Define entire device fleets in a single file +- **Multiple hardware types** - Desktops, laptops, Surface tablets, LXC containers, WSL +- **Flexible software configurations** - Desktop, headless, kiosk, and builder modes +- **External module support** - Load user dotfiles and system configs from Git repos +- **Declarative everything** - Reproducible builds with pinned dependencies + +## Software Types + +Enable different system configurations: + +- **desktop** - Full KDE Plasma 6 desktop environment +- **headless** - Minimal server/container configuration +- **tablet-kiosk** - Touch-optimized kiosk for Surface tablets +- **stateless-kiosk** - Diskless PXE boot kiosk +- **builders** - CI/CD build server with Gitea Actions runner + +## Hardware Types + +- **nix-desktop** - Desktop workstations +- **nix-laptop** - Laptop computers +- **nix-surface** - Microsoft Surface Pro tablets +- **nix-lxc** - LXC containers (Proxmox) +- **nix-wsl** - Windows Subsystem for Linux +- **nix-ephemeral** - Stateless systems (PXE boot) + +## Documentation + +Browse the documentation using the sidebar or start with: + +- [README](README) - Repository overview and getting started +- [Configuration Options](Configuration-Options) - Complete option reference +- [Inventory Guide](Inventory) - Managing the device fleet +- [External Modules](External-Modules) - Using external configurations + diff --git a/Inventory.md b/Inventory.md new file mode 100644 index 0000000..20eaacd --- /dev/null +++ b/Inventory.md @@ -0,0 +1,361 @@ +# Host Inventory Configuration + +This document explains the `inventory.nix` file, which defines all hosts in your fleet. + +## Table of Contents + +- [Overview](#overview) +- [Structure](#structure) +- [Hostname Generation](#hostname-generation) +- [Configuration Methods](#configuration-methods) +- [Options](#options) +- [Examples](#examples) + +## Overview + +`inventory.nix` defines your fleet of hosts. Top-level keys are hostname **prefixes**, and actual hostnames are generated from device specifications. This allows you to manage large fleets with minimal repetition. + +**Key concepts:** +- Each top-level key generates one or more NixOS configurations +- Host type defaults to the prefix name (can be overridden) +- System architecture defaults to `x86_64-linux` +- Common configuration can be applied to all devices in a group via `overrides` + +## Structure + +```nix +{ + "prefix-name" = { + # Optional: Device count or explicit device map + devices = 5; # or { "1" = { ... }; "alpha" = { ... }; } + + # Optional: Hardware type (defaults to prefix name) + type = "nix-desktop"; + + # Optional: System architecture + system = "x86_64-linux"; + + # Optional: Configuration applied to ALL devices in this group + overrides = { + athenix.users.student.enable = true; + }; + + # Optional: Per-device configuration + "device-suffix" = { ... }; + }; +} +``` + +## Hostname Generation + +Hostnames are generated automatically based on the device key: + +- **Numeric keys** (`"1"`, `"2"`, `"42"`) → no dash: `prefix1`, `prefix2`, `prefix42` +- **Non-numeric keys** (`"alpha"`, `"special"`) → with dash: `prefix-alpha`, `prefix-special` +- **Custom hostnames** → Set `athenix.host.useHostPrefix = false` to use the suffix as the full hostname (no prefix) + +**Examples:** + +```nix +nix-laptop = { + devices = 3; # Generates: nix-laptop1, nix-laptop2, nix-laptop3 +}; + +nix-surface = { + devices = { + "1" = { }; # → nix-surface1 + "special" = { }; # → nix-surface-special + }; +}; + +custom-machine = { + devices."lab-machine" = { + athenix.host.useHostPrefix = false; # → lab-machine (not custom-machine-lab-machine) + }; +}; +``` + +## Configuration Methods + +### Method 1: Simple Count + +Create N identical hosts: + +```nix +nix-laptop = { + devices = 5; +}; +# Generates: nix-laptop1, nix-laptop2, nix-laptop3, nix-laptop4, nix-laptop5 +``` + +### Method 2: Simple Count with Overrides + +Create N hosts with common configuration: + +```nix +nix-desktop = { + devices = 3; + overrides = { + athenix.users.student.enable = true; + athenix.sw.extraPackages = with pkgs; [ vim git ]; + services.openssh.enable = true; + }; +}; +# All three hosts get the overrides configuration +``` + +### Method 3: Explicit Device Map + +Configure each device individually: + +```nix +nix-surface = { + devices = { + "1".athenix.sw.kioskUrl = "https://dashboard1.example.com"; + "2".athenix.sw.kioskUrl = "https://dashboard2.example.com"; + "3" = { + athenix.sw.kioskUrl = "https://dashboard3.example.com"; + services.openssh.enable = false; + }; + }; +}; +``` + +### Method 4: External Module + +Reference a Git repository using the `external` field (lazy evaluation): + +```nix +nix-lxc = { + devices."builder".external = builtins.fetchGit { + url = "https://git.factory.uga.edu/org/builder-config"; + rev = "abc123..."; + }; +}; +``` + +### Method 5: Mixed Approach + +Combine default count, custom devices, and overrides: + +```nix +nix-lab = { + defaultCount = 5; # Creates nix-lab1 through nix-lab5 + devices = { + "special" = { + athenix.sw.extraPackages = with pkgs; [ special-software ]; + }; + }; + overrides = { + # Applied to all devices (default count + custom) + athenix.users.lab-admin.enable = true; + }; +}; +``` + +## Options + +### Top-Level Device Options + +#### `devices` + +Specify hosts to create. Can be: +- **Number**: Create N hosts with keys `"1"`, `"2"`, ..., `"N"` +- **Attribute set**: Map of device names to configurations + +**Type**: `int | attrs` + +**Examples:** +```nix +devices = 5; # Creates 5 hosts + +devices = { + "1" = { }; + "alpha" = { }; +}; +``` + +#### `defaultCount` + +When using a device map, also create N numbered hosts. + +**Type**: `int` (optional) + +**Example:** +```nix +defaultCount = 3; # Creates "1", "2", "3" in addition to devices map +devices = { + "special" = { }; +}; +# Result: hosts "1", "2", "3", and "special" +``` + +#### `type` + +Hardware type module to use. Defaults to the prefix name (inferred from top-level key). + +**Type**: `string` (optional) + +**Options**: `nix-desktop`, `nix-laptop`, `nix-surface`, `nix-lxc`, `nix-wsl`, `nix-ephemeral` + +**Example:** +```nix +lab-machines = { + type = "nix-desktop"; # Use desktop hardware configuration + devices = 5; +}; +``` + +#### `system` + +System architecture. Defaults to `x86_64-linux`. + +**Type**: `string` (optional) + +**Example:** +```nix +arm-devices = { + system = "aarch64-linux"; + devices = 2; +}; +``` + +#### `overrides` + +Configuration applied to all devices in this group. Useful for fleet-wide settings. + +**Type**: `attrs` (optional) + +**Example:** +```nix +nix-laptop = { + devices = 10; + overrides = { + # Applied to all 10 laptops + athenix.users.staff.enable = true; + services.openssh.enable = true; + boot.loader.timeout = 10; + }; +}; +``` + +### Per-Device Options + +Any NixOS or `athenix.*` option can be set per-device: + +```nix +nix-surface = { + devices = { + "1" = { + # athenix.* namespace options + athenix.users.student.enable = true; + athenix.host.filesystem.device = "/dev/sda"; + athenix.host.filesystem.swapSize = "16G"; + athenix.sw.kioskUrl = "https://dashboard1.example.com"; + athenix.sw.extraPackages = with pkgs; [ firefox ]; + + # Standard NixOS options + networking.firewall.enable = false; + services.openssh.enable = true; + time.timeZone = "America/New_York"; + boot.kernelPackages = pkgs.linuxPackages_latest; + }; + }; +}; +``` + +### Convenience: `athenix.forUser` + +Quick setup for single-user systems (especially WSL). This automatically enables a user and sets the WSL default user: + +```nix +nix-wsl = { + devices = { + "alice".athenix.forUser = "alice-username"; + }; +}; +``` + +This automatically enables the user account. + +### External System Configuration + +For complex configurations, use external modules (see [EXTERNAL_MODULES.md](../EXTERNAL_MODULES.md)): + +```nix +nix-lxc = { + devices = { + "special-server" = builtins.fetchGit { + url = "https://git.factory.uga.edu/org/server-config"; + rev = "abc123..."; + }; + }; +}; +``` + +## Examples + +### Simple Lab Computers + +```nix +nix-laptop = { + devices = 10; # Creates nix-laptop1 through nix-laptop10 + overrides = { + athenix.users.student.enable = true; + }; +}; +``` + +### Mixed Surface Tablets + +```nix +nix-surface = { + defaultCount = 5; # nix-surface1 through nix-surface5 (default config) + devices = { + "admin" = { # nix-surface-admin (special config) + athenix.sw.type = "desktop"; # Full desktop instead of kiosk + athenix.users.admin.enable = true; + }; + }; + overrides = { + athenix.sw.type = "tablet-kiosk"; + athenix.sw.kioskUrl = "https://dashboard.factory.uga.edu"; + }; +}; +``` + +### LXC Containers + +```nix +nix-lxc = { + devices = { + "nix-builder" = { + athenix.sw.type = "headless"; + }; + "webserver" = { + athenix.sw.type = "headless"; + services.nginx.enable = true; + }; + }; + overrides = { + athenix.host.useHostPrefix = false; # Use exact device key as hostname + }; +}; +``` + +### WSL Instances + +```nix +nix-wsl = { + devices = { + "alice".athenix.forUser = "alice-uga"; + "bob".athenix.forUser = "bob-uga"; + }; +}; +``` + +## See Also + +- [USER_CONFIGURATION.md](USER_CONFIGURATION.md) - User account management +- [EXTERNAL_MODULES.md](EXTERNAL_MODULES.md) - External configuration modules +- [Configuration Namespace Reference](NAMESPACE.md) - All `athenix.*` options diff --git a/Namespace.md b/Namespace.md new file mode 100644 index 0000000..6c55c7d --- /dev/null +++ b/Namespace.md @@ -0,0 +1,391 @@ +# Configuration Namespace Reference + +All UGA Innovation Factory-specific options are in the `athenix` namespace to avoid conflicts with standard NixOS options. + +## Table of Contents + +- [Host Configuration (`athenix.host`)](#host-configuration-athenixhost) +- [Software Configuration (`athenix.sw`)](#software-configuration-athenixsw) +- [User Management (`athenix.users`)](#user-management-athenixusers) +- [Convenience Options](#convenience-options) + +## Host Configuration (`athenix.host`) + +Hardware and boot-related settings. + +### `athenix.host.filesystem.device` + +Boot disk device path. + +**Type:** String or null + +**Default:** `null` (must be set by hardware type or per-host) + +**Example:** +```nix +athenix.host.filesystem.device = "/dev/nvme0n1"; +``` + +### `athenix.host.filesystem.swapSize` + +Swap partition size. + +**Type:** String (size with unit, e.g., `"32G"`, `"2G"`) or null + +**Default:** `null` (must be set by hardware type or per-host) + +**Example:** +```nix +athenix.host.filesystem.swapSize = "64G"; +``` + +### `athenix.host.buildMethods` + +Artifact types to build for this host. + +**Type:** List of strings + +**Options:** `"installer-iso"`, `"iso"`, `"ipxe"`, `"lxc"`, `"proxmox"` + +**Default:** `[ "installer-iso" ]` + +**Description:** +- `"installer-iso"` - Installer ISO with auto-install +- `"iso"` - Live ISO (boot without installation) +- `"ipxe"` - iPXE netboot artifacts +- `"lxc"` - LXC container tarball +- `"proxmox"` - Proxmox VMA template + +**Example:** +```nix +athenix.host.buildMethods = [ "installer-iso" "lxc" ]; +``` + +### `athenix.host.useHostPrefix` + +Whether to prepend the host type prefix to the generated hostname. + +**Type:** Boolean + +**Default:** `true` + +**Example:** +```nix +# With useHostPrefix = true (default) +# Device "1" under "nix-laptop" → "nix-laptop1" + +# With useHostPrefix = false +# Device "builder" under "nix-lxc" → "builder" (not "nix-lxc-builder") +athenix.host.useHostPrefix = false; +``` + +### `athenix.host.wsl.user` + +Default WSL user account (only for `nix-wsl` type). + +**Type:** String (username) + +**Example:** +```nix +athenix.host.wsl.user = "myusername"; +``` + +## Software Configuration (`athenix.sw`) + +System type, packages, and application configuration. + +### `athenix.sw.enable` + +Enable software configuration. + +**Type:** Boolean + +**Default:** `true` + +### `athenix.sw.type` + +System profile/type. Determines which software packages and services are installed. + +**Type:** String or list of strings + +**Options:** +- `"desktop"` - Full GNOME desktop environment with development tools +- `"tablet-kiosk"` - Surface tablets with Firefox kiosk browser +- `"stateless-kiosk"` - Diskless PXE-booted ephemeral systems +- `"headless"` - Servers and containers without GUI +- `"builders"` - Build servers with build dependencies + +**Default:** `"desktop"` + +**Example:** +```nix +athenix.sw.type = "desktop"; + +# Multiple types supported +athenix.sw.type = [ "desktop" "headless" ]; +``` + +### `athenix.sw.kioskUrl` + +URL to display in kiosk browser (for `tablet-kiosk` and `stateless-kiosk` types). + +**Type:** String (URL) + +**Default:** `"https://ha.factory.uga.edu"` + +**Example:** +```nix +athenix.sw.kioskUrl = "https://dashboard.example.com"; +``` + +### `athenix.sw.python.enable` + +Enable Python development tools (pixi, uv, etc.). + +**Type:** Boolean + +**Default:** `true` + +**Example:** +```nix +athenix.sw.python.enable = true; +``` + +### `athenix.sw.remoteBuild` + +Configure remote build servers for offloading builds. + +**Type:** Attribute set + +**Options:** +- `enable` - Enable remote builders (Boolean, default: `true` for tablets) +- `hosts` - List of remote builder hostnames (List of strings) + +**Example:** +```nix +athenix.sw.remoteBuild = { + enable = true; + hosts = [ "nix-builder" "nix-builder2" ]; +}; +``` + +### `athenix.sw.extraPackages` + +Additional system packages beyond the type defaults. + +**Type:** List of packages + +**Default:** `[ ]` + +**Example:** +```nix +athenix.sw.extraPackages = with pkgs; [ + vim + docker + htop + ripgrep +]; +``` + +### `athenix.sw.excludePackages` + +Packages to remove from the default list for this system type. + +**Type:** List of packages + +**Default:** `[ ]` + +**Example:** +```nix +athenix.sw.excludePackages = with pkgs; [ + firefox # Don't install Firefox on this system +]; +``` + +## User Management (`athenix.users`) + +User account configuration and access control. + +### `athenix.users..enable` + +Enable a user account on this system. + +**Type:** Boolean + +**Default:** `false` (except `root` and `engr-ugaif` which are `true`) + +**Example:** +```nix +# In inventory.nix +nix-laptop = { + devices = 5; + overrides.athenix.users.myuser.enable = true; +}; +``` + +### User Account Options (in `users.nix`) + +Define user accounts in `users.nix` with these options: + +#### `description` + +Full name or description of the user. + +**Type:** String + +```nix +athenix.users.myuser.description = "John Doe"; +``` + +#### `extraGroups` + +Additional Unix groups for the user. + +**Type:** List of strings + +**Common groups:** +- `"wheel"` - Sudo access +- `"networkmanager"` - Network configuration +- `"docker"` - Docker access +- `"video"` - Video device access +- `"audio"` - Audio device access +- `"input"` - Input device access (keyboards, mice) + +```nix +athenix.users.myuser.extraGroups = [ "wheel" "docker" "networkmanager" ]; +``` + +#### `shell` + +Login shell for the user. + +**Type:** Package + +**Default:** `pkgs.bash` + +```nix +athenix.users.myuser.shell = pkgs.zsh; +``` + +#### `hashedPassword` + +Password hash for the user. + +**Type:** String (SHA-512 hash) + +**Generation:** +```bash +mkpasswd -m sha-512 +``` + +```nix +athenix.users.myuser.hashedPassword = "$6$..."; +``` + +#### `opensshKeys` + +SSH public keys for this user. + +**Type:** List of strings + +```nix +athenix.users.myuser.opensshKeys = [ + "ssh-ed25519 AAAA... user@host" + "ssh-rsa AAAA... user@other" +]; +``` + +#### `useZshTheme` + +Apply system Zsh theme configuration to this user. + +**Type:** Boolean + +**Default:** `true` + +```nix +athenix.users.myuser.useZshTheme = true; +``` + +#### `useNvimPlugins` + +Apply system Neovim configuration to this user. + +**Type:** Boolean + +**Default:** `true` + +```nix +athenix.users.myuser.useNvimPlugins = true; +``` + +#### `external` + +Reference external user configuration (dotfiles, home-manager). + +**Type:** Path or Git reference + +**Example:** +```nix +athenix.users.myuser.external = builtins.fetchGit { + url = "https://git.factory.uga.edu/username/dotfiles"; + rev = "abc123..."; +}; +``` + +See [EXTERNAL_MODULES.md](EXTERNAL_MODULES.md) for detailed external module usage. + +### Enabling Users on Systems + +Users defined in `users.nix` are **not enabled by default**. Enable them in `inventory.nix`: + +```nix +# Option 1: Enable on all devices in a group +nix-laptop = { + devices = 5; + overrides.athenix.users.student.enable = true; +}; + +# Option 2: Enable on specific devices +nix-surface = { + devices = { + "1".athenix.users.admin.enable = true; + "2".athenix.users.admin.enable = true; + }; +}; +``` + +## Convenience Options + +### `athenix.forUser` + +Quick setup for single-user systems. Automatically enables a user and sets it as the default. + +**Type:** String (username) or null + +**Default:** `null` + +**Example:** +```nix +# In inventory.nix - enables the user automatically +nix-wsl = { + devices = { + "alice".athenix.forUser = "alice-uga"; + }; +}; +``` + +Equivalent to: +```nix +"alice" = { + athenix.users.alice-uga.enable = true; + athenix.host.wsl.user = "alice-uga"; +}; +``` + +## See Also + +- [INVENTORY.md](INVENTORY.md) - Host configuration examples +- [USER_CONFIGURATION.md](USER_CONFIGURATION.md) - User account management guide +- [EXTERNAL_MODULES.md](EXTERNAL_MODULES.md) - External module integration +- [README.md](../README.md) - Main documentation diff --git a/User-Configuration.md b/User-Configuration.md new file mode 100644 index 0000000..362ded1 --- /dev/null +++ b/User-Configuration.md @@ -0,0 +1,993 @@ +# User Configuration Guide + +Comprehensive guide to managing user accounts in Athenix. + +## Table of Contents + +- [Overview](#overview) +- [Quick Start](#quick-start) +- [Defining Users](#defining-users) +- [Enabling Users on Hosts](#enabling-users-on-hosts) +- [External User Configurations](#external-user-configurations) +- [Password Management](#password-management) +- [SSH Keys](#ssh-keys) +- [User Groups](#user-groups) +- [Examples](#examples) + +## Overview + +User accounts are defined in `users.nix` but are **not enabled by default**. Each host must explicitly enable users in `inventory.nix`. + +**Always-enabled users:** +- `root` - System administrator (enable: true) +- `engr-ugaif` - Innovation Factory default account (enable: true) + +All other users are disabled by default and must be explicitly enabled per-host. + +## Quick Start + +### 1. Define User in users.nix + +```nix +athenix.users.myuser = { + description = "John Doe"; + extraGroups = [ "wheel" "networkmanager" ]; + shell = pkgs.zsh; + hashedPassword = "$6$..."; # Generate with: mkpasswd -m sha-512 + opensshKeys = [ "ssh-ed25519 AAAA..." ]; +}; +``` + +### 2. Enable on Hosts in inventory.nix + +```nix +nix-laptop = { + devices = 5; + overrides.athenix.users.myuser.enable = true; +}; +``` + +### 3. Users can now log in + +Users defined and enabled this way are automatically created on the system. + +## Defining Users + +Define users in `users.nix` under `athenix.users`: + +### Inline User Definition + +```nix +athenix.users.myuser = { + description = "My Full Name"; + extraGroups = [ "wheel" "networkmanager" ]; + shell = pkgs.zsh; + hashedPassword = "$6$..."; + opensshKeys = [ "ssh-ed25519 AAAA..." ]; + useZshTheme = true; + useNvimPlugins = true; +}; +``` + +### External User Configuration + +Reference an external Git repository (recommended for personal dotfiles): + +```nix +athenix.users.myuser.external = builtins.fetchGit { + url = "https://git.factory.uga.edu/username/dotfiles"; + rev = "abc123..."; # Pin to specific commit +}; +``` + +The external repository should contain: +- `user.nix` (required) - User account options AND home-manager configuration +- `nixos.nix` (optional) - System-level configuration + +See [External User Configurations](#external-user-configurations) section below. + +## User Account Options + +### `description` + +Full name or description of the user. + +**Type:** String + +```nix +athenix.users.myuser.description = "John Doe"; +``` + +### `extraGroups` + +Additional Unix groups for the user. Default is empty. + +**Type:** List of strings + +**Common groups:** +- `"wheel"` - Sudo access +- `"networkmanager"` - Network configuration +- `"docker"` - Docker and Podman access +- `"video"` - Video device access (GPU, displays) +- `"audio"` - Audio device access +- `"input"` - Input devices (keyboards, mice) +- `"kvm"` - KVM virtual machine access +- `"libvirtd"` - Libvirt daemon access + +```nix +athenix.users.myuser.extraGroups = [ + "wheel" + "networkmanager" + "docker" + "video" +]; +``` + +### `shell` + +Login shell for the user. + +**Type:** Package + +**Default:** `pkgs.bash` + +```nix +athenix.users.myuser.shell = pkgs.zsh; +# or +athenix.users.myuser.shell = pkgs.fish; +``` + +### `hashedPassword` + +Password hash for the user. Use `!` to disable password login (SSH keys only). + +**Type:** String (SHA-512 hash) + +**Generation:** +```bash +# Generate a hashed password +mkpasswd -m sha-512 + +# Or interactively +mkpasswd -m sha-512 -c +``` + +```nix +athenix.users.myuser.hashedPassword = "$6$..."; + +# Disable password login (require SSH keys) +athenix.users.myuser.hashedPassword = "!"; +``` + +### `opensshKeys` + +SSH public keys for remote access. Users without SSH keys require password login. + +**Type:** List of strings + +```nix +athenix.users.myuser.opensshKeys = [ + "ssh-ed25519 AAAA... user@laptop" + "ssh-rsa AAAA... user@desktop" +]; +``` + +**Getting your SSH public key:** +```bash +# Print your public key +cat ~/.ssh/id_ed25519.pub + +# Generate a new key if needed +ssh-keygen -t ed25519 -C "user@host" +``` + +### `useZshTheme` + +Apply system Zsh theme configuration to this user (if using Zsh as shell). + +**Type:** Boolean + +**Default:** `true` + +```nix +athenix.users.myuser.useZshTheme = true; +``` + +### `useNvimPlugins` + +Apply system Neovim configuration and plugins to this user. + +**Type:** Boolean + +**Default:** `true` + +```nix +athenix.users.myuser.useNvimPlugins = true; +``` + +## Enabling Users on Hosts + +Users are **not enabled by default**. Enable them in `inventory.nix`: + +### Enable on All Devices in a Group + +```nix +nix-laptop = { + devices = 5; + overrides.athenix.users.myuser.enable = true; +}; +``` + +### Enable on Specific Devices + +```nix +nix-desktop = { + devices = { + "1".athenix.users.admin.enable = true; + "2".athenix.users.staff.enable = true; + "3".athenix.users.staff.enable = true; + }; +}; +``` + +### Enable Multiple Users + +```nix +nix-laptop = { + devices = 5; + overrides = { + athenix.users.student.enable = true; + athenix.users.teacher.enable = true; + }; +}; +``` + +### Using `athenix.forUser` Convenience + +Quick setup for single-user systems (especially WSL): + +```nix +nix-wsl = { + devices = { + "alice".athenix.forUser = "alice-uga"; + "bob".athenix.forUser = "bob-uga"; + }; +}; +``` + +This automatically enables the user and sets it as the default WSL user. + +## External User Configurations + +External user configurations (dotfiles) allow users to maintain their own home-manager setup in separate repositories. + +### Repository Structure + +``` +my-dotfiles/ +├── user.nix # Required: User options + home-manager config +├── nixos.nix # Optional: System-level configuration +└── config/ # Optional: Your actual dotfiles + ├── bashrc + ├── zshrc + ├── vimrc + └── ... +``` + +### user.nix (Required) + +This file must provide BOTH user account options AND home-manager configuration: + +```nix +{ inputs, ... }: +{ config, lib, pkgs, osConfig ? null, ... }: +{ + # ========== User Account Configuration ========== + # These options define the user account itself + athenix.users.myusername = { + description = "My Full Name"; + extraGroups = [ "wheel" "docker" "networkmanager" ]; + shell = pkgs.zsh; + hashedPassword = "!"; # SSH keys only + opensshKeys = [ + "ssh-ed25519 AAAA... user@host" + ]; + useZshTheme = true; + useNvimPlugins = true; + }; + + # ========== Home Manager Configuration ========== + # User environment, packages, and dotfiles + + home.packages = with pkgs; [ + vim + ripgrep + fzf + ] ++ 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"; + core.editor = "vim"; + }; + }; + + programs.zsh = { + enable = true; + initExtra = '' + # Your Zsh configuration + ''; + }; + + # Manage dotfiles + home.file.".config/zshrc".source = ./config/zshrc; + home.file.".config/bashrc".source = ./config/bashrc; + home.file.".vimrc".source = ./config/vimrc; +} +``` + +### nixos.nix (Optional) + +System-level configuration for this user (rarely needed): + +```nix +{ inputs, ... }: +{ config, lib, pkgs, ... }: +{ + # System-level configuration for this user + users.users.myusername.extraGroups = [ "docker" ]; + environment.systemPackages = [ pkgs.docker ]; +} +``` + +### Using External User Configuration + +In `users.nix`: + +```nix +athenix.users.myuser.external = builtins.fetchGit { + url = "https://git.factory.uga.edu/username/dotfiles"; + rev = "abc123..."; # Pin to specific commit +}; +``` + +Then enable on hosts in `inventory.nix`: + +```nix +nix-laptop = { + devices = 5; + overrides.athenix.users.myuser.enable = true; +}; +``` + +### External Module Parameters + +The `user.nix` module receives: + +- **`inputs`** - All flake inputs (nixpkgs, home-manager, etc.) +- **`config`** - Home-manager configuration +- **`lib`** - Nixpkgs library functions +- **`pkgs`** - Package set +- **`osConfig`** - OS-level configuration (read-only, can be used for conditional setup) + +### Creating External User Configuration + +Use the template: + +```bash +nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#user +``` + +## Password Management + +### Generate Password Hash + +```bash +# Interactive (won't echo) +mkpasswd -m sha-512 -c + +# From string +echo "mypassword" | mkpasswd -m sha-512 -s +``` + +### Disable Password Login + +Set `hashedPassword = "!"` and provide SSH keys: + +```nix +athenix.users.myuser = { + description = "SSH-only user"; + hashedPassword = "!"; + opensshKeys = [ "ssh-ed25519 AAAA..." ]; +}; +``` + +### Update User Password on Running System + +```bash +# As the user +passwd + +# As root (to change another user's password) +sudo passwd username +``` + +## SSH Keys + +### Add SSH Keys to a User + +```nix +athenix.users.myuser.opensshKeys = [ + "ssh-ed25519 AAAA... user@laptop" + "ssh-ed25519 BBBB... user@desktop" +]; +``` + +### Get Your SSH Public Key + +```bash +# Display your public key +cat ~/.ssh/id_ed25519.pub + +# Or for RSA +cat ~/.ssh/id_rsa.pub +``` + +### Generate New SSH Key + +```bash +# Ed25519 (recommended) +ssh-keygen -t ed25519 -C "user@host" + +# RSA (older systems) +ssh-keygen -t rsa -b 4096 -C "user@host" +``` + +## User Groups + +### wheel + +Allows passwordless sudo access. + +```nix +athenix.users.myuser.extraGroups = [ "wheel" ]; +``` + +### networkmanager + +Configure network connections (requires `networkmanager` to be enabled): + +```nix +athenix.users.myuser.extraGroups = [ "networkmanager" ]; +``` + +### docker + +Access Docker daemon (must have Docker enabled on system): + +```nix +athenix.users.myuser.extraGroups = [ "docker" ]; +``` + +### video and audio + +Access GPU and audio devices: + +```nix +athenix.users.myuser.extraGroups = [ "video" "audio" ]; +``` + +## Examples + +### Example 1: Basic Lab User + +```nix +# users.nix +athenix.users.student = { + description = "Student Account"; + extraGroups = [ "networkmanager" ]; + shell = pkgs.bash; + hashedPassword = "$6$..."; + opensshKeys = []; # Password login only +}; + +# inventory.nix +nix-laptop = { + devices = 20; + overrides.athenix.users.student.enable = true; +}; +``` + +### Example 2: Developer with SSH Keys + +```nix +# users.nix +athenix.users.developer = { + description = "Developer"; + extraGroups = [ "wheel" "docker" "networkmanager" ]; + shell = pkgs.zsh; + hashedPassword = "!"; + opensshKeys = [ + "ssh-ed25519 AAAA... dev@laptop" + ]; + useZshTheme = true; + useNvimPlugins = true; +}; + +# inventory.nix +nix-desktop = { + devices = 3; + overrides.athenix.users.developer.enable = true; +}; +``` + +### Example 3: WSL User with Dotfiles + +```nix +# users.nix +athenix.users.alice.external = builtins.fetchGit { + url = "https://git.factory.uga.edu/alice/dotfiles"; + rev = "abc123..."; +}; + +# inventory.nix +nix-wsl = { + devices = { + "alice".athenix.forUser = "alice-uga"; + }; +}; +``` + +### Example 4: Multiple Users on Single System + +```nix +# users.nix +athenix.users = { + admin = { + description = "System Administrator"; + extraGroups = [ "wheel" ]; + shell = pkgs.bash; + hashedPassword = "!"; + opensshKeys = [ "ssh-ed25519 AAAA..." ]; + }; + guest = { + description = "Guest User"; + extraGroups = []; + shell = pkgs.bash; + hashedPassword = "$6$..."; + }; +}; + +# inventory.nix +nix-desktop = { + devices = { + "admin-station" = { + athenix.users.admin.enable = true; + }; + "guest-station" = { + athenix.users.guest.enable = true; + }; + }; +}; +``` + +## See Also + +- [INVENTORY.md](INVENTORY.md) - Host configuration +- [NAMESPACE.md](NAMESPACE.md) - All configuration options +- [EXTERNAL_MODULES.md](EXTERNAL_MODULES.md) - External modules in detail +- [README.md](../README.md) - Main documentation + 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`: + +```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):** +```nix +{ 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):** +```nix +{ 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.` 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):** +```nix +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 + +```bash +nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#user +``` + +See [templates/user/README.md](../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 +nix-laptop = { + devices = 5; + overrides = { + athenix.users.student.enable = true; # All 5 laptops get this user + }; +}; +``` + +### Method 2: Enable per Device + +```nix +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 +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 + +```bash +mkpasswd -m sha-512 +# Enter password when prompted +# Copy the output hash +``` + +### In users.nix + +```nix +myuser = { + hashedPassword = "$6$rounds=656000$..."; # Paste hash here +}; +``` + +### Disable Password Login + +```nix +myuser = { + hashedPassword = "!"; # Locks password, SSH key only + opensshKeys = [ "ssh-ed25519 ..." ]; +}; +``` + +### Change Password Later + +On the system: +```bash +sudo passwd myuser +``` + +Or regenerate hash and update `users.nix`. + +## SSH Keys + +### Adding SSH Keys + +```nix +myuser = { + opensshKeys = [ + "ssh-ed25519 AAAAC3Nza... user@laptop" + "ssh-rsa AAAAB3NzaC1... user@desktop" + ]; +}; +``` + +### Generate SSH Key + +```bash +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: + +```nix +opensshKeys = [ + "ssh-ed25519 ... user@work-laptop" + "ssh-ed25519 ... user@home-desktop" + "ssh-ed25519 ... user@tablet" +]; +``` + +## Examples + +### Basic User + +```nix +student = { + description = "Student Account"; + extraGroups = [ "networkmanager" ]; + shell = pkgs.bash; + hashedPassword = "$6$..."; +}; +``` + +### Admin User with SSH + +```nix +admin = { + description = "System Administrator"; + extraGroups = [ "wheel" "networkmanager" "docker" ]; + shell = pkgs.zsh; + hashedPassword = "$6$..."; + opensshKeys = [ + "ssh-ed25519 AAAA... admin@laptop" + ]; +}; +``` + +### User with External Configuration + +```nix +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 + +```nix +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 +nix-wsl = { + devices."my-wsl".athenix.forUser = "wsl-user"; +}; +``` + +### User Without System Themes + +For users who want complete control over their shell/editor: + +```nix +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:** +```bash +nix eval .#nixosConfigurations.nix-laptop1.config.athenix.users.myuser.enable +``` + +**Check if user exists:** +```bash +# On the system +id myuser +``` + +### SSH Key Not Working + +**Check key in configuration:** +```bash +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:** +```bash +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:** +```nix +external = /path/to/local/dotfiles; +``` + +## See Also + +- [EXTERNAL_MODULES.md](EXTERNAL_MODULES.md) - External module guide +- [INVENTORY.md](INVENTORY.md) - Host configuration guide +- [NAMESPACE.md](NAMESPACE.md) - Configuration options reference +- [templates/user/](../templates/user/) - User module template +- [README.md](../README.md) - Main documentation