From a7ea91f52943c23cbcaba4a9848bcb5b1d728dca Mon Sep 17 00:00:00 2001 From: Jack O'Sullivan Date: Sun, 14 Jun 2026 22:40:13 +0100 Subject: [PATCH] docs: Document the boxes Add a top-level `README.md` mapping the boxes and per-machine docs under `docs/boxes/` (grouped `colony/`, `home/`, `misc/`), one file per host, VM and container documenting role, services and networking with source pointers. Also point `AGENTS.md` at the new docs. Co-Authored-By: Claude Opus 4.8 --- AGENTS.md | 9 ++- README.md | 80 +++++++++++++++++++++++++++ docs/boxes/colony/README.md | 68 +++++++++++++++++++++++ docs/boxes/colony/chatterbox.md | 19 +++++++ docs/boxes/colony/colony-psql.md | 18 ++++++ docs/boxes/colony/colony.md | 39 +++++++++++++ docs/boxes/colony/estuary.md | 41 ++++++++++++++ docs/boxes/colony/gam.md | 17 ++++++ docs/boxes/colony/git.md | 38 +++++++++++++ docs/boxes/colony/jackflix.md | 25 +++++++++ docs/boxes/colony/middleman.md | 63 +++++++++++++++++++++ docs/boxes/colony/object.md | 24 ++++++++ docs/boxes/colony/qclk.md | 22 ++++++++ docs/boxes/colony/shill.md | 48 ++++++++++++++++ docs/boxes/colony/toot.md | 19 +++++++ docs/boxes/colony/vaultwarden.md | 15 +++++ docs/boxes/colony/waffletail.md | 19 +++++++ docs/boxes/colony/whale2.md | 27 +++++++++ docs/boxes/home/README.md | 44 +++++++++++++++ docs/boxes/home/castle.md | 19 +++++++ docs/boxes/home/cellar.md | 39 +++++++++++++ docs/boxes/home/hass.md | 18 ++++++ docs/boxes/home/palace.md | 21 +++++++ docs/boxes/home/river.md | 25 +++++++++ docs/boxes/home/sfh.md | 24 ++++++++ docs/boxes/home/stream.md | 19 +++++++ docs/boxes/home/unifi.md | 23 ++++++++ docs/boxes/misc/README.md | 21 +++++++ docs/boxes/misc/britnet.md | 21 +++++++ docs/boxes/misc/britway.md | 27 +++++++++ docs/boxes/misc/installer.md | 19 +++++++ docs/boxes/misc/kelder-acquisition.md | 20 +++++++ docs/boxes/misc/kelder-spoder.md | 17 ++++++ docs/boxes/misc/kelder.md | 24 ++++++++ docs/boxes/misc/tower.md | 16 ++++++ 35 files changed, 986 insertions(+), 2 deletions(-) create mode 100644 README.md create mode 100644 docs/boxes/colony/README.md create mode 100644 docs/boxes/colony/chatterbox.md create mode 100644 docs/boxes/colony/colony-psql.md create mode 100644 docs/boxes/colony/colony.md create mode 100644 docs/boxes/colony/estuary.md create mode 100644 docs/boxes/colony/gam.md create mode 100644 docs/boxes/colony/git.md create mode 100644 docs/boxes/colony/jackflix.md create mode 100644 docs/boxes/colony/middleman.md create mode 100644 docs/boxes/colony/object.md create mode 100644 docs/boxes/colony/qclk.md create mode 100644 docs/boxes/colony/shill.md create mode 100644 docs/boxes/colony/toot.md create mode 100644 docs/boxes/colony/vaultwarden.md create mode 100644 docs/boxes/colony/waffletail.md create mode 100644 docs/boxes/colony/whale2.md create mode 100644 docs/boxes/home/README.md create mode 100644 docs/boxes/home/castle.md create mode 100644 docs/boxes/home/cellar.md create mode 100644 docs/boxes/home/hass.md create mode 100644 docs/boxes/home/palace.md create mode 100644 docs/boxes/home/river.md create mode 100644 docs/boxes/home/sfh.md create mode 100644 docs/boxes/home/stream.md create mode 100644 docs/boxes/home/unifi.md create mode 100644 docs/boxes/misc/README.md create mode 100644 docs/boxes/misc/britnet.md create mode 100644 docs/boxes/misc/britway.md create mode 100644 docs/boxes/misc/installer.md create mode 100644 docs/boxes/misc/kelder-acquisition.md create mode 100644 docs/boxes/misc/kelder-spoder.md create mode 100644 docs/boxes/misc/kelder.md create mode 100644 docs/boxes/misc/tower.md diff --git a/AGENTS.md b/AGENTS.md index ce454eb..2163f19 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,8 +4,8 @@ This file provides guidance to coding agents when working with code in this repo ## Overview -Personal Nix flake managing NixOS systems and home-manager configurations for a fleet of -machines (servers, home boxes, routers). It is built around a **custom module system** layered +Personal Nix flake managing NixOS systems and home-manager configurations for a set of +machines ("boxes": servers, home machines, routers). It is built around a **custom module system** layered on top of NixOS/home-manager, not the stock flake `nixosConfigurations` pattern. ## Commands @@ -91,6 +91,11 @@ Per-host configs live under `nixos/boxes/` (some are single `.nix` files, with nested VMs/containers under e.g. `colony/vms`). Many "systems" are VMs or containers managed via the `vms` / `containers` modules and the `l2mesh` VXLAN module. +For a human-readable map of what is actually deployed (per-machine roles, services and networking), +see `README.md` and the per-machine docs under `docs/boxes/` (grouped `docs/boxes/colony/`, +`docs/boxes/home/`, `docs/boxes/misc/`). Keep these in sync when adding, removing or repurposing +a machine or service. + ## Secrets age-encrypted secrets in `secrets/`, managed with **ragenix**. Each module declares diff --git a/README.md b/README.md new file mode 100644 index 0000000..962b70d --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +# nixfiles + +Personal Nix flake managing every machine I run: hosted servers, home +infrastructure, routers, a remote site, VPSes and personal workstations. It is +built around a **custom module system** layered on top of NixOS and +home-manager rather than the stock per-host `nixosConfigurations` pattern. + +For day-to-day commands and a deeper explanation of the module system, +conventions and secrets, see [`AGENTS.md`](AGENTS.md). This README is the map of +**what is actually deployed**; the per-machine details live under [`docs/boxes/`](docs/boxes). + +> **Note:** This documentation (the README and everything under `docs/`) is a +> work in progress and was **agent-generated** from the repository. It may be +> incomplete or out of date — treat the Nix configuration as the source of truth. + +## The boxes at a glance + +Machines are grouped by deployment/location. Each group has its own directory +under `docs/boxes/` with a `README.md` overview and one file per machine. + +| Group | What it is | Docs | +| --- | --- | --- | +| **colony** | Hosted dedicated server in Amsterdam (`ams1`). A VM host running the public-facing infrastructure: routing, web, git, media, object storage, chat, game servers. | [`docs/boxes/colony/`](docs/boxes/colony) | +| **home** | Home network: a VM host (`palace`), the home routers, storage, Home Assistant, and personal desktops. | [`docs/boxes/home/`](docs/boxes/home) | +| **misc** | Everything else: edge VPSes (`britway`, `britnet`), the remote `kelder` site, the `tower` workstation, and the installer image. | [`docs/boxes/misc/`](docs/boxes/misc) | + +## The "big machine" pattern + +The larger sites (`colony`, `home`) all follow the same shape: + +``` +physical host (VM host) +├── VM ── thing impractical to containerise (router, storage, podman host, …) +├── VM ── container host ──┬── NixOS container ── application +│ ├── NixOS container ──┬── application +│ │ ├── application +│ │ └── application +│ └── … +└── VM ── … +``` + +- A **physical host** (`colony`, `palace`) does little itself beyond running + **VMs** via the custom `my.vms` module (QEMU + systemd units, LVM-backed + disks). +- **VMs** exist for things that are impractical to put in a container — kernel + features, separate networking, podman/OCI workloads, foreign OSes. +- One VM is usually a **container host** (`shill` on colony, `sfh` on home; and + `kelder` directly). It runs **NixOS containers** via the custom `my.containers` + module (systemd-nspawn based, each with its own address on a bridge). +- **Most applications live in those NixOS containers.** A container isn't limited + to a single application — it commonly hosts a **group of related applications** + that belong together (e.g. `jackflix` runs Jellyfin, the *arr stack, + Transmission, PhotoPrism and copyparty; `object` runs MinIO, Harmonia, HedgeDoc + and wastebin). Each container is a first-class entry in `docs/boxes/`. + +Networking between everything is largely defined by per-system `assignments` +(IPs/prefixes) plus an L2 VXLAN mesh (`my.vpns.l2`, AS211024) that ties the edge +routers together. See [`AGENTS.md`](AGENTS.md) for the mechanics. + +## Repo layout + +``` +README.md <- you are here +nixos/ + boxes/ per-machine configuration ("boxes") + colony/ colony host + its VMs (vms/) + shill's containers + home/ palace host + its VMs, plus stream, castle + britway/ britnet.nix, kelder/, tower/, installer.nix … + modules/ shared NixOS modules (my.* options); registered in _list.nix +home-manager/ home-manager modules + configs +lib/ lib.my helpers, constants (lib.my.c), net/dns helpers +pkgs/ custom packages (overlays.default) +secrets/ age-encrypted secrets (ragenix) +devshell/ devshell commands (build/deploy/check/ssh helpers) +docs/boxes/ per-machine documentation (colony/, home/, misc/) +``` + +A machine is wired into the flake by adding its box file to the `configs` list +in `flake.nix`. See [`AGENTS.md`](AGENTS.md#architecture) for how `evalModules` +turns these into `nixosConfigurations`, `homeConfigurations` and `deploy` nodes. diff --git a/docs/boxes/colony/README.md b/docs/boxes/colony/README.md new file mode 100644 index 0000000..94ee605 --- /dev/null +++ b/docs/boxes/colony/README.md @@ -0,0 +1,68 @@ +# colony + +The hosted dedicated server in Amsterdam (`ams1`). This is the public-facing +half of the boxes: almost everything reachable from the internet lives here. + +- **Internal domain:** `ams1.int.nul.ie` +- **Public domain:** `nul.ie` (public services are published as `*.nul.ie`) +- **Source:** [`nixos/boxes/colony/`](../../../nixos/boxes/colony) + +## Shape + +`colony` is the physical VM host. It runs the VMs below; one of them (`shill`) +is itself a NixOS container host where most applications run. + +``` +colony (physical VM host) +├── estuary ── edge router / firewall / DNS / BGP +├── shill ──── NixOS container host ──┬── middleman (reverse proxy, ACME, SSO) +│ ├── colony-psql (shared PostgreSQL) +│ ├── vaultwarden (password manager) +│ ├── chatterbox (Matrix + bridges) +│ ├── toot (Mastodon) +│ ├── jackflix (media stack) +│ ├── object (MinIO, Nix cache, …) +│ ├── waffletail (Tailscale subnet router) +│ ├── qclk (clock service) +│ └── gam (game servers) +├── whale2 ─── podman/OCI host (game servers) +├── git ────── Gitea + Actions runner +├── mail ───── Debian VM running Mailcow (not NixOS — configured out of repo) +└── darts ──── third-party/customer VM (opaque to this repo) +``` + +## Machines + +| Machine | Role | Docs | +| --- | --- | --- | +| `colony` | Physical VM host (AMD, LVM-thin, borgthin backups → rsync.net) | [colony.md](colony.md) | +| `estuary` | Edge router: WAN, firewall/NAT, DNS, BGP, IXP peering, WireGuard | [estuary.md](estuary.md) | +| `shill` | NixOS container host (see containers below) | [shill.md](shill.md) | +| `whale2` | podman/OCI host for game servers | [whale2.md](whale2.md) | +| `git` | Gitea + Gitea Actions runner | [git.md](git.md) | + +### shill containers + +| Container | Role | Docs | +| --- | --- | --- | +| `middleman` | Front-end nginx reverse proxy, ACME certs, nginx-sso, librespeed | [middleman.md](middleman.md) | +| `colony-psql` | Shared PostgreSQL (14) for colony services | [colony-psql.md](colony-psql.md) | +| `vaultwarden` | Vaultwarden (Bitwarden-compatible password manager) | [vaultwarden.md](vaultwarden.md) | +| `chatterbox` | Matrix homeserver + bridges (heisenbridge, mautrix-*) | [chatterbox.md](chatterbox.md) | +| `toot` | Bluesky PDS (Mastodon disabled) | [toot.md](toot.md) | +| `jackflix` | Media: Jellyfin, *arr stack, Transmission, PhotoPrism, copyparty | [jackflix.md](jackflix.md) | +| `object` | MinIO (S3), Harmonia (Nix cache), HedgeDoc, wastebin | [object.md](object.md) | +| `waffletail` | Tailscale subnet router (advertises colony prefixes into the tailnet) | [waffletail.md](waffletail.md) | +| `qclk` | `qclk` clock service (reachable over WireGuard) | [qclk.md](qclk.md) | +| `gam` | Game servers (Terraria, …) | [gam.md](gam.md) | + +## Non-NixOS VMs + +These run on `colony` but are **not** managed by this repo (no NixOS config). The +QEMU instances are still declared in `colony`'s `my.vms.instances`, and colony's +networking routes/firewalls traffic to them: + +- **`mail`** — a Debian VM running [Mailcow](https://mailcow.email/) (`mail.nul.ie`). + ACME certs are pushed to it from `middleman` (see [middleman.md](middleman.md)). +- **`darts`** — a third-party/customer VM; opaque to this repo, given a routed + prefix and otherwise left alone. diff --git a/docs/boxes/colony/chatterbox.md b/docs/boxes/colony/chatterbox.md new file mode 100644 index 0000000..1dec117 --- /dev/null +++ b/docs/boxes/colony/chatterbox.md @@ -0,0 +1,19 @@ +# chatterbox + +The Matrix homeserver (`nul.ie`) and its chat-network bridges. + +- **Source:** [`shill/containers/chatterbox.nix`](../../../nixos/boxes/colony/vms/shill/containers/chatterbox.nix) +- **Host:** NixOS container on `shill` + +## Role + +- **Matrix homeserver** for `server_name = "nul.ie"`. +- **Bridges** to other chat networks: + - `heisenbridge` (IRC), + - `mautrix-whatsapp` (WhatsApp), + - `mautrix-meta` / `mautrix-messenger` (Facebook Messenger / Instagram). +- Fronted by `middleman` (federation on `:8448`). + +## Networking + +- `internal` assignment on the `ctrs` network (alt name `chatterbox-ctr`). diff --git a/docs/boxes/colony/colony-psql.md b/docs/boxes/colony/colony-psql.md new file mode 100644 index 0000000..9451196 --- /dev/null +++ b/docs/boxes/colony/colony-psql.md @@ -0,0 +1,18 @@ +# colony-psql + +The shared PostgreSQL instance for colony. Several other containers +(`middleman`, `chatterbox`, `toot`, `git`, …) connect here rather than each +running their own database. + +- **Source:** [`shill/containers/colony-psql.nix`](../../../nixos/boxes/colony/vms/shill/containers/colony-psql.nix) +- **Host:** NixOS container on `shill` + +## Role + +- **PostgreSQL 14** serving the other colony services over the `ctrs` network. + Consumers wait for it to be ready via the `systemdAwaitPostgres` helper. +- netdata for monitoring. + +## Networking + +- `internal` assignment on the `ctrs` network (alt name `colony-psql-ctr`). diff --git a/docs/boxes/colony/colony.md b/docs/boxes/colony/colony.md new file mode 100644 index 0000000..58c6a31 --- /dev/null +++ b/docs/boxes/colony/colony.md @@ -0,0 +1,39 @@ +# colony (host) + +The physical dedicated server in Amsterdam and the VM host for everything in +this group. + +- **Source:** [`nixos/boxes/colony/default.nix`](../../../nixos/boxes/colony/default.nix) + (VM instances in [`nixos/boxes/colony/vms/default.nix`](../../../nixos/boxes/colony/vms/default.nix)) +- **nixpkgs:** `mine-stable` + +## Role + +Bare-metal AMD host. It does little application work itself — its job is to run +the VMs and provide them with storage, networking and backups. + +- **Virtualisation:** QEMU/KVM (`kvm-amd`, IOMMU on) via the `my.vms` module. VM + disks are LVM logical volumes (`vm--`) in the `main` volume group; + `estuary` additionally gets a WAN NIC by PCI passthrough. +- **Storage:** LVM-thin (`services.lvm.boot.thin`), `/persist` for state, + `/mnt/backup` for the local borg repo. `smartd` + `rasdaemon` for health. +- **Backups:** `my.borgthin` snapshots the persist/data LVs of the host and its + VMs into `/mnt/backup/main`, which is then `rsync`'d (along with LVM metadata) + to rsync.net (`zh2855.rsync.net`). +- **Monitoring:** netdata (with freeipmi), smartd. + +## Networking + +- Two bridges: `base` (the colony "base" network, shared with `estuary`) and + `vms` (the VM network). Dummy interfaces keep the bridges up so dependent VMs + can start. +- Default gateway / edge is `estuary`; `colony` itself holds the `routing` and + `internal` (a.k.a. `vm`) assignments and routes container/OCI/Tailscale + prefixes to `shill` and `whale2`. +- `my.firewall` trusts the `vms` interface and forwards customer prefixes + (`vm-mail`, `vm-darts`) through. + +## VMs hosted here + +`estuary`, `shill`, `whale2`, `git` (all NixOS, documented in this directory), +plus the non-NixOS `mail` and `darts` (see [README](README.md#non-nixos-vms)). diff --git a/docs/boxes/colony/estuary.md b/docs/boxes/colony/estuary.md new file mode 100644 index 0000000..f7161aa --- /dev/null +++ b/docs/boxes/colony/estuary.md @@ -0,0 +1,41 @@ +# estuary + +The colony edge router and firewall — the machine that holds colony's public +IPs and connects everything else to the internet. + +- **Source:** [`nixos/boxes/colony/vms/estuary/`](../../../nixos/boxes/colony/vms/estuary) + (`default.nix`, `bgp.nix`, `dns.nix`, `bandwidth.nix`) +- **nixpkgs:** `mine` +- **Host:** VM on `colony` (gets the WAN NIC by PCI passthrough) + +## Role + +- **Edge routing / firewall / NAT:** owns the colony public IPv4/IPv6 + (`94.142.241.x` / `2a02:898:0:20::`), does NAT and port-forwarding for the + internal services (`my.firewall.nat.forwardPorts` driven by + `firewallForwards`). Forwards HTTP/S to `middleman`, git to `git`, game ports + to the OCI game servers on `whale2`, etc. +- **BGP:** runs BIRD2 ([`bgp.nix`](../../../nixos/boxes/colony/vms/estuary/bgp.nix)) + announcing AS211024, over VLANs on the WAN link: + - peers at the IXPs **Frys-IX**, **NL-ix** and **FogIXP**; + - plus **iFog transit** (`ifog-transit`) — an upstream transit provider from + iFog, **not** an IXP. +- **DNS:** authoritative/recursive DNS ([`dns.nix`](../../../nixos/boxes/colony/vms/estuary/dns.nix)), + redirected to port 5353 locally. +- **VPNs:** + - Part of the AS211024 **L2 VXLAN mesh** (`my.vpns.l2`) with `river`, `stream` + and `britway`. + - WireGuard endpoints for the remote `kelder` site, `hillcrest`, and + `john-valorant`. +- **Misc:** iperf3 server. (A bandwidth-accounting script, + [`bandwidth.py`](../../../nixos/boxes/colony/vms/estuary/bandwidth.py), exists but + is **legacy and not currently used**.) + +## Networking + +- `wan` — the passed-through igb NIC (9000 MTU), carrying the upstream uplink and + tagged IXP VLANs (`ifog` 409 → `frys-ix`/`nl-ix`/`fogixp`/`ifog-transit`). +- `base` — colony base network; sends RAs and provides DNS to the base prefix, + routes the VM/container/OCI/Tailscale prefixes back to `colony`. +- `as211024` — the L2 mesh interface. +- Assignments: `internal` (public, alt name `fw`), `base`, `as211024`. diff --git a/docs/boxes/colony/gam.md b/docs/boxes/colony/gam.md new file mode 100644 index 0000000..c4c325d --- /dev/null +++ b/docs/boxes/colony/gam.md @@ -0,0 +1,17 @@ +# gam + +A game-server container (the lightweight counterpart to the OCI game servers on +`whale2`). + +- **Source:** [`shill/containers/gam.nix`](../../../nixos/boxes/colony/vms/shill/containers/gam.nix) +- **Host:** NixOS container on `shill` + +## Role + +- Hosts game servers run directly as NixOS services — currently **Terraria** + (config/world from secrets). Exposed to the internet via `estuary`'s port + forwards (`:7777`). + +## Networking + +- `internal` assignment on the `ctrs` network (alt name `gam-ctr`). diff --git a/docs/boxes/colony/git.md b/docs/boxes/colony/git.md new file mode 100644 index 0000000..f61fcec --- /dev/null +++ b/docs/boxes/colony/git.md @@ -0,0 +1,38 @@ +# git + +The Gitea VM — source hosting and CI for the boxes (`git.nul.ie`). + +- **Source:** [`nixos/boxes/colony/vms/git/`](../../../nixos/boxes/colony/vms/git) + (`default.nix`, `gitea.nix`, `gitea-actions.nix`) +- **nixpkgs:** `mine` +- **Host:** VM on `colony` + +## Role + +- **Gitea** ([`gitea.nix`](../../../nixos/boxes/colony/vms/git/gitea.nix)) — the Git + forge (`git.nul.ie`). PostgreSQL-backed (the shared `colony-psql`), LFS + enabled, with object storage backed by MinIO on `object` (a MinIO secret is + spliced into `app.ini` at startup). +- **Gitea Actions runner** + ([`gitea-actions.nix`](../../../nixos/boxes/colony/vms/git/gitea-actions.nix)) — a + Docker-mode runner (`main-docker`) using podman. Labels provide Debian/node-24 + (Trixie) and Ubuntu 26.04 images; runner config comes from the upstream + module's `settings` option. The Actions cache lives on a dedicated disk + (`/var/cache/gitea-runner`). Runs as a fixed `gitea-runner` user (not + `DynamicUser`) so it can read its token. +- **nginx** — terminates TLS for `git.nul.ie` and proxies to Gitea on `:3000`. + ACME certs for `nul.ie` / `*.nul.ie` via the Cloudflare DNS challenge. +- **podman** — also hosts the OCI registry/build images; `/var/lib/containers` + is an XFS data disk. + +## Networking + +- `vms` interface with `routing` / `internal` assignments. +- HTTP/HTTPS forwarded in from `estuary`; podman default subnet `10.88.0.0/16` is + allowed to forward. + +## CI + +This runner is what executes the repo's own `.gitea/workflows/ci.yaml`, building +each `.#ci.x86_64-linux` attribute and pushing to the Harmonia binary cache. See +[`AGENTS.md`](../../../AGENTS.md#commands). diff --git a/docs/boxes/colony/jackflix.md b/docs/boxes/colony/jackflix.md new file mode 100644 index 0000000..423ef1f --- /dev/null +++ b/docs/boxes/colony/jackflix.md @@ -0,0 +1,25 @@ +# jackflix + +The media stack — acquisition, library and streaming. + +- **Source:** [`shill/containers/jackflix/`](../../../nixos/boxes/colony/vms/shill/containers/jackflix) + (`default.nix`, `networking.nix`) +- **Host:** NixOS container on `shill` + +## Role + +- **Streaming:** Jellyfin. +- **Acquisition (*arr stack):** Transmission, Jackett, FlareSolverr, Radarr, + Sonarr, and Jellyseerr (`seerr`) for requests. +- **Photos:** PhotoPrism (`photos.nul.ie`). +- **File sharing:** copyparty (`:3923`) serving public + private media volumes. +- Media lives on the shared `/mnt/media` volume (bind-mounted read-write from + `shill`). Downloaders bind to a VPN interface + ([`networking.nix`](../../../nixos/boxes/colony/vms/shill/containers/jackflix/networking.nix)), + so torrent traffic only flows while `systemd-networkd-wait-online@vpn` is up. +- A shared `media` group (gid 2000) gives the apps coordinated access. + +## Networking + +- `internal` assignment on the `ctrs` network (alt name `jackflix-ctr`), plus its + own VPN interface for the download clients. diff --git a/docs/boxes/colony/middleman.md b/docs/boxes/colony/middleman.md new file mode 100644 index 0000000..1e1c9ca --- /dev/null +++ b/docs/boxes/colony/middleman.md @@ -0,0 +1,63 @@ +# middleman + +The front-end reverse proxy for all public colony web services — the single +ingress that `estuary` forwards HTTP/HTTPS to. + +- **Source:** [`shill/containers/middleman/`](../../../nixos/boxes/colony/vms/shill/containers/middleman) + (`default.nix`, `vhosts.nix`) +- **Host:** NixOS container on `shill` + +## Role + +- **nginx** reverse proxy ([`vhosts.nix`](../../../nixos/boxes/colony/vms/shill/containers/middleman/vhosts.nix) + holds the per-service vhosts) with VTS stats, fancyindex, brotli, caching, and + a dynamic resolver pointed at `estuary` so upstreams can be re-resolved at + runtime. It is the single public ingress for almost every web service — colony, + home, and beyond. +- **ACME** — issues the wildcard certificates that **its own** vhosts are served + with (it is not a shared CA for the other boxes; `git`, `britway`, `kelder-spoder`, etc. each + run their own ACME): + - `nul.ie` / `*.nul.ie` (+ `*.s3.nul.ie`) via the Cloudflare DNS challenge, + - the internal `ams1.int.nul.ie` / `*` via an `exec` challenge that calls + `estuary`'s pdns over SSH. + - As a one-off consumer, it then pushes the public cert to the `mail` (Mailcow) + VM via `scp` + a remote `mailcow-ssl-reload`. +- **nginx-sso** — single-sign-on (`sso.nul.ie`) with Google OAuth and a simple + username/password provider; protects the SSO-gated vhosts below. +- **librespeed** — speed-test frontend + backend (`librespeed.${domain}` / + `speed.nul.ie`). + +## Published vhosts + +All under `*.nul.ie` with the wildcard cert unless noted. Upstreams are addressed +by their internal container/VM hostnames. "SSO" = gated behind nginx-sso. + +| Host(s) | Upstream | Notes | +| --- | --- | --- | +| `nul.ie` (default `_`) | static | landing page (CV, SSH pubkey) + Matrix/atproto `.well-known` | +| `sso.nul.ie` | nginx-sso | SSO endpoint | +| `pass.nul.ie` | `vaultwarden` | password manager | +| `matrix.nul.ie` (+`:8448`) | `chatterbox` | Matrix client + federation | +| `element.nul.ie` | element-web | Matrix web client | +| `toot.nul.ie` | `toot` :80 | Mastodon (currently disabled — see [toot.md](toot.md)) | +| `pds.nul.ie` | `toot` :3000 | Bluesky PDS | +| `jackflix.nul.ie` | `jackflix` Jellyfin | streaming | +| `torrents` / `jackett` / `radarr` / `sonarr` `.nul.ie` | `jackflix` | *arr stack (**SSO**) | +| `gib.nul.ie` | `jackflix` Jellyseerr | requests | +| `photos.nul.ie` | `jackflix` PhotoPrism | | +| `stuff` / `public` / `p.nul.ie` | `jackflix` copyparty + `/mnt/media` | file sharing / index | +| `share.nul.ie` | `object` :9090 | | +| `minio` / `s3` / `*.s3.nul.ie` | `object` MinIO | S3 + console (Docker manifest MIME hack) | +| `nix-cache.nul.ie` | `object` Harmonia | Nix binary cache (immutable cache headers) | +| `md.nul.ie` / `pb.nul.ie` | `object` | HedgeDoc / wastebin | +| `mc-map` / `mc-rail` / `mc-map-kink` `.nul.ie` | `whale2` OCI | Minecraft maps | +| `netdata-colony.nul.ie` | many hosts :19999 | netdata fan-out (**SSO**) | +| `pront.nul.ie` | `stream-hi` (home) | print/webcam (**SSO**) | +| `hass.nul.ie` | `hass` (home) | Home Assistant | +| `hass-john.nul.ie` | `john-valorant-tun` | remote HASS over WireGuard tunnel | + +## Networking + +- `internal` assignment on the `ctrs` network; bind-mounts `/mnt/media` for + serving static/media content. +- nginx waits for `colony-psql` before starting (DNS bootstrap hack). diff --git a/docs/boxes/colony/object.md b/docs/boxes/colony/object.md new file mode 100644 index 0000000..ee37cd0 --- /dev/null +++ b/docs/boxes/colony/object.md @@ -0,0 +1,24 @@ +# object + +Object storage and Nix binary cache, plus a couple of small self-hosted web +apps. + +- **Source:** [`shill/containers/object.nix`](../../../nixos/boxes/colony/vms/shill/containers/object.nix) +- **Host:** NixOS container on `shill` + +## Role + +- **MinIO** — S3-compatible object storage (`s3.nul.ie` / `*.s3.nul.ie`). Backs + several other services (Gitea LFS/artifacts, social-media uploads, …). Stored on the + `/mnt/minio` volume (XFS, bind-mounted from `shill`). +- **Harmonia** — serves the Nix binary cache for all the boxes (`nix-cache.nul.ie`), backed + by the `/mnt/nix-cache` volume. +- **atticd** — an alternative Nix cache (stores into MinIO/S3). **Currently + disabled** — present in the config but not running. +- **HedgeDoc** — collaborative markdown notes. +- **wastebin** — pastebin. + +## Networking + +- `internal` assignment on the `ctrs` network (alt name `object-ctr`). +- `/mnt/minio` and `/mnt/nix-cache` bind-mounted read-write from `shill`. diff --git a/docs/boxes/colony/qclk.md b/docs/boxes/colony/qclk.md new file mode 100644 index 0000000..8f0819c --- /dev/null +++ b/docs/boxes/colony/qclk.md @@ -0,0 +1,22 @@ +# qclk + +The `qclk` service container. + +- **Source:** [`shill/containers/qclk/`](../../../nixos/boxes/colony/vms/shill/containers/qclk) +- **Host:** NixOS container on `shill` + +## Role + +- Runs the custom `qclk` service, exposing an API that is reached over a + dedicated WireGuard **`management`** network. Managed devices are configured as + WireGuard peers (each gets an address in the `qclk` prefix), and AS211024 + trusted hosts are allowed to reach the API. +- `shill` routes the `qclk` prefix to this container. + +## Networking + +- `internal` assignment on the `ctrs` network (alt name `qclk-ctr`), plus the + `management` WireGuard interface carrying the `qclk` prefix. + +> Check `qclk/default.nix` for the current peer list and exactly what the service +> does — this entry intentionally stays high-level. diff --git a/docs/boxes/colony/shill.md b/docs/boxes/colony/shill.md new file mode 100644 index 0000000..6a1fec7 --- /dev/null +++ b/docs/boxes/colony/shill.md @@ -0,0 +1,48 @@ +# shill + +The colony **NixOS container host**. Most colony applications run as +systemd-nspawn containers on `shill`. + +- **Source:** [`nixos/boxes/colony/vms/shill/`](../../../nixos/boxes/colony/vms/shill) + (`default.nix`, `containers-ext.nix`, `hercules.nix`, `containers/`) +- **nixpkgs:** `mine` +- **Host:** VM on `colony` (large: 12 cores, 40 GiB RAM) + +## Role + +- Runs the colony NixOS containers via `my.containers.instances`, each attached + to the `ctrs` bridge with its own address. +- Provides shared data volumes to those containers via bind mounts from + LVM-backed disks: `/mnt/media` (→ `middleman`, `jackflix`), `/mnt/minio` and + `/mnt/nix-cache` (→ `object`). +- Acts as the router between the `vms` network and the `ctrs` container network + (sends RAs on `ctrs`, routes Tailscale prefixes via `waffletail` and the + `qclk` prefix via `qclk`). Includes an nftables `ct mark` hack to make + internal DNAT return paths work. +- Tuned sysctls for high connection counts / torrent traffic; netdata. + +## Containers + +Defined in [`shill/containers/`](../../../nixos/boxes/colony/vms/shill/containers) +and wired up in `shill`'s `my.containers.instances`: + +| Container | Role | +| --- | --- | +| [`middleman`](middleman.md) | Front-end nginx reverse proxy, ACME, nginx-sso, librespeed | +| [`colony-psql`](colony-psql.md) | Shared PostgreSQL | +| [`vaultwarden`](vaultwarden.md) | Password manager | +| [`chatterbox`](chatterbox.md) | Matrix homeserver + bridges | +| [`toot`](toot.md) | Bluesky PDS (Mastodon disabled) | +| [`jackflix`](jackflix.md) | Media stack | +| [`object`](object.md) | MinIO / Harmonia / HedgeDoc / wastebin | +| [`waffletail`](waffletail.md) | Tailscale subnet router | +| [`qclk`](qclk.md) | Clock service | +| [`gam`](gam.md) | Game servers | + +## Notes + +- Container systems set `my.deploy.enable = false` (they are deployed as part of + `shill`'s container profiles, not as standalone deploy nodes) and render via + `my.asContainer`. +- `hercules.nix` configures Hercules CI agent bits; + `containers-ext.nix` holds extra per-container host wiring. diff --git a/docs/boxes/colony/toot.md b/docs/boxes/colony/toot.md new file mode 100644 index 0000000..58a67af --- /dev/null +++ b/docs/boxes/colony/toot.md @@ -0,0 +1,19 @@ +# toot + +A federated-social container. Despite the name (Mastodon = "toots"), it currently +hosts a **Bluesky PDS**; the Mastodon instance is disabled. + +- **Source:** [`shill/containers/toot.nix`](../../../nixos/boxes/colony/vms/shill/containers/toot.nix) +- **Host:** NixOS container on `shill` + +## Role + +- **Bluesky PDS** (Personal Data Server) — the active service, published as + `pds.nul.ie` (proxied by `middleman` to `:3000`). +- **Mastodon** — **currently disabled**. The config is still present and + `toot.nul.ie` still maps to `:80`, but the instance is not running. (It was + backed by the shared `colony-psql` and MinIO/S3 on `object`.) + +## Networking + +- `internal` assignment on the `ctrs` network (alt name `toot-ctr`). diff --git a/docs/boxes/colony/vaultwarden.md b/docs/boxes/colony/vaultwarden.md new file mode 100644 index 0000000..37ef99a --- /dev/null +++ b/docs/boxes/colony/vaultwarden.md @@ -0,0 +1,15 @@ +# vaultwarden + +[Vaultwarden](https://github.com/dani-garcia/vaultwarden), a Bitwarden-compatible +password manager. + +- **Source:** [`shill/containers/vaultwarden.nix`](../../../nixos/boxes/colony/vms/shill/containers/vaultwarden.nix) +- **Host:** NixOS container on `shill` + +## Role + +- Runs Vaultwarden, fronted by `middleman` and published under `nul.ie`. + +## Networking + +- `internal` assignment on the `ctrs` network (alt name `vaultwarden-ctr`). diff --git a/docs/boxes/colony/waffletail.md b/docs/boxes/colony/waffletail.md new file mode 100644 index 0000000..2adea3f --- /dev/null +++ b/docs/boxes/colony/waffletail.md @@ -0,0 +1,19 @@ +# waffletail + +The colony Tailscale node / subnet router. + +- **Source:** [`shill/containers/waffletail.nix`](../../../nixos/boxes/colony/vms/shill/containers/waffletail.nix) +- **Host:** NixOS container on `shill` + +## Role + +- Joins the Tailscale tailnet (auth key from secrets) and **advertises the colony + prefixes** into it, acting as the subnet router so tailnet clients can reach + colony services and vice-versa. +- nftables rules SNAT/forward between `host0` and `tailscale0` for the colony + v4/v6 ranges. `shill` routes the Tailscale prefixes here. + +## Networking + +- `internal` assignment on the `ctrs` network (alt name `waffletail-ctr`); owns + the `tailscale0` interface. diff --git a/docs/boxes/colony/whale2.md b/docs/boxes/colony/whale2.md new file mode 100644 index 0000000..802f0f4 --- /dev/null +++ b/docs/boxes/colony/whale2.md @@ -0,0 +1,27 @@ +# whale2 + +A podman/OCI host on colony dedicated to game servers (kept off `shill` so the +container churn and resource use stay isolated). + +- **Source:** [`nixos/boxes/colony/vms/whale2/`](../../../nixos/boxes/colony/vms/whale2) + (`default.nix`, `valheim.nix`, `minecraft/`, `enshrouded.nix`) +- **nixpkgs:** `mine` +- **Host:** VM on `colony` + +## Role + +- Runs OCI containers via **podman** (`virtualisation.oci-containers`, netavark + backend) on a dedicated `colony` bridge network (`oci`) with both IPv4 and + IPv6, so each game server gets its own routable address. +- Game servers configured in-repo: **Valheim**, **Minecraft** (several worlds — + see `extraAssignments`: `simpcraft`, `simpcraft-staging`, `kevcraft`, + `kinkcraft`, `graeme`), and **Enshrouded** (currently commented out). +- `/var/lib/containers` is an XFS data disk (project quotas). + +## Networking + +- `vms` interface with `routing` / `internal` (alt name `oci`) assignments. +- An `oci` bridge carrying the `prefixes.oci` v4/v6 ranges; per-game addresses + are handed out via `extraAssignments` (`valheim-oci`, `simpcraft-oci`, …) and + exposed to the internet through `estuary`'s port forwards. +- Firewall trusts the `oci` interface and forwards `vms → oci`. diff --git a/docs/boxes/home/README.md b/docs/boxes/home/README.md new file mode 100644 index 0000000..c891cd7 --- /dev/null +++ b/docs/boxes/home/README.md @@ -0,0 +1,44 @@ +# home + +The home network. A VM host (`palace`), a redundant pair of routers, a storage +server, Home Assistant, and personal desktops. + +- **Domain:** `h.nul.ie` +- **Source:** [`nixos/boxes/home/`](../../../nixos/boxes/home) + +## Shape + +``` +palace (physical VM host) +├── river ──── home router (HA pair with stream) +├── cellar ── NVMe-oF storage server (SPDK) +└── sfh ───── NixOS container host ──┬── hass (Home Assistant) + └── unifi (UniFi controller — defined, currently disabled) + +stream ── standalone home router (HA pair with river) +castle ── desktop workstation (boots its disks over NVMe-oF from cellar) +``` + +The two routers `river` (a VM on `palace`) and `stream` (standalone hardware) +share the [`routing-common`](../../../nixos/boxes/home/routing-common) config and +form a **keepalived/VRRP high-availability pair**: DHCP (kea), router +advertisements (radvd), DNS with blocklists, NAT, and the AS211024 L2 mesh link +back to colony. + +## Machines + +| Machine | Role | Docs | +| --- | --- | --- | +| `palace` | Physical VM host | [palace.md](palace.md) | +| `river` | Home router (VM; VRRP pair with `stream`) | [river.md](river.md) | +| `cellar` | NVMe-oF storage server (SPDK) | [cellar.md](cellar.md) | +| `sfh` | NixOS container host | [sfh.md](sfh.md) | +| `stream` | Home router (standalone hardware; VRRP pair with `river`) | [stream.md](stream.md) | +| `castle` | Desktop workstation | [castle.md](castle.md) | + +### sfh containers + +| Container | Role | Docs | +| --- | --- | --- | +| `hass` | Home Assistant | [hass.md](hass.md) | +| `unifi` | UniFi network controller (defined, **currently not imported**) | [unifi.md](unifi.md) | diff --git a/docs/boxes/home/castle.md b/docs/boxes/home/castle.md new file mode 100644 index 0000000..75088c4 --- /dev/null +++ b/docs/boxes/home/castle.md @@ -0,0 +1,19 @@ +# castle + +A desktop workstation. + +- **Source:** [`nixos/boxes/home/castle/default.nix`](../../../nixos/boxes/home/castle/default.nix) + +## Role + +- AMD desktop running the GUI environment (`my.gui.enable`, Sway / Wayland via + home-manager). +- **Diskless-style boot:** its `/nix`, `/persist` and `/home` are NVMe-oF volumes + served by [`cellar`](cellar.md) (`/dev/nvmeof/{nix,persist,home}`). The + networking is careful not to drop the IP used for the NVMe-oF connection. +- Uses the `my.nvme` module for the NVMe-oF client setup. + +## Networking + +- Sits on the home network; depends on the high-speed link to `cellar` for its + root storage. diff --git a/docs/boxes/home/cellar.md b/docs/boxes/home/cellar.md new file mode 100644 index 0000000..df80c17 --- /dev/null +++ b/docs/boxes/home/cellar.md @@ -0,0 +1,39 @@ +# cellar + +The home storage server. Exports fast NVMe storage over the network so other +machines (notably `castle`) can boot and run from it. + +- **Source:** [`nixos/boxes/home/palace/vms/cellar/`](../../../nixos/boxes/home/palace/vms/cellar) + (`default.nix`, `spdk.nix`) +- **Host:** VM on `palace` (NVMe drives passed through) +- **Deploy address:** `192.168.68.80` + +## Role + +- Runs **SPDK** ([`spdk.nix`](../../../nixos/boxes/home/palace/vms/cellar/spdk.nix)) as + a userspace storage target. The kernel `nvme` driver is blacklisted so SPDK can + drive the NVMe devices directly (attached by PCI BDF). +- Builds a **RAID0** (`NVMeRaid`) across three NVMe drives, partitioned into three + namespaces, and exports each as an **NVMe-oF target over RDMA** (port 4420) on + the high-speed home network — one namespace per consumer: + + | Namespace | NQN | Consumer | + | --- | --- | --- | + | `NVMeRaidp1` | `nqn.2016-06.io.spdk:river` | [`river`](river.md) | + | `NVMeRaidp2` | `nqn.2016-06.io.spdk:castle` | [`castle`](castle.md) | + | `NVMeRaidp3` | `nqn.2016-06.io.spdk:sfh` | [`sfh`](sfh.md) | + + Each client is pinned by `hostnqn`, so `river`, `castle` and `sfh` all run their + storage off `cellar` over the network. + +## Networking + +- Exports on the high-speed home network (`lan-hi` / the `hi` assignment) over + RDMA; the SPDK target waits for that link to be online before starting. + +## Notes + +- The `ublk_*` calls in `my.spdk.debugCommands` are **only a debugging script** — + they let you create a local ublk block device to mount and inspect the RAID on + `cellar` itself. They are **not** how storage is exported to clients; that is the + `nvmf` config above. diff --git a/docs/boxes/home/hass.md b/docs/boxes/home/hass.md new file mode 100644 index 0000000..5a82af1 --- /dev/null +++ b/docs/boxes/home/hass.md @@ -0,0 +1,18 @@ +# hass + +[Home Assistant](https://www.home-assistant.io/) — home automation. + +- **Source:** [`sfh/containers/hass.nix`](../../../nixos/boxes/home/palace/vms/sfh/containers/hass.nix) +- **Host:** NixOS container on `sfh` + +## Role + +- Runs Home Assistant plus supporting services in the container. The `hass-cli` + is wired up against the local server for convenience. +- Integrations/automations are configured here (see commit history for things + like the "West Wood" integration). + +## Networking + +- `internal` assignment (alt name `hass-ctr`), plus a loopback assignment + (`hass-ctr-lo`) used internally. diff --git a/docs/boxes/home/palace.md b/docs/boxes/home/palace.md new file mode 100644 index 0000000..3fc8b45 --- /dev/null +++ b/docs/boxes/home/palace.md @@ -0,0 +1,21 @@ +# palace (host) + +The physical VM host for the home network — the home equivalent of `colony`. + +- **Source:** [`nixos/boxes/home/palace/default.nix`](../../../nixos/boxes/home/palace/default.nix) + (VM instances in [`palace/vms/default.nix`](../../../nixos/boxes/home/palace/vms/default.nix)) + +## Role + +- Bare-metal host whose job is to run the home VMs via the `my.vms` module: + `river` (router), `cellar` (storage), `sfh` (container host). +- Provides the bridged networking those VMs sit on and passes through hardware + where needed (e.g. NVMe drives to `cellar`, NICs to `river`). + +## VMs hosted here + +| VM | Role | Docs | +| --- | --- | --- | +| `river` | Home router (VRRP pair with `stream`) | [river.md](river.md) | +| `cellar` | NVMe-oF storage server | [cellar.md](cellar.md) | +| `sfh` | NixOS container host (Home Assistant, …) | [sfh.md](sfh.md) | diff --git a/docs/boxes/home/river.md b/docs/boxes/home/river.md new file mode 100644 index 0000000..7d1f108 --- /dev/null +++ b/docs/boxes/home/river.md @@ -0,0 +1,25 @@ +# river + +One of the two home routers. `river` is a VM on `palace`; it forms a +high-availability pair with the standalone `stream`. + +- **Source:** [`nixos/boxes/home/palace/vms/river.nix`](../../../nixos/boxes/home/palace/vms/river.nix), + built from [`routing-common`](../../../nixos/boxes/home/routing-common) (instance `0`) +- **Host:** VM on `palace` +- **Deploy address:** `192.168.68.1` + +## Role + +Everything in [`routing-common`](../../../nixos/boxes/home/routing-common): + +- **VRRP/keepalived** failover with `stream` (`keepalived.nix`) — one router is + master at a time, sharing virtual IPs. +- **DHCP** via kea (`kea.nix`), **router advertisements** via radvd + (`radvd.nix`). +- **DNS** (`dns.nix`) — local resolver with a blocklist + (`dns-blocklist.txt`) and a periodic update script. +- **NAT / firewall** for the home LAN, with policy routing. +- **AS211024 L2 mesh** link back to colony/`estuary` (and the other edge + routers), so home and colony networks interconnect. + +See [stream.md](stream.md) for the other half of the pair. diff --git a/docs/boxes/home/sfh.md b/docs/boxes/home/sfh.md new file mode 100644 index 0000000..1c514dd --- /dev/null +++ b/docs/boxes/home/sfh.md @@ -0,0 +1,24 @@ +# sfh + +The home **NixOS container host** ("smart from home" / home services). + +- **Source:** [`nixos/boxes/home/palace/vms/sfh/`](../../../nixos/boxes/home/palace/vms/sfh) + (`default.nix`, `containers/`) +- **Host:** VM on `palace` + +## Role + +- Runs the home NixOS containers via `my.containers.instances`, in the same way + `shill` does on colony. +- Sits on the home network and connects to NVMe-oF storage (`cellar`) where + needed. + +## Containers + +Defined in [`sfh/containers/`](../../../nixos/boxes/home/palace/vms/sfh/containers) +and imported from its `containers/default.nix`: + +| Container | Role | Docs | +| --- | --- | --- | +| `hass` | Home Assistant | [hass.md](hass.md) | +| `unifi` | UniFi controller — **defined but currently commented out** of `containers/default.nix` | [unifi.md](unifi.md) | diff --git a/docs/boxes/home/stream.md b/docs/boxes/home/stream.md new file mode 100644 index 0000000..ddd9a7e --- /dev/null +++ b/docs/boxes/home/stream.md @@ -0,0 +1,19 @@ +# stream + +One of the two home routers. `stream` is standalone hardware; it forms a +high-availability pair with `river` (a VM on `palace`). + +- **Source:** [`nixos/boxes/home/stream.nix`](../../../nixos/boxes/home/stream.nix), + built from [`routing-common`](../../../nixos/boxes/home/routing-common) (instance `1`) +- **Deploy address:** `192.168.68.2` + +## Role + +- Same [`routing-common`](../../../nixos/boxes/home/routing-common) role as + [`river`](river.md): keepalived/VRRP, kea DHCP, radvd, DNS + blocklist, NAT and + the AS211024 L2 mesh link to colony. +- Additionally pulls in `mstpd` (`routing-common/mstpd.nix`) for spanning-tree on + its bridged ports — `stream` is the one wired into the physical switching, so + it manages the L2 topology. + +See [river.md](river.md) for the other half of the pair. diff --git a/docs/boxes/home/unifi.md b/docs/boxes/home/unifi.md new file mode 100644 index 0000000..f881d02 --- /dev/null +++ b/docs/boxes/home/unifi.md @@ -0,0 +1,23 @@ +# unifi + +The UniFi network controller. + +- **Source:** [`sfh/containers/unifi.nix`](../../../nixos/boxes/home/palace/vms/sfh/containers/unifi.nix) +- **Host:** NixOS container on `sfh` + +## Status + +> **Currently disabled.** The system is still defined (`nixos.systems.unifi`), +> but its import is commented out in +> [`sfh/containers/default.nix`](../../../nixos/boxes/home/palace/vms/sfh/containers/default.nix), +> so it is not deployed as a container right now. Re-enable by uncommenting +> `./unifi.nix` there. + +## Role + +- Runs the UniFi controller (`services.unifi`) to manage the home UniFi network + gear. + +## Networking + +- `internal` assignment (alt name `unifi-ctr`). diff --git a/docs/boxes/misc/README.md b/docs/boxes/misc/README.md new file mode 100644 index 0000000..3881a28 --- /dev/null +++ b/docs/boxes/misc/README.md @@ -0,0 +1,21 @@ +# misc + +Everything that isn't part of the `colony` or `home` sites: the edge VPSes, the +remote `kelder` site, a workstation, and the installer image. + +| Machine | What it is | Docs | +| --- | --- | --- | +| `britway` | Vultr VPS (London, `lon1`): Headscale, Tailscale exit node, BGP edge, nginx | [britway.md](britway.md) | +| `britnet` | VPS (Birmingham, `bhx1`): Tailscale/WireGuard gateway | [britnet.md](britnet.md) | +| `kelder` | Remote site host (`hentai.engineer`): NixOS container host | [kelder.md](kelder.md) | +| `tower` | Framework Laptop 13 (12th-gen Intel) workstation | [tower.md](tower.md) | +| `installer` | Custom NixOS installer image | [installer.md](installer.md) | + +## kelder containers + +`kelder` is itself a container host (like `shill`/`sfh`): + +| Container | Role | Docs | +| --- | --- | --- | +| `kelder-acquisition` | Media stack (Jellyfin + *arr + Transmission) | [kelder-acquisition.md](kelder-acquisition.md) | +| `kelder-spoder` | nginx web host | [kelder-spoder.md](kelder-spoder.md) | diff --git a/docs/boxes/misc/britnet.md b/docs/boxes/misc/britnet.md new file mode 100644 index 0000000..deccc0d --- /dev/null +++ b/docs/boxes/misc/britnet.md @@ -0,0 +1,21 @@ +# britnet + +A VPS in Birmingham (`bhx1`) acting as a Tailscale/WireGuard gateway node. + +- **Source:** [`nixos/boxes/britnet.nix`](../../../nixos/boxes/britnet.nix) +- **Internal domain:** `bhx1.int.nul.ie` + +## Role + +- **Tailscale node** + **WireGuard** (`wg0`) gateway: provides a second egress / + entry point into the boxes' overlay networks. +- nftables SNATs traffic arriving on `tailscale0` / `wg0` out of the provider + interface (`veth0`), using the `allhost` assignment addresses. + +## Networking + +- Provider uplink with gateways `77.74.199.1` (v4) / `2a12:ab46:5344::1` (v6). +- `tailscale0` and `wg0` overlay interfaces; `allhost` assignment for SNAT. + +> `britnet` is a separate machine from [`britway`](britway.md) — different +> provider/site, narrower role (gateway rather than control plane + BGP edge). diff --git a/docs/boxes/misc/britway.md b/docs/boxes/misc/britway.md new file mode 100644 index 0000000..37e05ad --- /dev/null +++ b/docs/boxes/misc/britway.md @@ -0,0 +1,27 @@ +# britway + +A Vultr VPS in London (`lon1`) acting as a network edge node: the Tailscale +control plane, an exit node, and a BGP speaker in the AS211024 mesh. + +- **Source:** [`nixos/boxes/britway/`](../../../nixos/boxes/britway) + (`default.nix`, `bgp.nix`, `nginx.nix`, `tailscale.nix`) +- **Internal domain:** `lon1.int.nul.ie` + +## Role + +- **Headscale** ([`tailscale.nix`](../../../nixos/boxes/britway/tailscale.nix)) — the + self-hosted Tailscale control server (`hs.nul.ie`) the rest of the boxes log + into. +- **Tailscale node** — advertises itself as an **exit node** and advertises the + tailnet routes, so tailnet clients can egress / reach internal prefixes via + britway. +- **BGP** ([`bgp.nix`](../../../nixos/boxes/britway/bgp.nix)) — part of the AS211024 + L2 VXLAN mesh (`my.vpns.l2`) alongside `estuary`, `river` and `stream`. +- **nginx** ([`nginx.nix`](../../../nixos/boxes/britway/nginx.nix)) — reverse proxy / + web front-end with ACME certs. + +## Networking + +- `vultr` assignment on the provider interface; `as211024` on the mesh. +- A `veth0`/`tailscale0` setup with SNAT so tailnet traffic egresses via the VPS + public IP. diff --git a/docs/boxes/misc/installer.md b/docs/boxes/misc/installer.md new file mode 100644 index 0000000..d1d5b61 --- /dev/null +++ b/docs/boxes/misc/installer.md @@ -0,0 +1,19 @@ +# installer + +The custom NixOS installer image used to bootstrap new boxes. + +- **Source:** [`nixos/installer.nix`](../../../nixos/installer.nix) + +## Role + +- Defines `nixos.systems.installer`, a minimal system whose `my.buildAs.*` + outputs produce installable artifacts — primarily a bootable **ISO** + (`isoImage`), and the same base is reused for kexec/netboot trees. +- Build it with the devshell commands (see [`AGENTS.md`](../../../AGENTS.md#commands)): + - `build-iso installer` + - `build-kexec installer` / `build-netboot installer` +- A released ISO is what `colony`'s VM definitions reference as install media; the + `update-installer` devshell command tags a release to trigger a rebuild. + +This is a build target rather than a deployed machine — there is no running +`installer` host. diff --git a/docs/boxes/misc/kelder-acquisition.md b/docs/boxes/misc/kelder-acquisition.md new file mode 100644 index 0000000..9ee84a0 --- /dev/null +++ b/docs/boxes/misc/kelder-acquisition.md @@ -0,0 +1,20 @@ +# kelder-acquisition + +The media stack for the `kelder` site — a slimmer cousin of colony's +[`jackflix`](../colony/jackflix.md). + +- **Source:** [`kelder/containers/acquisition/`](../../../nixos/boxes/kelder/containers/acquisition) + (`default.nix`, `networking.nix`) +- **Host:** NixOS container on `kelder` + +## Role + +- **Jellyfin** for streaming (with hardware transcoding — the `jellyfin` user is + in the `render` group, `jellyfin-ffmpeg`). +- **Acquisition:** Transmission, Jackett, Radarr, Sonarr. +- Runs under the site's shared `kontent` user. + +## Networking + +- `internal` assignment (alt name `acquisition-ctr`) on the kelder container + network; download client networking in `networking.nix`. diff --git a/docs/boxes/misc/kelder-spoder.md b/docs/boxes/misc/kelder-spoder.md new file mode 100644 index 0000000..55c4232 --- /dev/null +++ b/docs/boxes/misc/kelder-spoder.md @@ -0,0 +1,17 @@ +# kelder-spoder + +An nginx web host on the `kelder` site. + +- **Source:** [`kelder/containers/spoder/`](../../../nixos/boxes/kelder/containers/spoder) + (`default.nix`, `nginx.nix`) +- **Host:** NixOS container on `kelder` + +## Role + +- Serves web content via **nginx** ([`nginx.nix`](../../../nixos/boxes/kelder/containers/spoder/nginx.nix)), + with ACME-managed certificates (nginx in the `acme` group, reloads on renewal). +- Runs under the site's shared `kontent` user. + +## Networking + +- `internal` assignment (alt name `spoder-ctr`) on the kelder container network. diff --git a/docs/boxes/misc/kelder.md b/docs/boxes/misc/kelder.md new file mode 100644 index 0000000..1622dfe --- /dev/null +++ b/docs/boxes/misc/kelder.md @@ -0,0 +1,24 @@ +# kelder + +A host at a remote site ("kelder" = cellar/basement), linked back to the rest of +the other boxes over WireGuard. It is itself a **NixOS container host**. + +- **Source:** [`nixos/boxes/kelder/`](../../../nixos/boxes/kelder) + (`default.nix`, `boot.nix`, `containers/`, `plymouth/`) +- **Domain:** `hentai.engineer` + +## Role + +- **Site uplink:** connects to colony's `estuary` over **WireGuard** + (`kelder` peer; see [estuary.md](../colony/estuary.md)), so the remote site is + reachable through the colony edge. A periodic `dns_update.py` keeps DNS current. +- **Container host:** runs NixOS containers via `my.containers.instances` + (`acquisition`, `spoder`). +- Custom boot/splash (`boot.nix`, Plymouth theme in `plymouth/`). + +## Containers + +| Container | Role | Docs | +| --- | --- | --- | +| `kelder-acquisition` | Media stack (Jellyfin + *arr + Transmission) | [kelder-acquisition.md](kelder-acquisition.md) | +| `kelder-spoder` | nginx web host | [kelder-spoder.md](kelder-spoder.md) | diff --git a/docs/boxes/misc/tower.md b/docs/boxes/misc/tower.md new file mode 100644 index 0000000..9b060d8 --- /dev/null +++ b/docs/boxes/misc/tower.md @@ -0,0 +1,16 @@ +# tower + +A laptop workstation — a Framework Laptop 13 (12th-gen Intel). + +- **Source:** [`nixos/boxes/tower/default.nix`](../../../nixos/boxes/tower/default.nix) + +## Role + +- Framework Laptop 13 (12th-gen Intel) running the GUI environment + (`my.gui.enable`) with home-manager on the `mine` channel. +- Joins the tailnet via the self-hosted Headscale on [`britway`](britway.md) + (`tailscale up --login-server=https://hs.nul.ie --accept-routes`). +- Local virtualisation enabled (`kvm-intel`, IOMMU on). + +> Unlike [`castle`](../home/castle.md), `tower` lives outside the `home/` box +> tree and boots from local disks rather than NVMe-oF.