- Update NAMESPACE.md: filesystem.device and swapSize defaults now null - Update README.md: add 'Using Athenix as a Library' section with lib.mkFleet - Update copilot-instructions.md: reflect new directory structure and defaults - Update EXTERNAL_MODULES.md: correct paths from variants/ and glue/ to hw/ and fleet/ - Update PROXMOX_LXC.md: update hardware type path reference
484 lines
11 KiB
Markdown
484 lines
11 KiB
Markdown
# External Configuration Modules
|
|
|
|
Guide to using external modules for system and user configurations.
|
|
|
|
## Table of Contents
|
|
|
|
- [Overview](#overview)
|
|
- [System Modules](#system-modules)
|
|
- [User Modules](#user-modules)
|
|
- [Fetch Methods](#fetch-methods)
|
|
- [Creating External Modules](#creating-external-modules)
|
|
- [Best Practices](#best-practices)
|
|
|
|
## Overview
|
|
|
|
External modules allow you to maintain configurations in separate Git repositories and reference them from Athenix.
|
|
|
|
**Benefits:**
|
|
- **Separation** - Keep complex configs in separate repositories
|
|
- **Reproducibility** - Pin specific commits for deterministic builds
|
|
- **Reusability** - Share configurations across multiple deployments
|
|
- **Flexibility** - Mix external modules with local configuration
|
|
- **Ownership** - Users maintain their own dotfiles
|
|
|
|
## System Modules
|
|
|
|
External system modules provide host-specific NixOS configurations.
|
|
|
|
### Usage
|
|
|
|
In `inventory.nix`, reference an external module using the `external` field:
|
|
|
|
```nix
|
|
nix-lxc = {
|
|
devices = {
|
|
# Inline configuration (traditional method)
|
|
"local-server" = {
|
|
athenix.sw.type = "headless";
|
|
services.nginx.enable = true;
|
|
};
|
|
|
|
# External module (lazy evaluation - fetched only when building this host)
|
|
"remote-server".external = builtins.fetchGit {
|
|
url = "https://git.factory.uga.edu/org/server-config";
|
|
rev = "abc123def456..."; # Must pin to specific commit
|
|
};
|
|
|
|
# External module with additional local config
|
|
"mixed-server" = {
|
|
external = builtins.fetchGit {
|
|
url = "https://git.factory.uga.edu/org/server-config";
|
|
rev = "abc123def456...";
|
|
};
|
|
# Additional local overrides
|
|
athenix.users.admin.enable = true;
|
|
services.openssh.permitRootLogin = "no";
|
|
};
|
|
};
|
|
};
|
|
```
|
|
|
|
**Key Features:**
|
|
- **Lazy Evaluation**: External modules are only fetched when building the specific host
|
|
- **Efficient Rebuilds**: Other hosts can be rebuilt without fetching unrelated external modules
|
|
- **Submodule Support**: Works with Git submodules without affecting other hosts
|
|
|
|
### Repository Structure
|
|
|
|
```
|
|
server-config/
|
|
├── default.nix # Required: NixOS module
|
|
├── README.md # Recommended: Documentation
|
|
└── optional/
|
|
├── config/ # Optional: Configuration files
|
|
└── scripts/ # Optional: Helper scripts
|
|
```
|
|
|
|
### Module Content (default.nix)
|
|
|
|
```nix
|
|
# The module receives inputs and standard NixOS module parameters
|
|
{ inputs, ... }:
|
|
{ config, lib, pkgs, ... }:
|
|
{
|
|
# Your NixOS configuration
|
|
# Use any standard NixOS option or athenix.* options
|
|
|
|
services.nginx = {
|
|
enable = true;
|
|
virtualHosts."example.com" = {
|
|
root = "/var/www";
|
|
forceSSL = true;
|
|
enableACME = true;
|
|
};
|
|
};
|
|
|
|
# Use athenix options
|
|
athenix.sw.type = "headless";
|
|
athenix.sw.extraPackages = with pkgs; [ git htop ];
|
|
|
|
# Standard NixOS configuration
|
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
|
services.openssh.enable = true;
|
|
}
|
|
```
|
|
|
|
### What System Modules Receive
|
|
|
|
- **`inputs`** - All flake inputs (nixpkgs, home-manager, disko, etc.)
|
|
- **`config`** - Current NixOS configuration (read/write)
|
|
- **`lib`** - Nixpkgs library functions
|
|
- **`pkgs`** - Package set
|
|
|
|
### Configuration Order
|
|
|
|
When a host is built, modules load in this order:
|
|
|
|
1. Hardware type module (from `hw/nix-*.nix`)
|
|
2. Common system configuration (from `fleet/common.nix`)
|
|
3. Software type module (from `sw/{type}/`)
|
|
4. User NixOS modules (from `users.nix` - `nixos.nix` files)
|
|
5. Device-specific overrides (from `inventory.nix`)
|
|
6. External system module (if present)
|
|
|
|
Each later module can override earlier ones using standard NixOS precedence rules.
|
|
|
|
## User Modules
|
|
|
|
External user modules provide home-manager configurations (dotfiles, environment setup).
|
|
|
|
### Usage
|
|
|
|
In `users.nix`, reference an external user module:
|
|
|
|
```nix
|
|
athenix.users = {
|
|
# External user module
|
|
myuser.external = builtins.fetchGit {
|
|
url = "https://git.factory.uga.edu/username/dotfiles";
|
|
rev = "abc123def456..."; # Pin to specific commit
|
|
};
|
|
|
|
# Inline user definition
|
|
otheruser = {
|
|
description = "Other User";
|
|
extraGroups = [ "wheel" ];
|
|
shell = pkgs.zsh;
|
|
hashedPassword = "$6$...";
|
|
};
|
|
};
|
|
```
|
|
|
|
Then enable on hosts in `inventory.nix`:
|
|
|
|
```nix
|
|
nix-laptop = {
|
|
devices = 5;
|
|
overrides.athenix.users.myuser.enable = true;
|
|
};
|
|
```
|
|
|
|
### Repository Structure
|
|
|
|
```
|
|
my-dotfiles/
|
|
├── user.nix # Required: User options + home-manager config
|
|
├── nixos.nix # Optional: System-level configuration
|
|
├── README.md # Recommended: Documentation
|
|
└── config/ # Optional: Your actual dotfiles
|
|
├── zshrc
|
|
├── vimrc
|
|
├── nvim/
|
|
└── ...
|
|
```
|
|
|
|
### user.nix (Required)
|
|
|
|
Provides both user account settings AND home-manager configuration:
|
|
|
|
```nix
|
|
# Receives { inputs } and standard home-manager module parameters
|
|
{ inputs, ... }:
|
|
{ config, lib, pkgs, osConfig ? null, ... }:
|
|
{
|
|
# ========== User Account Configuration ==========
|
|
# These options define the user account itself
|
|
|
|
athenix.users.myusername = {
|
|
description = "My Full Name";
|
|
extraGroups = [ "wheel" "docker" ];
|
|
shell = pkgs.zsh;
|
|
hashedPassword = "!"; # SSH keys only
|
|
opensshKeys = [
|
|
"ssh-ed25519 AAAA... user@laptop"
|
|
];
|
|
useZshTheme = true;
|
|
useNvimPlugins = true;
|
|
};
|
|
|
|
# ========== Home Manager Configuration ==========
|
|
# User environment, packages, and dotfiles
|
|
|
|
# Packages
|
|
home.packages = with pkgs; [
|
|
vim
|
|
git
|
|
ripgrep
|
|
fzf
|
|
] ++ lib.optional (osConfig.athenix.sw.type or null == "desktop") firefox;
|
|
|
|
# Programs
|
|
programs.git = {
|
|
enable = true;
|
|
userName = "My Name";
|
|
userEmail = "me@example.com";
|
|
extraConfig = {
|
|
init.defaultBranch = "main";
|
|
core.editor = "vim";
|
|
};
|
|
};
|
|
|
|
programs.zsh = {
|
|
enable = true;
|
|
initExtra = ''
|
|
# Your Zsh configuration
|
|
export EDITOR=vim
|
|
'';
|
|
};
|
|
|
|
# Manage dotfiles
|
|
home.file.".zshrc".source = ./config/zshrc;
|
|
home.file.".vimrc".source = ./config/vimrc;
|
|
home.file.".config/nvim".source = ./config/nvim;
|
|
|
|
# Services
|
|
services.gpg-agent.enable = true;
|
|
}
|
|
```
|
|
|
|
### nixos.nix (Optional)
|
|
|
|
System-level configuration for this user (rarely needed):
|
|
|
|
```nix
|
|
{ inputs, ... }:
|
|
{ config, lib, pkgs, ... }:
|
|
{
|
|
# System-level configuration
|
|
# Only needed if the user requires specific system-wide settings
|
|
|
|
users.users.myusername.extraGroups = [ "docker" ];
|
|
environment.systemPackages = [ pkgs.docker ];
|
|
|
|
# Security settings
|
|
security.sudo.extraRules = [{
|
|
users = [ "myusername" ];
|
|
commands = [{
|
|
command = "/usr/bin/something";
|
|
options = [ "NOPASSWD" ];
|
|
}];
|
|
}];
|
|
}
|
|
```
|
|
|
|
### What User Modules Receive
|
|
|
|
**In user.nix:**
|
|
- **`inputs`** - All flake inputs (nixpkgs, home-manager, etc.)
|
|
- **`config`** - Home-manager configuration (read/write)
|
|
- **`lib`** - Nixpkgs library functions
|
|
- **`pkgs`** - Package set
|
|
- **`osConfig`** - OS configuration (read-only) - useful for conditional setup
|
|
|
|
**In nixos.nix:**
|
|
- **`inputs`** - Flake inputs
|
|
- **`config`** - NixOS configuration (read/write)
|
|
- **`lib`** - Nixpkgs library functions
|
|
- **`pkgs`** - Package set
|
|
|
|
### Conditional Setup Example
|
|
|
|
Use `osConfig` to conditionally set up dotfiles based on the system type:
|
|
|
|
```nix
|
|
# In user.nix
|
|
{ inputs, ... }:
|
|
{ config, lib, pkgs, osConfig ? null, ... }:
|
|
{
|
|
athenix.users.myuser = { /* ... */ };
|
|
|
|
# Install Firefox only on desktop systems
|
|
home.packages = with pkgs; [
|
|
ripgrep
|
|
] ++ lib.optional (osConfig.athenix.sw.type or null == "desktop") firefox;
|
|
|
|
# Different shell config per system
|
|
programs.zsh.initExtra = ''
|
|
${lib.optionalString (osConfig.athenix.sw.type or null == "headless") "
|
|
# Headless-only settings
|
|
"}
|
|
'';
|
|
}
|
|
```
|
|
|
|
## Fetch Methods
|
|
|
|
### builtins.fetchGit (Recommended)
|
|
|
|
Pin to a specific Git revision:
|
|
|
|
```nix
|
|
builtins.fetchGit {
|
|
url = "https://git.factory.uga.edu/username/dotfiles";
|
|
rev = "abc123def456..."; # Required: specific commit hash
|
|
}
|
|
```
|
|
|
|
**Advantages:**
|
|
- Reproducible (pinned to exact commit)
|
|
- Works with any Git repository
|
|
- Supports SSH or HTTPS URLs
|
|
|
|
**Important:** Always specify `rev` (commit hash) for reproducibility. Don't use branches which can change.
|
|
|
|
### builtins.fetchTarball
|
|
|
|
Download specific release archives:
|
|
|
|
```nix
|
|
builtins.fetchTarball {
|
|
url = "https://github.com/user/repo/archive/v1.0.0.tar.gz";
|
|
sha256 = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
|
}
|
|
```
|
|
|
|
**Get the hash:**
|
|
```bash
|
|
nix-prefetch-url --unpack https://github.com/user/repo/archive/v1.0.0.tar.gz
|
|
```
|
|
|
|
### Local Path (For Testing)
|
|
|
|
Use local directories during development:
|
|
|
|
```nix
|
|
# users.nix
|
|
athenix.users.myuser.external = /home/user/my-dotfiles;
|
|
|
|
# inventory.nix
|
|
nix-laptop = {
|
|
devices = {
|
|
"dev".athenix.users.myuser.enable = true;
|
|
};
|
|
};
|
|
```
|
|
|
|
**Note:** Only works if the path exists on the machine running `nix flake check` or `nix build`.
|
|
|
|
## Creating External Modules
|
|
|
|
### System Module Template
|
|
|
|
Create a new system module repository from the template:
|
|
|
|
```bash
|
|
nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#system
|
|
```
|
|
|
|
This creates:
|
|
|
|
```
|
|
my-system-config/
|
|
├── flake.nix # Optional: for testing standalone
|
|
├── default.nix # Your NixOS module
|
|
└── README.md # Documentation
|
|
```
|
|
|
|
### User Module Template
|
|
|
|
Create a new user module repository:
|
|
|
|
```bash
|
|
nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#user
|
|
```
|
|
|
|
This creates:
|
|
|
|
```
|
|
my-dotfiles/
|
|
├── flake.nix # Optional: for testing standalone
|
|
├── user.nix # User options + home-manager config
|
|
├── nixos.nix # Optional: system-level config
|
|
└── README.md # Documentation
|
|
```
|
|
|
|
### Testing External Modules
|
|
|
|
Test your external module locally before pushing:
|
|
|
|
```bash
|
|
# In your module repository
|
|
cd /path/to/my-module
|
|
|
|
# Test the Nix syntax
|
|
nix flake check
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### 1. Always Pin to Specific Commits
|
|
|
|
❌ Wrong - using branch names:
|
|
```nix
|
|
builtins.fetchGit {
|
|
url = "https://git.factory.uga.edu/username/dotfiles";
|
|
# No rev specified or using "main"
|
|
}
|
|
```
|
|
|
|
✅ Correct - using commit hash:
|
|
```nix
|
|
builtins.fetchGit {
|
|
url = "https://git.factory.uga.edu/username/dotfiles";
|
|
rev = "abc123def456789...";
|
|
}
|
|
```
|
|
|
|
### 2. Keep External Modules Focused
|
|
|
|
Each external module should have a clear purpose:
|
|
- User dotfiles (one repo per user)
|
|
- System service configuration (one repo per service/cluster)
|
|
- Hardware-specific config (one repo per hardware setup)
|
|
|
|
### 3. Document Your Modules
|
|
|
|
Include a README with:
|
|
- What the module configures
|
|
- Required dependencies
|
|
- Usage examples
|
|
- Configuration options
|
|
|
|
### 4. Use Semantic Versioning
|
|
|
|
Tag releases in Git:
|
|
|
|
```bash
|
|
git tag v1.0.0
|
|
git push origin v1.0.0
|
|
```
|
|
|
|
Reference specific versions:
|
|
|
|
```nix
|
|
builtins.fetchGit {
|
|
url = "https://git.factory.uga.edu/org/server-config";
|
|
rev = "v1.0.0"; # Can use tags too
|
|
}
|
|
```
|
|
|
|
### 5. Test Before Updating Pins
|
|
|
|
When updating commit hashes:
|
|
|
|
```bash
|
|
# Test new revision locally
|
|
nix flake update
|
|
|
|
# Validate all configurations
|
|
nix flake check --show-trace
|
|
|
|
# Only commit after validation
|
|
git add . && git commit -m "Update module versions"
|
|
```
|
|
|
|
## See Also
|
|
|
|
- [USER_CONFIGURATION.md](USER_CONFIGURATION.md) - User management
|
|
- [INVENTORY.md](INVENTORY.md) - Host configuration
|
|
- [NAMESPACE.md](NAMESPACE.md) - Configuration options
|
|
- [README.md](../README.md) - Main documentation
|
|
- [templates/user/](../templates/user/) - User module template
|
|
- [templates/system/](../templates/system/) - System module template
|