# changelog 2026-08-07 -- dc0 .7 Tailscale install: office1-mirrored (untagged), site-tailscale.sh prep+forwarding

Session goal: finish the dc0 `.7` Tailscale subnet-router install so the operator can log into
Headscale and approve the route -> unblocks dc0 Step 3.3 (Horizon-over-tailnet). Operator
directive: mirror the working Office1 router; defer tags/autoApprovers/ACL to the bare-metal build.

Branch `dc-dc-stage5-preconditions`. Status authority is CURRENT-STATE.md (this file is history).

## Measured ground truth (read-only, this session)

- **dc0 `.7` (`10.12.8.7`, MAAS name `known-marten`, user `ubuntu`, sudo ok):** tailscale package
  **ABSENT**; snap present; default route `via 10.12.4.1 dev enp2s0`; apt proxy
  `http://10.12.8.6:8000/`; **IP forwarding OFF** (`ip_forward=0`, `all.forwarding=0`), no
  `/etc/sysctl.d/99-tailscale.conf`. iptables 1.8.7 + iproute2 5.15 present (tailscale deps).
- **office1-tailscale (working reference):** deb `tailscale 1.98.9`, tailscaled active, forwarding
  ON via `/etc/sysctl.d/99-tailscale.conf`; `tailscale debug prefs`: `Tags: None` (UNTAGGED),
  `AdvertiseRoutes: ['10.10.0.0/22']`, `RouteAll: True` (accept-routes), `NoSNAT: False` (SNAT on),
  control `https://tailscale.baldurkeep.com:443`.
- **Egress for the package:** `.7` cannot resolve/reach `pkgs.tailscale.com` (external DNS blocked;
  apt-proxy will not forward it). The **rack and vcloud both have egress**; vcloud pulls office1's
  exact `pool/tailscale_1.98.9_amd64.deb` (SHA256 `c739c29ec2342cc7df1a24cd102a3dfb51b359f79338d433ce8f052aeebc62ff`,
  Depends: `iptables`). Method = staged `.deb` via a host with egress -> scp to `.7` -> `dpkg -i`.
- **Custody:** operator placed the plain Headscale pre-auth key on vcloud at
  `~/vr1-tailnet-creds/headscale-preauth-vr1-dc0.key` (0600; sha256 `d2e74720...`); never read into
  session context. Used only via `$TS_AUTHKEY_FILE`.

## Changes (repo delivery; ALL GREEN before any live step)

1. **`scripts/site-tailscale.sh` -- three verbs (`prep|install|check`) + untagged VR1 + forwarding.**
   - New **`prep <site>`**: installs the tailscale package from a rack-staged `.deb` (`$TS_DEB`,
     since `.7` has no egress) and enables IP forwarding (writes `/etc/sysctl.d/99-tailscale.conf`,
     `sysctl --system`, then ASSERTS v4+v6 forwarding took).
   - **Tag now OPTIONAL**: `TS_TAG` defaults EMPTY = untagged (office1-mirrored, VR1); `install`
     omits `--advertise-tags` and adds `--accept-routes` (office1 `RouteAll`); `check` skips the tag
     assertion when untagged. `TS_TAG=tag:subnet-router` restores the D-129(iii) tagged design.
   - **`check` now ASSERTS IP forwarding** -- the load-bearing subnet-router property. Root cause it
     closes (advisor 2026-08-07): `tailscale up --advertise-routes` WARNS-and-succeeds with
     forwarding off, so the join completes and Headscale approves the route while NOTHING forwards
     to Horizon -- a green gate blind to the one property that makes the router work.
   - Why (revert): `git checkout <prev> -- scripts/site-tailscale.sh` restores the tagged-only,
     no-prep, no-forwarding form. Evidence: harness below.
2. **`tests/site-tailscale/run-tests.sh` -- 23 cases, up from ~15.** New failing-direction fixtures
   for every new path: `prep-noforward`->4, `prep-nopkg-nodeb`->4, `prep-fromdeb`->0, `check-noforward`
   ->1, `check-tag-happy`->0, `check-tag-notag`->1, `install-tag-happy`->0. Fakes `sysctl`/`dpkg` added.
   Result: **23 pass / 0 fail**. Revert: restore the file with the script.
3. **`docs/design-decisions.md` -- D-129(iii) AMENDMENT (2026-08-07 b), [OPS], no new D-number.**
   Records the operator's untagged/office1-mirror deferral (verbatim utterance quoted) and the
   accepted VR1 exposure (key-expiry clock + no ACL star boundary yet); the Roosevelt tagged/ACL
   design in ruling (b)/notes 1-2 is UNCHANGED, only deferred. Revert: delete the `### D-129(iii)
   -- AMENDMENT (2026-08-07 b)` subsection.

Gates: `repo-lint` 0 fail / 1 pre-existing legacy L1 warn; harness 23/23.

## NOT YET DONE (live, gated -- pending this delivery's commit)

Stage the `.deb` (vcloud dl + sha256 verify -> scp to `.7`) -> `dpkg -i` -> `prep vr1-dc0` ->
`install vr1-dc0` (untagged, key via `$TS_AUTHKEY_FILE`, removed after) -> **operator approves the
`10.12.8.0/22` route in Headscale** -> `check vr1-dc0` green -> confirm Horizon over the tailnet
(closes Step 3.3). dc1 `.7` is downstream of the dc1 node rebuild -- not prepped this session.

## Findings queued for the close sweep

- F1: `.7` MAAS machine name is still the auto name (`known-marten`), not `vr1-dc0-tailscale-01`
  (naming convention owed; cosmetic, does not affect the join -- tailnet name set by `--hostname`).
- F2: raw `grep DOCFIX-` returns a stray `DOCFIX-1004` string somewhere (ledger-scan's next-free is
  213); verify it is not a real assignment collision.
