UGA Innovation Factory d04fc7c1a4 git on path
2025-12-16 16:10:49 -05:00
2025-12-16 16:09:08 -05:00
2025-12-16 14:36:52 -05:00
2025-12-16 16:10:49 -05:00
2025-12-11 17:42:17 -05:00
2025-12-16 16:09:08 -05:00
2025-12-16 16:09:08 -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, and surface tablets. It provides a declarative, reproducible system configuration using Nix flakes.

Table of Contents

Repository Structure

  • flake.nix: The entry point for the configuration.
  • inventory.nix: Defines the fleet inventory (host types, counts, and device-specific overrides).
  • users.nix: Defines user accounts, passwords, and package sets.
  • hosts/: Contains the logic for generating host configurations and hardware-specific types.
  • sw/: Software modules (Desktop, Kiosk, Python, Neovim, etc.).

Configuration Namespace

All UGA Innovation Factory-specific NixOS options are organized under the ugaif namespace to clearly distinguish them from standard NixOS options. The main option groups are:

  • ugaif.host: Hardware and host-level configuration

    • ugaif.host.filesystem: Disk device and swap size settings
    • ugaif.host.buildMethods: Supported artifact build methods (ISO, LXC, etc.)
    • ugaif.host.wsl: WSL-specific configuration
  • ugaif.sw: Software and system type configuration

    • ugaif.sw.enable: Enable the software configuration module
    • ugaif.sw.type: System type (desktop, tablet-kiosk, headless, stateless-kiosk)
    • ugaif.sw.kioskUrl: URL for kiosk mode browsers
    • ugaif.sw.python: Python development tools settings
    • ugaif.sw.remoteBuild: Remote build configuration
  • ugaif.users: User account management

    • ugaif.users.accounts: User account definitions
    • ugaif.users.enabledUsers: List of users enabled on the system
    • ugaif.users.shell: Default shell for users

Prerequisites

To work with this repository on a non-NixOS system (like macOS or another Linux distro), you need to install Nix. We recommend the Determinate Systems installer for a reliable and feature-complete setup (including Flakes support out of the box).

curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install

Quick Start

For End Users: Updating Your System

The easiest way to update your system is using the included update-system utility:

update-system

This command:

  • Pulls the latest configuration from GitHub
  • Rebuilds the system with any changes
  • Automatically uses remote builders if you're on a Surface tablet

If you use external flakes (personal dotfiles), add the --impure flag:

update-system --impure

For Administrators: Managing the Fleet

Applying Configuration Changes

After modifying files in this repository:

# Test the configuration builds
nix flake check

# Push changes to GitHub
git add .
git commit -m "Description of changes"
git push

# Users can then run: update-system

Manual Rebuilds

For testing or emergency fixes:

# Rebuild current host
sudo nixos-rebuild switch --flake .

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

# Test without switching
sudo nixos-rebuild test --flake .#nix-laptop1

Updating Dependencies

Update nixpkgs, home-manager, and other flake inputs:

# Update all inputs
nix flake update

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

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

Building Artifacts (ISOs, LXC, Proxmox)

You can generate installation media and virtual machine images directly from this flake.

Installer ISOs

To build an auto-install ISO for a specific host (e.g., nix-laptop1):

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

To speed up the build by offloading to a powerful build server (e.g., nix-builder), use the --builders flag:

nix build github:UGA-Innovation-Factory/nixos-systems#installer-iso-nix-laptop1 \
  --builders "ssh://engr-ugaif@nix-builder x86_64-linux - 16 1 big-parallel"

The resulting ISO will be in result/iso/.

LXC / Proxmox Images

For hosts configured as containers (e.g., nix-lxc1), you can build LXC tarballs or Proxmox VMA archives:

# Build LXC tarball
nix build .#lxc-nix-lxc1

# Build Proxmox VMA
nix build .#proxmox-nix-lxc1

Configuration Guide

User Management

Adding a New User

  1. Open users.nix.
  2. Add a new entry to ugaif.users.accounts:
ugaif.users.accounts = {
  # ... existing users ...
  
  newuser = {
    description = "New User Name";
    extraGroups = [ "networkmanager" "wheel" ];
    hashedPassword = "$6$..."; # Generate with: mkpasswd -m sha-512
    opensshKeys = [ "ssh-ed25519 AAAA..." ];
  };
};
  1. Generate a hashed password using mkpasswd -m sha-512 (requires whois package).
  2. Commit and push the changes.

Note: Hashed passwords are for shared credentials only. For personal secrets, use external secret management.

Assigning Users to Hosts

By default, only root and engr-ugaif are enabled on all systems. To enable additional users on specific devices:

  1. Open inventory.nix.
  2. Locate the host type (e.g., nix-laptop).
  3. Add the user to the device's extraUsers list:
nix-laptop = {
  count = 2;
  devices = {
    "1".extraUsers = [ "newuser" "hdh20267" ];
  };
};

Using External Flakes for User Configuration

Users can manage their own dotfiles and configuration in a separate flake repository. This allows full control over shell configuration, editor settings, and Home Manager modules.

Security Note: External flakes run with the same privileges as the system configuration. Only use trusted flakes and pin to specific commits.

To enable this:

  1. Open users.nix.
  2. Set the flakeUrl for the user:
hdh20267 = {
  description = "User Name";
  extraGroups = [ "networkmanager" "wheel" ];
  hashedPassword = "$6$...";
  flakeUrl = "github:hdh20267/dotfiles";
  
  # Optional: Disable system defaults
  useZshTheme = false;      # Manage your own Zsh config
  useNvimPlugins = false;   # Manage your own Neovim config
};

The external flake must provide a nixosModules.default output. See User Flake Template below for an example.

Host Configuration

Adding a New Host

To add more devices of an existing type:

  1. Open inventory.nix.
  2. Increment the count for the host type:
nix-laptop.count = 3;  # Creates nix-laptop1, nix-laptop2, nix-laptop3

Device-Specific Configuration Overrides

You can customize individual devices in inventory.nix using either shortcut keys or direct configuration.

Shortcut Keys (for common settings):

  • extraUsers → Sets ugaif.users.enabledUsers
  • hostname → Sets a custom hostname (default: {type}{number})
  • buildMethods → Sets ugaif.host.buildMethods
  • wslUser → Sets ugaif.host.wsl.user
  • flakeUrl → Imports an external system flake

Direct Configuration (using the ugaif namespace or standard NixOS options):

nix-laptop = {
  count = 2;
  devices = {
    "1" = {
      # Shortcut keys
      extraUsers = [ "hdh20267" ];
      hostname = "laptop-special";
      
      # UGAIF options
      ugaif.host.filesystem.swapSize = "64G";
      ugaif.sw.extraPackages = with pkgs; [ docker vim ];
      
      # Standard NixOS options
      networking.firewall.enable = false;
      services.openssh.enable = true;
    };
  };
};

Customizing Kiosk URLs for Surface Tablets

Surface tablets run in kiosk mode with a full-screen Chromium browser. Set the URL per-device:

nix-surface = {
  count = 3;
  devices = {
    "1".ugaif.sw.kioskUrl = "https://ha.factory.uga.edu/dashboard-1";
    "2".ugaif.sw.kioskUrl = "https://ha.factory.uga.edu/dashboard-2";
  };
};

Using External Flakes for System Configuration

For complex system customizations (Docker, custom services, hardware tweaks), use an external flake:

nix-laptop = {
  count = 2;
  devices = {
    "2".flakeUrl = "github:myuser/my-system-config";
  };
};

The external flake must provide a nixosModules.default output. See System Flake Template below for an example.

External Flake Templates

If you're creating a flake to use with flakeUrl, you can use the provided templates as starting points.

Quick Start with Templates

Initialize a new configuration from templates:

# User configuration template (for users.nix)
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#user

# System configuration template (for inventory.nix)
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#system

Important: Do not specify inputs in your flake. This ensures your flake uses the exact same nixpkgs version as the main system, preventing version drift and saving disk space.

User Flake (for users.nix)

Use this template for user-specific dotfiles, shell configuration, Home Manager modules, and overriding user account settings.

{
  description = "My User Configuration";

  # No inputs needed! We use the system's packages.

  outputs = { self }: {
    # This output is what nixos-systems looks for
    nixosModules.default = { pkgs, lib, ... }: {
      
      # 1. Override System-Level User Settings
      ugaif.users.accounts.hdh20267 = {
        shell = pkgs.fish;
        extraGroups = [ "docker" ];
        
        # Optional: Disable system defaults if you manage your own
        useZshTheme = false;
        useNvimPlugins = false;
      };
      
      # Enable programs needed for the shell
      programs.fish.enable = true;

      # 2. Define Home Manager Configuration
      home-manager.users.hdh20267 = { pkgs, ... }: {
        home.stateVersion = "25.11";
        
        home.packages = with pkgs; [ 
          ripgrep 
          bat 
          fzf
        ];

        programs.git = {
          enable = true;
          userName = "My Name";
          userEmail = "me@example.com";
        };
      };
    };
  };
}

System Flake (for inventory.nix)

Use this template for host-specific system services (Docker, databases, web servers), hardware configuration tweaks, or system-wide packages.

{
  description = "My System Configuration Override";

  # No inputs needed! We use the system's packages.

  outputs = { self }: {
    # This output is what nixos-systems looks for
    nixosModules.default = { pkgs, lib, ... }: {
      environment.systemPackages = [ pkgs.docker ];
      
      virtualisation.docker.enable = true;
      
      # Example: Override hardware settings defined in the main repo
      ugaif.host.filesystem.swapSize = lib.mkForce "64G";

      # Example: Enable specific users
      ugaif.users.enabledUsers = [ "myuser" ];
      
      # Example: Add a custom binary cache
      nix.settings.substituters = [ "https://nix-community.cachix.org" ];
      nix.settings.trusted-public-keys = [ "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" ];
    };
  };
}

Development

Python Environment

All systems include pixi and uv for Python project management. Use these tools for project-specific environments instead of installing global Python packages (which can cause conflicts).

Creating a new project with Pixi:

pixi init my_project
cd my_project
pixi add pandas numpy matplotlib
pixi run python script.py

Using uv for quick tasks:

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

Testing Changes Locally

Before pushing changes, verify your configuration builds correctly:

# Check all configurations
nix flake check

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

# Test an ISO build
nix build .#installer-iso-nix-laptop1

Common Configuration Patterns

Adding System Packages to All Hosts

Edit sw/desktop/programs.nix (or the appropriate type directory) to add packages to the base system:

basePackages = with pkgs; [
  htop
  vim
  git
  # Add your packages here
];

Changing Default User Shell

Edit users.nix to set a different shell for a specific user:

myuser = {
  description = "My User";
  shell = pkgs.fish;  # or pkgs.zsh, pkgs.bash
  # ... other settings
};

Then ensure the program is enabled in the system configuration (usually already done for common shells).

Troubleshooting

Flake Check Errors

If nix flake check fails, use --show-trace for detailed error information:

nix flake check --show-trace

External Flakes Not Loading

If using flakeUrl, ensure:

  1. The flake repository is public or you have SSH access configured
  2. The flake has a nixosModules.default output
  3. You're using --impure flag if the flake has impure operations

Build Failures on Surface Tablets

Surface tablets automatically offload builds to remote builders. If builds fail:

  1. Verify the remote builder is accessible: ssh engr-ugaif@nix-builder
  2. Check remote builder has sufficient disk space: df -h
  3. Try building locally with remote builds disabled by commenting out ugaif.sw.remoteBuild.enable
Description
No description provided
Readme 48 MiB
Languages
Nix 91.3%
Shell 8.7%