feat: Add templates for external configs

This commit is contained in:
UGA Innovation Factory
2025-12-16 16:09:08 -05:00
committed by Hunter Halloran
parent f658a4a5cc
commit 11edaada84
17 changed files with 1102 additions and 23 deletions

109
EXTERNAL_MODULES.md Normal file
View File

@@ -0,0 +1,109 @@
# External Module Support Implementation
## Summary
Modified `nixos-systems` to support external system configurations via Nix modules instead of flakes. Device configurations can now point to URLs using `builtins.fetchGit`, `builtins.fetchTarball`, or local paths.
## Changes Made
### 1. `inventory.nix`
- Added documentation for external module syntax
- Added comprehensive examples showing different fetch methods
- Demonstrated usage: `devices."hostname" = builtins.fetchGit { url = "..."; rev = "..."; }`
### 2. `hosts/default.nix`
- Modified `mkHost` function to accept `externalModulePath` parameter
- Added logic to import and integrate external modules into the module list
- Updated device processing to detect path/derivation types (from fetchGit/fetchTarball)
- External modules are imported with `{ inputs; }` parameter, receiving same flake inputs
- External modules are merged alongside other configuration modules
### 3. `system-module-template/`
- Created `default.nix` template showing proper module structure
- Created `README.md` with usage instructions and examples
- Documented how external modules integrate with nixos-systems
## How It Works
### In inventory.nix:
```nix
{
"my-type" = {
devices = {
# Option 1: Traditional config attrset
"local-host" = {
extraUsers = [ "user1" ];
# ... normal NixOS config
};
# Option 2: External module from Git
"remote-host" = builtins.fetchGit {
url = "https://github.com/org/config";
rev = "abc123...";
};
};
};
}
```
### Detection Logic:
The system detects if a device value is:
1. A path (`builtins.isPath`)
2. A string starting with `/` (absolute path)
3. A derivation (`lib.isDerivation`)
If any of these are true, it treats it as an external module path.
### Module Import:
External modules are imported as:
```nix
import externalModulePath { inherit inputs; }
```
They receive the same flake inputs and can use all available modules and packages.
### Integration Order:
1. User flake modules (from users.nix)
2. Host type module (from hosts/types/)
3. Config override module
4. Hostname assignment
5. External flake module (if flakeUrl specified in config)
6. External path module (if fetchGit/fetchurl/path detected)
## Benefits
- **Separation**: Keep system configs in separate repos
- **Reusability**: Share configs across multiple deployments
- **Versioning**: Pin to specific commits for reproducibility
- **Flexibility**: Mix external modules with local overrides
- **Compatibility**: Works with all existing build methods (ISO, LXC, Proxmox)
## Testing
All existing configurations continue to work:
```bash
nix flake check # Passes ✓
nix eval .#nixosConfigurations.nix-desktop1.config.networking.hostName # Works ✓
```
## Example External Module Repository Structure
```
my-server-config/
├── default.nix # Main module (required)
├── README.md # Documentation
└── custom-service.nix # Additional modules (optional)
```
The `default.nix` must export a NixOS module:
```nix
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
config = {
# Your configuration here
};
}
```

View File

@@ -305,7 +305,19 @@ The external flake must provide a `nixosModules.default` output. See [System Fla
## External Flake Templates
If you're creating a flake to use with `flakeUrl`, use these templates as starting points.
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:
```bash
# 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.

288
USER_CONFIGURATION.md Normal file
View File

@@ -0,0 +1,288 @@
# External User Configuration
This document explains how to use external modules for user configuration in nixos-systems.
## Overview
Users can now maintain their home-manager configurations in separate Git repositories and reference them from `users.nix` using `builtins.fetchGit`, similar to how external system configurations work.
## Changes from Previous System
### Before (Flakes)
```nix
hdh20267 = {
description = "Hunter Halloran";
flakeUrl = "github:hdh20267/dotfiles";
};
```
### After (Modules with fetchGit)
```nix
hdh20267 = {
description = "Hunter Halloran";
home = builtins.fetchGit {
url = "https://github.com/hdh20267/dotfiles";
rev = "abc123...";
};
};
```
## Configuration Methods
### 1. External Repository (fetchGit)
```nix
myuser = {
description = "My Name";
extraGroups = [ "wheel" "networkmanager" ];
home = builtins.fetchGit {
url = "https://github.com/username/dotfiles";
rev = "commit-hash"; # For reproducibility
ref = "main"; # Optional branch
};
};
```
### 2. Local Path (for testing)
```nix
myuser = {
description = "My Name";
home = /home/username/dev/dotfiles;
};
```
### 3. Inline Configuration
```nix
myuser = {
description = "My Name";
home = {
home.packages = with pkgs; [ vim git ];
programs.git = {
enable = true;
userName = "My Name";
};
};
};
```
### 4. No External Config (legacy)
```nix
myuser = {
description = "My Name";
homePackages = [ pkgs.vim ];
# home = null; # Default
};
```
## External Repository Structure
When using `fetchGit` or a path, the repository must contain:
### Required: home.nix
```nix
{ inputs, ... }:
{ config, lib, pkgs, osConfig, ... }:
{
# Home-manager configuration
home.packages = with pkgs; [ ... ];
programs.git = { ... };
}
```
### Optional: nixos.nix
```nix
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
# System-level configuration (if needed)
users.users.myuser.extraGroups = [ "docker" ];
}
```
## Integration with System
External user modules:
1. **Receive inputs**: Same flake inputs as nixos-systems (nixpkgs, home-manager, etc.)
2. **Access osConfig**: Can read system configuration via `osConfig` parameter
3. **Merged with system settings**: Combined with inventory.nix user settings
4. **System themes applied**: Zsh/nvim themes from system if enabled
### Module Loading Order
For home-manager configuration:
1. External module (`home.nix`)
2. System theme module (if `useZshTheme = true`)
3. System nvim config (if `useNvimPlugins = true`)
For NixOS configuration:
1. User's NixOS module (`nixos.nix`, if exists)
2. All other system modules
## Available Parameters
In `home.nix`, you receive:
- `inputs` - Flake inputs (nixpkgs, home-manager, etc.)
- `config` - Home-manager configuration
- `lib` - Nixpkgs library functions
- `pkgs` - Package set
- `osConfig` - OS-level configuration (readonly)
In `nixos.nix`, you receive:
- `inputs` - Flake inputs
- `config` - NixOS configuration
- `lib` - Nixpkgs library functions
- `pkgs` - Package set
## User Options in users.nix
When defining a user with external config:
```nix
username = {
# Required
description = "Full Name";
# External configuration
home = builtins.fetchGit { ... };
# System settings (still configured here)
extraGroups = [ "wheel" ];
hashedPassword = "$6$...";
opensshKeys = [ "ssh-ed25519 ..." ];
shell = pkgs.zsh;
# Control system integration
useZshTheme = true; # Apply system zsh theme
useNvimPlugins = true; # Apply system nvim config
# Legacy options (ignored if home is set)
homePackages = [ ]; # Use home.packages in home.nix instead
extraImports = [ ]; # Use imports in home.nix instead
};
```
## Examples
### Minimal Dotfiles Repository
```
my-dotfiles/
├── home.nix
└── README.md
```
**home.nix:**
```nix
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
home.packages = with pkgs; [ vim git htop ];
programs.git = {
enable = true;
userName = "My Name";
userEmail = "me@example.com";
};
}
```
### With Dotfiles
```
my-dotfiles/
├── home.nix
├── nixos.nix
├── dotfiles/
│ ├── bashrc
│ └── vimrc
└── README.md
```
**home.nix:**
```nix
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
home.file.".bashrc".source = ./dotfiles/bashrc;
home.file.".vimrc".source = ./dotfiles/vimrc;
programs.git = {
enable = true;
userName = "My Name";
userEmail = "me@example.com";
};
}
```
### With System Configuration
**nixos.nix:**
```nix
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
# Add user to docker group
users.users.myusername.extraGroups = [ "docker" ];
# Install system-level packages
environment.systemPackages = [ pkgs.docker ];
}
```
## Migration Guide
### From flakeUrl to home
1. **Update users.nix:**
```diff
- flakeUrl = "github:user/dotfiles";
+ home = builtins.fetchGit {
+ url = "https://github.com/user/dotfiles";
+ rev = "latest-commit-hash";
+ };
```
2. **Update your dotfiles repository:**
- Rename or ensure you have `home.nix` (not `flake.nix`)
- Change module signature from flake to simple module:
```diff
- { inputs, outputs, ... }:
+ { inputs, ... }:
{ config, lib, pkgs, ... }:
```
3. **Optional: Add nixos.nix** for system-level config
4. **Test locally first:**
```nix
home = /path/to/local/dotfiles;
```
5. **Deploy:**
```bash
nix flake check
./deploy hostname
```
## Benefits
- **No Flakes Required**: Simpler for users unfamiliar with flakes
- **Explicit Versioning**: Pin to specific commits with `rev`
- **Faster Evaluation**: No flake evaluation overhead
- **Local Testing**: Easy to test with local paths
- **Flexibility**: Supports Git, paths, or inline configs
- **Reproducibility**: Commit hashes ensure exact versions
## Templates
See `/home/engr-ugaif/user-config-template/` for templates and detailed examples.

View File

@@ -105,5 +105,8 @@
modules = import ./installer/modules.nix { inherit inputs; };
in
modules.homeModules or { };
# Templates for external configurations
templates = import ./templates;
};
}

View File

@@ -38,18 +38,31 @@ let
system ? "x86_64-linux",
hostType,
configOverrides ? { },
externalModulePath ? null,
}:
let
# Load users.nix to find external user flakes
# Load users.nix to find external user modules
pkgs = nixpkgs.legacyPackages.${system};
usersData = import ../users.nix { inherit pkgs; };
accounts = usersData.ugaif.users or { };
# Extract flakeUrls and convert to modules
userFlakeModules = lib.mapAttrsToList (
# Extract external user NixOS modules (if they exist)
# External user modules can optionally provide a nixos.nix file for system-level config
userNixosModules = lib.mapAttrsToList (
name: user:
if (user ? flakeUrl && user.flakeUrl != "") then
(builtins.getFlake user.flakeUrl).nixosModules.default
if (user ? home && user.home != null) then
let
homePath =
if builtins.isAttrs user.home && user.home ? outPath then
user.home.outPath
else
user.home;
nixosModulePath = homePath + "/nixos.nix";
in
if (builtins.isPath homePath || (builtins.isString homePath && lib.hasPrefix "/" homePath)) && builtins.pathExists nixosModulePath then
import nixosModulePath { inherit inputs; }
else
{ }
else
{ }
) accounts;
@@ -69,6 +82,13 @@ let
else
{ };
# External module from fetchGit/fetchurl
externalPathModule =
if externalModulePath != null then
import externalModulePath { inherit inputs; }
else
{ };
# Config override module - translate special keys to ugaif options
overrideModule =
{ ... }:
@@ -108,13 +128,14 @@ let
};
allModules =
userFlakeModules
userNixosModules
++ [
typeModule
overrideModule
{ networking.hostName = hostName; }
]
++ lib.optional (configOverrides ? flakeUrl) externalFlakeModule;
++ lib.optional (configOverrides ? flakeUrl) externalFlakeModule
++ lib.optional (externalModulePath != null) externalPathModule;
in
{
system = lib.nixosSystem {
@@ -170,16 +191,52 @@ let
lib.mapAttrsToList (
deviceKey: deviceConfig:
let
# Merge: base config -> overrides -> device-specific config
mergedConfig = lib.recursiveUpdate (lib.recursiveUpdate baseConfig overrides) deviceConfig;
# Check if deviceConfig is a path/derivation (from fetchGit, fetchurl, etc.)
# fetchGit/fetchTarball return an attrset with outPath attribute
isExternalModule =
(builtins.isPath deviceConfig)
|| (builtins.isString deviceConfig && lib.hasPrefix "/" deviceConfig)
|| (lib.isDerivation deviceConfig)
|| (builtins.isAttrs deviceConfig && deviceConfig ? outPath);
# Extract the actual path from fetchGit/fetchTarball results
extractedPath =
if builtins.isAttrs deviceConfig && deviceConfig ? outPath then
deviceConfig.outPath
else
deviceConfig;
# If external module, we use base config + overrides as the config
# and pass the module path separately
actualConfig = if isExternalModule then (lib.recursiveUpdate baseConfig overrides) else deviceConfig;
# Merge: base config -> overrides -> device-specific config (only if not external module)
mergedConfig =
if isExternalModule then
actualConfig
else
lib.recursiveUpdate (lib.recursiveUpdate baseConfig overrides) deviceConfig;
# Check useHostPrefix from the merged config
usePrefix = mergedConfig.ugaif.host.useHostPrefix or true;
hostName = mkHostName prefix deviceKey usePrefix;
# If external module, also add a default.nix path for import
externalModulePath =
if isExternalModule then
if builtins.isPath extractedPath then
extractedPath + "/default.nix"
else if lib.isDerivation extractedPath then
extractedPath + "/default.nix"
else
extractedPath + "/default.nix"
else
null;
in
{
name = hostName;
value = mkHost {
inherit hostName system hostType;
inherit hostName system hostType externalModulePath;
configOverrides = mergedConfig;
};
}

View File

@@ -49,10 +49,16 @@ let
type = lib.types.listOf lib.types.path;
default = [ ];
};
flakeUrl = lib.mkOption {
type = lib.types.str;
default = "";
description = "URL of a flake to import Home Manager configuration from (e.g. github:user/dotfiles).";
home = lib.mkOption {
type = lib.types.nullOr (lib.types.oneOf [ lib.types.path lib.types.package lib.types.attrs ]);
default = null;
description = ''
External home-manager configuration. Can be:
- A path to a local module
- A fetchGit/fetchTarball result pointing to a repository
- An attribute set with home-manager configuration
Example: builtins.fetchGit { url = "https://github.com/user/dotfiles"; rev = "..."; }
'';
};
opensshKeys = lib.mkOption {
type = lib.types.listOf lib.types.str;
@@ -138,18 +144,37 @@ in
name: user:
{ ... }:
let
isExternal = user.flakeUrl != "";
# Check if user has external home configuration
hasExternalHome = user.home != null;
# Extract path from fetchGit/fetchTarball if needed
externalHomePath =
if hasExternalHome then
if builtins.isAttrs user.home && user.home ? outPath then
user.home.outPath
else
user.home
else
null;
# Import external module if it's a path
externalHomeModule =
if externalHomePath != null && (builtins.isPath externalHomePath || (builtins.isString externalHomePath && lib.hasPrefix "/" externalHomePath)) then
import (externalHomePath + "/home.nix") { inherit inputs; }
else if builtins.isAttrs user.home && !(user.home ? outPath) then
user.home # Direct attrset configuration
else
{ };
# Common imports based on flags
commonImports = lib.optional user.useZshTheme ../sw/theme.nix ++ [
(import ../sw/nvim.nix { inherit user; })
];
in
if isExternal then
if hasExternalHome then
{
# External users: Only apply requested system modules.
# The external flake is responsible for home.username, home.packages, etc.
imports = commonImports;
# External users: Merge external config with common imports
imports = commonImports ++ [ externalHomeModule ];
}
else
{

View File

@@ -43,6 +43,10 @@
# Convenience options:
# ugaif.forUser = "username"; # Automatically adds user to extraUsers and sets wslUser for WSL
#
# External modules (instead of config):
# Device values can be either a config attrset OR a fetchGit/fetchurl call
# that points to an external Nix module. The module will be imported and evaluated.
#
# Examples:
# "lab" = { devices = 3; }; # Quick: lab1, lab2, lab3
# "lab" = { count = 3; }; # Same as above
@@ -56,6 +60,12 @@
# };
# "wsl" = {
# devices."alice".ugaif.forUser = "alice123"; # Sets up for user alice123
# };
# "external" = {
# devices."remote" = builtins.fetchGit { # External module via Git
# url = "https://github.com/example/config";
# rev = "abc123...";
# };
# }; # ========== Lab Laptops ==========
# Creates: nix-laptop1, nix-laptop2
# Both get hdh20267 user via overrides
@@ -87,7 +97,10 @@
nix-lxc = {
devices = {
"nix-builder" = { };
"usda-dash" = { };
"usda-dash" = builtins.fetchGit {
url = "https://git.factory.uga.edu/MODEL/usda-dash-config.git";
rev = "4491f7826824c41a8e5047c04b198040d397a219";
};
};
overrides = {
ugaif.host.useHostPrefix = false;
@@ -105,4 +118,35 @@
# ========== Ephemeral/Netboot System ==========
# Creates: nix-ephemeral1
nix-ephemeral.devices = 1;
# ========== Example: External Module Configurations ==========
# Uncomment to use external modules from Git repositories:
#
# external-systems = {
# devices = {
# # Option 1: fetchGit with specific revision (recommended for reproducibility)
# "prod-server" = builtins.fetchGit {
# url = "https://github.com/example/server-config";
# rev = "abc123def456..."; # Full commit hash
# ref = "main"; # Optional: branch/tag name
# };
#
# # Option 2: fetchGit with latest from branch (less reproducible)
# "dev-server" = builtins.fetchGit {
# url = "https://github.com/example/server-config";
# ref = "develop";
# };
#
# # Option 3: fetchTarball for specific release
# "test-server" = builtins.fetchTarball {
# url = "https://github.com/example/server-config/archive/v1.0.0.tar.gz";
# sha256 = "sha256:0000000000000000000000000000000000000000000000000000";
# };
#
# # Option 4: Mix external module with local overrides
# # Note: The external module's default.nix should export a NixOS module
# # that accepts { inputs, ... } as parameters
# };
# };
}

View File

@@ -60,6 +60,11 @@ with lib;
systemd.services.update-system = {
enable = true;
description = "System daemon to one-shot run the Nix updater from fleet flake as root";
path = with pkgs; [
git
nixos-rebuild
nix
];
serviceConfig = {
Type = "oneshot";
ExecStart =

40
templates/default.nix Normal file
View File

@@ -0,0 +1,40 @@
{
system = {
path = ./system;
description = "External NixOS system configuration module";
welcomeText = ''
# External System Configuration Template
This template creates an external NixOS system configuration module
that can be referenced from nixos-systems/inventory.nix.
## Quick Start
1. Edit `default.nix` with your system configuration
2. Commit to a Git repository
3. Reference in inventory.nix using the `flakeUrl` field
See README.md for detailed documentation.
'';
};
user = {
path = ./user;
description = "External user home-manager configuration";
welcomeText = ''
# User Configuration Template
This template creates an external user configuration module
that can be referenced from nixos-systems/users.nix.
## Quick Start
1. Edit `home.nix` with your home-manager configuration
2. (Optional) Edit `nixos.nix` for system-level configuration
3. Commit to a Git repository
4. Reference in users.nix using the `flakeUrl` field
See README.md for detailed documentation.
'';
};
}

3
templates/system/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
result
result-*
.direnv/

View File

@@ -0,0 +1,99 @@
# External System Module Template
This directory contains a template for creating external system configuration modules that can be referenced from the main `nixos-systems` repository.
## Overview
External modules allow you to maintain system configurations in separate Git repositories and reference them from the main `nixos-systems/inventory.nix` file using `builtins.fetchGit` or `builtins.fetchTarball`.
## Usage
### 1. Create Your Module Repository
Copy `default.nix` from this template to your own Git repository. Customize it with your system configuration.
### 2. Reference It in inventory.nix
```nix
{
"my-system-type" = {
devices = {
"hostname" = builtins.fetchGit {
url = "https://github.com/your-org/your-config-repo";
rev = "abc123def456..."; # Full commit hash for reproducibility
ref = "main"; # Optional: branch/tag name
};
};
};
}
```
### 3. Module Structure
Your `default.nix` must:
- Accept `{ inputs, ... }` as parameters (you'll receive the same flake inputs)
- Return a valid NixOS module with `{ config, lib, pkgs, ... }: { ... }`
- Export configuration under the `config` attribute
## Examples
### Simple Configuration Module
```nix
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
config = {
time.timeZone = "America/New_York";
environment.systemPackages = with pkgs; [
vim
git
htop
];
services.openssh.enable = true;
};
}
```
### Advanced Module with Options
```nix
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
options.myorg.databaseUrl = lib.mkOption {
type = lib.types.str;
description = "Database connection URL";
};
config = {
# Use the option
services.postgresql = {
enable = true;
# ... configuration using config.myorg.databaseUrl
};
};
}
```
## Benefits
- **Separation of Concerns**: Keep specialized configurations in dedicated repositories
- **Reusability**: Share configurations across multiple NixOS fleets
- **Version Control**: Pin to specific commits for reproducibility
- **Team Ownership**: Different teams can maintain their own config repos
- **Security**: Private repositories for sensitive configurations
## Integration with nixos-systems
External modules are automatically integrated into the nixos-systems build:
- They receive the same flake inputs (nixpkgs, home-manager, etc.)
- They can use ugaif.* options if defined in the host type
- They are merged with local overrides and base configuration
- They work with all build methods (ISO, LXC, Proxmox, etc.)

View File

@@ -0,0 +1,56 @@
{ inputs, ... }:
# ============================================================================
# External System Module Template
# ============================================================================
# This is a template for creating external system configuration modules
# that can be referenced from nixos-systems/inventory.nix using builtins.fetchGit
#
# Usage in inventory.nix:
# "my-type" = {
# devices = {
# "hostname" = builtins.fetchGit {
# url = "https://github.com/your-org/your-config-repo";
# rev = "commit-hash";
# };
# };
# };
#
# This module will receive the same `inputs` flake inputs as the main
# nixos-systems configuration, allowing you to use nixpkgs, home-manager, etc.
{
config,
lib,
pkgs,
...
}:
{
# ========== Module Options ==========
# Define any custom options your module needs
options = {
# Example: myorg.customOption = lib.mkOption { ... };
};
# ========== Module Configuration ==========
config = {
# Your system configuration goes here
# This can include any NixOS options
# Example: Set timezone
# time.timeZone = "America/New_York";
# Example: Install packages
# environment.systemPackages = with pkgs; [
# vim
# git
# ];
# Example: Configure services
# services.openssh.enable = true;
# Example: Use ugaif options if available from nixos-systems
# ugaif.users.myuser.enable = true;
};
}

3
templates/user/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
result
result-*
.direnv/

183
templates/user/README.md Normal file
View File

@@ -0,0 +1,183 @@
# User Configuration Template
This directory contains templates for creating external user configuration modules that can be referenced from the main `nixos-systems/users.nix` file.
## Overview
External user modules allow users to maintain their personal configurations (dotfiles, packages, settings) in separate Git repositories and reference them from the main `nixos-systems` repository using `builtins.fetchGit`.
## Structure
```
user-dotfiles-repo/
├── home.nix # Required: Home-manager configuration
├── nixos.nix # Optional: System-level NixOS configuration
├── README.md # Documentation
└── dotfiles/ # Optional: Dotfiles to symlink
```
## Usage
### 1. Create Your User Configuration Repository
Copy the templates from this directory to your own Git repository:
- `home.nix` - Required for home-manager configuration
- `nixos.nix` - Optional for system-level configuration
### 2. Reference It in users.nix
```nix
{
ugaif.users = {
myusername = {
description = "My Name";
extraGroups = [ "wheel" "networkmanager" ];
shell = pkgs.zsh;
# Option 1: External module from Git
home = builtins.fetchGit {
url = "https://github.com/username/dotfiles";
rev = "abc123def456..."; # Full commit hash for reproducibility
ref = "main"; # Optional: branch/tag name
};
# Option 2: Local path for testing
# home = /path/to/local/dotfiles;
# Option 3: Inline configuration
# home = {
# home.packages = [ pkgs.vim ];
# programs.git.enable = true;
# };
};
};
}
```
### 3. Enable on Systems
Enable the user in `inventory.nix`:
```nix
{
"my-system" = {
devices = {
"hostname" = {
extraUsers = [ "myusername" ];
};
};
};
}
```
## File Descriptions
### home.nix (Required)
This file contains your home-manager configuration. It must be a valid NixOS module that accepts `{ inputs, ... }` and returns a home-manager configuration.
**Must export:**
- Home-manager options (programs.*, home.packages, etc.)
**Receives:**
- `inputs` - Flake inputs (nixpkgs, home-manager, etc.)
- `config` - Home-manager config
- `pkgs` - Nixpkgs package set
- `osConfig` - Access to OS-level configuration
### nixos.nix (Optional)
This file contains system-level NixOS configuration. Only needed for:
- System services related to the user
- System packages requiring root
- Special permissions or system settings
## Examples
### Minimal home.nix
```nix
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
home.packages = with pkgs; [
vim
git
htop
];
programs.git = {
enable = true;
userName = "My Name";
userEmail = "me@example.com";
};
}
```
### With Dotfiles
```nix
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
home.packages = with pkgs; [ ripgrep fd bat ];
# Symlink dotfiles
home.file.".bashrc".source = ./dotfiles/bashrc;
home.file.".vimrc".source = ./dotfiles/vimrc;
programs.git = {
enable = true;
userName = "My Name";
userEmail = "me@example.com";
};
}
```
### With System Configuration (nixos.nix)
```nix
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
# Add user to docker group
users.users.myusername.extraGroups = [ "docker" ];
# Install system package
environment.systemPackages = [ pkgs.docker ];
}
```
## Integration Features
External user modules:
- Receive the same flake inputs as nixos-systems
- Can use all home-manager options
- Optionally provide system-level configuration (nixos.nix)
- System zsh theme applied if `useZshTheme = true` (default)
- System nvim config applied if `useNvimPlugins = true` (default)
- Merged with inventory.nix user settings (groups, shell, etc.)
## Development Workflow
1. Create your user config repository with `home.nix`
2. Test locally: `home = /path/to/local/repo;`
3. Build: `nix build .#nixosConfigurations.hostname.config.system.build.toplevel`
4. Commit and push changes
5. Update users.nix with commit hash
6. Deploy to systems
## Benefits
- **Personal Ownership**: Users maintain their own configs
- **Version Control**: Track dotfile changes over time
- **Portability**: Use same config across multiple machines
- **Reproducibility**: Pin to specific commits
- **Privacy**: Use private repositories for personal settings
- **Separation**: Keep personal configs separate from system configs

91
templates/user/home.nix Normal file
View File

@@ -0,0 +1,91 @@
{ inputs, ... }:
# ============================================================================
# User Home Manager Configuration Template
# ============================================================================
# This file provides home-manager configuration for a user.
# It will be imported into the NixOS system's home-manager configuration.
#
# Usage in users.nix:
# myusername = {
# description = "My Name";
# home = builtins.fetchGit {
# url = "https://github.com/username/dotfiles";
# rev = "commit-hash";
# };
# };
#
# This module receives the same `inputs` flake inputs as the main
# nixos-systems configuration (nixpkgs, home-manager, etc.).
{
config,
lib,
pkgs,
osConfig, # Access to the OS-level config
...
}:
{
# ========== Home Manager Configuration ==========
# User identity (required)
home.username = lib.mkDefault config.home.username; # Set by system
home.homeDirectory = lib.mkDefault config.home.homeDirectory; # Set by system
home.stateVersion = lib.mkDefault "25.11";
# ========== Packages ==========
home.packages = with pkgs; [
# Add your preferred packages here
# htop
# ripgrep
# fd
# bat
];
# ========== Programs ==========
# Git configuration
programs.git = {
enable = true;
userName = "Your Name";
userEmail = "your.email@example.com";
extraConfig = {
init.defaultBranch = "main";
};
};
# Zsh configuration
programs.zsh = {
enable = true;
# System theme is applied automatically if useZshTheme = true in users.nix
# Add your custom zsh config here
};
# Neovim configuration
# programs.neovim = {
# enable = true;
# # System nvim config is applied automatically if useNvimPlugins = true
# # Add your custom neovim config here
# };
# ========== Shell Environment ==========
home.sessionVariables = {
EDITOR = "vim";
# Add your custom environment variables
};
# ========== Dotfiles ==========
# You can manage dotfiles with home.file
# home.file.".bashrc".source = ./dotfiles/bashrc;
# home.file.".vimrc".source = ./dotfiles/vimrc;
# Or use programs.* options for better integration
# ========== XDG Configuration ==========
xdg.enable = true;
# xdg.configFile."app/config.conf".source = ./config/app.conf;
}

47
templates/user/nixos.nix Normal file
View File

@@ -0,0 +1,47 @@
{ inputs, ... }:
# ============================================================================
# User NixOS System Configuration (Optional)
# ============================================================================
# This file provides system-level NixOS configuration for a user.
# It's optional - most user configuration should go in home.nix.
#
# Use this for:
# - System-level services that depend on the user (e.g., user systemd services)
# - Special system permissions or configurations
# - Installing system packages that require root
#
# This module receives the same `inputs` flake inputs as the main
# nixos-systems configuration.
{
config,
lib,
pkgs,
...
}:
{
# ========== System Configuration ==========
# Example: Enable a system service for this user
# systemd.services.my-user-service = {
# description = "My User Service";
# wantedBy = [ "multi-user.target" ];
# serviceConfig = {
# Type = "oneshot";
# User = "myusername";
# ExecStart = "${pkgs.bash}/bin/bash -c 'echo Hello'";
# };
# };
# Example: Install system-wide packages needed by this user
# environment.systemPackages = with pkgs; [
# docker
# ];
# Example: Add user to additional groups
# users.users.myusername.extraGroups = [ "docker" ];
# Most configuration should be in home.nix instead of here
}

View File

@@ -10,6 +10,16 @@
# Define the users here using the new option
# To generate a password hash, run: mkpasswd -m sha-512
# Set enabled = true on systems where the user should exist
#
# External Home Configuration:
# Users can specify external home-manager configuration via the 'home' attribute:
# home = builtins.fetchGit { url = "..."; rev = "..."; };
# home = /path/to/local/config;
# home = { home.packages = [ ... ]; }; # Direct attrset
#
# External repositories should contain:
# - home.nix (required): Home-manager configuration
# - nixos.nix (optional): System-level NixOS configuration
ugaif.users = {
root = {
isNormalUser = false;
@@ -38,8 +48,12 @@
];
homePackages = [ pkgs.ghostty ];
shell = pkgs.zsh;
# Example of using an external flake for configuration:
# flakeUrl = "github:hdh20267/dotfiles";
# Example of using an external module for home-manager configuration:
# home = builtins.fetchGit {
# url = "https://github.com/hdh20267/dotfiles";
# rev = "abc123...";
# };
# This expects a home.nix file in the repository with home-manager config
# enable = false by default, set to true per-system
};
sv22900 = {