IoC for my homelab using opentofu
  • Python 35.2%
  • Jinja 29.4%
  • HCL 25.7%
  • JavaScript 3.8%
  • Just 3.1%
  • Other 2.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-11-02 19:33:55 +00:00
.forgejo/workflows feat(monitoring): deploy dedicated HA Kuma and expand health checks 2026-10-14 22:20:14 +02:00
ansible feat: optimize ceph cluster writes 2026-11-02 20:33:14 +01:00
dns Refactor infrastructure workflow and add versioned Packer templates 2026-10-22 19:17:57 +02:00
docs feat: optimize ceph cluster writes 2026-11-02 20:33:14 +01:00
images/debian Refine Packer SSH setup and refresh infrastructure notes 2026-10-25 09:39:16 +01:00
opentofu feat: add cluster wide zram to VMs 2026-10-28 12:39:07 +01:00
scripts Refactor infrastructure workflow and add versioned Packer templates 2026-10-22 19:17:57 +02:00
services feat: optimize ceph cluster writes 2026-11-02 20:33:14 +01:00
tests Refactor infrastructure workflow and add versioned Packer templates 2026-10-22 19:17:57 +02:00
.env Rotate SOPS age recipient for Fedora laptop 2026-09-26 19:52:55 +02:00
.env.example fix: correct stale variables, dead handlers, and redundant role 2026-06-01 23:55:21 +02:00
.gitignore Refactor infrastructure workflow and add versioned Packer templates 2026-10-22 19:17:57 +02:00
.sops.yaml Rotate SOPS age recipient for Fedora laptop 2026-09-26 19:52:55 +02:00
AGENTS.md Refactor infrastructure workflow and add versioned Packer templates 2026-10-22 19:17:57 +02:00
ansible-refactoring-plan.md Refine Packer SSH setup and refresh infrastructure notes 2026-10-25 09:39:16 +01:00
assh.yml feat: add tandoor app 2026-10-27 10:59:24 +01:00
justfile Refine Packer SSH setup and refresh infrastructure notes 2026-10-25 09:39:16 +01:00
README.md Refactor infrastructure workflow and add versioned Packer templates 2026-10-22 19:17:57 +02:00

Infrastructure Monorepo

OpenTofu provisions the Proxmox infrastructure; Ansible configures guests. The root justfile provides the command interface.

Layout

Directory Ownership
opentofu/ Guests, storage registration, HA, backup jobs, seed and inventory
dns/ Static Porkbun DNS records in an independent state
images/debian/ Direct Packer builds and explicitly approved template catalog
ansible/ Guest software, configuration and generated inventory consumers
services/ Workload configuration and operational SKILL.md guides
docs/ Architecture, operations/recovery instructions and deferred work

Both OpenTofu roots use locked remote S3 state in Garage. Keep independent restricted recovery copies; state and plan artifacts contain credentials.

Prerequisites and secrets

Install just >=1.59, OpenTofu >=1.13 and <2.0, Python 3, Ansible, SOPS/age, and an SSH client. Image builds additionally require Packer >=1.14 and <2.0. Keep the age key at ~/.config/age/keys.txt; agent-run playbooks pass the existing Vault password file directly to Ansible without reading it.

just --list
just secrets-decrypt

The encrypted .env remains the source for .env.local. Just loads only the plaintext local file through a small compatibility adapter in the existing Python workflow helper. It quotes the legacy bare JSON SSH-key array in memory, without rewriting either file or interpreting their contents as shell code. Recipe listing and initial decryption work before .env.local exists. Never print the adapter's dotenv output; it contains credentials.

Provision and configure

Proxmox and public DNS use independent state. See the operations and recovery guide.

just tofu-init
just tofu-plan
# Review the saved plan and obtain deployment authorization first.
just tofu-apply
just ansible-deps
just ansible-check --limit openclaw
# Requires separate authorization for guest configuration.
just ansible-site-limit openclaw

The apply recipe consumes the exact saved plan and rejects modified artifacts or changed configuration. just tofu-plan-offline is an unsaved stale-state preview. Generated inventory comes from state outputs; the Ansible recipes regenerate it before check/site/role runs and preserve stopped-host filtering.

Command interface

Taskfile has been replaced. Names use hyphens and arguments are positional; there are no CLI_ARGS=... strings or wildcard recipe names to construct.

just tofu-cli show .artifacts/reviewed.plan
just tofu-state-backup /absolute/independent/infrastructure.tfstate
just dns-plan
just ansible-update zigbee2mqtt
just ansible-role pihole --limit pihole
just ssh-forget openclaw
just image-build images/debian/build.pkrvars.hcl

Arguments with spaces or shell metacharacters remain literal arguments. The old refresh aliases are unnecessary: planning refreshes by default and applying uses the reviewed saved artifact. just home-deploy applies that plan and then configures all hosts, requiring explicit authorization for both operations.

Local checks

just tofu-init
just dns-init
just check

Checks validate both roots, run mocked OpenTofu contracts and Python workflow/ recipe tests. Recipe integration tests use fake executables; they do not apply plans, decrypt real secrets or deploy services. Check/live-service results remain separate from first-image boot evidence. Image builds use direct Packer commands and a separate Ansible smoke playbook; see the architecture decision.

Operations

Consult a workload's services/<name>/SKILL.md before changing or diagnosing it. Commits, applies, image builds/tests and deployments require explicit reviewed authorization; changing the command runner does not grant it.