Commit 0b5cc5a96fb6

Vincent Demeester <vincent@sbr.pm>
2026-06-30 00:02:15
docs(imperative): regenerate top-level README
Replaced stale wakasu host with current aomi and nagoya hosts. Documented the Nix-on-host (system-manager + home-manager) approach alongside the legacy bash script fallback.
1 parent 79a9d9c
Changed files (1)
imperative
imperative/README.md
@@ -1,226 +1,158 @@
 # Imperative Configuration
 
-Idempotent configuration scripts for systems not managed by NixOS.
+Configuration for hosts **not** managed declaratively by NixOS.
 
 ## Overview
 
-This directory contains configuration scripts for hosts that cannot or do not use NixOS. Unlike the declarative NixOS configurations in `/systems`, these scripts use an imperative approach but are designed to be idempotent - safe to run multiple times.
+This directory holds configuration for machines that run a traditional Linux
+distribution (Fedora, Debian) instead of NixOS. Two complementary approaches
+live here:
 
-### Philosophy
+1. **Nix on top of the host OS** — using the [Determinate Nix installer] with
+   `system-manager` (system services) and `home-manager` (user environment).
+   This is the current, preferred approach. See [aomi](aomi/) and
+   [nagoya](nagoya/).
+2. **Idempotent bash scripts** — self-contained `apply.sh` scripts that bring a
+   host to the desired state. Kept as a fallback / bootstrap aid (e.g. the
+   legacy nagoya `apply.sh`).
 
-While NixOS provides declarative configuration management, some systems need to use traditional Linux distributions for various reasons:
-- Hardware compatibility requirements
-- Organizational constraints
-- Testing different distributions
-- Transition periods before migrating to NixOS
+[Determinate Nix installer]: https://github.com/DeterminateSystems/nix-installer
 
-These scripts bridge the gap by providing repeatable, documented configuration management for non-NixOS systems.
+### Why this exists
 
-### Key Principles
+Some systems can't run NixOS directly:
 
-1. **Idempotent** - Scripts can be run multiple times safely
-2. **Self-contained** - Each host directory is independent
-3. **Documented** - Each host has a README explaining its setup
-4. **Versioned** - Configuration is tracked in git like NixOS configs
+- Hardware or organizational constraints (e.g. IT-managed corporate laptop)
+- Transition periods before a full NixOS migration
+- Lightweight servers where a single script is enough
 
 ## Directory Structure
 
-Each host has its own directory containing:
-
 ```
 imperative/
 ├── README.md           # This file
-├── nagoya/             # Debian server
-│   ├── README.md       # Host-specific documentation
-│   └── apply.sh        # Main configuration script
-└── wakasu/             # Fedora desktop
-    ├── README.md       # Host-specific documentation
-    └── apply.sh        # Main configuration script
+├── aomi/               # Fedora CSB laptop — Nix (system-manager + home-manager)
+│   ├── README.md
+│   └── bootstrap.sh
+└── nagoya/             # Debian server — Nix (system-manager), bash fallback
+    ├── README.md
+    └── apply.sh
 ```
 
 ## Current Hosts
 
-### nagoya - Debian Server
-- **OS:** Debian (aarch64)
+### aomi — Fedora CSB + Nix
+
+- **OS:** Red Hat CSB (Fedora), aarch64/x86_64 laptop (ThinkPad P1 Gen 3)
+- **Type:** Work desktop/laptop, IT-managed base OS
+- **Approach:** Nix (Determinate installer) with `system-manager` +
+  `home-manager`
+- **Components:** WireGuard, Syncthing, shell, editors, dev tools
+- **Bootstrap:** `bootstrap.sh`
+
+See [aomi/README.md](aomi/README.md) for details.
+
+### nagoya — Debian Server
+
+- **OS:** Debian, aarch64
 - **Type:** Server
-- **Components:** Docker, Kind, Wireguard, Syncthing
+- **Approach:** Nix `system-manager` (`systems/nagoya/system.nix`), with a
+  legacy idempotent `apply.sh` bash script as fallback
+- **Components:** Docker, Kind, WireGuard, Syncthing
 - **VPN IP:** 10.100.0.80/24
+- **Status:** 🚧 Needs rework — being consolidated onto the system-manager
+  config; the `apply.sh` script remains as a bootstrap fallback.
 
 See [nagoya/README.md](nagoya/README.md) for details.
 
-### wakasu - Fedora Desktop
-- **OS:** Fedora
-- **Type:** Desktop
-- **User:** vincent
-- **Components:** Helix, ACPI, Wireguard, Syncthing
-- **VPN IP:** 10.100.0.90/24
-
-See [wakasu/README.md](wakasu/README.md) for details.
-
 ## Usage
 
-### Running Configuration Scripts
+### Nix-managed hosts (aomi)
 
-From the repository root:
+```bash
+cd ~/src/home
+
+# System-manager (WireGuard, Syncthing, system services)
+nix build .#systemConfigs.<hostname> && sudo ./result/bin/activate
+
+# Home-manager (shell, editors, dev tools)
+home-manager switch --flake .#vdemeest@<hostname>
+```
+
+Initial provisioning is done via the host's `bootstrap.sh`. See the host
+README for the exact invocation.
+
+### Script-managed hosts (nagoya)
 
 ```bash
 # Apply configuration for a specific host
 sudo ./imperative/<hostname>/apply.sh
 
-# With environment variables (e.g., for wireguard)
+# With environment variables (e.g. wireguard key)
 sudo WG_PRIVATE_KEY="..." ./imperative/<hostname>/apply.sh
 ```
 
-### Adding a New Host
+## Adding a New Host
 
-1. Create a new directory for the host:
-   ```bash
-   mkdir imperative/<hostname>
-   ```
+Pick the approach that fits the machine:
 
-2. Create an `apply.sh` script following the existing patterns:
-   - Use `set -euo pipefail` for safety
-   - Implement colored logging functions
-   - Make functions idempotent
-   - Use `setup.*` naming convention for functions
+### Nix-managed (preferred)
 
-3. Create a `README.md` documenting:
-   - System information
-   - Components installed
-   - Usage instructions
-   - Environment variables needed
+1. Add a `systemConfigs.<hostname>` (system-manager) and/or
+   `homeConfigurations."vdemeest@<hostname>"` entry in `flake.nix`.
+2. Create `imperative/<hostname>/bootstrap.sh` to install Nix and run the first
+   activation.
+3. Document the host in `imperative/<hostname>/README.md`.
 
-4. Make the script executable:
-   ```bash
-   chmod +x imperative/<hostname>/apply.sh
-   ```
+### Script-managed (fallback)
 
-5. Update this README to include the new host
+1. Create `imperative/<hostname>/apply.sh` following the existing patterns:
+   - `set -euo pipefail` for safety
+   - Colored logging helpers (`log_info`, `log_warn`, `log_error`)
+   - Idempotent `setup.*` functions
+2. Document the host in `imperative/<hostname>/README.md` (system info,
+   components, env vars, usage).
+3. `chmod +x imperative/<hostname>/apply.sh`.
 
-### Testing Scripts
-
-Test scripts in a VM or container before running on production systems:
-
-```bash
-# Example with Docker
-docker run -it --rm -v $(pwd):/repo debian:latest
-cd /repo
-./imperative/<hostname>/apply.sh
-```
+Then update this README to list the new host.
 
 ## Script Conventions
 
-### Error Handling
+Bash scripts in this directory follow these conventions:
 
-All scripts use strict error handling:
+- **Strict mode:** `set -euo pipefail`
+- **Idempotency:** check before mutating, guard re-runs, avoid destructive ops
+- **Function naming:** `setup.*` prefix (`setup.docker`, `setup.wireguard`, …)
+- **Logging:** colored `log_info` / `log_warn` / `log_error` helpers
+- **Environment variables:** documented per-host, fail or warn gracefully when
+  missing
+- **Linting:** run `shellcheck imperative/<hostname>/apply.sh`
 
-```bash
-set -euo pipefail
-```
+## Integration with NixOS / globals.nix
 
-This ensures:
-- `set -e` - Exit on any error
-- `set -u` - Exit on undefined variable
-- `set -o pipefail` - Catch errors in pipes
+Even imperative hosts share the repo's source of truth:
 
-### Logging
+- **WireGuard** addressing follows the topology in `globals.nix`
+  (`10.100.0.0/24`)
+- **Syncthing** device IDs are coordinated via `globals.nix` and accepted on
+  other nodes
+- New keys/IDs generated on first activation should be written back into
+  `globals.nix`
 
-Use colored logging functions for clarity:
+## Transitioning to Full NixOS
 
-```bash
-log_info "Normal operation message"
-log_warn "Warning message"
-log_error "Error message"
-```
+When migrating a host to NixOS:
 
-### Function Naming
+1. Use the imperative config as a reference for current state
+2. Create `systems/<hostname>` and test in a VM
+3. Perform the migration, then archive the imperative config
 
-Use `setup.*` prefix for setup functions:
+## Comparison
 
-```bash
-setup.docker() { ... }
-setup.wireguard() { ... }
-setup.syncthing() { ... }
-```
-
-### Environment Variables
-
-- Document all required environment variables in the host's README
-- Provide sensible defaults where possible
-- Fail gracefully or warn when optional variables are missing
-
-### Idempotency
-
-Make operations idempotent by:
-- Checking if software is already installed
-- Using `||` for commands that might fail on re-run
-- Avoiding destructive operations
-- Using configuration management tools when available
-
-## Integration with NixOS Configs
-
-While these scripts are imperative, they share concepts with the NixOS configurations:
-
-- **Wireguard configuration** matches the network topology in `globals.nix`
-- **Syncthing** IDs should be coordinated with NixOS hosts
-- **VPN IP addressing** follows the same scheme (10.100.0.0/24)
-
-## Transitioning to NixOS
-
-When ready to migrate a host to NixOS:
-
-1. Document the current system state using the imperative script as reference
-2. Create a new NixOS configuration in `/systems/<hostname>`
-3. Test the NixOS configuration in a VM
-4. Perform the migration
-5. Archive or remove the imperative configuration
-
-## Maintenance
-
-### Updating Scripts
-
-When updating scripts:
-
-1. Test changes in a VM or non-production system
-2. Update the host's README if behavior changes
-3. Run shellcheck to catch common issues:
-   ```bash
-   shellcheck imperative/<hostname>/apply.sh
-   ```
-
-### Version Control
-
-All changes to imperative configurations should be:
-- Committed to git
-- Documented in commit messages
-- Tagged if significant milestones are reached
-
-## Comparison: Imperative vs NixOS
-
-| Aspect           | Imperative (this directory) | NixOS (`/systems`)          |
-|------------------|-----------------------------|-----------------------------|
-| **Approach**     | Scripts to reach state      | Declare desired state       |
-| **Idempotency**  | Manual (via careful coding) | Automatic                   |
-| **Rollback**     | Manual/difficult            | Built-in generations        |
-| **Reproducibility** | Best effort              | Guaranteed                  |
-| **Documentation** | README + comments          | Code is documentation       |
-| **OS Support**   | Any Linux distro            | NixOS only                  |
-| **Learning Curve** | Familiar bash scripts     | Steeper (Nix language)      |
-| **State Management** | Imperative commands     | Declarative configuration   |
-
-## Resources
-
-### Similar Approaches
-- Ansible playbooks (declarative automation)
-- Chef/Puppet recipes (configuration management)
-- Shell scripts (traditional approach)
-
-### Why Not Use These Tools?
-
-For simple single-host configurations, a well-written bash script:
-- Has no dependencies beyond bash and standard tools
-- Is easy to understand and modify
-- Runs quickly without agent overhead
-- Keeps everything in this repository
-
-For managing many similar hosts, consider tools like Ansible.
+| Aspect              | Nix on host (aomi)        | Bash script (nagoya)      | Full NixOS (`/systems`) |
+|---------------------|---------------------------|---------------------------|-------------------------|
+| **Approach**        | Declare via Nix           | Scripts to reach state    | Declare desired state   |
+| **Base OS**         | Any (Fedora, …)           | Any Linux                 | NixOS only              |
+| **Idempotency**     | Automatic                 | Manual (careful coding)   | Automatic               |
+| **Rollback**        | Per-generation (Nix)      | Manual/difficult          | Built-in generations    |
+| **Reproducibility** | High                      | Best effort               | Guaranteed              |