Skip to main content

workspace (component)

A Kustomize component that does the unglamorous-but-required boilerplate every app needs: create the namespace, label it for the platform controllers, set up a baseline ServiceAccount, and ensure the homelab-standard annotations are present.

It's the first component most apps pull in. Other components (cnpg, valkey, backups, app-network-policy) assume workspace already established the namespace and labels.

What it composes

  • Namespace <app> — created with the standard homelab labels:
    • kubernetes.io/metadata.name: <app> (set automatically; restated for cross-cluster consistency)
    • pod-security.kubernetes.io/enforce: restricted (with per-app override patches when an app legitimately needs root, e.g. linuxserver images using PUID/PGID).
    • homelab.kueber.eu/cluster: <cluster> — for the monitoring and Kyverno layers.
  • ServiceAccount <app> — the default identity any pod runs as if not otherwise configured.
  • Role / RoleBinding for the per-app ServiceAccount — minimum permissions to read its own Secrets and ConfigMaps, nothing more.

How an app uses it

Almost always pulled in first:

# k8s/apps/talos/<app>/kustomization.yaml
namespace: <app>
components:
- ../../../components/talos/workspace # always first
- ../../../components/talos/app-network-policy
- ../../../components/talos/cnpg # if needed
- ../../../components/talos/backups # if PVCs exist

The order in the components: list matters when components override each other; in practice workspace is always first because everything else assumes its labels are already set.

Why a component, not just a hand-written namespace per app

  • Single point of policy. Pod Security Standards, default ServiceAccount tokens, default annotations — change once and every app picks up the new defaults at the next reconciliation.
  • Consistency for cross-cluster tooling. Monitoring scrapes, Kyverno policies, and the backup scheduler all key off the homelab.kueber.eu/cluster label. If one app's namespace forgot to set it, the silence is hard to debug.
  • No boilerplate copy-paste. A new app's kustomization.yaml doesn't need to repeat the namespace + RBAC plumbing.

Operational notes

  • Restricted Pod Security is the default. Apps that legitimately need root (linuxserver images, Gitea for SSH) patch their namespace's pod-security label to baseline and document the reason in the cluster README — see Content model.
  • Deleting the namespace deletes everything in it. The component doesn't add finalizers — if an app is being decommissioned, deleting the Namespace directly is the cleanest path.
  • The same component on the edge cluster is slightly thinner — no homelab.kueber.eu/cluster: talos label, no monitoring annotation (edge apps aren't scraped from the production Prometheus).

Composition source

No partial — there's no README.md in k8s/components/<cluster>/workspace/ yet. See k8s/components/talos/workspace for the actual manifests.