Implements Phase 2 of the automated deployment pipeline. This commit adds a Python CLI tool that automates the creation of NixOS host configurations, eliminating manual boilerplate and reducing errors. Features: - Python CLI using typer framework with rich terminal UI - Comprehensive validation (hostname format/uniqueness, IP subnet/uniqueness) - Jinja2 templates for NixOS configurations - Automatic updates to flake.nix and terraform/vms.tf - Support for both static IP and DHCP configurations - Dry-run mode for safe previews - Packaged as Nix derivation and added to devShell Usage: create-host --hostname myhost --ip 10.69.13.50/24 The tool generates: - hosts/<hostname>/default.nix - hosts/<hostname>/configuration.nix - Updates flake.nix with new nixosConfigurations entry - Updates terraform/vms.tf with new VM definition All generated configurations include full system imports (monitoring, SOPS, autoupgrade, etc.) and are validated with nix flake check and tofu validate. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
6.3 KiB
NixOS Host Configuration Generator
Automated tool for generating NixOS host configurations, flake.nix entries, and Terraform VM definitions for homelab infrastructure.
Installation
The tool is available in the Nix development shell:
nix develop
Usage
Basic Usage
Create a new host with DHCP networking:
python -m scripts.create_host.create_host create --hostname test01
Create a new host with static IP:
python -m scripts.create_host.create_host create \
--hostname test01 \
--ip 10.69.13.50/24
Create a host with custom resources:
python -m scripts.create_host.create_host create \
--hostname bighost01 \
--ip 10.69.13.51/24 \
--cpu 8 \
--memory 8192 \
--disk 100G
Dry Run Mode
Preview what would be created without making changes:
python -m scripts.create_host.create_host create \
--hostname test01 \
--ip 10.69.13.50/24 \
--dry-run
Options
-
--hostname(required): Hostname for the new host- Must be lowercase alphanumeric with hyphens
- Must be unique (not already exist in repository)
-
--ip(optional): Static IP address with CIDR notation- Format:
10.69.13.X/24 - Must be in
10.69.13.0/24subnet - Last octet must be 1-254
- Omit this option for DHCP configuration
- Format:
-
--cpu(optional, default: 2): Number of CPU cores- Must be at least 1
-
--memory(optional, default: 2048): Memory in MB- Must be at least 512
-
--disk(optional, default: "20G"): Disk size- Examples: "20G", "50G", "100G"
-
--dry-run(flag): Preview changes without creating files
What It Does
The tool performs the following actions:
-
Validates the configuration:
- Hostname format (RFC 1123 compliance)
- Hostname uniqueness
- IP address format and subnet (if provided)
- IP address uniqueness (if provided)
-
Generates host configuration files:
hosts/<hostname>/default.nix- Import wrapperhosts/<hostname>/configuration.nix- Full host configuration
-
Updates repository files:
flake.nix- Adds new nixosConfigurations entryterraform/vms.tf- Adds new VM definition
-
Displays next steps for:
- Reviewing changes with git diff
- Verifying NixOS configuration
- Verifying Terraform configuration
- Committing changes
- Deploying the VM
Generated Configuration
Host Features
All generated hosts include:
-
Full system imports from
../../system:- Nix binary cache integration
- SSH with root login
- SOPS secrets management
- Internal ACME CA integration
- Daily auto-upgrades with auto-reboot
- Prometheus node-exporter
- Promtail logging to monitoring01
-
VM guest agent from
../../common/vm -
Hardware configuration from
../template/hardware-configuration.nix
Networking
Static IP mode (when --ip is provided):
systemd.network.networks."ens18" = {
matchConfig.Name = "ens18";
address = [ "10.69.13.50/24" ];
routes = [ { Gateway = "10.69.13.1"; } ];
linkConfig.RequiredForOnline = "routable";
};
DHCP mode (when --ip is omitted):
systemd.network.networks."ens18" = {
matchConfig.Name = "ens18";
networkConfig.DHCP = "ipv4";
linkConfig.RequiredForOnline = "routable";
};
DNS Configuration
All hosts are configured with:
- DNS servers:
10.69.13.5,10.69.13.6(ns1, ns2) - Domain:
home.2rjus.net
Examples
Create a test VM with defaults
python -m scripts.create_host.create_host create --hostname test99
This creates a DHCP VM with 2 CPU cores, 2048 MB memory, and 20G disk.
Create a database server with static IP
python -m scripts.create_host.create_host create \
--hostname pgdb2 \
--ip 10.69.13.52/24 \
--cpu 4 \
--memory 4096 \
--disk 50G
Preview changes before creating
python -m scripts.create_host.create_host create \
--hostname test99 \
--ip 10.69.13.99/24 \
--dry-run
Error Handling
The tool validates input and provides clear error messages for:
- Invalid hostname format (must be lowercase alphanumeric with hyphens)
- Duplicate hostname (already exists in repository)
- Invalid IP format (must be X.X.X.X/24)
- Wrong subnet (must be 10.69.13.0/24)
- Invalid last octet (must be 1-254)
- Duplicate IP address (already in use)
- Resource constraints (CPU < 1, memory < 512 MB)
Integration with Deployment Pipeline
This tool implements Phase 2 of the automated deployment pipeline:
- Phase 1: Template building ✓ (build-and-deploy-template.yml)
- Phase 2: Host configuration generation ✓ (this tool)
- Phase 3: Bootstrap automation (planned)
- Phase 4: Secrets management (planned)
- Phase 5: DNS automation (planned)
- Phase 6: Full integration (planned)
Development
Project Structure
scripts/create-host/
├── create_host.py # Main CLI entry point (typer app)
├── __init__.py # Package initialization
├── validators.py # Validation logic
├── generators.py # File generation using Jinja2
├── manipulators.py # Text manipulation for flake.nix and vms.tf
├── models.py # Data models (HostConfig)
├── templates/
│ ├── default.nix.j2 # Template for default.nix
│ └── configuration.nix.j2 # Template for configuration.nix
└── README.md # This file
Testing
Run the test cases from the implementation plan:
# Test 1: DHCP host with defaults
python -m scripts.create_host.create_host create --hostname testdhcp --dry-run
# Test 2: Static IP host
python -m scripts.create_host.create_host create \
--hostname test50 --ip 10.69.13.50/24 --dry-run
# Test 3: Custom resources
python -m scripts.create_host.create_host create \
--hostname test51 --ip 10.69.13.51/24 \
--cpu 8 --memory 8192 --disk 100G --dry-run
# Test 4: Duplicate hostname (should error)
python -m scripts.create_host.create_host create --hostname ns1 --dry-run
# Test 5: Invalid subnet (should error)
python -m scripts.create_host.create_host create \
--hostname testbad --ip 192.168.1.50/24 --dry-run
# Test 6: Invalid hostname (should error)
python -m scripts.create_host.create_host create --hostname Test_Host --dry-run
License
Part of the nixos-servers homelab infrastructure repository.