Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
cbd78f0
feat(planar-topology): Phases 0-5 — planar JSON topology + dormant re…
Jul 20, 2026
1fa5b4f
fix(planar-topology): Phases 4-1.0 + 4-1.1 — genNginx two-arg fix + v…
Jul 20, 2026
5d0a528
fix(planar-topology): Phase 4-1.2 — fix all 8 registry data errors
Jul 20, 2026
f52faf2
fix(planar-topology): Phases 4-1.3 + 4-1.4 — fix validator inversion …
Jul 20, 2026
29748cd
fix(planar-topology): Phase 4-1.5 — remove dead code + clean up ceremony
Jul 20, 2026
bc21d94
refactor(planar-topology): Phase 5-1.0 — remove _legacy from all JSON
Jul 20, 2026
a9c8952
feat(planar-topology): Phase 5-1.1 — rename vhosts, add exporters, re…
Jul 20, 2026
69dc31b
fix(planar-topology): add exportersShape validator to mkRegistry.nix
Jul 20, 2026
67d445b
feat(planar-topology): Phase 5-1.2 — populate exporters + vhosts in JSON
Jul 20, 2026
04c590b
feat(planar-topology): Phase 5-1.3.1 — topology-derive.nix foundation…
Jul 20, 2026
380efc3
test(planar-topology): Phase 5-1.3.2 — topology-derive unit tests + m…
Jul 20, 2026
15bd06e
docs(planar-topology): PONR-0 baseline + fidelity inventory
Jul 20, 2026
693e797
fix(planar-topology): PONR-1 fidelity — topology-derive matches basel…
Jul 20, 2026
716b9bd
fix(planar-topology): PONR-2 neutralize competing nginx/exporter prod…
Jul 20, 2026
e48e66d
feat(planar-topology): PONR-3 wire topology-derive + full golden green
Jul 20, 2026
3e0688d
feat(planar-topology): PONR — topology-derive wired, goldens green
Jul 20, 2026
baf54c0
docs(planar-topology): Record PONR freeze SHA 7af771c
Jul 20, 2026
dc73c5e
docs: PONR freeze tip SHA
Jul 20, 2026
0352034
fix(planar-topology): restore full system eval — nginx user stub + we…
Jul 21, 2026
18ec8fd
docs: update PONR-FREEZE — awaiting deployment tests
Jul 21, 2026
bf35b67
docs: review fixes plan — RF-0 through RF-2 (incorporated Q1-Q4 decis…
Jul 21, 2026
632f5e4
fix(planar-topology): RF-0 — clean up JSON data quality
Jul 21, 2026
b850b01
fix(planar-topology): RF-0 listenAddresses fix + golden regen
Jul 21, 2026
e6a8684
feat(planar-topology): RF-1 — populate routes, wireguard, firewall, d…
Jul 21, 2026
8b36ec6
feat(planar-topology): RF-2 — Tailscale ACL drift validator + full ve…
Jul 21, 2026
a2cafcb
refactor(planar-topology): M-0 — derive topoIp from JSON registry
Jul 22, 2026
63d42f4
refactor(planar-topology): M-1 — WireGuard from JSON registry
Jul 22, 2026
7142a16
refactor(planar-topology): M-2 — firewall/DNS/forwarding/tailscale/Wi…
Jul 22, 2026
99f736e
refactor(planar-topology): M-3 — delete legacy topology files
Jul 22, 2026
f1f0dc8
refactor(planar-topology): delete shared.nix — all consumers use JSON…
Jul 22, 2026
a9a9f2f
chore: gitignore documentation/2026-* review directories
Jul 23, 2026
cb21977
fix(checks): network-config golden check as build-time derivation + g…
Jul 23, 2026
849112b
fix(LINDA): use pkgs.xrandr instead of deprecated pkgs.xorg.xrandr
Jul 24, 2026
b696580
fix(staging): resolve review blockers — remote-worker coordinates, Ta…
Jul 25, 2026
8fba3aa
fix: rename machines/beta → machines/beta-one to match flake config name
Jul 25, 2026
a51eff2
check: add --fail flag to deadnix check, capture current output
Jul 25, 2026
6459e66
docs: add deadnix cleanup plan
Jul 25, 2026
ba588e4
docs: update deadnix plan with adversarial review synthesis
Jul 25, 2026
1298374
deadnix: remove unused let bindings (lib/)
Jul 25, 2026
94524d1
deadnix: remove unused bindings (modules/, modifier_imports/)
Jul 25, 2026
1faec22
deadnix: remove unused bindings (server_services/)
Jul 25, 2026
749ac28
deadnix: remove unused mkLibVirtImage binding (flake.nix)
Jul 25, 2026
8b24db1
deadnix: remove unused bindings (tests/)
Jul 25, 2026
834a3fb
deadnix: prefix unused lambda args with _ (Phase 2)
Jul 25, 2026
95fa068
deadnix: add --no-lambda-arg flag with audit comment (Phase 3)
Jul 25, 2026
72c056b
deadnix: remove WIP interfaceConfig/prefixLengthFromSubnet
Jul 25, 2026
b1ec079
fix: formatting in samba_server.nix
Jul 25, 2026
10a1be7
docs: resolve stale overlord tasks, delete hedgedoc.nix
Jul 26, 2026
cde254e
docs: correct F4 description, audit F5/F6 details
Jul 26, 2026
fbafcbf
docs: consolidate documentation, remove stale topology references
Jul 26, 2026
25f537c
docs: add F6 getExe conversion plan
Jul 26, 2026
4121322
refactor: convert LINDA getExe patterns
Jul 26, 2026
461f3cb
refactor: convert machine/environment getExe patterns
Jul 26, 2026
6562339
refactor: convert input-methods getExe pattern
Jul 26, 2026
58d87b7
refactor: convert LINDA scream getExe pattern
Jul 26, 2026
fe5621e
refactor: convert core-router and energy_saving getExe patterns
Jul 26, 2026
f08a55e
refactor: convert game server getExe patterns
Jul 26, 2026
40278d6
refactor: convert lib getExe patterns
Jul 26, 2026
af15f3e
refactor: convert credential and service getExe patterns
Jul 26, 2026
09884dc
refactor: convert test assertion getExe patterns
Jul 26, 2026
ddd4da4
docs: archive completed/planning docs to opencode/
Jul 26, 2026
ad8a585
docs: complete documentation cleanup — fix stale refs, deduplicate, a…
Jul 26, 2026
4abf722
docs: mark F6 getExe plan complete
Jul 26, 2026
5cf6b77
docs: archive completed F6 getExe plan to opencode/
Jul 26, 2026
5ec904f
docs: add F5 writeShellApplication conversion plan
Jul 26, 2026
625cde7
refactor: convert bargman-greeter-vm-serial to writeShellApplication
Jul 26, 2026
281e9e8
refactor: convert mkRunners askpass to writeShellApplication
Jul 26, 2026
a926ba9
refactor: convert gitlab-credentials to writeShellApplication, fix SC…
Jul 26, 2026
a3fef64
fix: restore lib.getExe in gitlab-credentials, fix PD#19 in netrc-copy
Jul 26, 2026
7076592
refactor: convert github-runner writeShellScript to writeShellApplica…
Jul 26, 2026
f31dee0
refactor: convert sysdiag to writeShellApplication, fix PD#19
Jul 26, 2026
bc92101
fix: formatting in sysdiag.nix and flake.nix
Jul 26, 2026
4849b96
docs: mark F5 writeShellApplication plan complete
Jul 26, 2026
d15a5f6
baseline for next phase - Rollback target for RC7
Jul 27, 2026
6c385b4
feat(overlord-ii): close three generator gaps (B4 prep)
Jul 27, 2026
6759e23
docs: topology generator principle stated in every document
Jul 27, 2026
b2265cd
feat(overlord-ii): topology-derive uses pure generators via specialArgs
Jul 27, 2026
561646f
feat(overlord-ii): backup pipeline 1:1 replacement via topology JSON
Jul 27, 2026
67ebec6
B3: Wire genWireguard into mktopology.nix
Jul 29, 2026
e95d98c
feat(overlord-ii): implement mktopology — flake-level topology-to-config
Jul 29, 2026
02909e7
fmt
Jul 29, 2026
a80b557
fix(overlord-ii): fix flake check — golden regeneration and webroot path
Jul 29, 2026
ac1d396
docs: add topology architecture diagram with Mermaid
Jul 30, 2026
35555de
docs: improve topology architecture diagram and add migration pattern
Jul 30, 2026
c29d2a4
refactor: rename check-network to validate-goldens — separate topolog…
Jul 30, 2026
c97b940
fix(ci): suppress evaluation warnings in generate-ci-workflow
Jul 30, 2026
82a0104
fix: remove stale locale/tailscale.nix import from remote-worker
Jul 30, 2026
465f6ae
fix: apply nginx-overhaul changes after rebase
Jul 30, 2026
8fc119e
Merge remote-tracking branch 'origin/main' into overlord-ii-planar-to…
Jul 31, 2026
f9500e2
feat: resolve B1 — derive interface IPs from topology via genNetwork.nix
Aug 1, 2026
f95a860
format and topofix
Aug 1, 2026
2e87494
fix: restore squaremap public access on gaming-host-1
Aug 2, 2026
7e2cd02
feat: add genForwarding.nix — restore NAT masquerade for LAN clients
Aug 2, 2026
6b975f5
feat: add genTailscale + genMonitoring — complete topology pipeline
Aug 3, 2026
08f6c62
fmt
Aug 3, 2026
8bb790e
fix: revert remote-worker carmelsite listen addresses to main behavior
Aug 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ result
.opencode
*.qcow2
documentation/logs/
documentation/2026-*/
sqlite_mcp_server.db
nix
277 changes: 167 additions & 110 deletions AGENTS.md

Large diffs are not rendered by default.

45 changes: 21 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
# NixOS-Configuration

## TOPOLOGY GENERATOR PRINCIPLE (STATED IN FULL — REPEATED)

No function in the entire topology toolset reads anything except JSON topology files. It is exclusive, totally isolated, and never touches a single user Nix file. The generators are pure JSON-to-attrset functions. They take JSON data and produce config attrsets. They do not reference, read, access, view, or manipulate any NixOS config, any module system state, or any user Nix file. The resulting attrsets are merged later with system config by the NixOS module system.

No function in the entire topology toolset reads anything except JSON topology files. It is exclusive, totally isolated, and never touches a single user Nix file. The generators are pure JSON-to-attrset functions. They take JSON data and produce config attrsets. They do not reference, read, access, view, or manipulate any NixOS config, any module system state, or any user Nix file. The resulting attrsets are merged later with system config by the NixOS module system.

No function in the entire topology toolset reads anything except JSON topology files. It is exclusive, totally isolated, and never touches a single user Nix file. The generators are pure JSON-to-attrset functions. They take JSON data and produce config attrsets. They do not reference, read, access, view, or manipulate any NixOS config, any module system state, or any user Nix file. The resulting attrsets are merged later with system config by the NixOS module system.

topology derived from json to config attrset — json → config attrset, pure function, no bullshit — no module system, no hostname, no legacy paths, just json to attrset — generators read json, produce attrset, period — the json is the source of truth; the generator is a pure transformation — config attrset is produced from json by a pure function; nothing else — topology to config: json in, attrset out, no module system in the middle — a generator is a pure function: topology → attrset, no more, no less — topology derives from json, the generator maps json to config attrset, nothing more — json is parsed, attrset is produced, the generator is pure, the module system is not involved

**Architecture diagram:** See `lib/topology/ARCHITECTURE.md` for the generator data flow diagram.

My personal NixOS-Configuration, including public keys.


Expand All @@ -7,7 +20,7 @@ This repository now allows me to deploy to any hardware, with my expected enviro

So; here's a little summary for the TL;DR types.

- Every machine is deployed via VPN, with the command "nix run .#machine-name"
- Every machine is deployed via VPN, with the command "nix run .#machine-name -- switch"
- Every machine is fully RAGE-secret encrypted (sops is basically a kids toy full of vulnerabilitites at this point in comparison to secrix @pinktrink keeps the world turning)
- My greatest weakness is watching ubuntu users, WSL users, and Mac users prove, endlessly, that Nix is superior.

Expand All @@ -17,21 +30,12 @@ So; here's a little summary for the TL;DR types.

## Adding a New Machine

1. Imperatively install NixOS on new host (`nixos-install`).
2. `$ scp user@host-ip:/etc/nixos/* ./machines/new-host/; mv machines/new-host/configuration.nix machines/new-host/default.nix`
3. Edit `default.nix`: `{ config, lib, pkgs, self, hostname, ... }: { networking.hostName = hostname; /* imports, envs, secrix.services.wireguard... */ }`
4. `$ scp user@host-ip:/etc/ssh/ssh_host_ed25519.pub ./secrets/public_keys/host_keys/new-host.pub`
5. Local WG: `$ wg genkey | tee priv | wg pubkey > pub; nix run .#secrix create ./secrets/wireguard/wg_new-host -- -u John88 < priv`
6. `./lib/wg_peers.nix` consumes the attrset from `./cortex-alpha/default.nix` - peerlist : `"new-host" = "90";` (pick free IP 10.88.127.X)
7. `flake.nix`: `new-host = mkX86_64 "new-host" { host = "10.88.127.90"; };`
8. Test: `$ nix fmt; nix flake check; nixos-rebuild build --flake .#new-host`

**Notes:**
1. First deploy via public IP using the settings `sshUser` `sshPort` and `host` under nixinate in flake.nix: then `nix run .#new-host` to 'test' deploy.
2. Then setup deploy user/VPN.
For the current add-machine procedure, see `documentation/development-guide.md#adding-a-new-machine`.
The topology-driven workflow requires creating a `topology/<machine>.json` file,
generating a golden test, and running `check-network` before deployment.

## VPN
simplified heavily by using the module `./modules/enable-wg.nix`
WireGuard VPN is managed via `modules/enable-wg-topology.nix` on client machines; see `documentation/operations-runbooks.md`.

## CI/CD Pipeline
Automated CI/CD pipeline with configuration generated from Nix evaluation:
Expand All @@ -46,7 +50,7 @@ nix run .#validate-ci-workflow
```

### CI Features
- **19 Machine Coverage**: All machines tested (14 x86_64, 5 ARM)
- **17 Machine Coverage**: All machines tested (12 x86_64, 5 ARM)
- **Job Dependencies**: Validation → Security → Builds → Deploy
- **Artifact Preservation**: 7-day build retention, 30-day logs
- **Enhanced Security**: Gitleaks + pattern matching + IP validation
Expand All @@ -55,15 +59,8 @@ nix run .#validate-ci-workflow
### CI Jobs
1. **Validation** - Formatting, flake check, dead code detection
2. **Security** - Gitleaks scanning, secret detection, IP validation
3. **Build x86** - Parallel builds for 14 x86_64 machines
3. **Build x86** - Parallel builds for 12 x86_64 machines
4. **Build ARM** - Parallel builds for 5 ARM machines
5. **Deploy** - Manual trigger for single machine deployment

## TODO
- Configure IPv6 forwarding
- Document Nixinate usage
- Make ``enable-wg.nix``, ``cortex-alpha/default.nix`` and ``wg_peers.nix`` both consume the same IP postfix-configuration.
- Implement LDAP authentication
- Automate scraper configuration
- Implement GPG-based SSH authentication
- Continue library-splitting efforts

217 changes: 217 additions & 0 deletions docs/genForwarding-PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
# genForwarding.nix Implementation Plan

## Problem Statement

LAN clients on `10.88.128.0/24` lost WAN connectivity after deploying
`overlord-ii-planar-topology`. Root cause: `mktopology.nix` has no
`genForwarding` generator — the NAT masquerade and DNAT port forwarding
rules are never created.

On `main`, `core-router-topology.nix` imports `mkForwarding.nix` which
reads `topology.forwarding.{tcp,udp}` and generates the full nftables
NAT table. The branch replaced this module with `mktopology.nix` but
omitted the forwarding generator.

## Architecture Constraint

genForwarding.nix MUST follow the topology generator principle:
- Pure JSON-to-attrset function
- Reads ONLY topology JSON
- Produces `{ networking.nftables = { enable = true; ruleset = "..."; }; }`
- No module system, no hostname, no legacy paths

## Input Schema (topology JSON)

The `routes` array in `topology/cortex-alpha.json`:
```json
{
"routes": [
{ "from": "wan", "port": 2208, "proto": "tcp", "to": "10.88.128.3:22", "reason": "SSH to local-nas" },
{ "from": "wan", "port": 27015, "proto": "tcp", "to": "10.88.128.88:27015", "reason": "Game server (TCP)" }
]
}
```

## Expected Output (nftables ruleset)

Must match the output of `main`'s `mkForwarding.nix`:
```nftables
table ip nat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
iifname "enp2s0" tcp dport 2208 dnat to 10.88.128.3:22
iifname "enp2s0" tcp dport 27015 dnat to 10.88.128.88:27015
...
};
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
oifname "enp2s0" ip saddr 10.88.128.0/24 masquerade
};
}
```

## Key Differences from Old Schema

| Old (`main`) | New (branch JSON) |
|-------------|-------------------|
| `topology.forwarding.tcp[].{port, dest}` | `topology.routes[].{port, proto, to}` |
| `topology.forwarding.udp[].{port, dest}` | Same array, `proto` field distinguishes |
| `topology.lan.wanInterface` | Derived from coordinate with `-wan` suffix |
| `topology.lan.subnet` | Derived from coordinate with `.lan` suffix |

## Phases

### Phase A: Implement genForwarding.nix

**Step A1**: Create `lib/topology/genForwarding.nix`

Prompt for bellana-deepseek:
> Create `/speed-storage/bargman-tech/NixOS-Configuration/lib/topology/genForwarding.nix`
>
> This is a pure topology generator following the same pattern as genFirewall.nix,
> genDns.nix, genNginx.nix, genBackup.nix, genNetwork.nix.
>
> Requirements:
> 1. Takes the full topology JSON as input
> 2. Reads `topology.routes` array
> 3. Derives the WAN interface from coordinates where plane_name ends with "-wan" or ".wan"
> 4. Derives the LAN subnet from coordinates where plane_name ends with ".lan" or is a hub_of entry
> 5. Generates nftables DNAT rules for each route entry
> 6. Generates masquerade postrouting rule for LAN → WAN NAT
> 7. Returns `{ networking.nftables = { enable = true; ruleset = "..."; }; }`
> 8. Returns `{ }` if no routes exist
>
> Route entry schema:
> ```json
> { "from": "wan", "port": 2208, "proto": "tcp", "to": "10.88.128.3:22", "reason": "..." }
> ```
>
> The `from` field is always "wan" (the WAN interface).
> The `proto` field is "tcp" or "udp".
> The `to` field is "ip:port" (DNAT destination).
>
> The generator MUST:
> - Include the standard topology principle header comment (copy from genFirewall.nix)
> - Use `lib` parameter pattern: `{ lib }:`
> - Handle empty routes array gracefully (return `{ }`)
> - Use lib.concatStringsSep for rule assembly
> - Match the nftables syntax from the old mkForwarding.nix exactly:
> - `iifname "${wanInterface}" ${proto} dport ${port} dnat to ${dest}`
> - `oifname "${wanInterface}" ip saddr ${subnet} masquerade`
>
> Reference files:
> - `/speed-storage/bargman-tech/NixOS-Configuration/lib/topology/genFirewall.nix` (pattern)
> - `/speed-storage/bargman-tech/NixOS-Configuration/lib/topology/genNetwork.nix` (coordinate parsing)
> - Old mkForwarding.nix (nftables syntax — retrieved via `git show main:lib/topology/mkForwarding.nix`)
> - `/speed-storage/bargman-tech/NixOS-Configuration/topology/cortex-alpha.json` (routes schema)

**Step A2**: Validate genForwarding.nix produces correct output

Prompt for bellana-deepseek:
> Test genForwarding.nix by evaluating it against cortex-alpha's topology JSON.
>
> Run:
> ```bash
> nix eval --json --expr '
> let
> lib = (import <nixpkgs> {}).lib;
> gen = import ./lib/topology/genForwarding.nix { inherit lib; };
> topology = builtins.fromJSON (builtins.readFile ./topology/cortex-alpha.json);
> in gen topology
> ' | jq .
> ```
>
> Verify the output contains:
> - `networking.nftables.enable = true`
> - `networking.nftables.ruleset` with all 14 DNAT rules from cortex-alpha.json routes
> - Masquerade postrouting rule for `10.88.128.0/24` via WAN interface
>
> Compare the ruleset content against the old mkForwarding.nix output:
> ```bash
> git show main:lib/topology/mkForwarding.nix
> ```
>
> The DNAT rules and masquerade rule MUST match.

### Phase B: Wire into mktopology.nix

**Step B1**: Add genForwarding to mktopology.nix

Prompt for bellana-deepseek:
> Wire genForwarding.nix into `/speed-storage/bargman-tech/NixOS-Configuration/lib/topology/mktopology.nix`
>
> Changes needed:
> 1. Add import: `genForwarding = import ./genForwarding.nix { inherit lib; };`
> (after the genNetwork import, around line 55)
>
> 2. Add to mkMachineConfig fold (after genNetwork, before DNS):
> ```nix
> # ── Forwarding/NAT (conditional on topology.routes) ─────
> (if topology ? routes then genForwarding topology else { })
> ```
>
> Reference: `/speed-storage/bargman-tech/NixOS-Configuration/lib/topology/mktopology.nix`
> The genForwarding call should be placed AFTER genNetwork and BEFORE genDns in the
> mkMachineConfig function's filter list.

### Phase C: Validate against golden and main

**Step C1**: Run golden validation for cortex-alpha

Prompt for bellana-deepseek:
> Run golden validation for cortex-alpha:
> ```bash
> nix run .#validate-goldens -- cortex-alpha 2>&1
> ```
>
> If it fails, regenerate the golden and inspect the diff:
> ```bash
> nix run .#dump-config -- cortex-alpha > /tmp/cortex-alpha-new.json
> diff /tmp/cortex-alpha-main.json /tmp/cortex-alpha-new.json
> ```
>
> The nftables ruleset in the golden MUST now contain the NAT table.
> Compare against main's nftables config.
>
> Key validation: the `networking.nftables.ruleset` field must contain
> the DNAT rules and masquerade rule.

**Step C2**: Validate all other machines still pass

Prompt for bellana-deepseek:
> Run golden validation for ALL machines to ensure no regressions:
> ```bash
> for m in $(ls machines/); do
> echo -n "$m: "
> nix run .#validate-goldens -- "$m" 2>&1 | tail -1
> done
> ```
>
> All 19 machines must pass. If any fail, investigate and fix.

**Step C3**: Commit

Prompt for bellana-deepseek:
> Stage and commit all changes:
> ```bash
> git add -A
> git commit -m "feat: add genForwarding.nix — restore NAT masquerade for LAN clients
>
> mktopology was missing a forwarding generator. LAN clients lost WAN
> connectivity because the nftables NAT masquerade rule was never created.
>
> - Add lib/topology/genForwarding.nix (routes → nftables NAT table)
> - Wire into mktopology.nix (conditional on topology.routes)
> - Regenerate cortex-alpha golden
>
> Fixes: LAN clients can now NAT through cortex-alpha to WAN"
> ```

## Verification Criteria

1. genForwarding.nix exists and follows generator pattern
2. mktopology.nix calls genForwarding conditionally on `topology.routes`
3. cortex-alpha golden contains nftables NAT table with all 14 DNAT rules
4. cortex-alpha golden contains masquerade postrouting rule
5. All 19 machines pass golden validation
6. The nftables ruleset matches main's output
Loading
Loading