Files
homelab-infrastructure-as-code/CLAUDE.md
T
kasun 13549a8d37
Deploy k8s Infra / Pulumi Preview (push) Has been skipped
Deploy k8s Infra / Pulumi Deploy (push) Successful in 58s
Deploy k8s Apps / Pulumi Preview (push) Has been skipped
Deploy k8s Apps / Pulumi Deploy (push) Successful in 48s
Deploy Monitoring / Pulumi Preview (push) Has been skipped
Deploy Monitoring / Pulumi Deploy (push) Successful in 59s
docs: updated documentation to current progress
2026-06-11 22:36:20 +02:00

3.3 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code when working anywhere in this repository. Each stack directory (01-proxmox-infra, 02-k8s-bootstrap, etc.) has its own CLAUDE.md with stack-specific commands and architecture — Claude Code loads both this file and the stack's file automatically when working inside a stack directory.

Project overview

Pulumi (TypeScript) IaC for a Proxmox-based k3s homelab. Independent Pulumi projects ("stacks"), each with its own Pulumi.yaml/package.json, deployed in order and linked via pulumi.StackReference:

# Directory Pulumi stack Purpose
1 01-proxmox-infra proxmox-infra Provisions k3s VMs + DHCP on Proxmox/pfSense
2 02-k8s-bootstrap k8s-bootstrap Installs k3s on the VMs over SSH
3 03-k8s-infra k8s-infra Cluster infra: storage, cert-manager, kube-vip
4 04-k8s-apps k8s-apps Application workloads (e.g. heimdall)
5 05-monitoring monitoring kube-prometheus-stack (Prometheus + Grafana)

All stacks use the Pulumi stack name dev.

Deployment order & StackReferences

proxmox-infra → k8s-bootstrap → k8s-infra
                              ↘ k8s-apps → monitoring
  • k8s-bootstrap reads VM IDs, Proxmox credentials, and the SSH private key from proxmox-infra via StackReference.
  • k8s-infra, k8s-apps, and monitoring all read kubeconfig from k8s-bootstrap via StackReference (requireOutput("kubeconfig")) — never set kubeconfig as Pulumi config in these stacks.
  • monitoring additionally reads domain from k8s-apps via StackReference.
  • StackReference format: ${pulumi.getOrganization()}/<stack-name>/dev.

A stack's outputs must exist (i.e. it must have been deployed) before any downstream stack referencing it will succeed.

Shared conventions

  • TypeScript: strict: true, target: es2024, module/moduleResolution: nodenext, noImplicitReturns, noFallthroughCasesInSwitch — functions need explicit return types where TS can't infer them.
  • Secrets: read via config.requireSecret(), never via environment variables or hardcoded values.
  • Pulumi.dev.yaml: gitignored (contains the encryption salt) — never delete it or secrets become unrecoverable. Encrypted with PULUMI_CONFIG_PASSPHRASE.
  • Backend: self-hosted Postgres state backend, set via PULUMI_BACKEND_URL.
  • Don't add a co-author when committing to git.

Common commands (run from a stack directory)

npm install
pulumi preview
pulumi up --yes
pulumi destroy
pulumi stack output
pulumi config

Requires PULUMI_BACKEND_URL and PULUMI_CONFIG_PASSPHRASE in the environment (or pulumi login).

CI/CD (Gitea Actions)

One workflow per stack: .gitea/workflows/0N-deploy-<stack>.yaml, scoped to changes under that stack's directory.

  • Pull request → main: pulumi preview only.
  • 01/02 (VM provisioning / cluster bootstrap — riskier to automate): deploy only via manual workflow_dispatch.
  • 0305: deploy on push to main or workflow_dispatchpulumi refresh then pulumi up.
  • Each workflow restores Pulumi.dev.yaml from a base64-encoded Gitea secret (<STACK>_PULUMI_DEV_YAML). After changing local config, re-encode and update the secret:
    base64 -w 0 0N-<stack>/Pulumi.dev.yaml