2026-01-02 15:12:26 +01:00
|
|
|
# NIXOS CONFIGURATION KNOWLEDGE BASE
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
**Generated:** 2025-12-31 16:13:40 UTC
|
|
|
|
|
**Commit:** ebc8291
|
|
|
|
|
**Branch:** HEAD
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
## OVERVIEW
|
|
|
|
|
Personal NixOS configuration managing 6 hosts (4 servers, 2 desktops) using flakes, agenix secrets, and feature-based home-manager setup.
|
2025-12-29 18:55:52 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
## STRUCTURE
|
2025-12-28 11:28:19 +01:00
|
|
|
```
|
2026-01-02 15:12:26 +01:00
|
|
|
./
|
|
|
|
|
├── flake.nix # Main entry: host definitions, inputs, outputs
|
2025-12-28 11:28:19 +01:00
|
|
|
├── secrets.nix # Agenix public key mappings
|
|
|
|
|
├── hosts/
|
2026-01-02 15:12:26 +01:00
|
|
|
│ ├── common/ # Shared: base config, users, extraServices, ports
|
|
|
|
|
│ ├── m3-atlas/ # Server: 20+ containerized services with Traefik
|
|
|
|
|
│ ├── m3-helios/ # Server: AdGuard, internal routing
|
|
|
|
|
│ ├── m3-ares/ # Desktop: NVIDIA GPU, Btrfs
|
|
|
|
|
│ ├── m3-kratos/ # Desktop: AMD GPU, ZFS
|
|
|
|
|
│ └── m3-aether/ # Cloud VM
|
|
|
|
|
├── home/
|
|
|
|
|
│ ├── common/ # Home-manager base config
|
|
|
|
|
│ ├── features/ # Modular feature toggles (cli, desktop, coding)
|
|
|
|
|
│ └── m3tam3re/ # Per-host user configs
|
2025-12-28 11:28:19 +01:00
|
|
|
├── modules/ # Custom NixOS/home-manager modules
|
2026-01-02 15:12:26 +01:00
|
|
|
├── overlays/ # Package overlays (stable, locked, pinned, master)
|
2025-12-28 11:28:19 +01:00
|
|
|
├── pkgs/ # Custom package definitions
|
2026-01-02 15:12:26 +01:00
|
|
|
└── secrets/ # Agenix encrypted .age files (19 secrets)
|
2025-12-28 11:28:19 +01:00
|
|
|
```
|
|
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
## WHERE TO LOOK
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
| Task | Location | Notes |
|
|
|
|
|
|------|----------|-------|
|
|
|
|
|
| Add new host | `flake.nix` + `hosts/<name>/` | Copy template from m3-atlas (server) or m3-ares (desktop) |
|
|
|
|
|
| Add service to m3-atlas | `hosts/m3-atlas/services/` | See containers/ for Podman + Traefik pattern |
|
|
|
|
|
| Configure desktop features | `home/features/desktop/` | Feature toggles with mkEnableOption |
|
|
|
|
|
| Add CLI tool | `home/features/cli/` | Fish + Nushell integration expected |
|
|
|
|
|
| Manage secrets | `secrets.nix` + `agenix -e` | SSH keys defined in secrets.nix |
|
|
|
|
|
| Define ports | `hosts/common/ports.nix` | Centralized port registry |
|
|
|
|
|
| Add user | `hosts/common/users/` | Shared across all hosts |
|
|
|
|
|
| Custom packages | `pkgs/default.nix` | Exposed via flake outputs |
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
## CONVENTIONS
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
### Secrets (agenix)
|
|
|
|
|
- **Create**: `agenix -e secrets/<name>.age` after adding keys to `secrets.nix`
|
|
|
|
|
- **Reference**: `config.age.secrets.<name>.path` in service configs
|
|
|
|
|
- **Pattern**: Service env files use `environmentFiles = [config.age.secrets.<service>-env.path]`
|
|
|
|
|
|
|
|
|
|
### Service Organization
|
|
|
|
|
- **Native services**: `hosts/<host>/services/<service>.nix`
|
|
|
|
|
- **Containers**: `hosts/<host>/services/containers/<service>.nix`
|
|
|
|
|
- **Traefik integration**: All m3-atlas services include dynamic config for SSL + routing
|
|
|
|
|
- **Networking**: Containers use dedicated `web` network (10.89.0.0/24) with static IPs
|
|
|
|
|
|
|
|
|
|
### Port Management
|
|
|
|
|
- **Registry**: All ports defined in `hosts/common/ports.nix`
|
|
|
|
|
- **Access**: `config.m3ta.ports.get "service-name"`
|
|
|
|
|
- **Convention**: Internal services use 3000-3020 range
|
|
|
|
|
|
|
|
|
|
### Home-Manager Features
|
|
|
|
|
- **Enable**: `features.<category>.<feature>.enable = true` in user config
|
|
|
|
|
- **Categories**: `cli`, `desktop`, `coding`
|
|
|
|
|
- **Pattern**: Features are opt-in modules with default.nix aggregators
|
|
|
|
|
|
|
|
|
|
### Multiple nixpkgs Inputs
|
|
|
|
|
- **stable**: 25.11 release
|
|
|
|
|
- **locked/pinned**: Specific commits for compatibility
|
|
|
|
|
- **master**: Bleeding edge
|
|
|
|
|
- **m3ta-nixpkgs**: Custom local overlay at `path:/home/m3tam3re/p/nix/nixpkgs`
|
|
|
|
|
|
2026-04-22 17:59:23 +02:00
|
|
|
## CODING RULES
|
|
|
|
|
|
|
|
|
|
This project uses coding rules from the AGENTS repository (`inputs.agents`) plus project-specific conventions.
|
|
|
|
|
|
|
|
|
|
### Standard Rules (AGENTS repo)
|
|
|
|
|
|
|
|
|
|
| Rule | Source | Purpose |
|
|
|
|
|
|------|--------|---------|
|
|
|
|
|
| `languages/nix.md` | AGENTS/rules/ | Nix language conventions, flake patterns |
|
|
|
|
|
| `concerns/coding-style.md` | AGENTS/rules/ | General coding principles |
|
|
|
|
|
| `concerns/naming.md` | AGENTS/rules/ | Naming conventions per language |
|
|
|
|
|
| `concerns/documentation.md` | AGENTS/rules/ | Documentation standards |
|
|
|
|
|
| `concerns/testing.md` | AGENTS/rules/ | Testing guidelines |
|
|
|
|
|
| `concerns/git-workflow.md` | AGENTS/rules/ | Commit message format, branch naming |
|
|
|
|
|
| `concerns/project-structure.md` | AGENTS/rules/ | Project layout conventions |
|
|
|
|
|
|
|
|
|
|
### NixOS-Config Specific Rules
|
|
|
|
|
|
|
|
|
|
#### Project Structure
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
nixos-config/
|
|
|
|
|
├── flake.nix # Entry point
|
|
|
|
|
├── hosts/ # Host-specific NixOS configs
|
|
|
|
|
│ ├── common/ # Shared: ports, users, base config
|
|
|
|
|
│ ├── m3-atlas/ # Server with Traefik hub
|
|
|
|
|
│ ├── m3-helios/ # AdGuard DNS
|
|
|
|
|
│ ├── m3-ares/ # Desktop (NVIDIA)
|
|
|
|
|
│ └── m3-kratos/ # Desktop (AMD)
|
|
|
|
|
├── home/ # Home-manager configs
|
|
|
|
|
│ ├── common/ # Shared home config
|
|
|
|
|
│ ├── features/ # Feature modules (cli, desktop, coding)
|
|
|
|
|
│ └── m3tam3re/ # User-specific configs
|
|
|
|
|
├── modules/ # Custom NixOS/HM modules
|
|
|
|
|
├── overlays/ # Package overlays
|
|
|
|
|
├── pkgs/ # Custom packages
|
|
|
|
|
└── secrets/ # Agenix encrypted secrets
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Naming Conventions
|
|
|
|
|
|
|
|
|
|
| Type | Convention | Example |
|
|
|
|
|
|------|------------|---------|
|
|
|
|
|
| Hosts | mythological-names | `m3-atlas`, `m3-helios` |
|
|
|
|
|
| Files | hyphen-case | `my-service.nix` |
|
|
|
|
|
| Variables | camelCase | `portHelpers`, `serviceConfig` |
|
|
|
|
|
| Options | m3ta.* | `config.m3ta.ports.get` |
|
|
|
|
|
| Packages | lowercase-hyphen | `hyprpaper-random` |
|
|
|
|
|
|
|
|
|
|
#### Nix Module Pattern
|
|
|
|
|
|
|
|
|
|
```nix
|
|
|
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
|
with lib; let
|
|
|
|
|
cfg = config.m3ta.myModule;
|
|
|
|
|
in {
|
|
|
|
|
options.m3ta.myModule = {
|
|
|
|
|
enable = mkEnableOption "my module";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
config = mkIf cfg.enable {
|
|
|
|
|
# Configuration here
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Anti-Patterns (Never Do)
|
|
|
|
|
|
|
|
|
|
| Don't | Do Instead |
|
|
|
|
|
|-------|------------|
|
|
|
|
|
| Hardcode ports | `config.m3ta.ports.get "service"` |
|
|
|
|
|
| Skip secrets.nix update | Add keys first, then `agenix -e` |
|
|
|
|
|
| Containers outside web network | `--network=web --ip=10.89.0.N` |
|
|
|
|
|
| Skip Traefik for public services | Configure dynamic config |
|
|
|
|
|
| Bypass extraServices flags | Use feature flags properly |
|
|
|
|
|
| Use `fetchTarball` | Use flake inputs |
|
|
|
|
|
| Use `with pkgs;` in modules | Explicit `pkgs.package` |
|
|
|
|
|
|
|
|
|
|
### Formatting & Linting
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# Format (alejandra)
|
|
|
|
|
nix fmt
|
|
|
|
|
|
|
|
|
|
# Lint (statix, deadnix - only in dev shell)
|
|
|
|
|
nix develop
|
|
|
|
|
statix check .
|
|
|
|
|
deadnix .
|
|
|
|
|
|
|
|
|
|
# Validate flake
|
|
|
|
|
nix flake check
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Commit Conventions
|
|
|
|
|
|
|
|
|
|
Format: `<type>: <brief description>`
|
|
|
|
|
|
|
|
|
|
Types: `feat`, `fix`, `docs`, `style`, `refactor`, `chore`
|
|
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
|
- `feat: add new host m3-hermes`
|
|
|
|
|
- `fix: resolve port conflict in mem0 module`
|
|
|
|
|
- `docs: update AGENTS.md with new service`
|
|
|
|
|
- `style: format nix files`
|
|
|
|
|
- `refactor: simplify port management`
|
|
|
|
|
- `chore: update nixpkgs inputs`
|
|
|
|
|
|
|
|
|
|
### Tools in Dev Shell
|
|
|
|
|
|
|
|
|
|
| Tool | Purpose |
|
|
|
|
|
|------|---------|
|
|
|
|
|
| `alejandra` | Nix code formatter |
|
|
|
|
|
| `nixd` | Nix language server |
|
|
|
|
|
| `statix` | Nix linter |
|
|
|
|
|
| `deadnix` | Find dead code |
|
|
|
|
|
| `agenix` | Secret management |
|
|
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
## COMMANDS
|
|
|
|
|
```bash
|
|
|
|
|
# Build/deploy specific host
|
|
|
|
|
sudo nixos-rebuild switch --flake .#m3-ares
|
|
|
|
|
|
|
|
|
|
# Build/deploy current host
|
|
|
|
|
sudo nixos-rebuild switch --flake .#$(uname -n)
|
|
|
|
|
|
|
|
|
|
# Home-manager update
|
|
|
|
|
home-manager --flake . switch
|
|
|
|
|
|
|
|
|
|
# Update all flake inputs
|
|
|
|
|
nix flake update
|
|
|
|
|
|
|
|
|
|
# Add/edit secret
|
|
|
|
|
agenix -e secrets/<name>.age
|
|
|
|
|
|
|
|
|
|
# Infrastructure shell (OpenTofu)
|
|
|
|
|
nix develop .#infraShell
|
|
|
|
|
|
|
|
|
|
# Check configuration (no activation)
|
|
|
|
|
nixos-rebuild dry-build --flake .#<hostname>
|
2025-12-28 11:28:19 +01:00
|
|
|
```
|
|
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
## TRAEFIK PATTERNS (m3-atlas only)
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
### SSL Termination
|
|
|
|
|
- **Provider**: Godaddy DNS challenge
|
|
|
|
|
- **Cert storage**: `/var/lib/traefik/acme.json`
|
|
|
|
|
- **Config**: `hosts/m3-atlas/services/traefik.nix`
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
### Service Integration Template
|
2025-12-28 11:28:19 +01:00
|
|
|
```nix
|
2026-01-02 15:12:26 +01:00
|
|
|
services.traefik.dynamicConfigOptions.http = {
|
|
|
|
|
services.<name>.loadBalancer.servers = [{ url = "http://127.0.0.1:<port>"; }];
|
|
|
|
|
routers.<name> = {
|
|
|
|
|
rule = "Host(`<subdomain>.m3ta.dev`)";
|
|
|
|
|
service = "<name>";
|
|
|
|
|
tls.certResolver = "godaddy";
|
2025-12-28 11:28:19 +01:00
|
|
|
};
|
2026-01-02 15:12:26 +01:00
|
|
|
};
|
2025-12-28 11:28:19 +01:00
|
|
|
```
|
|
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
### Container Pattern
|
|
|
|
|
- **Network**: `--network=web --ip=10.89.0.<sequential>`
|
|
|
|
|
- **Ports**: Bind localhost only (`127.0.0.1:<external>:<internal>`)
|
|
|
|
|
- **Database access**: `--add-host=mysql:10.89.0.1` (gateway IP)
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
## HOST ROLES
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
| Host | Type | Hardware | Purpose |
|
|
|
|
|
|------|------|----------|---------|
|
|
|
|
|
| m3-atlas | Server | x86_64, disko | 20+ services, Traefik hub, PostgreSQL, MySQL |
|
|
|
|
|
| m3-helios | Server | x86_64, disko | AdGuard DNS, internal routing |
|
|
|
|
|
| m3-ares | Desktop | NVIDIA, Btrfs | Personal workstation, n8n, PostgreSQL |
|
|
|
|
|
| m3-kratos | Desktop | AMD, ZFS | Workstation, mem0, PostgreSQL |
|
|
|
|
|
| m3-aether | Cloud | QEMU | General purpose VM |
|
|
|
|
|
| m3-daedalus | Laptop | home-only | Portable (no full NixOS config) |
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
## ANTI-PATTERNS (THIS PROJECT)
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
- **DON'T** add secrets to `secrets/` without updating `secrets.nix` public keys
|
|
|
|
|
- **DON'T** hardcode ports - use `config.m3ta.ports.get` or add to registry
|
|
|
|
|
- **DON'T** create containers outside the `web` network on m3-atlas
|
|
|
|
|
- **DON'T** skip Traefik config for public-facing services on m3-atlas
|
|
|
|
|
- **DON'T** bypass extraServices flags - use `hosts/common/extraServices/` pattern
|
|
|
|
|
- **DON'T** commit unencrypted secrets or test with real credentials
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
## UNIQUE TO THIS CONFIG
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
- **Custom m3ta-nixpkgs**: Local overlay for unreleased/patched packages
|
|
|
|
|
- **extraServices abstraction**: Boolean flags to toggle Podman, Ollama, virtualisation per host
|
|
|
|
|
- **Mythological naming**: All hosts named after Greek mythology
|
|
|
|
|
- **Dual domain strategy**: New services on `m3ta.dev`, legacy redirects from `m3tam3re.com`
|
|
|
|
|
- **Per-host nixpkgs versions**: Different hosts can use different nixpkgs commits via specialArgs
|
|
|
|
|
- **Container IP registry**: Static IP assignments in 10.89.0.0/24 subnet for predictable networking
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
## NOTES
|
2025-12-28 11:28:19 +01:00
|
|
|
|
2026-01-02 15:12:26 +01:00
|
|
|
- m3-atlas is the service hub - most complex configuration
|
|
|
|
|
- Secrets require host SSH keys defined in `secrets.nix` before `agenix -e` works
|
|
|
|
|
- Fish and Nushell both configured - choose per-user with shell aliases
|
|
|
|
|
- Color scheme (Dracula) applied via nix-colors across all visual tools
|
|
|
|
|
- See subdirectory AGENTS.md for deep dives on containers, desktop features, CLI tools
|