OpenTofu infrastructure for the Proxmox VE homelab: VMs, LXC containers, resource pools, firewall rules, certificates, and the published Ansible inventory.
Terrakube owns state, native workspace locking, execution, and audit history. It exchanges workload identity for a short-lived OpenBao token. Providers then read Proxmox, SSH, Route53, and RustFS credentials with native ephemeral resources; no credential is stored in repository configuration or Terrakube workspace variables.
This repo is consumed by CI and Terrakube, not installed. For local static
checks, the Nix dev shell provides tofu via direnv:
direnv allowStatic checks run locally without credentials; credentialed plans and applies run remotely — see How to apply / redeploy below.
| Source | Contents |
|---|---|
Private RustFS deployment.json |
Desired state, topology, domain, and public SSH key |
OpenBao secret/infrastructure/proxmox |
Proxmox API and SSH credentials |
OpenBao secret/platform/object-storage |
RustFS endpoint and credentials |
Every apply publishes ansible_inventory.json back to RustFS through the
OpenTofu resource graph. Terrakube workspace locking replaces the former
backend-specific lock; no second global OpenBao lock is used.
The Nix dev shell activates through direnv. Local checks never require live credentials:
direnv allow
tofu fmt -check -recursive
tofu init -backend=false
tofu validate
tofu test
tofu -chdir=modules/proxmox-stack init -backend=false
tofu -chdir=modules/proxmox-stack testCredentialed plans, applies, imports, and state operations run only in the
private tofu-proxmox Terrakube workspace.
Authenticate once per machine, then plan like any other tofu command — the run
executes remotely on a Terrakube executor, so no local Proxmox, AWS, or GitHub
credential is ever needed:
tofu login terrakube-api.<domain> # one-time per machine
tofu init
tofu planApplying is not a CLI step. Every workspace sets allowRemoteApply = false,
so a CLI-driven apply is refused server-side regardless of who runs it. An apply
is a Terrakube job, started from the Terrakube UI or its API, and executed by
Terrakube itself — which is what puts every apply in the run audit, under the
workspace lock, and on the workspace's own OpenBao workload identity instead of
an operator's ambient shell.
Run the CLI half from the iac-platform guest rather than a macOS workstation:
macOS Local Network privacy denies the ad-hoc-signed tofu binary, and the
symptom is a misleading connect: no route to host against a Terrakube that is
in fact healthy.
Full runbook (access model, credential lifecycle, token scoping): docs.jacobpevans.com/infrastructure/applying-via-terrakube.
| Doc | Purpose |
|---|---|
| docs/ARCHITECTURE.md | Pipeline architecture and IP derivation |
| docs/EXECUTION_HOSTS.md | Which commands may apply, and which host to run them from |
| docs/INVENTORY_PUBLISHING.md | Native RustFS inventory contract |
| docs/SECRETS_ROADMAP.md | OpenBao and Terrakube secret contract |
| TROUBLESHOOTING.md | Operational recovery guidance |
Apache License 2.0 — see LICENSE.