# Homelab Configuration for my homelab: Kubernetes manifests, Docker Compose stacks, and the Gitea Actions that build and deploy them. Most applications have both deployment formats. Headscale and Nextcloud AIO have Compose deployments with Kubernetes ingress; the media stack has Compose and Kubernetes routing configuration. These files contain this lab's domains, IP addresses, storage paths, and private registry names. Running them on another machine takes some editing. ## Start here - [Service list](#services) — what each directory contains. - [Deployment workflow](.gitea/README.md) — selection, validation, and recovery. - [Repository review](docs/repository-review.md) — findings from the 6 October baseline and their status. - [EDU ownership handoff](.gitea/EDU_HANDOFF.md) — the EDU workloads now live in their own repository. - [Shared PostgreSQL](postgres/README.md), [Traefik](traefik/README.md), and [cert-manager](cert-manager/README.md) — common dependencies. ## What gets deployed The `active` files are switches for the deploy workflow, not health indicators. | File | Effect | | ---------------------- | ----------------------------------------------------------- | | `/active` | Include that directory's `compose.yaml` or `compose.yml`. | | `/k8s/active` | Include its Kubernetes manifests or Kustomize overlay. | | Both | Run the Compose stack and apply the Kubernetes resources. | | Neither | Keep the configuration in Git without automatic deployment. | `shared-compose.yaml`, `client.compose.yaml`, and `renovate-compose.yaml` are manual entry points. The deploy script does not discover them. Kubernetes selection excludes secret files, examples, Helm values, and patches. Helm releases listed in `deploy-lib.sh` are upgraded separately. Traefik, cert-manager, and CrowdSec have additional bootstrap steps; an `active` marker does not install their charts. The table below describes committed configuration. It does not claim that a service is currently healthy or running. ## Services | Service | Configuration | Selected by markers | | ---------------------------------------------- | ---------------------------- | ------------------- | | [AdGuard Home](adguardhome/README.md) | Kubernetes + Compose | Kubernetes | | [Authentik](authentik/README.md) | Kubernetes + Compose | Kubernetes | | [cert-manager](cert-manager/README.md) | Kubernetes / Helm | Manual | | [Cloudflare DDNS](cfddns/README.md) | Kubernetes + Compose | Kubernetes | | [Checkmk](checkmk/README.md) | Kubernetes + Compose | Manual | | [Cloudflare Tunnel](cloudflared/README.md) | Kubernetes / Helm | Manual | | [File converters](converters/README.md) | Kubernetes + Compose | Kubernetes | | [CrowdSec](crowdsec/README.md) | Kubernetes / Helm | Manual | | [Dockmon](dockmon/README.md) | Kubernetes + Compose | Manual | | [Downtify](downtify/README.md) | Kubernetes + Compose | Manual | | [Error pages](errorpages/README.md) | Kubernetes + Compose | Kubernetes | | [Gitea](gitea/README.md) | Kubernetes + Compose | Kubernetes | | [Glance](glance/README.md) | Kubernetes + Compose | Manual | | [Headscale](headscale/README.md) | Compose + Kubernetes routing | Compose, Kubernetes | | [Homarr](homarr/README.md) | Kubernetes + Compose | Manual | | [Homepages](homepages/README.md) | Kubernetes + Compose | Kubernetes | | [Immich](immich/README.md) | Kubernetes + Compose | Kubernetes | | [Kener](kener/README.md) | Kubernetes + Compose | Manual | | [Loki and Alloy](loki/README.md) | Kubernetes / Helm | Kubernetes | | [MeTube](metube/README.md) | Kubernetes + Compose | Kubernetes | | [n8n](n8n/README.md) | Kubernetes + Compose | Manual | | [NetBird](netbird/README.md) | Kubernetes + Compose | Kubernetes | | [NetBox](netbox/README.md) | Kubernetes + Compose | Kubernetes | | [Netronome](netronome/README.md) | Kubernetes + Compose | Kubernetes | | [Nextcloud AIO](nextcloud/README.md) | Compose + Kubernetes routing | Compose, Kubernetes | | [Penpot](penpot/README.md) | Compose | Manual | | [Portainer](portainer/README.md) | Kubernetes + Compose | Manual | | [Shared PostgreSQL](postgres/README.md) | Kubernetes + Compose | Kubernetes | | [Monitoring stack](prometheus-stack/README.md) | Kubernetes + Compose | Kubernetes | | [RackPeek](rackpeek/README.md) | Kubernetes + Compose | Kubernetes | | [Reloader](reloader/README.md) | Kubernetes / Helm | Kubernetes | | [Renovate](renovate/README.md) | Kubernetes + Compose | Kubernetes | | [SearXNG](searxng/README.md) | Kubernetes + Compose | Manual | | [Media stack](streaming/README.md) | Compose + Kubernetes routing | Manual | | [Termix](termix/README.md) | Kubernetes + Compose | Manual | | [Traefik](traefik/README.md) | Kubernetes + Compose | Kubernetes | | [Uptime Kuma](uptime-kuma/README.md) | Kubernetes + Compose | Kubernetes | | [Vaultwarden](vaultwarden/README.md) | Kubernetes + Compose | Kubernetes | | [3x-ui](vpn/xui/README.md) | Kubernetes | Kubernetes | ## Running a Compose stack Use the service README first. Where a service has an env example, copy it inside that service's directory and replace the placeholders. The root `.env.example` is an older collection of variables, not a complete configuration for every stack. For example, from the repository root: ```sh cd netbox cp .env.example .env $EDITOR .env docker compose config --quiet docker compose up -d docker compose ps ``` Stacks that attach to `proxy` require an existing Docker network of that name and an appropriate reverse proxy. Published host ports still work independently of Traefik. Check port conflicts before starting an alternative to a Kubernetes service: DNS, STUN, and HTTP listeners can share the same host. `docker compose down` keeps named volumes. Adding `-v` removes them. ## Preparing Kubernetes The manifests assume Traefik CRDs, cert-manager, and a working storage provisioner. PrometheusRule and ServiceMonitor resources also need the Prometheus Operator. Replace the lab's hosts and addresses before using the configuration elsewhere. Create a service's namespace, then prepare its ignored Secret from the example. For example: ```sh kubectl apply -f netbox/k8s/namespace.yaml cp netbox/k8s/secrets.yaml.example netbox/k8s/secrets.yaml $EDITOR netbox/k8s/secrets.yaml kubectl apply -f netbox/k8s/secrets.yaml ``` The deploy workflow applies the tracked resources for marked services. Avoid applying an entire `k8s/` directory blindly: some directories contain Helm values, examples, and alternative routes. For a manual change, apply the selected manifest explicitly and check the resulting rollout. Shared database passwords must agree between the `database` namespace and each application's Secret. Updating the PostgreSQL Secret does not change an existing role's password; see the database README. ## Local checks CI pins its tools in `.gitea/workflows/tool-versions.env`. Use the same versions: ```fish set tools_dir (bash .gitea/workflows/install-ci-tools.sh) set -gx PATH $tools_dir $PATH ruff check . ruff format --check . actionlint -config-file .gitea/actionlint.yaml .gitea/workflows/*.yaml .gitea/workflows/sync-renovate-configmap.sh --check ``` The [workflow README](.gitea/README.md#ci) lists the rest of the checks. Structure checks do not establish that local Secrets, mounted files, storage, or external services are ready. ## Data and recovery State lives outside Git: PVCs, Docker volumes, bind mounts, databases, and ignored configuration. Keep backups of application data and the keys needed to read it. An image rollback does not roll back database migrations or ConfigMap contents. Many PVCs use the cluster's default StorageClass; monitoring explicitly uses `local-path`. Check the PV reclaim policy before deleting a PVC or namespace. The manifests do not provide a repository-wide backup schedule. `incident-archive/` contains past incident notes. `.docs/storage-audit-instruction.md` is a planning document, not evidence that NFS has been installed.