UGA Innovation Factory e6e96bd315 update usda-dash commit
2025-12-16 17:50:05 -05:00
2025-12-16 16:09:08 -05:00
2025-12-16 17:30:33 -05:00
2025-12-16 16:10:49 -05:00
2025-12-11 17:42:17 -05:00
2025-12-16 16:48:21 -05:00
2025-12-16 17:50:05 -05:00
2025-12-16 16:20:42 -05:00
2025-12-16 16:09:08 -05:00

UGA Innovation Factory - NixOS Systems

This repository contains the NixOS configuration for the Innovation Factory's fleet of laptops, desktops, surface tablets, and containers. It provides a declarative, reproducible system configuration using Nix flakes.

Table of Contents

Quick Start

For End Users: Updating Your System

Update your system to the latest configuration from GitHub:

update-system

This command automatically:

  • Fetches the latest configuration
  • Rebuilds your system
  • Uses remote builders on Surface tablets to speed up builds

Note: If you use external user configurations (personal dotfiles), run sudo nixos-rebuild switch --flake github:UGA-Innovation-Factory/nixos-systems --impure instead.

For Administrators: Applying Configuration Changes

  1. Make changes to configuration files
  2. Test the configuration builds:
    nix flake check
    
  3. Commit and push changes:
    git add .
    git commit -m "Description of changes"
    git push
    
  4. Users can now run update-system to get the changes

Repository Structure

nixos-systems/
├── flake.nix           # Flake entry point with inputs/outputs
├── inventory.nix       # Fleet inventory (hosts, types, counts)
├── users.nix           # User account definitions
├── hosts/              # Host generation logic and hardware types
│   ├── default.nix     # Core host generation functions
│   ├── types/          # Hardware type definitions
│   │   ├── nix-desktop.nix
│   │   ├── nix-laptop.nix
│   │   ├── nix-surface.nix
│   │   ├── nix-lxc.nix
│   │   ├── nix-wsl.nix
│   │   └── nix-ephemeral.nix
│   └── user-config.nix # User configuration integration
├── sw/                 # Software configurations by system type
│   ├── desktop/        # Desktop system software
│   ├── tablet-kiosk/   # Surface tablet kiosk mode
│   ├── stateless-kiosk/# Stateless kiosk systems
│   ├── headless/       # Headless server systems
│   ├── ghostty.nix     # Ghostty terminal emulator
│   ├── nvim.nix        # Neovim configuration
│   ├── python.nix      # Python development tools
│   ├── theme.nix       # UI theme configuration
│   └── updater.nix     # System update service
├── installer/          # Build artifact generation
│   ├── artifacts.nix   # ISO, LXC, Proxmox builds
│   ├── auto-install.nix # Automated installer
│   └── modules.nix     # Exported modules
├── templates/          # Templates for external configs
│   ├── system/         # System configuration template
│   └── user/           # User configuration template
└── assets/             # Assets (Plymouth theme, etc.)

Configuration Namespace

All UGA Innovation Factory-specific options are under the ugaif namespace:

ugaif.host - Hardware Configuration

  • ugaif.host.filesystem: Disk device and swap size settings
    • ugaif.host.filesystem.device - Boot disk device (default: /dev/sda)
    • ugaif.host.filesystem.swapSize - Swap file size (default: "32G")
  • ugaif.host.buildMethods: List of supported artifact types (["iso"], ["lxc", "proxmox"], etc.)
  • ugaif.host.useHostPrefix: Whether to prepend type prefix to hostname (default: true)
  • ugaif.host.wsl: WSL-specific configuration
    • ugaif.host.wsl.user - Default WSL user

ugaif.sw - Software Configuration

  • ugaif.sw.enable: Enable software configuration module (default: true)
  • ugaif.sw.type: System type - "desktop", "tablet-kiosk", "stateless-kiosk", or "headless"
  • ugaif.sw.kioskUrl: URL for kiosk mode browsers
  • ugaif.sw.python: Python development tools configuration
    • ugaif.sw.python.enable - Enable Python tools (pixi, uv)
  • ugaif.sw.remoteBuild: Remote build configuration
    • ugaif.sw.remoteBuild.enable - Use remote builders (default: enabled on tablets)
    • ugaif.sw.remoteBuild.hosts - List of build servers
  • ugaif.sw.extraPackages: Additional system packages to install

ugaif.users - User Management

  • ugaif.users.accounts: Attrset of user definitions with account settings
  • ugaif.users.enabledUsers: List of users to enable on this system (default: ["root", "engr-ugaif"])
  • ugaif.forUser: Convenience option to set up a system for a specific user (sets enabledUsers and wslUser)

Prerequisites

To work with this repository, install Nix with flakes support:

# Recommended: Determinate Systems installer (includes flakes)
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install

# Alternative: Official installer (requires enabling flakes)
sh <(curl -L https://nixos.org/nix/install) --daemon

User Management

Understanding User Configuration

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

Default enabled users on all systems:

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

Adding a New User

  1. Edit users.nix and add a new user:
ugaif.users.accounts = {
  # ... existing users ...
  
  myuser = {
    description = "My Full Name";
    extraGroups = [ "networkmanager" "wheel" ];
    shell = pkgs.zsh;  # or pkgs.bash, pkgs.fish
    hashedPassword = "$6$...";  # Generate with: mkpasswd -m sha-512
    opensshKeys = [
      "ssh-ed25519 AAAA... user@machine"
    ];
    # enable = false;  # Will be enabled per-system in inventory.nix
  };
};
  1. Generate a hashed password:
mkpasswd -m sha-512  # Enter password when prompted
  1. Enable the user on specific hosts in inventory.nix:
nix-laptop = {
  devices = 2;
  overrides.extraUsers = [ "myuser" ];  # Enables on all nix-laptop hosts
};

# Or for individual devices:
nix-desktop = {
  devices = {
    "1".extraUsers = [ "myuser" "otheruser" ];
  };
};

User Configuration Options

Each user in users.nix can have:

myuser = {
  description = "Full Name";              # User's full name
  isNormalUser = true;                    # Default: true
  extraGroups = [ ... ];                  # Additional groups (wheel, docker, etc.)
  shell = pkgs.zsh;                       # Login shell
  hashedPassword = "$6$...";              # Hashed password
  opensshKeys = [ "ssh-ed25519 ..." ];    # SSH public keys
  homePackages = with pkgs; [ ... ];      # Home-manager packages (if no external config)
  useZshTheme = true;                     # Use system Zsh theme (default: true)
  useNvimPlugins = true;                  # Use system Neovim config (default: true)
  
  # External home-manager configuration (optional)
  home = builtins.fetchGit {
    url = "https://github.com/username/dotfiles";
    rev = "abc123...";
  };
};

External User Configuration

Users can maintain their dotfiles and home-manager configuration in separate repositories. See External Modules and USER_CONFIGURATION.md for details.

Quick example:

myuser = {
  description = "My Name";
  home = builtins.fetchGit {
    url = "https://github.com/username/dotfiles";
    rev = "commit-hash";
  };
};

The external repository should contain:

  • home.nix (required) - Home-manager configuration
  • nixos.nix (optional) - System-level user configuration

Create a template:

nix flake init -t github:UGA-Innovation-Factory/nixos-systems#user

Host Configuration

Understanding Inventory Structure

The inventory.nix file defines all hosts in the fleet using a flexible system:

Hostname Generation Rules:

  • Numeric suffixes: no dash (e.g., nix-laptop1, nix-laptop2)
  • Non-numeric suffixes: with dash (e.g., nix-laptop-alpha, nix-laptop-beta)
  • Set ugaif.host.useHostPrefix = false to use suffix as full hostname

Adding Hosts

Method 1: Quick count (simplest)

nix-laptop = {
  devices = 5;  # Creates: nix-laptop1, nix-laptop2, ..., nix-laptop5
};

Method 2: Explicit count with overrides

nix-laptop = {
  devices = 5;
  overrides = {
    # Applied to ALL nix-laptop hosts
    extraUsers = [ "student" ];
    ugaif.sw.extraPackages = with pkgs; [ vim git ];
  };
};

Method 3: Individual device configuration

nix-surface = {
  devices = {
    "1".ugaif.sw.kioskUrl = "https://dashboard1.example.com";
    "2".ugaif.sw.kioskUrl = "https://dashboard2.example.com";
    "3".ugaif.sw.kioskUrl = "https://dashboard3.example.com";
  };
};

Method 4: Mixed (default count + custom devices)

nix-surface = {
  defaultCount = 2;  # Creates nix-surface1, nix-surface2
  devices = {
    "special" = {  # Creates nix-surface-special
      ugaif.sw.kioskUrl = "https://special-dashboard.example.com";
    };
  };
  overrides = {
    # Applied to all devices (including "special")
    ugaif.sw.kioskUrl = "https://default-dashboard.example.com";
  };
};

Device Configuration Options

Convenience shortcuts (automatically converted to proper options):

  • extraUsersugaif.users.enabledUsers
  • hostname → Custom hostname (overrides default naming)
  • buildMethodsugaif.host.buildMethods
  • wslUserugaif.host.wsl.user

Direct configuration (any NixOS or ugaif option):

"1" = {
  # Convenience
  extraUsers = [ "myuser" ];
  
  # UGAIF options
  ugaif.host.filesystem.swapSize = "64G";
  ugaif.sw.extraPackages = with pkgs; [ docker ];
  ugaif.sw.kioskUrl = "https://example.com";
  
  # Standard NixOS options
  networking.firewall.enable = false;
  services.openssh.enable = true;
  time.timeZone = "America/New_York";
};

Convenience: ugaif.forUser

Quick setup for single-user systems (especially WSL):

nix-wsl = {
  devices = {
    "alice".ugaif.forUser = "alice-username";
  };
};

This automatically:

  • Adds user to extraUsers (enables the account)
  • Sets ugaif.host.wsl.user to the username (for WSL)

External System Configuration

For complex configurations, use external modules. See External Modules and EXTERNAL_MODULES.md.

nix-lxc = {
  devices = {
    "special-server" = builtins.fetchGit {
      url = "https://github.com/org/server-config";
      rev = "abc123...";
    };
  };
};

Create a template:

nix flake init -t github:UGA-Innovation-Factory/nixos-systems#system

External Modules

External modules allow you to maintain user or system configurations in separate Git repositories and reference them from users.nix or inventory.nix.

Benefits

  • Separation: Keep configs in separate repositories
  • Versioning: Pin to specific commits for reproducibility
  • Reusability: Share configurations across deployments
  • Flexibility: Mix external modules with local overrides

Templates

Initialize a new external configuration:

# User configuration (home-manager, dotfiles)
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#user

# System configuration (services, packages, hardware)
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#system

User Module Example

In users.nix:

myuser = {
  description = "My Name";
  home = builtins.fetchGit {
    url = "https://github.com/username/dotfiles";
    rev = "abc123...";  # Pin to specific commit
  };
};

External repository structure:

dotfiles/
├── home.nix    # Required: Home-manager configuration
└── nixos.nix   # Optional: System-level user configuration

See USER_CONFIGURATION.md and templates/user/ for details.

System Module Example

In inventory.nix:

nix-lxc = {
  devices = {
    "custom-server" = builtins.fetchGit {
      url = "https://github.com/org/server-config";
      rev = "abc123...";
    };
  };
};

External repository structure:

server-config/
└── default.nix  # Required: NixOS module

See EXTERNAL_MODULES.md and templates/system/ for details.

Fetch Methods

Recommended: fetchGit with revision

builtins.fetchGit {
  url = "https://github.com/user/repo";
  rev = "abc123def456...";  # Full commit hash
  ref = "main";              # Optional: branch name
}

Local path (for testing)

/path/to/local/config

Tarball (for releases)

builtins.fetchTarball {
  url = "https://github.com/user/repo/archive/v1.0.0.tar.gz";
  sha256 = "sha256:...";
}

Building Artifacts

Build installation media and container images from this flake.

Installer ISOs

Build an auto-install ISO for a specific host:

# Build locally
nix build github:UGA-Innovation-Factory/nixos-systems#installer-iso-nix-laptop1

# Build using remote builder
nix build github:UGA-Innovation-Factory/nixos-systems#installer-iso-nix-laptop1 \
  --builders "ssh://engr-ugaif@nix-builder x86_64-linux"

Result: result/iso/nixos-*.iso

Available Artifacts

# List all available builds
nix flake show github:UGA-Innovation-Factory/nixos-systems

# Common artifacts:
nix build .#installer-iso-nix-laptop1    # Installer ISO
nix build .#iso-nix-ephemeral1           # Live ISO (no installer)
nix build .#ipxe-nix-ephemeral1          # iPXE netboot
nix build .#lxc-nix-builder              # LXC container tarball
nix build .#proxmox-nix-builder          # Proxmox VMA

Using Remote Builders

Speed up builds by offloading to a build server:

# In ~/.config/nix/nix.conf or /etc/nix/nix.conf:
builders = ssh://engr-ugaif@nix-builder x86_64-linux

# Or use --builders flag for one-time builds
nix build ... --builders "ssh://engr-ugaif@nix-builder x86_64-linux"

Development

Testing Configuration Changes

Before committing changes:

# Check all configurations build correctly
nix flake check

# Check with verbose trace on error
nix flake check --show-trace

# Build a specific host configuration
nix build .#nixosConfigurations.nix-laptop1.config.system.build.toplevel

# Test rebuild locally
sudo nixos-rebuild test --flake .

Manual System Rebuilds

For testing or emergency fixes:

# Rebuild current host from local directory
sudo nixos-rebuild switch --flake .

# Rebuild specific host
sudo nixos-rebuild switch --flake .#nix-laptop1

# Test without switching (temporary, doesn't persist reboot)
sudo nixos-rebuild test --flake .#nix-laptop1

# Rebuild from GitHub
sudo nixos-rebuild switch --flake github:UGA-Innovation-Factory/nixos-systems

Updating Flake Inputs

Update nixpkgs, home-manager, and other dependencies:

# Update all inputs
nix flake update

# Update specific input
nix flake lock --update-input nixpkgs

# After updating, test and commit
git add flake.lock
git commit -m "Update flake inputs"

Python Development

All systems include pixi and uv for project-based Python environments:

Pixi (recommended for projects):

pixi init my-project
cd my-project
pixi add pandas numpy matplotlib
pixi run python script.py

uv (quick virtual environments):

uv venv
source .venv/bin/activate
uv pip install requests

Adding Packages System-Wide

To all desktop systems:

  • Edit sw/desktop/programs.nix

To all tablet kiosks:

  • Edit sw/tablet-kiosk/programs.nix

To all headless systems:

  • Edit sw/headless/programs.nix

To specific hosts:

  • Add to ugaif.sw.extraPackages in inventory.nix

Example:

nix-laptop = {
  devices = 2;
  overrides = {
    ugaif.sw.extraPackages = with pkgs; [ vim docker ];
  };
};

Changing System Type

System types are defined in hosts/types/ and set the software profile:

  • desktop: Full desktop environment (GNOME)
  • tablet-kiosk: Surface tablets with kiosk mode browser
  • stateless-kiosk: Diskless PXE boot kiosks
  • headless: Servers and containers without GUI

To change a host's type, edit the type module it imports in hosts/types/.

Troubleshooting

Common Issues

"error: executing 'git': No such file or directory"

  • The update-system service needs git in PATH (fixed in latest version)
  • Workaround: Run sudo nixos-rebuild switch --flake github:UGA-Innovation-Factory/nixos-systems manually

Build errors after flake update

# Check what changed
git diff flake.lock

# Try with show-trace for details
nix flake check --show-trace

# Revert if needed
git checkout flake.lock

External modules not loading

  • Ensure repository is accessible (public or SSH configured)
  • Module must export proper structure (see templates)
  • For users: requires home.nix and optionally nixos.nix
  • For systems: requires default.nix that accepts { inputs, ... }

Remote build failures

# Test SSH access
ssh engr-ugaif@nix-builder

# Check builder disk space
ssh engr-ugaif@nix-builder df -h

# Temporarily disable remote builds in inventory.nix:
ugaif.sw.remoteBuild.enable = false;

"dirty git tree" warnings

  • Commit or stash uncommitted changes
  • These warnings don't prevent builds but affect reproducibility

Getting Help

Useful Commands

# Show all available outputs
nix flake show

# Evaluate a specific option
nix eval .#nixosConfigurations.nix-laptop1.config.networking.hostName

# List all hosts
nix eval .#nixosConfigurations --apply builtins.attrNames

# Check flake metadata
nix flake metadata

# Update and show what changed
nix flake update && git diff flake.lock
Description
No description provided
Readme 48 MiB
Languages
Nix 91.3%
Shell 8.7%