Initial Site Bootstrap
The bare-metal → operational-baseline runbook: temp LAN, hardware install, Proxmox, edge VMs (OPNsense, UOS, OpenBao) via Pulumi, and the bao-first secrets migration.
Everything that happens before the phased cutover work in Build Phases: racked hardware on the temp LAN → Proxmox on every node → edge VMs provisioned and configured → repo secrets running bao-first. End state is "Phase 0 complete, Phase 1 ready," with the whole edge stack rebuildable from the repo. Captured 2026-07-01 from the Site A bring-up; this is the repeatable template for Site B.
Status correction (2026-07-03)
The sa-fw-01 OPNsense VM from the captured bring-up was destroyed / never finished and is not currently running; its provision stack is parked at enabled: false. Site A stands at "Phase 0 minus step 3.1" — re-run the OPNsense provision + config sequence (step 3.1) before Phase-1 work. See Current Build State.
Temp-LAN Plan (Phase-0 addressing)
Flat network behind the existing UniFi router — no VLANs yet: ISP → UniFi router (.1) → Netgear core (unconfigured L2) → all servers.
| Site A | Site B | |
|---|---|---|
| Temp subnet | 192.168.1.0/24 | 192.168.16.0/24 |
| Gateway (UniFi router) | 192.168.1.1 | 192.168.16.1 |
*-edge-01 Proxmox | 192.168.1.10 | 192.168.16.10 (tentative) |
sa-uos-01 (UOS VM) | 192.168.1.40 | — (no 2nd controller) |
*-fw-01 seed mgmt (OPNsense VM) | 192.168.1.41 | 192.168.16.41 (tentative) |
*-bao-01 (OpenBao VM) | DHCP — lease recorded in BAO_ADDR | DHCP (when built) |
Step 0 — Workstation Prerequisites (tier 0)
Clone the repo, cp .env.local.example .env.local, fill the tier-0 values (PULUMI_CONFIG_PASSPHRASE, Proxmox credential, ANSIBLE_VAULT_PASSWORD), leave the BAO_* knobs empty — every tool runs in pure fallback mode until step 4. ssh-add the operator key (the Proxmox provider authenticates via the agent), then make install.
Step 1 — Hardware Install
NICs, boot M.2 (512 GB — never a 1.92 TB enterprise SSD), RDIMMs, and data SSDs per the hardware allocation. Cable per the faceplate guide even though VLANs come later — recabling racked E200s twice is worse than idle trunks.
IPMI first contact
Change ADMIN/ADMIN (or the sticker password) immediately; IPMI lands on the access switch, never the internet. macOS iKVM pain: see IPMI / KVM.
Step 2 — Proxmox on Bare Metal
Install PVE on every node via IPMI virtual media using the temp IPs above. Create the Pulumi API credential (Datacenter → Permissions → API Tokens, privilege separation OFF) into .env.local. Then host baseline/hardening one node at a time (make baseline-check LIMIT=<node> → baseline-apply), edge node last — it will carry the firewall VM.
Step 3 — Edge VMs via Pulumi (order matters)
All on *-edge-01, all make targets against STACK=site-a|site-b; preview before every up; export and commit config after each milestone.
- OPNsense — provision (
opnsense-provision-set/preview/up: FreeBSD image + cloud-initopnsense-bootstrapconversion, API-ready on the seed IP), then app config (opnsense-config-check/apply: Phase-1 outbound NAT + baseline firewall). - UOS controller (Site A only) —
unifi-provision-*, thenunifi-config-setup(first-run owner/console via the UOS API). - OpenBao —
openbao-provision-*(VM boots sealed and uninitialized by design), then the manual init runbook:bao operator init→ Shamir keys + root token → password manager. Set the E200 VM startup order: OPNsenseorder=1, baoorder=2plus delay.
Step 4 — Secrets Go bao-first
Executes the tier-1 migration for the site (Site A done 2026-07-01): set BAO_ADDR (+ ad-hoc BAO_ADMIN_TOKEN), run make openbao-config-setup (KV v2 homelab mount, per-scope policies, AppRoles → paste the printed role_id/one-time secret_id pairs into .env.local), then make openbao-config-seed. Drop BAO_ADMIN_TOKEN afterwards — the password manager keeps it.
Verification Gates
| After step | Gate |
|---|---|
| 0 | make help lists targets; scripts/vault-pass.sh prints, not errors |
| 1 | IPMI reachable on new creds from the temp LAN only |
| 2 | PVE web UI on every node; make baseline-check LIMIT=<node> clean re-run |
| 3.1 | OPNsense API answers on the seed IP; opnsense-config-apply re-run = 0 changes |
| 3.2 | UOS UI on :11443; unifi-config-check clean |
| 3.3 | bao status = unsealed + initialized; VM start order set |
| 4 | Config runs succeed via bao (vault files renamed away) AND via fallback (BAO_ADDR unset) |
Related Pages
- Current Build State — where the build actually stands today
- Build Phases — the phased cutover that follows this runbook
- Secrets — OpenBao — the full secrets architecture