Skip to content

UniFi Terraform adoption

What: a tf/unifi HCP workspace that imports all nine UniFi networks, DHCP Guard included, through our provider fork (app.terraform.io/fzymgc-house/unifi), plus the doc corrections the spikes turned up. Approach: import-only adoption with the View Only credential. The plan is 9 to import, 0 to change, so adoption writes nothing to the controller, and the controller rejects any write that slips through. Riskiest assumption: that an arm64 agent-pool run can install the private provider and reach unifi.fzymgc.house:443. Spikes 004 and 006 proved everything around this except the run itself; the workspace’s first plan settles it.

Evidence: .planning/spikes/001006; runbook docs/operations/terraform-provider-fork.md.

1. Decisions you’ll probably want to tweak

Section titled “1. Decisions you’ll probably want to tweak”
# Decision Alternative Cost of changing later
D1 Workspace credential: View Only (unifi/readonly). Plans and the import-only apply work; any change that needs a write fails loudly at apply, because the controller refuses it Add unifi/admin now so merged config changes (e.g. a guard list) apply Small: a Vault path, one policy line, and an ephemeral-path swap. Until then, controller changes happen in the UI and the next plan shows the drift
D2 Scope: all nine networks. Guard can be switched on for any network, and an unmanaged network is invisible to the plan Only the four vlan-only networks, or only Main Adding one later is an import block and a resource; dropping one is a removed {} block. The five corporate networks carry inert leftovers (stale subnets, dhcpd_start 192.168.2.6), marked as such in one file comment
D3 One PR for the whole branch: spikes, registry.tf (already applied), docs, the Vault role and policy, the workspace entry, and tf/unifi Two PRs: spikes, registry and docs now; adoption after Cheap either way. One PR works because the workspace doesn’t exist at merge, so the tf/vault and tf/unifi runs can’t race (see §3 ordering)
D4 Import blocks stay after adoption (repo convention) Remove after the first apply Trivial
D5 The todo’s “unifi skill” is dropped. A docs/operations/unifi.md runbook plus the plan itself replace it: the pre-cut check becomes “read dhcpd_ip_1..3” or “look at the plan” Build the skill anyway (inventory, guard dump, pre-cut verb) The spike 001 scripts (unifi_session.py, probe_admin_activity.py) are the skill’s core if it’s wanted later
Unknown Default Pivot signal
Agent pod → controller (spike 004) Proceed. Nodes are on Main, and tpi-alpha-4’s node IP already reaches the controller First plan fails with a connect timeout → check node egress and Firewalla Main→Core. The Lab-VLAN cutover (mahfn5xfva) may move the source address later; re-plan after it
Agent installs the private provider (spike 006) Proceed. HashiCorp’s docs say org runs install private providers automatically init fails on registry auth → check the agent token’s org scope
Controller drift before merge The plan is the check First plan ≠ 0 to change → reconcile networks.tf or the UI before the apply
Workspace Terraform ~> 1.15.0 vs local 1.16.3 required_version = "~> 1.15" like the other modules init or lock complaints
  • tf/vault: vault_policy.terraform_unifi (read on secret/data/fzymgc-house/infrastructure/unifi/readonly only) and vault_jwt_auth_backend_role.tfc_unifi bound to main-cluster-unifi, modelled on tfc_dns_records.
  • tf/hcp-terraform: main-cluster-unifi = { dir = "tf/unifi", tags = ["main-cluster", "unifi"] } (agent mode by default).
  • tf/unifi: versions.tf (fork, exact pin), terraform.tf (cloud block, ephemeral "vault_kv_secret_v2" for the credential, provider "unifi"), imports.tf and networks.tf from spike 005’s api-truth, and .terraform.lock.hcl locked for linux_arm64 + darwin_arm64.
  • Docs: new docs/operations/unifi.md (what the controller governs, credentials, what Terraform manages, the admin-activity drift check, the DHCP Guard pre-cut check); fix dns.md (the list is dhcpd_ip_1..3, drop “trust the live test over dhcpguard_ip”, keep the .20.1 rollback note); docs/reference/network.md pointer; operations index.
  • Todo: close 2026-08-24-bring-the-unifi-configuration-into-the-repo through its GSD verb, not by hand.
  • Ordering after merge: tf/vault auto-applies the role → the operator applies tf/hcp-terraform (creates the workspace) → queue its first run → plan 9 to import, 0 to change → the import-only apply writes state only. That run closes spikes 004 and 006.
  • Verification before the PR: local plan against the published provider (already 9/0), terraform fmt, and speculative plans of tf/vault and tf/hcp-terraform.
  1. D1: unifi/admin now (not the recommendation). The workspace reads secret/fzymgc-house/infrastructure/unifi/admin (account automation-admin, Network: Full Management) through policy terraform-unifi; unifi/readonly stays for agents and probes. Merged config changes apply to the controller, and the first run is still import-only.
  2. D2: all nine networks.
  3. D3: one PR.
  4. D5: the unifi skill is dropped; docs/operations/unifi.md and the plan replace it.