Compare commits
2 Commits
0d1562d150
...
8c4223af18
| Author | SHA1 | Date | |
|---|---|---|---|
| 8c4223af18 | |||
| b95992735e |
@@ -2,6 +2,13 @@
|
||||
|
||||
This file provides guidance to coding agents when working with code in this repository.
|
||||
|
||||
`CLAUDE.md` at the repo root is a symlink to this file — edit `AGENTS.md`, not the symlink (some
|
||||
tools refuse to write through a symlink and will error on `CLAUDE.md`).
|
||||
|
||||
**Prefer this file over agent memory.** When you learn something durable about this repo — a
|
||||
convention, a workflow gotcha, a design rationale — record it here (or in a repo doc this file points
|
||||
to, e.g. `home-switches.md`), not in agent memory. AGENTS.md is versioned and shared; memory is not.
|
||||
|
||||
## Overview
|
||||
|
||||
Personal Nix flake managing NixOS systems and home-manager configurations for a set of
|
||||
@@ -28,11 +35,16 @@ Common ones:
|
||||
Pass the flake-qualified node, e.g. `deploy .#git`. The deploy node name is **always** the system
|
||||
name (`deploy-rs.nix` keys nodes directly off `nixos.systems` / `home-manager.homes`); a system is
|
||||
only a deploy target when `config.my.deploy.enable` is true (defaults true; auto-disabled for dev
|
||||
VMs and containers).
|
||||
VMs and containers). Pass `--boot` to stage a config as the boot default **without** live-switching
|
||||
(`deploy --boot .#<host>`) — the box keeps running its current generation until it reboots. Use this
|
||||
when a live `switch` would break connectivity mid-change (e.g. a router's WAN VLAN rework), then
|
||||
reboot to cut over.
|
||||
- `ssh-machine <name> [cmd]` — SSH to a NixOS system or home-manager config by name. Resolves the
|
||||
target and ssh options (identity, port) from its deploy-rs node, so it needs `my.deploy.enable`
|
||||
(same gate as `deploy`). Boxes default to the `fish` login shell, so pipe multi-statement remote
|
||||
scripts through `bash` (e.g. `ssh-machine <name> bash -s < script.sh`) rather than `&&`/`for`.
|
||||
If outbound SSH hangs at the publickey step (flaky `ssh-agent`), disable the agent for the call:
|
||||
`SSH_AUTH_SOCK= ssh-machine …` (or add `-o IdentityAgent=none` to a raw `ssh`).
|
||||
- `ragenix` — edit age secrets using `.keys/dev.key` as identity (see Secrets).
|
||||
- `repl` — `nix repl .#`.
|
||||
- `update-nixpkgs` / `update-home-manager` — bump pinned inputs.
|
||||
@@ -115,6 +127,20 @@ box file, not `routing-common`.
|
||||
easy to mix up. Set an interface MTU via the `.network`'s `linkConfig.MTUBytes` (`[Link]`), not
|
||||
`netdevConfig` (`[NetDev]` rejects `MTUBytes`).
|
||||
|
||||
### Home switches (`jim` / `dave` / `brian`)
|
||||
The home boxes and the Digiweb WAN hang off hand-configured switches that are **not** managed by
|
||||
this flake: `jim` and `dave` (MikroTik, RouterOS) and `brian` (Ubiquiti, UniFi). The full topology,
|
||||
VLAN map, and the ONT/WAN path live in **`home-switches.md`** at the repo root — read it before
|
||||
touching anything WAN/VLAN-related, and update it when the switch layout changes.
|
||||
- **Access:** the switches resolve by **short hostname** on the home network (the routers serve
|
||||
their records in the home zone — `routing-common/dns.nix`: `jim`/`dave`/`brian`). From a home box,
|
||||
SSH to the MikroTiks as `admin`/`admin` (e.g. `ssh admin@jim`); `brian` is configured via the
|
||||
UniFi controller, not a CLI.
|
||||
- **Changing switch config is out-of-band and hard to revert — always confirm before applying:**
|
||||
print the affected menu, make the change, then re-verify. The nix config and the switches must
|
||||
agree on VLAN numbering (e.g. `lib.my.c.home.vlans`), so a switch-side change usually pairs with a
|
||||
box change; `home-switches.md` documents the switch layout and per-switch config for the WAN design.
|
||||
|
||||
## Secrets
|
||||
|
||||
age-encrypted secrets in `secrets/`, managed with **ragenix**. Each module declares
|
||||
@@ -130,6 +156,9 @@ private keys) is required for editing secrets, deploying, and running dev VMs.
|
||||
**Ask before running `fmt`** — some files aren't canonically formatted, so `fmt` can reindent a
|
||||
whole file and bury a logical change in whitespace churn. Match the surrounding style by hand and
|
||||
leave formatting to the user unless they ask.
|
||||
- Comment where it genuinely aids understanding, but not for trivial/obvious code — match the file's
|
||||
existing (fairly sparse) comment density. When adding something general, comment its general
|
||||
purpose, not the specific change or one-off reason it was introduced for.
|
||||
- Prefer `lib.my` helpers (`mkOpt'`, `mkBoolOpt'`, `mkDefault'`) and `lib.my.c` constants over
|
||||
reimplementing.
|
||||
- New shared functionality → a module in `*/modules/` + entry in `_list.nix`, options under `my.*`.
|
||||
|
||||
+5
-3
@@ -314,9 +314,11 @@ rec {
|
||||
wan = 130;
|
||||
|
||||
# Digiweb delivers the ISP VLAN (pon-isp, 10) single-tagged at the ONT alongside the ONT's
|
||||
# own untagged management traffic. The switch feeding river tags the untagged ONT port as
|
||||
# wan-pon-ont (140) and swaps ingress VLAN 10 to wan-pon-isp (141), so river sees both
|
||||
# single-tagged and never has to touch VLAN 10 itself (PPPoE runs on wan-pon-isp).
|
||||
# own untagged management traffic. With a single ONT we trunk pon-isp (10) straight through
|
||||
# the switches to river (PPPoE runs directly on it), and the switch at the ONT edge PVIDs the
|
||||
# untagged management port onto wan-pon-ont (140). wan-pon-isp (141) is reserved for the
|
||||
# future multi-ONT case, where per-port VLAN translation on a dedicated switch swaps each
|
||||
# ONT's VLAN 10 to a distinct fabric VLAN (see home-switches.md).
|
||||
pon-isp = 10;
|
||||
wan-pon-ont = 140;
|
||||
wan-pon-isp = 141;
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
inherit (lib.my.c.home) vlans domain prefixes roceBootModules routersPubV4;
|
||||
|
||||
# river reaches the ONT over its 100G `lan` uplink to the dave switch (which downlinks to
|
||||
# jim, where the ONT's fibre lands). Digiweb delivers the ISP VLAN (pon-isp, 10) single-tagged
|
||||
# at the ONT alongside the ONT's untagged management traffic. The switch tags the ONT's
|
||||
# untagged port as wan-pon-ont (140) and swaps the ISP's VLAN 10 to wan-pon-isp (141) on
|
||||
# ingress, so both arrive at river single-tagged and PPPoE runs directly on wan-pon-isp.
|
||||
# brian, where the ONT lands). Digiweb delivers the ISP VLAN (pon-isp, 10) single-tagged at
|
||||
# the ONT alongside the ONT's untagged management traffic. With a single ONT there's no VLAN
|
||||
# collision, so the switches simply trunk the ISP's VLAN 10 straight through to river (PPPoE
|
||||
# runs directly on it) and PVID the ONT's untagged management port onto wan-pon-ont (140).
|
||||
# river takes .100 in the ONT's /24 (matching stream's modem-mgmt .100) to reach its web
|
||||
# UI at 192.168.100.1.
|
||||
# UI at 192.168.100.1. (See home-switches.md for the switch side and the multi-ONT plan.)
|
||||
ontV4 = net.cidr.host 100 prefixes.ont.v4;
|
||||
|
||||
# river is routing-common index 0; the Digiweb static IP we request via IPCP
|
||||
@@ -148,7 +148,8 @@
|
||||
systemd.network = {
|
||||
netdevs = mkMerge [
|
||||
(mkVLAN "wan-pon-ont" vlans.wan-pon-ont)
|
||||
(mkVLAN "wan-pon-isp" vlans.wan-pon-isp)
|
||||
# The ISP VLAN is trunked through untranslated, so this is the raw pon-isp (10)
|
||||
(mkVLAN "wan-pon-isp" vlans.pon-isp)
|
||||
];
|
||||
|
||||
links = {
|
||||
@@ -180,13 +181,15 @@
|
||||
|
||||
networks = {
|
||||
"55-lan" = {
|
||||
# both WAN VLANs arrive single-tagged on the 100G uplink to dave
|
||||
# both WAN VLANs arrive single-tagged on the 100G uplink to dave: wan-pon-ont (140,
|
||||
# the ONT's management, PVID-tagged at the brian edge) and the ISP's VLAN 10, trunked
|
||||
# straight through
|
||||
vlan = [ "wan-pon-ont" "wan-pon-isp" ];
|
||||
};
|
||||
# So we don't drop the IP we use to connect to NVMe-oF!
|
||||
"60-lan-hi".networkConfig.KeepConfiguration = "static";
|
||||
|
||||
# ONT management: the switch tags the ONT's untagged port as wan-pon-ont, so give
|
||||
# ONT management: the brian edge PVIDs the ONT's untagged port onto wan-pon-ont, so give
|
||||
# ourselves an address in its /24 to reach the ONT's web UI at 192.168.100.1.
|
||||
"70-wan-pon-ont" = {
|
||||
matchConfig.Name = "wan-pon-ont";
|
||||
@@ -196,8 +199,8 @@
|
||||
MTUBytes = "1500";
|
||||
};
|
||||
};
|
||||
# pppd attaches PPPoE to this; just needs to be up with no L3. Carries the ISP's
|
||||
# VLAN 10, swapped to wan-pon-isp by the switch (see "55-lan").
|
||||
# pppd attaches PPPoE to this; just needs to be up with no L3. This is the ISP's
|
||||
# VLAN 10 trunked straight through from the ONT (no switch translation; see "55-lan").
|
||||
"71-wan-pon-isp" = {
|
||||
matchConfig.Name = "wan-pon-isp";
|
||||
linkConfig = {
|
||||
|
||||
Reference in New Issue
Block a user