11 KiB
Development Guide
This guide covers development workflows for maintaining and extending the nixos-systems repository.
Table of Contents
- Prerequisites
- Testing Changes
- Continuous Integration
- System Rebuilds
- Updating Dependencies
- Adding Packages
- Python Development
- Contributing
Prerequisites
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 manually)
sh <(curl -L https://nixos.org/nix/install) --daemon
Testing Changes
Always test configuration changes before committing.
Validate All Configurations
# Check all configurations build correctly
nix flake check
# Check with verbose error traces
nix flake check --show-trace
Test Specific Host Build
# Build a specific host's configuration
nix build .#nixosConfigurations.nix-laptop1.config.system.build.toplevel
# Build installer for specific host
nix build .#installer-iso-nix-laptop1
Test Local Changes
If you're on a NixOS system managed by this flake:
# Test changes without committing (temporary, doesn't survive reboot)
sudo nixos-rebuild test --flake .
# Apply and switch to new configuration
sudo nixos-rebuild switch --flake .
# Build without switching
sudo nixos-rebuild build --flake .
Continuous Integration
The repository uses Gitea Actions for automated testing and validation. CI jobs run on the self-hosted nix-builder machine.
CI Workflow
All pull requests and pushes to main trigger the CI pipeline, which includes:
-
Flake Check - Validates all NixOS configurations
- Runs
nix flake checkto ensure all systems build correctly - Catches configuration errors early
- Runs
-
Format Check - Ensures code formatting consistency
- Verifies code is formatted with
nix fmt - Automatically fails if formatting is incorrect
- Verifies code is formatted with
-
Build Key Configurations - Tests critical system builds
- Builds:
nix-builder,nix-laptop1,nix-desktop1 - Ensures core configurations compile successfully
- Builds:
-
Build Artifacts - Validates installer and container builds
- Builds:
lxc-nix-builder,installer-iso-nix-laptop1 - Verifies deployment artifacts are buildable
- Builds:
Viewing CI Status
Check the CI status badge at the top of the README or view detailed logs:
# View workflow status
https://git.factory.uga.edu/UGA-Innovation-Factory/athenix/actions
Running CI Checks Locally
Before pushing changes, run the same checks that CI performs:
# Run all checks
nix flake check --show-trace
# Check formatting
nix fmt
git diff --exit-code # Should return no changes
# Build specific configuration
nix build .#nixosConfigurations.nix-builder.config.system.build.toplevel
# Build artifacts
nix build .#lxc-nix-builder
Self-Hosted Runner
CI jobs run on the nix-builder host as a self-hosted Gitea Actions runner. This provides:
- Native Nix environment without installation overhead
- Access to local Nix store for faster builds
- Consistent build environment matching deployment targets
- Direct access to build caching infrastructure
Setting Up the Gitea Actions Runner
The nix-builder host is configured with a Gitea Actions self-hosted runner in inventory.nix. To complete the setup:
-
Generate a Gitea Runner Token:
- Go to https://git.factory.uga.edu/UGA-Innovation-Factory/athenix/settings/actions/runners
- Click "Create new Runner"
- Copy the registration token
-
Create the token file on nix-builder:
ssh engr-ugaif@nix-builder echo "YOUR_TOKEN_HERE" | sudo tee /var/lib/gitea-runner-token > /dev/null sudo chmod 600 /var/lib/gitea-runner-token -
Rebuild the system to start the runner:
sudo nixos-rebuild switch --flake git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#nix-builder -
Verify the runner is registered:
- Check https://git.factory.uga.edu/UGA-Innovation-Factory/athenix/settings/actions/runners
- The runner should appear with the
nix-builderlabel
The runner service is configured in the nix-builder device configuration and will automatically:
- Register with the repository on first start
- Use the
nix-builderlabel for workflow targeting - Run as the
engr-ugaifuser - Store work in
/var/lib/gitea-runner
Troubleshooting CI Failures
If CI fails:
- Check the error logs in the Gitea Actions tab
- Run the same command locally to reproduce the issue
- Use
--show-tracefor detailed error information - Verify formatting with
nix fmtif format check fails - Check for external dependencies that might be unavailable
Common CI issues:
- Flake check fails: Configuration error in a host definition
- Format check fails: Run
nix fmtlocally and commit changes - Build fails: Missing dependency or syntax error in Nix expressions
- Cache issues: Usually self-resolving; can retry the workflow
System Rebuilds
From Local Directory
# 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
# Build a new generation without activating it
sudo nixos-rebuild build --flake .
From GitHub
# Rebuild from GitHub main branch
sudo nixos-rebuild switch --flake git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git
# Use --impure for external user configurations with fetchGit
sudo nixos-rebuild switch --flake git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git --impure
# Rebuild specific host from GitHub
sudo nixos-rebuild switch --flake git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#nix-laptop1
Boot into Previous Generation
If something breaks:
# List generations
sudo nixos-rebuild list-generations
# Rollback to previous generation
sudo nixos-rebuild switch --rollback
# Or select specific generation at boot (GRUB menu)
# Reboot and select "NixOS - Configuration X" from boot menu
Updating Dependencies
Update All Inputs
# Update all flake inputs (nixpkgs, home-manager, etc.)
nix flake update
# Review changes
git diff flake.lock
# Test the updates
nix flake check
# Commit if successful
git add flake.lock
git commit -m "Update flake inputs"
git push
Update Specific Input
# Update only nixpkgs
nix flake lock --update-input nixpkgs
# Update home-manager
nix flake lock --update-input home-manager
# Update multiple specific inputs
nix flake lock --update-input nixpkgs --update-input home-manager
Check for Security Updates
# After updating, check for known vulnerabilities
nix flake check
# Review nixpkgs changelog
git log HEAD..nixpkgs/nixos-25.11 --oneline | head -20
Adding Packages
System-Wide Packages by Type
Add packages based on system type:
Desktop systems:
# Edit sw/desktop/programs.nix
vim sw/desktop/programs.nix
Tablet kiosks:
# Edit sw/tablet-kiosk/programs.nix
vim sw/tablet-kiosk/programs.nix
Headless systems:
# Edit sw/headless/programs.nix
vim sw/headless/programs.nix
Packages for Specific Hosts
Add to athenix.sw.extraPackages in inventory.nix:
nix-laptop = {
devices = 2;
overrides = {
athenix.sw.extraPackages = with pkgs; [
vim
docker
kubernetes-helm
];
};
};
User-Specific Packages
Add to user's home-manager configuration in their external user.nix:
# In external user.nix
home.packages = with pkgs; [
ripgrep
fd
bat
];
Search for Packages
# Search nixpkgs
nix search nixpkgs firefox
nix search nixpkgs python3
# Show package details
nix eval nixpkgs#firefox.meta.description
Python Development
All systems include modern Python tools: pixi and uv.
Pixi (Recommended for Projects)
# Initialize new project
pixi init my-project
cd my-project
# Add dependencies
pixi add pandas numpy matplotlib jupyter
# Run Python
pixi run python
# Run Jupyter
pixi run jupyter notebook
# Run scripts
pixi run python script.py
# Shell with dependencies
pixi shell
uv (Quick Virtual Environments)
# Create virtual environment
uv venv
# Activate
source .venv/bin/activate
# Install packages
uv pip install requests pandas
# Freeze requirements
uv pip freeze > requirements.txt
# Install from requirements
uv pip install -r requirements.txt
System Python
Python development tools are configured in sw/python.nix and can be controlled via:
athenix.sw.python.enable = true; # Default: enabled
Contributing
Code Style
- Run formatter before committing:
nix fmt - Follow existing code structure and conventions
- Add comments for complex logic
- Use the
athenix.*namespace for all custom options
Testing Workflow
- Make changes
- Run formatter:
nix fmt - Test locally:
nix flake check - Test specific builds if needed
- Commit changes
- Push to GitHub
# Full workflow
nix fmt
nix flake check
git add .
git commit -m "Description of changes"
git push
Documentation
Update relevant documentation when making changes:
README.md- Overview and quick startdocs/INVENTORY.md- Inventory configurationdocs/NAMESPACE.md- Configuration optionsUSER_CONFIGURATION.md- User managementEXTERNAL_MODULES.md- External modules
Creating Issues
When reporting bugs or requesting features:
- Check existing issues first
- Provide clear description
- Include error messages and traces
- Specify which hosts are affected
- Include
flake.lockinfo if relevant
Useful Commands
# Show all available outputs
nix flake show
# Evaluate 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
# Show evaluation trace
nix eval --show-trace .#nixosConfigurations.nix-laptop1
# Build and enter debug shell
nix develop
# Clean up old generations
nix-collect-garbage -d
# Optimize Nix store
nix store optimise
See Also
- README.md - Main documentation
- INVENTORY.md - Host inventory configuration
- BUILDING.md - Building installation media
- USER_CONFIGURATION.md - User management