Appendix: Local Development Environment

Incident Hook

A learner tests every infrastructure and GitOps change only against the cloud cluster. Feedback is slow, mistakes are expensive, and trivial YAML errors burn real time and real money. By the time the change reaches the shared environment, the debugging loop is already too wide. A local cluster exists to reduce that blast radius before cloud validation even starts.

Why This Appendix Exists

The main course teaches the production path first. This appendix shows the fastest safe feedback loop for local experimentation:

  • a Terraform-managed kind cluster
  • generated kubeconfig and context wiring
  • optional local image registry
  • Flux bootstrap for GitOps-shaped testing

Use it when you need fast iteration on manifests, hooks, or application behavior before touching Hetzner-backed environments.

SafeOps Baseline

In the current SafeOps implementation:

  • Terraform manages the lifecycle of the local kind cluster.
  • the cluster is multi-node, so scheduling behavior is closer to reality than a single-node toy setup.
  • Flux Operator + FluxInstance can bootstrap the local cluster from the same GitOps layout.
  • local registry support keeps image iteration fast.

Investigation Snapshots

Here is the Terraform module layout used for the local cluster in the SafeOps system.

Local kind cluster Terraform module

Snippet unavailable during this build.

Here is the local development runbook used in the SafeOps system.

Local development runbook

Snippet unavailable during this build.

Safe Workflow (Step-by-Step)

  1. Confirm local prerequisites first: Docker Engine, Terraform, kubectl, make, and enough CPU/RAM for a three-node kind cluster.
  2. Move to infra/terraform/kind_cluster/ and decide whether local Flux should reconcile from the same Git path as the main platform.
  3. If you want GitOps reconciliation locally, export the Flux repository variables before apply.
  4. Run terraform init and terraform apply from the kind_cluster module.
  5. Point kubectl to the generated kubeconfig or switch to the merged sre-control-plane context.
  6. Verify nodes, namespaces, and Flux controllers before testing workloads.
  7. If you iterate on images, start the local registry before cluster apply so the mirror config is valid.
  8. Tear the cluster down with terraform destroy when the test cycle is finished.

Verification Commands

cd infra/terraform/kind_cluster
terraform init
terraform apply

export KUBECONFIG="$(pwd)/kubeconfig.yaml"
kubectl config use-context sre-control-plane
kubectl get nodes
kubectl -n flux-system get pods

Optional local registry:

docker run -d --restart=always -p 5001:5000 --name kind-registry registry:2

When to Prefer Local Development

Prefer the local path when:

  • you are validating manifests, hooks, or GitOps wiring
  • you need a fast loop for backend or frontend changes
  • you want to reproduce a failure without risking shared environments

Do not treat the local path as a substitute for provider-realistic verification. Hetzner, external DNS, cloud load balancers, and real certificate issuance still need cloud-side validation.

Guardrail Principle

Use the local cluster to shrink the feedback loop and the blast radius. Use the cloud cluster to validate provider-specific behavior. Do not confuse the two.

Done When

  • you can create and destroy the local cluster from Terraform
  • kubectl can target the local context without ambiguity
  • Flux controllers reconcile in the local cluster when enabled
  • you can explain which tests belong locally and which still require cloud validation