No description
  • Python 30.8%
  • Shell 28.8%
  • HCL 23.7%
  • Dockerfile 8.6%
  • Go Template 7.9%
  • Other 0.2%
Find a file
flux-image-automation 142311d9d2
Some checks failed
homelab-validation / validate (push) Failing after 8s
Update Portfolio image
sha256:87d9fd9ee48f5ec84ad2b3042703ffe5d22ebc777be1b53b3132eb61a33a4277 -> sha256:0abe97a78b3f9f47e2b2d3d06dd9ef2580dbc16dd2003436ead04c93a30561b0
2026-09-19 16:28:15 +00:00
${XDG_CONFIG_HOME:-/home/tmendy/.config}/homelab Automate Portfolio image updates with Flux 2026-09-08 13:52:58 +02:00
.forgejo/workflows fix(coder): add Chromium launcher for desktop workspace 2026-09-15 20:45:45 +00:00
backlogs Remove Private Activity And Planning Files 2026-08-28 18:06:31 +02:00
docs Merge personal desktop workspace changes 2026-09-15 19:58:43 +02:00
kubernetes Update Portfolio image 2026-09-19 16:28:15 +00:00
scripts Automate Portfolio image updates with Flux 2026-09-08 13:52:58 +02:00
.gitattributes feat: add .gitattributes file to manage line endings and file types for web project 2026-05-15 18:08:13 +09:00
.gitignore Add NymVPN sidecar and Forgejo domain 2026-08-10 16:31:39 +02:00
.pre-commit-config.yaml Harden secret scanning and clean up docs 2026-08-26 12:34:46 +02:00
AGENTS.md Remove Private Activity And Planning Files 2026-08-28 18:06:31 +02:00
CONTRIBUTING.md Add public publication tooling and CI validation 2026-08-27 17:16:14 +02:00
LICENSE Add public publication tooling and CI validation 2026-08-27 17:16:14 +02:00
network_migration.md Remove Private Activity And Planning Files 2026-08-28 18:06:31 +02:00
NOTICE Add public publication tooling and CI validation 2026-08-27 17:16:14 +02:00
README.md Refresh README and architecture documentation 2026-08-29 10:42:41 +02:00
SECURITY.md Remove Private Activity And Planning Files 2026-08-28 18:06:31 +02:00
THIRD-PARTY-NOTICES.md Add public publication tooling and CI validation 2026-08-27 17:16:14 +02:00
todo.md Remove obsolete updater and expand recovery tasks 2026-08-28 18:17:07 +02:00

Homelab Kubernetes platform

Infrastructure as code for a three-node Kubernetes homelab. The cluster is managed with Flux GitOps and runs platform services, self-hosted applications, databases, CI runners, and an internal developer environment.

This repository shows how I operate a small platform over time: changes are reviewed in Git, rendered and checked in CI, reconciled by Flux, and backed by recovery procedures. It is an operational project, not a generic Kubernetes starter template.

What the project demonstrates

  • GitOps reconciliation with Flux, Helm releases, and Kustomize.
  • Local Helm charts for project-specific Kubernetes resources.
  • Identity and SSO with Authentik and OIDC.
  • Runtime secret delivery with Infisical, without committing credentials.
  • PostgreSQL clusters managed by CloudNativePG.
  • Shared NFS-backed persistent storage that is independent of worker nodes.
  • Ingress and TLS routing with Traefik.
  • Observability with Prometheus and Grafana.
  • Forgejo Actions and GitHub Actions runners for CI workloads.
  • Validation gates for secret scanning, Helm rendering, Kubernetes schemas, and storage policy.
  • Backup, restore, node maintenance, and disaster recovery runbooks.

Architecture at a glance

The live cluster has one control-plane node and two workers:

Area Implementation
Nodes node1 control plane, node2 and node3 workers
Reconciliation Flux Operator, Flux controllers, native Flux resources
Git source Private Forgejo repository inside the cluster
Ingress Traefik
Identity Authentik with OIDC integrations
Secrets Infisical Operator and external secret resources
Databases CloudNativePG PostgreSQL clusters
Persistent storage Synology NFS at 10.0.0.11:/volume1/k8s, exposed as nfs-k8s
Observability Prometheus and Grafana

The dependency direction is deliberate. Flux applies platform services first. Identity, storage, and database releases then provide prerequisites for application releases. HelmReleases declare these dependencies with dependsOn.

See docs/architecture.md for the component map and deployment flow. The repository contains environment-specific values for the live homelab, so review docs/publication.md before sharing a copy publicly.

Repository layout

homelab/
├── kubernetes/
│   ├── flux/                 # Flux bootstrap and cluster reconciliation
│   ├── <service>/            # Local Helm charts and service configuration
│   └── active-local-charts.txt
├── docs/                     # Architecture, operations, and recovery runbooks
├── scripts/                  # Rendering, validation, and hardware utilities
├── .forgejo/workflows/       # CI validation and image build workflows
├── CONTRIBUTING.md
└── README.md

The kubernetes/ directory contains both local charts and values consumed by external charts. kubernetes/flux/cluster/ is the entry point for steady-state reconciliation. active-local-charts.txt defines the charts rendered by the local validation scripts.

Getting started

Validate changes locally

This is the safe starting point. It does not require cluster access.

Prerequisites:

  • Bash, Helm 3, and kubeconform.
  • rumdl for Markdown checks.
  • kubectl only if you also want to render or validate Kustomize resources.

Run the same core checks used by Forgejo Actions:

./scripts/check-storage-policy.sh
./scripts/test-helm-chart.sh
./scripts/render-local-charts-for-kubeconform.sh
kubeconform -strict -summary -ignore-missing-schemas .forgejo-rendered
rumdl check --fix .

The render script recreates .forgejo-rendered/, which is ignored by Git. To validate the Flux cluster resources separately:

kubectl kustomize --load-restrictor=LoadRestrictionsNone \
  kubernetes/flux/cluster

Bootstrap or recover the cluster

A live deployment requires an existing Kubernetes cluster, access to the Synology NFS export, a private Forgejo deploy key, and Infisical bootstrap credentials. A full cluster rebuild also depends on Forgejo data being available before Flux can fetch its source.

Follow docs/flux-gitops.md for the ordered bootstrap procedure. It covers preparing external identity and secret material, installing Flux Operator, creating the Flux SSH source Secret, applying the Flux instance, and verifying reconciliation before changing any previous GitOps owner.

Do not put deploy keys, kubeconfig files, client secrets, or rendered Secrets in Git. For data recovery and node loss, use docs/backup-procedures.md and docs/disaster-recovery.md.

Add a service

  1. Add or update kubernetes/<service>/.
  2. Add its HelmRelease to the appropriate file in kubernetes/flux/cluster/apps/.
  3. Add an external chart source to kubernetes/flux/cluster/sources.yaml when needed.
  4. Add ingress, DNS, identity, and homepage configuration when applicable.
  5. Store runtime credentials in Infisical and reference them from the chart.
  6. Run the local validation commands before opening a change.

For persistent workloads, use storageClassName: nfs-k8s. Worker-local storage is forbidden by the repository policy.

Scope and known limits

This is a real homelab with explicit trade-offs. The current design still has one control-plane node, one central NFS backend, single-replica services, and some hardware-specific workloads. The runbooks document the resulting failure modes and recovery steps.

Further reading

License

Apache License 2.0. See LICENSE.