Flux GitOps Platform

SkillCloud & infra

Flux GitOps patterns for the homelab Kubernetes platform using ResourceSets.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Flux GitOps Platform skill

What this skill tells your AI

The instructions your AI receives, as published by ionfury/homelab in .claude/skills/flux-gitops/SKILL.md and read by ahel’s review.

The homelab Kubernetes platform uses Flux ResourceSets for centralized, declarative management of Helm releases and configurations.

For ResourceSet patterns, version management, and platform architecture, see kubernetes/platform/CLAUDE.md.

How to Add a New Helm Release

Add to helm-charts.yaml inputs → create charts/<release-name>.yaml values file → register in kustomization.yaml configMapGenerator → optionally add config/<name>/ resources.

helm-charts.yaml entry

inputs:
  - name: "my-new-chart"
    namespace: "my-namespace"
    chart:
      name: "actual-chart-name"
      version: "${my_chart_version}"   # From versions.env via Flux substitution
      url: "https://example.com/charts"
    dependsOn: [cilium]

For OCI registries, prefix url with oci://:

    chart:
      url: "oci://ghcr.io/bjw-s/helm"

The ResourceSet template auto-detects OCI URLs and sets type: oci on the HelmRepository.

Values file

Create charts/<release-name>.yaml:

# yaml-language-server: $schema=<chart-schema-url>
---
replicas: 1

kustomization.yaml registration

configMapGenerator:
  - name: platform-values
    files:
      - charts/my-new-chart.yaml

PodSecurity compliance

Check the target namespace's security level in namespaces.yaml. For restricted namespaces (cert-manager, external-secrets, system, database, kromgo), every container requires:

# Pod-level
podSecurityContext:
  runAsNonRoot: true
  seccompProfile:
    type: RuntimeDefault

# Container-level (every container including init containers)
securityContext:
  allowPrivilegeEscalation: false
  capabilities:
    drop: ["ALL"]
  readOnlyRootFilesystem: true
  runAsNonRoot: true
  seccompProfile:
    type: RuntimeDefault

If the image runs as root, set runAsUser: 65534. task k8s:validate does NOT catch PodSecurity violations — only admission time reveals them.

ResourceSet Template Syntax

The resourcesTemplate uses Go text/template with << >> delimiters. See templates.md for full template examples.

Key functions:

  • << inputs.field >> — access input field
  • <<- if condition >> / <<- end >> — conditional (leading - trims whitespace)
  • <<- range $item := inputs.array >> — loop
  • hasPrefix "oci://" inputs.chart.url — string prefix check

Dependency Management

Release dependencies (waits for other HelmReleases):

inputs:
  - name: "grafana"
    dependsOn: [kube-prometheus-stack, alloy]

ResourceSet dependencies (waits for another ResourceSet):

spec:
  dependsOn:
    - apiVersion: fluxcd.controlplane.io/v1
      kind: ResourceSet
      name: platform-namespaces

Version Management

Add a version entry to kubernetes/platform/versions.env with a Renovate annotation, then reference via ${variable_name} in helm-charts.yaml. For annotation syntax and datasource selection, see the versions-renovate skill.

Debugging Flux

Check status: kubectl get resourcesets -n flux-systemkubectl describe resourceset platform-resources -n flux-system

Check HelmRelease: kubectl get helmreleases -Akubectl describe helmrelease <name> -n <namespace>

Force reconciliation: flux reconcile helmrelease <name> -n <namespace> or flux reconcile kustomization flux-system -n flux-system

SymptomCauseSolution
waiting for dependenciesDependency not readyCheck dependsOn releases
values key not foundMissing values fileAdd to kustomization.yaml configMapGenerator
chart not foundWrong chart name/URLVerify chart exists in repository
namespace not foundNamespace not createdAdd to namespaces.yaml

Signals

GitHub stars
25
Forks
3
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
flux-gitops
Source
github.com/ionfury/homelab