658 lines
18 KiB
Markdown
658 lines
18 KiB
Markdown
# 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](#quick-start)
|
|
- [Repository Structure](#repository-structure)
|
|
- [Configuration Namespace](#configuration-namespace)
|
|
- [User Management](#user-management)
|
|
- [Host Configuration](#host-configuration)
|
|
- [External Modules](#external-modules)
|
|
- [Building Artifacts](#building-artifacts)
|
|
- [Development](#development)
|
|
- [Troubleshooting](#troubleshooting)
|
|
|
|
## Quick Start
|
|
|
|
### For End Users: Updating Your System
|
|
|
|
Update your system to the latest configuration from GitHub:
|
|
|
|
```bash
|
|
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:
|
|
```bash
|
|
nix flake check
|
|
```
|
|
3. Commit and push changes:
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```nix
|
|
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
|
|
};
|
|
};
|
|
```
|
|
|
|
2. Generate a hashed password:
|
|
```bash
|
|
mkpasswd -m sha-512 # Enter password when prompted
|
|
```
|
|
|
|
3. Enable the user on specific hosts in `inventory.nix`:
|
|
|
|
```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:
|
|
|
|
```nix
|
|
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](#external-modules) and [USER_CONFIGURATION.md](USER_CONFIGURATION.md) for details.
|
|
|
|
**Quick example:**
|
|
```nix
|
|
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:**
|
|
```bash
|
|
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
|
|
nix-laptop = {
|
|
devices = 5; # Creates: nix-laptop1, nix-laptop2, ..., nix-laptop5
|
|
};
|
|
```
|
|
|
|
**Method 2: Explicit count with overrides**
|
|
```nix
|
|
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
|
|
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
|
|
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):
|
|
- `extraUsers` → `ugaif.users.enabledUsers`
|
|
- `hostname` → Custom hostname (overrides default naming)
|
|
- `buildMethods` → `ugaif.host.buildMethods`
|
|
- `wslUser` → `ugaif.host.wsl.user`
|
|
|
|
**Direct configuration** (any NixOS or ugaif option):
|
|
```nix
|
|
"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
|
|
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](#external-modules) and [EXTERNAL_MODULES.md](EXTERNAL_MODULES.md).
|
|
|
|
```nix
|
|
nix-lxc = {
|
|
devices = {
|
|
"special-server" = builtins.fetchGit {
|
|
url = "https://github.com/org/server-config";
|
|
rev = "abc123...";
|
|
};
|
|
};
|
|
};
|
|
```
|
|
|
|
**Create a template:**
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
# 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`:
|
|
```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](USER_CONFIGURATION.md) and [templates/user/](templates/user/) for details.
|
|
|
|
### System Module Example
|
|
|
|
In `inventory.nix`:
|
|
```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](EXTERNAL_MODULES.md) and [templates/system/](templates/system/) for details.
|
|
|
|
### Fetch Methods
|
|
|
|
**Recommended: fetchGit with revision**
|
|
```nix
|
|
builtins.fetchGit {
|
|
url = "https://github.com/user/repo";
|
|
rev = "abc123def456..."; # Full commit hash
|
|
ref = "main"; # Optional: branch name
|
|
}
|
|
```
|
|
|
|
**Local path (for testing)**
|
|
```nix
|
|
/path/to/local/config
|
|
```
|
|
|
|
**Tarball (for releases)**
|
|
```nix
|
|
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:
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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):**
|
|
```bash
|
|
pixi init my-project
|
|
cd my-project
|
|
pixi add pandas numpy matplotlib
|
|
pixi run python script.py
|
|
```
|
|
|
|
**uv (quick virtual environments):**
|
|
```bash
|
|
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
|
|
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**
|
|
```bash
|
|
# 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**
|
|
```bash
|
|
# 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
|
|
|
|
- Check documentation: [USER_CONFIGURATION.md](USER_CONFIGURATION.md), [EXTERNAL_MODULES.md](EXTERNAL_MODULES.md)
|
|
- Review templates: `templates/user/` and `templates/system/`
|
|
- Contact Innovation Factory IT team
|
|
|
|
### Useful Commands
|
|
|
|
```bash
|
|
# 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
|
|
```
|