9.1 KiB
External Configuration Modules
This guide explains how to use external modules for system and user configurations in nixos-systems.
Table of Contents
Overview
External modules allow you to maintain configurations in separate Git repositories and reference them from inventory.nix (for systems) or users.nix (for users).
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
System Modules
External system modules provide complete NixOS configurations for hosts.
Usage in inventory.nix
nix-lxc = {
devices = {
# Traditional inline configuration
"local-server" = {
ugaif.users.admin.enable = true;
services.nginx.enable = true;
};
# External module from Git
"remote-server" = builtins.fetchGit {
url = "https://github.com/org/server-config";
rev = "abc123..."; # Pin to specific commit
};
};
};
External Repository Structure
server-config/
├── default.nix # Required: NixOS module
└── README.md # Optional: Documentation
default.nix:
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
# Your NixOS configuration
services.nginx = {
enable = true;
virtualHosts."example.com" = {
root = "/var/www";
};
};
# Use ugaif namespace options
ugaif.users.admin.enable = true;
ugaif.sw.type = "headless";
}
What External Modules Receive
inputs- All flake inputs (nixpkgs, home-manager, etc.)config- Full NixOS configurationlib- Nixpkgs library functionspkgs- Package set
Module Integration Order
When a host is built, modules are loaded in this order:
- User NixOS modules (from
users.nix-nixos.nixfiles) - Host type module (from
hosts/types/) - Configuration overrides (from
inventory.nix) - Hostname assignment
- External system module (if using
builtins.fetchGit)
Later modules can override earlier ones using standard NixOS module precedence.
Template
Create a new system module:
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#system
See templates/system/ for the complete template.
User Modules
External user modules provide home-manager configurations (dotfiles, packages, programs).
Usage in users.nix
ugaif.users = {
myuser = {
description = "My Name";
extraGroups = [ "wheel" "networkmanager" ];
hashedPassword = "$6$...";
# External home-manager configuration
home = builtins.fetchGit {
url = "https://github.com/username/dotfiles";
rev = "abc123...";
};
};
};
External Repository Structure
dotfiles/
├── home.nix # Required: Home-manager config
├── nixos.nix # Optional: System-level config
└── dotfiles/ # Optional: Actual dotfiles
├── bashrc
└── vimrc
home.nix (required):
{ inputs, ... }:
{ config, lib, pkgs, osConfig, ... }:
{
# Home-manager configuration
home.packages = with pkgs; [ vim git htop ];
programs.git = {
enable = true;
userName = "My Name";
userEmail = "me@example.com";
};
# Manage dotfiles
home.file.".bashrc".source = ./dotfiles/bashrc;
}
nixos.nix (optional):
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
# System-level configuration for this user
users.users.myuser.extraGroups = [ "docker" ];
environment.systemPackages = [ pkgs.docker ];
}
What User Modules Receive
In home.nix:
inputs- Flake inputs (nixpkgs, home-manager, etc.)config- Home-manager configurationlib- Nixpkgs library functionspkgs- Package setosConfig- OS-level configuration (read-only)
In nixos.nix:
inputs- Flake inputsconfig- NixOS configurationlib- Nixpkgs library functionspkgs- Package set
User Options in users.nix
username = {
# Identity
description = "Full Name";
# External configuration
home = builtins.fetchGit { ... };
# System settings
extraGroups = [ "wheel" "networkmanager" ];
hashedPassword = "$6$...";
opensshKeys = [ "ssh-ed25519 ..." ];
shell = pkgs.zsh;
# Theme integration
useZshTheme = true; # Apply system zsh theme (default: true)
useNvimPlugins = true; # Apply system nvim config (default: true)
# Enable on specific systems (see docs/INVENTORY.md)
enable = false; # Set in inventory.nix via ugaif.users.username.enable
};
Template
Create a new user module:
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#user
See templates/user/ for the complete template.
Fetch Methods
Recommended: fetchGit with Revision
Pin to a specific commit for reproducibility:
builtins.fetchGit {
url = "https://github.com/user/repo";
rev = "abc123def456..."; # Full commit hash (40 characters)
ref = "main"; # Optional: branch name
}
Finding the commit hash:
# Latest commit on main branch
git ls-remote https://github.com/user/repo main
# Or from a local clone
git rev-parse HEAD
fetchGit with Branch (Less Reproducible)
Always fetches latest from branch:
builtins.fetchGit {
url = "https://github.com/user/repo";
ref = "develop";
}
⚠️ Warning: Builds may not be reproducible as the branch HEAD can change.
fetchTarball (For Releases)
Download specific release archives:
builtins.fetchTarball {
url = "https://github.com/user/repo/archive/v1.0.0.tar.gz";
sha256 = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
}
Get the hash:
nix-prefetch-url --unpack https://github.com/user/repo/archive/v1.0.0.tar.gz
Local Path (For Testing)
Use local directories during development:
/home/username/dev/my-config
# Or relative to repository
./my-local-config
⚠️ Warning: Only for testing. Use Git-based methods for production.
Templates
System Module Template
# Initialize in new directory
mkdir my-server-config
cd my-server-config
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#system
See templates/system/README.md for detailed usage.
User Module Template
# Initialize in new directory
mkdir my-dotfiles
cd my-dotfiles
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#user
See templates/user/README.md for detailed usage.
Integration Details
Detection Logic
The system automatically detects external modules when a device or user value is:
- A path (
builtins.isPath) - A string starting with
/(absolute path) - A derivation (
lib.isDerivation) - An attrset with
outPathattribute (result offetchGit/fetchTarball)
System Module Integration
External system modules are imported and merged into the NixOS configuration:
import externalModulePath { inherit inputs; }
They can use all standard NixOS options plus ugaif.* namespace options.
User Module Integration
External user modules are loaded separately for home-manager (home.nix) and NixOS (nixos.nix if it exists):
Home-manager:
import (externalHomePath + "/home.nix") { inherit inputs; }
NixOS (optional):
import (externalHomePath + "/nixos.nix") { inherit inputs; }
Combining External and Local Config
You can mix external modules with local overrides:
nix-lxc = {
devices = {
"server" = builtins.fetchGit {
url = "https://github.com/org/base-config";
rev = "abc123...";
};
};
overrides = {
# Apply to all devices, including external ones
ugaif.users.admin.enable = true;
networking.firewall.allowedTCPPorts = [ 80 443 ];
};
};
Examples
Minimal System Module
default.nix:
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
ugaif.sw.type = "headless";
services.nginx.enable = true;
}
Minimal User Module
home.nix:
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
home.packages = with pkgs; [ vim git ];
}
Full User Module with Dotfiles
dotfiles/
├── home.nix
├── nixos.nix
└── config/
├── bashrc
├── vimrc
└── gitconfig
home.nix:
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
home.packages = with pkgs; [ ripgrep fd bat ];
home.file = {
".bashrc".source = ./config/bashrc;
".vimrc".source = ./config/vimrc;
".gitconfig".source = ./config/gitconfig;
};
}
See Also
- docs/INVENTORY.md - Host configuration guide
- docs/NAMESPACE.md - Configuration options reference
- templates/system/ - System module template
- templates/user/ - User module template
- README.md - Main documentation