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>
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.