UGA Innovation Factory - NixOS Systems
This repository contains the NixOS configuration for the Innovation Factory's fleet of laptops, desktops, and surface tablets.
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.).
Quick Start
Updating the System
The system includes a utility script update-system that handles rebuilding and switching configurations. It automatically detects if it is running on a Surface tablet and offloads the build to a more powerful host if necessary.
To apply changes to the current system:
update-system
This command pulls the latest configuration from GitHub and rebuilds the system.
If your configuration uses external flakes (e.g., via flakeUrl), you may need to allow impure evaluation:
update-system --impure
Manual Rebuilds
If you need to rebuild manually or target a specific host:
# Local build
sudo nixos-rebuild switch --flake .
# Build for a specific host
sudo nixos-rebuild switch --flake .#nix-laptop1
Updating Flake Inputs
To update the lockfile (nixpkgs, home-manager versions, etc.):
nix flake update
Configuration Guide
Adding a New User
- Open
users.nix. - Add a new entry to
modules.users.accounts. - Generate a hashed password using
mkpasswd -m sha-512(requireswhoispackage or similar). - Commit and push.
Assigning Users to Hosts
By default, only root and engr-ugaif are enabled. To enable a specific student user on a specific device:
- Open
inventory.nix. - Locate the host type (e.g.,
nix-laptop). - Add or update the
devicessection for the specific index:
nix-laptop = {
count = 2;
devices = {
"1" = { extraUsers = [ "student_username" ]; };
};
};
Using External Flakes for User Configuration
Users can manage their own configuration (both Home Manager and System-level settings) in a separate flake repository. To use this:
- Open
users.nix. - In the user's configuration block, set the
flakeUrloption:
hdh20267 = {
# ... other settings ...
flakeUrl = "github:hdh20267/dotfiles";
};
The external flake must provide a nixosModules.default output. This module is imported into the system configuration, allowing the user to override their own system settings (like shell, extraGroups) and define their Home Manager configuration.
You can also opt-out of the default system configurations for Zsh and Neovim if you prefer to manage them entirely yourself:
useZshTheme(default:true): Set tofalseto disable the system-wide Zsh theme and configuration.useNvimPlugins(default:true): Set tofalseto disable the system-wide Neovim plugins and configuration.
Using External Flakes for System Configuration
You can also override the system-level configuration for a specific host using an external flake. This is useful for adding system services (like Docker), changing boot parameters, installing system-wide packages, or even overriding hardware settings (like swap size) without modifying inventory.nix.
- Open
inventory.nix. - In the
devicesoverride for the host, set theflakeUrl:
nix-laptop = {
count = 2;
devices = {
"2" = {
flakeUrl = "github:myuser/my-system-config";
};
};
};
The external flake must provide a nixosModules.default output. Any configuration defined in that module will be merged with the host's configuration.
External Flake Templates
If you are creating a new flake to use with flakeUrl, use these templates as a starting point.
User Flake (for users.nix)
Use this for user-specific dotfiles, shell configuration, and user packages. It can also override system-level user settings.
Note that inputs are omitted. This ensures the flake uses the exact same nixpkgs version as the main system, preventing version drift and saving disk space.
{
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
modules.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 for host-specific system services, hardware tweaks, or root-level 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
host.filesystem.swapSize = lib.mkForce "64G";
# Example: Enable specific users
modules.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=" ];
};
};
}
Adding a New Host
- Open
inventory.nix. - Increment the
countfor the relevant host type. - The new host will be named sequentially (e.g.,
nix-laptop3).
Development
Python Environment
The system comes with pixi and uv for Python project management. It is recommended to use these tools for project-specific environments rather than installing global Python packages.
pixi init my_project
cd my_project
pixi add pandas numpy