Skip to content

Vault Overview

Vault

HashiCorp Vault is the single source of truth for every credential in devhome — vCenter/ESXi logins, VM admin passwords, ArgoCD/Rancher tokens, HAProxy certs, and Terraform provider auth. Nothing should ever be hardcoded in a .tfvars, .pkrvars.hcl, or script.

Official download

Vault install/downloads — always current.

Why this matters more than it might elsewhere

This repo replaced a previous one (devhome-gitops, ~2026-06-18) that had to be abandoned outright because secrets were committed to its git history across scattered, ad-hoc paths (devhome/vcenter, devhome/terraform/vsphere, devhome/terraform/compute, devhome/terraform/azure, devhome/packer/windows, devhome/personal/govc, and plaintext .auto.pkrvars.hcl/.tfvars files) — rather than rewrite that git history, the whole working tree was copied to a fresh location with a clean history and pushed to a new Azure DevOps repo. That relocation is why the current TrueNAS-hosted repo path (/mnt/backup/config/devhome, \\truenas-dr\backup\config\devhome) exists in the first place, and why "secrets in Vault, never in git" isn't a nice-to-have here — it's a lesson already paid for once.

The consolidation that followed (~2026-06-16 to 2026-06-17) collapsed all of those scattered paths into the small, domain-organized set below, all managed by terraform/vault/ (one .tf file per secret). Values are supplied from /mnt/backup/config/terraform/vault/terraform.tfvars (gitignored, TrueNAS-only) via make tf-apply-vault. The old paths (devhome/vcenter and the rest listed above) still technically exist in Vault but are unreferenced by any code — if you find a script or doc pointing at one of them, it's stale, not a hint that the path is real.

Two Azure DevOps repos with the same content, only one of them live

For about two days after the relocation, the old devhome-gitops repo and the new devhome repo both existed with byte-identical k8s/ trees but zero shared git history — and ArgoCD's Application/ApplicationSet objects were still pointed at the old one. Fixes pushed to devhome had silently zero effect on the live cluster until this was caught and every repoURL (in git and live-patched directly onto the cluster objects, since they aren't self-syncing app-of-apps) was repointed. If a git push ever seems to have "no effect" on a live ArgoCD-managed resource, checking argocd app get <name> for which repo it's actually synced from is a real diagnostic step, not paranoia — see ArgoCD.

Runs on truenas-dr

Vault runs as a Docker container on truenas-dr (see TrueNAS Services), with an unsealer sidecar container that re-unseals it automatically after a restart — which matters, because "restart the Vault container" is a real, sometimes-necessary fix (see Kubernetes Auth).

KV mount layout — devhome

Path Contents
devhome/vmware The big one: vsphere_server, vsphere_username, vsphere_password, esxi_host_username, esxi_host_password, esxi_license, vcsa_root_user/vcsa_root_passowrd (typo kept intentionally — matches the live field name), vm_admin_password, haproxy_cert_chain/haproxy_lb_username/haproxy_lb_password/haproxy_root_password, govc_datacenter/govc_insecure. Consumed by all 3 vsphere Terraform roots, every Packer builder, WSL's configure-personal.sh, and Ansible.
devhome/dir_path truenas_base_path, kubeconfig_base_dir, secrets_base_dir, terraform_state_dir, ssh_key_dir — shared filesystem base paths used to build config/cert directory paths consistently across scripts
devhome/azure arm_client_id/arm_tenant_id/arm_client_secret/arm_subscription_id, azuredevops_pat/azuredevops_org_service_url, dns_zone/resource_group (the last two were added directly to Vault but aren't wired into terraform/azure/main.tf yet — that file still hardcodes devhome-prod/devhome.cloud, a known gap)
devhome/argocd argocd_server_addr, argocd_username, argocd_password
devhome/rancher rancher_url, rancher_admin_password
devhome/packer build_username, dsrm_password, ssh_password, plus a flat (not nested — Packer's vault() HCL function can't read nested JSON) os_metadata block of Windows image/KMS keys

Packer's vault() function needs a literal /data/ segment

vault("devhome/data/<secret>", "<field>") — KV-v2's API path always has /data/ in the middle, easy to forget when every other consumer's syntax hides it (Terraform's data source, Ansible's lookup plugin, and PowerShell's Invoke-RestMethod calls all take the mount/path separately rather than as one concatenated string).

There is no devhome/vcenter path

A couple of older scripts referenced a devhome/vcenter secret with username/ password fields that never actually existed post-reorg — the real path is devhome/vmware with vsphere_username/vsphere_password. If a script 403s or gets an empty {"errors":[]} response from Vault, check for this exact mistake before assuming a permissions problem.

Reading secrets from Terraform

data.vault_kv_secret_v2 data sources pull these at plan/apply time — see Terraform.