Files
home-kubernetes/CLAUDE.md
Jan Novak ed10cc837a chore: add CLAUDE.md, kubectl notes, and settings/gitignore tweaks
Document the repo for Claude Code, note a couple of handy kubectl
one-liners, allow a few more Bash/WebFetch/WebSearch permissions used
during this session, and ignore the relocated zot sync-credentials.json.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-09 00:05:56 +02:00

4.2 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Repository Purpose

Home Kubernetes lab infrastructure-as-code. Manages VM provisioning (Terraform/KVM), Kubernetes cluster configuration, and application deployments via Flux GitOps — all pointing at a self-hosted Gitea instance.

Common Commands

Terraform (kubernetes-kvm-terraform/)

cd kubernetes-kvm-terraform
tofu init
tofu plan
tofu apply
tofu destroy

Flux GitOps

# Check reconciliation status
kubectl get kustomizations -A
kubectl get helmreleases -A

# Force reconcile
flux reconcile kustomization flux-system --with-source
flux reconcile helmrelease <name> -n <namespace>

# Watch logs
flux logs --follow

# Check source sync
flux get sources git

kubectl — common ops

export KUBECONFIG=kubernetes-kvm-terraform/kubeconfig
kubectl get nodes
kubectl get pods -A
kubectl get secrets -A

Docker Compose (docker-30/ services)

# These run on 192.168.0.30 (docker-30), accessed via SSH
ssh novakj@192.168.0.30
cd /path/to/service && docker compose up -d
docker compose logs -f

Architecture

Infrastructure Layer

  • Hypervisors: homer (192.168.0.7) and beelink (192.168.0.6) run KVM/libvirt
  • Terraform provider: primary qemu+ssh://novakj@192.168.0.7/system, secondary alias kvm-beelink for 192.168.0.6
  • Kubernetes master: kube-master-31 @ 192.168.0.31:6443, bootstrapped via kubeadm
  • OS: Ubuntu 24.04 Noble cloud images, network bridge br0, subnet 192.168.0.0/24

GitOps Layer (gitops/home-kubernetes/)

Flux syncs from Gitea (https://gitea.home.hrajfrisbee.cz, main branch, every 10 minutes). The reconciliation order is enforced via dependsOn in flux-system/extra-kustomizations.yaml:

00-crds → 00-rbac → cilium → cert-manager → external-secrets → everything else

Each application lives in its own subdirectory under gitops/home-kubernetes/ and is referenced as a Flux Kustomization resource. Prune is enabled — removing a manifest from git removes it from the cluster.

Secrets Flow

Vault (docker-30) → External-Secrets controller (in-cluster) → Kubernetes Secret objects. Applications reference ExternalSecret CRs that pull from Vault paths. Do not put real secrets in git.

Networking

  • CNI: Cilium 1.19.x with Gateway API and Hubble UI enabled
  • L2 LB: Cilium CiliumL2AnnouncementPolicy + CiliumLoadBalancerIPPool for bare-metal load-balancer IPs (defined in gitops/home-kubernetes/cilium/)
  • Ingress: ingress-nginx for HTTP(S) workloads; Gateway API for newer apps
  • TLS: cert-manager issues wildcard cert (*.home.hrajfrisbee.cz) referenced by apps

Storage

  • democratic-CSI: iSCSI volumes backed by FreeNAS at 192.168.0.40
  • Longhorn: configured but disabled in Flux (directory present, not in extra-kustomizations.yaml)

Supporting Services on docker-30 (192.168.0.30)

All managed with Docker Compose:

  • Gitea — Git server + act_runner (GitHub Actions-compatible CI)
  • Vault — secrets backend for External Secrets
  • Zot — private OCI/container registry
  • Kanidm — identity management / OIDC provider
  • nginx — reverse proxy for docker-30 services

Key Conventions

  • New application: create a directory under gitops/home-kubernetes/<app-name>/, add a Kustomization entry in flux-system/extra-kustomizations.yaml with appropriate dependsOn.
  • Helm apps: use a HelmRepository + HelmRelease pair; pin chart versions explicitly.
  • Secrets: add an ExternalSecret CR pointing to the Vault path; never commit actual secret values.
  • Terraform state: kubernetes-kvm-terraform/terraform.tfstate* is gitignored/sensitive; treat it carefully.
  • kubeconfig: kubernetes-kvm-terraform/kubeconfig is gitignored; obtain it from the master node after provisioning.

Plans

When Claude Code's plan mode is used, save the plan file inside the repo at docs/plans/YYYY-MM-DD-HHMM-<slug>.md instead of the default ~/.claude/plans/ location. Get the timestamp with date "+%Y-%m-%d-%H%M" (matches the changelog convention). The <slug> should be a short kebab-case summary of the plan's topic.