Newer
Older
openstack-caracal-dc-dc / runbooks / dc-dc-office1-service-reip.md

Office1 service re-IP -- move NetBox + Tailscale into the D-120 static band

Gated mutation on TWO RUNNING services. Do not run until D-120 is ADOPTED (the operator has ratified the band layout AND the target addresses). Present each step, justify it as minimal, get individual approval. This is also the reference procedure the DCs reuse for their own compose /24s.

Target (D-120 PROPOSED; confirm against the adopted decision before running)

office1-netbox     10.10.1.201 -> 10.10.1.10   (static, band .2-.49)
office1-tailscale  10.10.1.202 -> 10.10.1.11   (static, band .2-.49)

Both VMs are MAAS-COMPOSED LXD VMs on voffice1; their addresses come from MAAS. The edge's static route 10.10.1.0/24 -> 10.10.0.20 is /24-wide and is UNAFFECTED by the change.

Preconditions (READ-ONLY)

  1. D-120 ADOPTED; target addresses confirmed.
  2. Coordinate with sandbox/C2 work -- the NetBox re-IP briefly interrupts the sandbox NetBox.
  3. Record current state: office1-netbox 10.10.1.201, office1-tailscale 10.10.1.202 (as-built).
  4. Access: ssh -J jessea123@10.10.0.20 ubuntu@10.10.1.201 (and .202); MAAS on voffice1 (10.10.0.20), secrets in /root/maas-secrets/ on the box (operator-held).

Step 1 -- MAAS: static-assign the new address to each VM's interface [MUTATION: gated]

For each machine, set its interface on the 10.10.1.0/24 subnet to static-assign the target address (a fixed IP outside MAAS's .100-.200 dynamic range). The .2-.49 band is already outside the dynamic range, so NO dynamic-range edit is required.

<PENDING VERIFICATION: the exact MAAS CLI. In the MAAS UI: Machine -> Network -> the interface on
10.10.1.0/24 -> Edit -> Mode = "Static assign" -> IP = 10.10.1.10 (netbox) / .11 (tailscale).
CLI form is roughly `maas $PROFILE interface link-subnet <system_id> <iface_id> mode=STATIC
subnet=<subnet_id> ip_address=10.10.1.10` -- CONFIRM the subcommand/args against the installed
MAAS 3.7 before running; do not run a guessed command against live MAAS.>

Step 2 -- Apply the new address on the VM [MUTATION: gated]

A composed VM picks up the MAAS assignment on a network reconfigure or redeploy.

<PENDING VERIFICATION: whether MAAS pushes the static IP without a redeploy, or whether the VM
needs `netplan apply` / a reboot / a MAAS re-deploy. Prefer the least disruptive path that
actually takes -- verify the address changed by reading `ip -4 addr` on the VM, NOT by assuming.>

Step 3 -- Fix each SERVICE's own address config [MUTATION: gated]

  • NetBox (office1-netbox, netbox-docker): NetBox binds 0.0.0.0:8000, so it follows the host IP -- BUT ALLOWED_HOSTS / CSRF_TRUSTED_ORIGINS may name the old 10.10.1.201. <PENDING VERIFICATION: read the netbox-docker env (e.g. /opt/netbox-docker/env/netbox.env or the compose .env on the box) -- if ALLOWED_HOSTS lists 10.10.1.201, add/replace 10.10.1.10 and restart the stack (docker compose up -d). If it is*, no change needed.>
  • Tailscale (office1-tailscale): it advertises 10.10.0.0/22 as a subnet router; the ADVERTISED routes do not change, but its own LAN interface address does. <PENDING VERIFICATION: confirm tailscaled still routes after the interface IP change --tailscale status, and that 10.10.0.0/22 is still advertised/approved. Atailscale up ... --advertise-routes=10.10.0.0/22re-assert may be needed; the node identity/key is unchanged.>

Step 4 -- Verify on the wire (READ-ONLY)

ssh -J jessea123@10.10.0.20 ubuntu@10.10.1.10 'ip -4 addr'      # netbox at .10
curl -s -o /dev/null -w "%{http_code}\n" http://10.10.1.10:8000/api/    # 403/200 = up
ssh -J jessea123@10.10.0.20 ubuntu@10.10.1.11 'tailscale status'        # tailscale at .11

Step 5 -- Update the 20 repo references + the importer allowlist [repo change; gated]

10.10.1.201 -> 10.10.1.10 and 10.10.1.202 -> 10.10.1.11 across (measured 2026-07-15):

  • CODE (must, or the guard breaks): SANDBOX_HOSTS in netbox/roles-aggregates-import.py and netbox/dc-dc-prefixes-import.py (the .201 entry -> .10); netbox/d115-office-carve.py's SANDBOX_HOSTS; tests/dc-dc-prefixes-import/test_logic.py (the sandbox-URL host it sets); tests/roles-aggregates-import/run-tests.sh (the SANDBOX_HOSTS assertion).
  • Docs (forward-looking): docs/vr1-office1-as-built.md, docs/session-ledger.md, docs/dc-dc-netbox-buildout-scope.md, docs/dc-dc-deployment-workflow.md, runbooks/dc-dc-phase1-office1-standup.md. Leave dated changelogs as historical snapshots.
  • Re-run bash scripts/run-tests-all.sh (the SANDBOX_HOSTS harnesses must stay green) + repo-lint.

Step 6 -- Record the D-120 carve in NetBox (via the sandbox loop)

Register 10.10.1.0/24's child ranges (static .2-.49 / dynamic .100-.200 / node .201-.254) and the two service IP assignments in the sandbox NetBox, then feed upstream with C2. NetBox is the IPAM authority for this; do not leave the layout recorded only in prose.

Rollback

Re-run Steps 1-3 with the old addresses (.201/.202), git revert the Step-5 repo change. Nothing here is destructive -- the VMs and their data are untouched; only the L3 address changes.

DC replication note

When a DC's compose /24 is built, its services get D-120 static-band addresses FROM DAY ONE via this same procedure -- there is no "assign in the node band then re-IP later" for the DCs. This runbook is the reference.