Repository: xunholy/k8s-gitops Branch: main Commit: 98d45949a862 Files: 1068 Total size: 1.7 MB Directory structure: gitextract_vikb4s18/ ├── .archive/ │ └── kubernetes/ │ ├── apps/ │ │ └── base/ │ │ └── flux-system/ │ │ └── repositories/ │ │ ├── git/ │ │ │ └── archive/ │ │ │ └── origin-ca-issuer-chart.yaml │ │ └── helm/ │ │ └── archive/ │ │ ├── actions-runner-controller.yaml │ │ ├── backube-charts.yaml │ │ ├── bitnami-charts.yaml │ │ ├── cilium-chart.yaml │ │ ├── coredns-charts.yaml │ │ ├── crossplane-charts.yaml │ │ ├── csi-driver-nfs-chart.yaml │ │ ├── descheduler-chart.yaml │ │ ├── emberstack-charts.yaml │ │ ├── emqx-charts.yaml │ │ ├── external-dns-chart.yaml │ │ ├── falco-security-charts.yaml │ │ ├── flagger-charts.yaml │ │ ├── grafana-charts.yaml │ │ ├── jaegertracing-charts.yaml │ │ ├── jetstack-charts.yaml │ │ ├── kiali-charts.yaml │ │ ├── kubefed-charts.yaml │ │ ├── kubereboot-charts.yaml │ │ ├── kubernetes-stable-charts.yaml │ │ ├── kyverno-charts.yaml │ │ ├── litmuschaos-charts.yaml │ │ ├── mayastor-chart.yaml │ │ ├── metallb-charts.yaml │ │ ├── metrics-server-chart.yaml │ │ ├── node-feature-discovery-chart.yaml │ │ ├── oauth2-proxy-chart.yaml │ │ ├── openebs-charts.yaml │ │ ├── openfaas-charts.yaml │ │ ├── otel-charts.yaml │ │ ├── postfinance-charts.yaml │ │ ├── rook-ceph.yaml │ │ ├── sealed-secrets-charts.yaml │ │ ├── secrets-store-csi-driver-chart.yaml │ │ ├── stakater-charts.yaml │ │ ├── traefik-charts.yaml │ │ ├── vernemq-charts.yaml │ │ ├── vmware-charts.yaml │ │ └── xunholy-charts.yaml │ ├── bazarr/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ ├── httproute.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── ocirepository.yaml │ │ │ ├── pvc.yaml │ │ │ ├── resources/ │ │ │ │ └── subcleaner.sh │ │ │ └── secret.enc.age.yaml │ │ └── ks.yaml │ ├── blocky/ │ │ ├── app/ │ │ │ ├── configs/ │ │ │ │ └── config.yml │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── cert-manager-csi-driver/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── cloudflare-ddns/ │ │ ├── app/ │ │ │ ├── deployment.yaml │ │ │ ├── kustomization.yaml │ │ │ └── secret.enc.yaml │ │ └── ks.yaml │ ├── coredns/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── cross-seed/ │ │ ├── app/ │ │ │ ├── externalsecret.yaml │ │ │ ├── helmrelease.yaml │ │ │ ├── kustomization.yaml │ │ │ └── ocirepository.yaml │ │ └── ks.yaml │ ├── csi-driver-nfs/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── emqx/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ ├── cluster/ │ │ │ ├── cluster.yaml │ │ │ ├── httproute.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── podmonitor.yaml │ │ │ └── secret.enc.age.yaml │ │ └── ks.yaml │ ├── external-dns-unifi/ │ │ ├── app/ │ │ │ ├── externalsecret.yaml │ │ │ ├── helmrelease.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── ocirepository.yaml │ │ │ └── values.yaml │ │ └── ks.yaml │ ├── goldilocks/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ ├── httproute.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── istio-csr/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ ├── issuer.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── istio-ingress/ │ │ ├── README.md │ │ ├── bedrock-broadcaster/ │ │ │ ├── app/ │ │ │ │ ├── certificates.yaml │ │ │ │ ├── gateway.yaml │ │ │ │ └── kustomization.yaml │ │ │ └── ks.yaml │ │ ├── github/ │ │ │ ├── httproute.yaml │ │ │ ├── kustomization.yaml │ │ │ └── service.yaml │ │ ├── istio-gateway/ │ │ │ ├── app/ │ │ │ │ ├── authorization-policy.yaml │ │ │ │ ├── certificates.yaml │ │ │ │ ├── gateway.yaml │ │ │ │ ├── helmrelease.yaml │ │ │ │ └── kustomization.yaml │ │ │ └── ks.yaml │ │ ├── kustomization.yaml │ │ ├── namespace.yaml │ │ └── plex/ │ │ ├── httproute.yaml │ │ └── kustomization.yaml │ ├── istio-system/ │ │ ├── README.md │ │ ├── flagger/ │ │ │ ├── app/ │ │ │ │ ├── helmrelease.yaml │ │ │ │ └── kustomization.yaml │ │ │ └── ks.yaml │ │ ├── istio-base/ │ │ │ ├── app/ │ │ │ │ ├── helmrelease.yaml │ │ │ │ └── kustomization.yaml │ │ │ └── ks.yaml │ │ ├── istio-cni/ │ │ │ ├── app/ │ │ │ │ ├── helmrelease.yaml │ │ │ │ └── kustomization.yaml │ │ │ └── ks.yaml │ │ ├── istiod/ │ │ │ ├── app/ │ │ │ │ ├── helmrelease.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ └── podmonitor.yaml │ │ │ └── ks.yaml │ │ ├── kustomization.yaml │ │ └── namespace.yaml │ ├── jaeger/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ ├── httproute.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── k8s-gateway/ │ │ ├── app/ │ │ │ ├── Corefile │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── kiali/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ ├── httproute.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── kubefed/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── kured/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── litmus/ │ │ ├── kustomization.yaml │ │ ├── litmus/ │ │ │ ├── app/ │ │ │ │ ├── helmrelease.yaml │ │ │ │ ├── httproute.yaml │ │ │ │ └── kustomization.yaml │ │ │ └── ks.yaml │ │ ├── litmus-core/ │ │ │ ├── app/ │ │ │ │ ├── helmrelease.yaml │ │ │ │ └── kustomization.yaml │ │ │ └── ks.yaml │ │ └── namespace.yaml │ ├── loki-stack/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── metallb/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ ├── config/ │ │ │ ├── ipaddresspool.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── node-feature-discovery/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ ├── kustomization.yaml │ │ │ └── networkpolicy.yaml │ │ └── ks.yaml │ ├── openclaw/ │ │ ├── app/ │ │ │ ├── backendtrafficpolicy.yaml │ │ │ ├── configmap.yaml │ │ │ ├── externalsecret.yaml │ │ │ ├── helmrelease.yaml │ │ │ ├── httproute.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── pvc.yaml │ │ │ ├── replicationsource.yaml │ │ │ └── volsync-externalsecret.yaml │ │ └── ks.yaml │ ├── openebs-system/ │ │ ├── kustomization.yaml │ │ ├── namespace.yaml │ │ └── openebs/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── openfaas/ │ │ ├── README.md │ │ ├── kustomization.yaml │ │ ├── namespace.yaml │ │ ├── networkpolicy.yaml │ │ └── openfaas/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── openfaas-fn/ │ │ ├── kustomization.yaml │ │ ├── namespace.yaml │ │ └── networkpolicy.yaml │ ├── origin-ca-issuer/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── plex/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ ├── httproute.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── reloader/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── sealed-secrets/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ ├── httproute.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── secret-store-csi-driver/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── snmp-exporter/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── speedtest/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── tf-controller/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ ├── ks.yaml │ │ └── terraform/ │ │ └── gcp/ │ │ ├── secret.enc.age.yaml │ │ └── terraform.yaml │ ├── thanos/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ ├── httproute.yaml │ │ │ ├── kustomization.yaml │ │ │ └── secret.enc.age.yaml │ │ └── ks.yaml │ ├── traefik-ingress/ │ │ ├── kustomization.yaml │ │ ├── namespace.yaml │ │ └── traefik/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ └── kustomization.yaml │ │ └── ks.yaml │ ├── velero/ │ │ ├── kustomization.yaml │ │ ├── namespace.yaml │ │ └── velero/ │ │ ├── app/ │ │ │ ├── helmrelease.yaml │ │ │ ├── kustomization.yaml │ │ │ └── secret.enc.age.yaml │ │ └── ks.yaml │ └── vmangos/ │ ├── README.md │ ├── app/ │ │ ├── dnsendpoint.yaml │ │ ├── helmrelease.yaml │ │ ├── kustomization.yaml │ │ ├── pvc-data.yaml │ │ ├── pvc-database.yaml │ │ ├── replicationsource.yaml │ │ ├── tcproutes.yaml │ │ └── volsync-externalsecret.yaml │ └── ks.yaml ├── .claude/ │ └── agents/ │ ├── README.md │ ├── dependency-mapper.md │ ├── flux-troubleshooter.md │ ├── gitops-deployer.md │ ├── resource-optimizer.md │ └── security-auditor.md ├── .gitattributes ├── .github/ │ ├── CODEOWNERS │ ├── CODE_OF_CONDUCT.md │ ├── CONTRIBUTING.md │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yaml │ │ └── feature_request.yaml │ ├── pull_request_template.md │ ├── renovate.json5 │ └── workflows/ │ ├── azerothcore.yaml │ ├── cmangos-registration.yaml │ ├── cmangos.yaml │ ├── dex-k8s-authenticator.yaml │ ├── flux-local.yaml │ ├── oci.yaml │ ├── oidc.yaml │ ├── render-talos-manifests.yaml │ ├── renovate.yaml │ ├── terraform.yaml │ └── test-e2e.yaml ├── .gitignore ├── .pre-commit-config.yaml ├── .renovate/ │ ├── autoMerge.json5 │ ├── changelogs.json5 │ ├── customManagers.json5 │ ├── grafanaDashboards.json5 │ ├── groups.json5 │ ├── labels.json5 │ └── semanticCommits.json5 ├── .sops.yaml ├── .sourceignore ├── .taskfiles/ │ ├── bootstrap/ │ │ └── Taskfile.yaml │ ├── core/ │ │ └── Taskfile.yaml │ ├── flux/ │ │ └── Taskfile.yaml │ └── talos/ │ └── Taskfile.yaml ├── .yamllint.yaml ├── CLAUDE.md ├── LICENSE ├── README.md ├── Taskfile.yml ├── docs/ │ └── index.html ├── hack/ │ ├── cf-terraforming.sh │ ├── delete-all.sh │ ├── finalizer-pods.sh │ ├── finalizer.sh │ ├── openebs.sh │ ├── restart.sh │ └── update.sh ├── kubernetes/ │ ├── apps/ │ │ ├── base/ │ │ │ ├── actions-runner-system/ │ │ │ │ ├── gha-runner-scale-set/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ └── rbac.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── gha-runner-scale-set-controller/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ └── namespace.yaml │ │ │ ├── ai-system/ │ │ │ │ ├── kagent/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ ├── values.enc.age.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ ├── crds/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kgateway/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ ├── crds/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kmcp/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ ├── values.enc.age.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ ├── crds/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── n8n/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── helmrepository.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── values.enc.age.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── namespace.yaml │ │ │ │ ├── ollama/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ └── kustomization.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ └── open-webui/ │ │ │ │ ├── app/ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ └── kustomization.yaml │ │ │ │ └── ks.yaml │ │ │ ├── crossplane-system/ │ │ │ │ ├── crossplane/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ ├── ks.yaml │ │ │ │ │ ├── packages/ │ │ │ │ │ │ └── gitops/ │ │ │ │ │ │ ├── composition.yaml │ │ │ │ │ │ ├── crossplane.yaml │ │ │ │ │ │ └── definition.yaml │ │ │ │ │ └── providers/ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ └── provider.yaml │ │ │ │ ├── examples/ │ │ │ │ │ ├── example.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ ├── providerconfig.yaml │ │ │ │ │ └── secret.enc.age.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ └── namespace.yaml │ │ │ ├── democratic-csi/ │ │ │ │ ├── democratic-csi/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── secret.enc.age.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ └── namespace.yaml │ │ │ ├── development/ │ │ │ │ ├── backstage/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ └── kustomization.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── namespace.yaml │ │ │ │ ├── open-feature-operator/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ └── kustomization.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ └── vcluster/ │ │ │ │ ├── app/ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ └── kustomization.yaml │ │ │ │ └── ks.yaml │ │ │ ├── external-secrets/ │ │ │ │ ├── external-secrets/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── grafanadashboard.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ ├── pdb.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── namespace.yaml │ │ │ │ └── onepassword/ │ │ │ │ ├── app/ │ │ │ │ │ ├── clustersecretstore.yaml │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ └── values.yaml │ │ │ │ └── ks.yaml │ │ │ ├── flux-system/ │ │ │ │ ├── artifact-generator/ │ │ │ │ │ ├── artifactgenerator.yaml │ │ │ │ │ └── kustomization.yaml │ │ │ │ ├── flux-instance/ │ │ │ │ │ ├── extras/ │ │ │ │ │ │ ├── grafanadashboard.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── podmonitor.yaml │ │ │ │ │ │ ├── prometheusrule.yaml │ │ │ │ │ │ ├── receiver.yaml │ │ │ │ │ │ └── secret.enc.age.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ └── repositories/ │ │ │ │ ├── git/ │ │ │ │ │ └── kustomization.yaml │ │ │ │ ├── helm/ │ │ │ │ │ ├── backstage-charts.yaml │ │ │ │ │ ├── crowdsec-charts.yaml │ │ │ │ │ ├── democratic-csi-charts.yaml │ │ │ │ │ ├── dex-chart.yaml │ │ │ │ │ ├── fairwinds-charts.yaml │ │ │ │ │ ├── fluxcd-kustomize-mutating-webhook-chart.yaml │ │ │ │ │ ├── gatekeeper-charts.yaml │ │ │ │ │ ├── harbor-charts.yaml │ │ │ │ │ ├── ingress-nginx-chart.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ ├── loft-charts.yaml │ │ │ │ │ ├── minecraft-server-charts.yaml │ │ │ │ │ ├── ollama-charts.yaml │ │ │ │ │ ├── open-webui-charts.yaml │ │ │ │ │ └── openfeature-charts.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ └── oci/ │ │ │ │ ├── bjw-charts.yaml │ │ │ │ ├── controlplaneio-charts.yaml │ │ │ │ ├── gha-runner-scale-set-charts.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── prometheus-community-charts.yaml │ │ │ │ └── xentra-charts.yaml │ │ │ ├── game-servers/ │ │ │ │ ├── adminer/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ └── kustomization.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── azerothcore/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── dnsendpoint.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── pvc-client-data.yaml │ │ │ │ │ │ ├── pvc-cores.yaml │ │ │ │ │ │ ├── pvc-database.yaml │ │ │ │ │ │ ├── realm-config-job.yaml │ │ │ │ │ │ ├── realmlist.sql │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ ├── resources/ │ │ │ │ │ │ │ ├── Dockerfile │ │ │ │ │ │ │ └── fifo-wrapper.sh │ │ │ │ │ │ ├── tcproutes.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── cmangos/ │ │ │ │ │ ├── README.md │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── achievements-migration-job.yaml │ │ │ │ │ │ ├── attunement-migration-job.yaml │ │ │ │ │ │ ├── barber-migration-job.yaml │ │ │ │ │ │ ├── dnsendpoint.yaml │ │ │ │ │ │ ├── dualspec-migration-job.yaml │ │ │ │ │ │ ├── externalsecret-database.yaml │ │ │ │ │ │ ├── hardcore-migration-job.yaml │ │ │ │ │ │ ├── hearthstone-cd-migration-job.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── lookup-gm-security-migration-job.yaml │ │ │ │ │ │ ├── mangos-string-517-migration-job.yaml │ │ │ │ │ │ ├── prometheusrule.yaml │ │ │ │ │ │ ├── pvc-cores.yaml │ │ │ │ │ │ ├── pvc-data.yaml │ │ │ │ │ │ ├── pvc-database.yaml │ │ │ │ │ │ ├── pvc-logs.yaml │ │ │ │ │ │ ├── realm-address-migration-job.yaml │ │ │ │ │ │ ├── realm-pvp-migration-job.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ ├── tcproutes.yaml │ │ │ │ │ │ ├── trainingdummies-migration-job.yaml │ │ │ │ │ │ ├── transmog-migration-job.yaml │ │ │ │ │ │ ├── twink-vendor-migration-job.yaml │ │ │ │ │ │ ├── vip-master-spell-migration-job.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── cmangos-ptr/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── db-init-job.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── pvc-cores.yaml │ │ │ │ │ │ ├── pvc-data.yaml │ │ │ │ │ │ ├── pvc-logs.yaml │ │ │ │ │ │ ├── realm-row-migration-job.yaml │ │ │ │ │ │ └── tcproute.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── emberstone-portal/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret-soap.yaml │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ └── resources/ │ │ │ │ │ │ ├── bot_filter.php │ │ │ │ │ │ ├── config.php │ │ │ │ │ │ ├── footer.php │ │ │ │ │ │ ├── header.php │ │ │ │ │ │ ├── howtoconnect.php │ │ │ │ │ │ ├── main.php │ │ │ │ │ │ └── posts.php │ │ │ │ │ └── ks.yaml │ │ │ │ ├── enemy-territory/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── configmap.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── secret.enc.age.yaml │ │ │ │ │ │ └── udproute.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── minecraft/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── config/ │ │ │ │ │ │ │ └── geysermc.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ ├── secret.enc.age.yaml │ │ │ │ │ │ ├── tcproute.yaml │ │ │ │ │ │ ├── values.enc.age.yaml │ │ │ │ │ │ ├── values.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── minecraft-bedrock/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ ├── udproute.yaml │ │ │ │ │ │ ├── values.enc.age.yaml │ │ │ │ │ │ ├── values.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── minecraft-bedrock-broadcaster/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ ├── udproute.yaml │ │ │ │ │ │ ├── values.enc.age.yaml │ │ │ │ │ │ ├── values.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── minecraft-pixelmon/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── minecraft-proxy/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── minecraft-rcon-web/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── secret.enc.age.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── minecraft-router/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── minecraft-witherstorm/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ └── namespace.yaml │ │ │ ├── harbor/ │ │ │ │ ├── harbor/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ └── namespace.yaml │ │ │ ├── home-system/ │ │ │ │ ├── autobrr/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── bazarr/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── home-assistant/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── jellyseerr/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── mosquitto/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── namespace.yaml │ │ │ │ ├── prowlarr/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── qbittorrent/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── qui/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── radarr/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── recyclarr/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ ├── resources/ │ │ │ │ │ │ │ └── recyclarr.yml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── sabnzbd/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ ├── resources/ │ │ │ │ │ │ │ └── xseed.sh │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── smtp-relay/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ └── kustomization.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── sonarr/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── tautulli/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ └── zigbee2mqtt/ │ │ │ │ ├── app/ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ ├── pvc-ceph.yaml │ │ │ │ │ ├── pvc.yaml │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ └── ks.yaml │ │ │ ├── kguardian/ │ │ │ │ ├── kguardian/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── auditnetworkpolicy-baseline.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ ├── pvc-database.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ └── namespace.yaml │ │ │ ├── kube-system/ │ │ │ │ ├── cilium/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── grafanadashboard.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── loadbalancer.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── descheduler/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── keda/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kubelet-csr-approver/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── metrics-server/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── namespace.yaml │ │ │ │ ├── priorityclass.yaml │ │ │ │ ├── reflector/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── snapshot-controller/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── spegel/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ └── tetragon/ │ │ │ │ ├── app/ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ └── values.yaml │ │ │ │ └── ks.yaml │ │ │ ├── network-system/ │ │ │ │ ├── README.md │ │ │ │ ├── cert-manager/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── clusterissuer-prod.yaml │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── grafanadashboard.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ ├── prometheusrule.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── cloudflare-tunnel/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── dnsendpoint.yaml │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── grafanadashboard.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ └── kustomization.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── dex/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── README.md │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── dex-k8s-authenticator/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── clusterrolebinding.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── resources/ │ │ │ │ │ │ ├── Dockerfile │ │ │ │ │ │ ├── dex-auth.go │ │ │ │ │ │ ├── entrypoint.sh │ │ │ │ │ │ ├── go.mod │ │ │ │ │ │ ├── go.sum │ │ │ │ │ │ ├── html/ │ │ │ │ │ │ │ └── static/ │ │ │ │ │ │ │ ├── main.css │ │ │ │ │ │ │ ├── snippets.js │ │ │ │ │ │ │ ├── styles.css │ │ │ │ │ │ │ ├── tabs.css │ │ │ │ │ │ │ └── tooltips.js │ │ │ │ │ │ ├── main.go │ │ │ │ │ │ ├── templates/ │ │ │ │ │ │ │ ├── error.html │ │ │ │ │ │ │ ├── id-token-tab.html │ │ │ │ │ │ │ ├── index.html │ │ │ │ │ │ │ ├── kubeconfig.html │ │ │ │ │ │ │ ├── linux-mac-common.html │ │ │ │ │ │ │ ├── linux-tab.html │ │ │ │ │ │ │ ├── mac-tab.html │ │ │ │ │ │ │ └── windows-tab.html │ │ │ │ │ │ └── templates.go │ │ │ │ │ └── ks.yaml │ │ │ │ ├── echo-server/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ └── kustomization.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── envoy-gateway/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── certificates.yaml │ │ │ │ │ │ ├── envoy.yaml │ │ │ │ │ │ ├── gatewayclass.yaml │ │ │ │ │ │ ├── gateways.yaml │ │ │ │ │ │ ├── grafanadashboards.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproutes.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── monitors.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ ├── pdb.yaml │ │ │ │ │ │ └── policies.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── external-dns/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── grafanadashboard.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ ├── pdb.yaml │ │ │ │ │ │ ├── prometheusrule.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── external-dns-unifi/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── multus/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── rbac.yaml │ │ │ │ │ ├── ks.yaml │ │ │ │ │ └── networks/ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ └── network.yaml │ │ │ │ ├── namespace.yaml │ │ │ │ └── oauth2-proxy/ │ │ │ │ ├── app/ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ └── ocirepository.yaml │ │ │ │ └── ks.yaml │ │ │ ├── nginx-ingress/ │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── namespace.yaml │ │ │ │ └── nginx-ingress/ │ │ │ │ ├── app/ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ └── kustomization.yaml │ │ │ │ └── ks.yaml │ │ │ ├── observability/ │ │ │ │ ├── blackbox-exporter/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ ├── probes.yaml │ │ │ │ │ │ └── values.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── grafana/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ ├── instance/ │ │ │ │ │ │ ├── grafana.yaml │ │ │ │ │ │ ├── grafanadatasource.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── replicationsource.yaml │ │ │ │ │ │ ├── servicemonitor.yaml │ │ │ │ │ │ └── volsync-externalsecret.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kromgo/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ │ └── resources/ │ │ │ │ │ │ └── config.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kube-prometheus-stack/ │ │ │ │ │ ├── README.md │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── alertmanager-replicationsource.yaml │ │ │ │ │ │ ├── alertmanager-volsync-externalsecret.yaml │ │ │ │ │ │ ├── alertmanagerconfig.yaml │ │ │ │ │ │ ├── grafanadashboard.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ │ ├── prometheus-replicationsource.yaml │ │ │ │ │ │ ├── prometheus-volsync-externalsecret.yaml │ │ │ │ │ │ ├── resources/ │ │ │ │ │ │ │ └── flux-metrics.yaml │ │ │ │ │ │ ├── scrapeconfig.yaml │ │ │ │ │ │ └── silence-watchdog.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── loki/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── namespace.yaml │ │ │ │ ├── otel/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── silence-operator/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ └── vpa/ │ │ │ │ ├── app/ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ └── kustomization.yaml │ │ │ │ └── ks.yaml │ │ │ ├── preview-system/ │ │ │ │ ├── app/ │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ ├── resourceset.yaml │ │ │ │ │ └── resourcesetinputprovider.yaml │ │ │ │ ├── ks.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ └── namespace.yaml │ │ │ ├── rook-ceph/ │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── namespace.yaml │ │ │ │ └── rook-ceph/ │ │ │ │ ├── app/ │ │ │ │ │ ├── grafanadashboard.yaml │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ ├── pdb.yaml │ │ │ │ │ └── values.yaml │ │ │ │ ├── cluster/ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ ├── ocirepository.yaml │ │ │ │ │ └── values.yaml │ │ │ │ └── ks.yaml │ │ │ ├── security-system/ │ │ │ │ ├── crowdsec/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ │ └── kustomization.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── falco/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── falco-exporter/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── gatekeeper/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── grafanadashboard.yaml │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── podmonitor.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── kyverno/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ │ └── ocirepository.yaml │ │ │ │ │ └── ks.yaml │ │ │ │ └── namespace.yaml │ │ │ └── volsync-system/ │ │ │ ├── kopia/ │ │ │ │ ├── app/ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ ├── httproute.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ └── values.yaml │ │ │ │ └── ks.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── namespace.yaml │ │ │ └── volsync/ │ │ │ ├── app/ │ │ │ │ ├── grafanadashboard.yaml │ │ │ │ ├── helmrelease.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ ├── mutatingadmissionpolicy.yaml │ │ │ │ ├── ocirepository.yaml │ │ │ │ ├── prometheusrule.yaml │ │ │ │ └── values.yaml │ │ │ ├── ks.yaml │ │ │ └── maintenance/ │ │ │ ├── kopiamaintenance.yaml │ │ │ ├── kustomization.yaml │ │ │ └── mutatingadmissionpolicy.yaml │ │ └── overlays/ │ │ └── cluster-00/ │ │ └── kustomization.yaml │ ├── bootstrap/ │ │ └── helmfile.yaml │ ├── clusters/ │ │ └── cluster-00/ │ │ ├── flux-system/ │ │ │ ├── flux-instance/ │ │ │ │ ├── app/ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ └── values.yaml │ │ │ │ └── ks.yaml │ │ │ ├── flux-operator/ │ │ │ │ ├── app/ │ │ │ │ │ ├── helmrelease.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ │ └── values.yaml │ │ │ │ └── ks.yaml │ │ │ └── kustomize-mutating-webhook/ │ │ │ ├── app/ │ │ │ │ ├── helmrelease.yaml │ │ │ │ ├── kustomization.yaml │ │ │ │ ├── kustomizeconfig.yaml │ │ │ │ └── values.yaml │ │ │ └── ks.yaml │ │ ├── ks.yaml │ │ └── secrets/ │ │ ├── .sops.pub.asc │ │ ├── cluster-config.yaml │ │ ├── cluster-secrets.enc.age.yaml │ │ ├── github-auth.enc.age.yaml │ │ └── sops-age.encrypted.yaml │ ├── components/ │ │ ├── common/ │ │ │ ├── alerts/ │ │ │ │ ├── github/ │ │ │ │ │ ├── alerts.yaml │ │ │ │ │ ├── externalsecret.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ └── provider.yaml │ │ │ │ └── kustomization.yaml │ │ │ └── kustomization.yaml │ │ └── volsync/ │ │ ├── externalsecret.yaml │ │ ├── kustomization.yaml │ │ ├── pvc.yaml │ │ ├── replicationdestination.yaml │ │ └── replicationsource.yaml │ └── tenants/ │ └── .gitkeep ├── talos/ │ ├── README.md │ ├── generated/ │ │ ├── controlplane.enc.age.yaml │ │ └── talosconfig.enc.age.yaml │ ├── integrations/ │ │ ├── cert-approver/ │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── cert-approver.yaml │ │ │ ├── kustomization.yaml │ │ │ └── transformers.yaml │ │ └── cilium/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── cilium.yaml │ │ ├── kustomization.yaml │ │ └── transformers.yaml │ └── patches/ │ ├── iscsi.yaml │ ├── metric-server.yaml │ └── metrics.yaml ├── terraform/ │ └── gcp/ │ ├── README.md │ ├── _backend.tf │ ├── _provider.tf │ ├── install.sh │ ├── sops.tf │ ├── thanos.tf │ ├── variables.tf │ └── velero.tf └── wrangler.toml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/git/archive/origin-ca-issuer-chart.yaml ================================================ --- # TODO: Once the chart is published use HelmRepository apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: origin-ca-issuer-chart-git namespace: flux-system spec: interval: 10m url: https://github.com/cloudflare/origin-ca-issuer ref: branch: trunk ignore: | # exclude all /* # include charts directory !/deploy/ ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/actions-runner-controller.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: actions-runner-controller namespace: flux-system spec: interval: 2h url: https://actions-runner-controller.github.io/actions-runner-controller ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/backube-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: backube-charts namespace: flux-system spec: interval: 2h url: https://backube.github.io/helm-charts/ ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/bitnami-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: bitnami-charts namespace: flux-system spec: interval: 2h url: https://charts.bitnami.com/bitnami ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/cilium-chart.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: cilium-chart namespace: flux-system spec: interval: 2h url: https://helm.cilium.io/ ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/coredns-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: coredns-charts namespace: flux-system spec: interval: 2h url: https://coredns.github.io/helm ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/crossplane-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: crossplane-charts namespace: flux-system spec: interval: 2h url: https://charts.crossplane.io/stable ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/csi-driver-nfs-chart.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: csi-driver-nfs-chart namespace: flux-system spec: interval: 2h url: https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/charts ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/descheduler-chart.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: descheduler-chart namespace: flux-system spec: interval: 2h url: https://kubernetes-sigs.github.io/descheduler ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/emberstack-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: emberstack-charts namespace: flux-system spec: interval: 2h url: https://emberstack.github.io/helm-charts/ ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/emqx-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: emqx-charts namespace: flux-system spec: interval: 2h url: https://repos.emqx.io/charts ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/external-dns-chart.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: external-dns-chart namespace: flux-system spec: interval: 2h url: https://kubernetes-sigs.github.io/external-dns ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/falco-security-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: falco-security-charts namespace: flux-system spec: interval: 2h url: https://falcosecurity.github.io/charts ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/flagger-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: flagger-charts namespace: flux-system spec: interval: 2h url: https://flagger.app ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/grafana-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: grafana-charts namespace: flux-system spec: interval: 2h url: https://grafana.github.io/helm-charts ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/jaegertracing-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: jaegertracing-charts namespace: flux-system spec: interval: 2h url: https://jaegertracing.github.io/helm-charts ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/jetstack-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: jetstack-charts namespace: flux-system spec: interval: 2h url: https://charts.jetstack.io/ ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/kiali-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: kiali-charts namespace: flux-system spec: interval: 2h url: https://kiali.org/helm-charts ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/kubefed-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: kubefed-charts namespace: flux-system spec: interval: 2h url: https://raw.githubusercontent.com/kubernetes-sigs/kubefed/master/charts ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/kubereboot-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: kubereboot-charts namespace: flux-system spec: interval: 2h url: https://kubereboot.github.io/charts/ ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/kubernetes-stable-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: kubernetes-stable-charts namespace: flux-system spec: interval: 2h url: https://charts.helm.sh/stable ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/kyverno-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: kyverno-charts namespace: flux-system spec: interval: 2h url: https://kyverno.github.io/kyverno/ ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/litmuschaos-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: litmuschaos-charts namespace: flux-system spec: interval: 2h url: https://litmuschaos.github.io/litmus-helm/ ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/mayastor-chart.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: mayastor-chart namespace: flux-system spec: interval: 2h url: https://openebs.github.io/mayastor-extensions/ ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/metallb-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: metallb-charts namespace: flux-system spec: interval: 2h url: https://metallb.github.io/metallb ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/metrics-server-chart.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: metrics-server-chart namespace: flux-system spec: interval: 2h url: https://kubernetes-sigs.github.io/metrics-server ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/node-feature-discovery-chart.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: node-feature-discovery-chart namespace: flux-system spec: interval: 2h url: https://kubernetes-sigs.github.io/node-feature-discovery/charts ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/oauth2-proxy-chart.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: oauth2-proxy-chart namespace: flux-system spec: interval: 2h url: https://oauth2-proxy.github.io/manifests ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/openebs-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: openebs-chart namespace: flux-system spec: interval: 2h url: https://openebs.github.io/openebs ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/openfaas-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: openfaas-charts namespace: flux-system spec: interval: 2h url: https://openfaas.github.io/faas-netes/ ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/otel-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: otel-charts namespace: flux-system spec: interval: 2h url: https://open-telemetry.github.io/opentelemetry-helm-charts ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/postfinance-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: postfinance-charts namespace: flux-system spec: interval: 2h url: https://postfinance.github.io/kubelet-csr-approver ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/rook-ceph.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: rook-ceph namespace: flux-system spec: interval: 2h url: https://charts.rook.io/release ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/sealed-secrets-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: sealed-secrets-charts namespace: flux-system spec: interval: 2h url: https://bitnami-labs.github.io/sealed-secrets ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/secrets-store-csi-driver-chart.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: secrets-store-csi-driver-chart namespace: flux-system spec: interval: 2h url: https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/stakater-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: stakater-charts namespace: flux-system spec: interval: 2h url: https://stakater.github.io/stakater-charts ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/traefik-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: traefik-charts namespace: flux-system spec: interval: 2h url: https://helm.traefik.io/traefik ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/vernemq-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: vernemq-charts namespace: flux-system spec: interval: 2h url: https://vernemq.github.io/docker-vernemq ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/vmware-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: vmware-charts namespace: flux-system spec: interval: 2h url: https://vmware-tanzu.github.io/helm-charts ================================================ FILE: .archive/kubernetes/apps/base/flux-system/repositories/helm/archive/xunholy-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: xunholy-charts namespace: flux-system spec: interval: 3m url: https://xunholy.github.io/charts timeout: 3m ================================================ FILE: .archive/kubernetes/bazarr/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.jsonapiVersion: helm.toolkit.fluxcd.io/v2 apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app bazarr namespace: home-system spec: interval: 1h chartRef: kind: OCIRepository name: bazarr install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: controllers: *app : containers: app: image: repository: ghcr.io/home-operations/bazarr tag: 1.5.6@sha256:79fc37491f55c7e24427bcd669bce3df2d7415ca432a47ce9d53cc5988af8411 env: TZ: Australia/Melbourne envFrom: - secretRef: name: bazarr-secret probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /health port: &port 6767 initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes startup: enabled: true spec: failureThreshold: 30 periodSeconds: 10 securityContext: &securityContext allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 10m limits: memory: 1Gi subcleaner: image: repository: registry.k8s.io/git-sync/git-sync tag: v4.6.0@sha256:228a26d5f55ac5ae9c51635812570ba0073e0b1e0bd8fc3a653a0523b918c092 env: GITSYNC_REPO: https://github.com/KBlixt/subcleaner GITSYNC_REF: master GITSYNC_PERIOD: 24h GITSYNC_ROOT: /subcleaner resources: requests: cpu: 10m limits: memory: 128Mi securityContext: *securityContext defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: controller: *app ports: http: port: *port persistence: config: existingClaim: bazarr config-cache: type: emptyDir globalMounts: - path: /config/cache config-log: type: emptyDir globalMounts: - path: /config/log media: type: nfs server: expanse.internal path: /mnt/tank/media globalMounts: - path: /media scripts: type: configMap name: bazarr-scripts defaultMode: 0775 globalMounts: - path: /scripts/subcleaner.sh subPath: subcleaner.sh readOnly: true subcleaner: type: emptyDir tmp: type: emptyDir ================================================ FILE: .archive/kubernetes/bazarr/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: bazarr namespace: home-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'bazarr.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: bazarr port: 6767 weight: 100 ================================================ FILE: .archive/kubernetes/bazarr/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: home-system resources: - helmrelease.yaml - httproute.yaml - ocirepository.yaml - pvc.yaml - secret.enc.age.yaml configMapGenerator: - name: bazarr-scripts namespace: home-system files: - subcleaner.sh=./resources/subcleaner.sh generatorOptions: annotations: kustomize.toolkit.fluxcd.io/substitute: disabled ================================================ FILE: .archive/kubernetes/bazarr/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: bazarr spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 4.6.2 url: oci://ghcr.io/bjw-s-labs/helm/app-template ================================================ FILE: .archive/kubernetes/bazarr/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: bazarr namespace: home-system spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 5Gi storageClassName: truenas-iscsi-csi ================================================ FILE: .archive/kubernetes/bazarr/app/resources/subcleaner.sh ================================================ #!/usr/bin/env bash printf "Cleaning subtitles for '%s' ...\n" "$1" python3 /subcleaner/subcleaner/subcleaner.py "$1" -s case $1 in *movies*) section="1";; *shows*) section="2";; esac if [[ -n "$section" ]]; then printf "Refreshing Plex section '%s' for '%s' ...\n" "$section" "$(dirname "$1")" /usr/bin/curl -I -X GET -G \ --data-urlencode "path=$(dirname "$1")" \ --data-urlencode "X-Plex-Token=${PLEX_TOKEN}" \ --no-progress-meter \ "http://plex.home-system.svc.cluster.local:32400/library/sections/${section}/refresh" fi ================================================ FILE: .archive/kubernetes/bazarr/app/secret.enc.age.yaml ================================================ apiVersion: v1 kind: Secret metadata: name: bazarr-secret namespace: home-system type: Opaque stringData: PLEX_TOKEN: ENC[AES256_GCM,data:dH2SinyDwDsQ+h10nspxcXemmXI=,iv:6w7IHfDLw5C0gctPWGsM3Mgqt2F34Mt3xoePexq66d0=,tag:vb+DOOM57tL6oqo5zt/NaA==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5VnhsL2ZxY0ppaW53NFBL S0RtaDZ5TUNHZGNjSXExM0FIV05Ma0Q5SEVjCkJldmE5YTFVNWllOHUzd1JMeEpP bEFMOFlISitOZ0lXTHBuZFlaOWRQalUKLS0tIGVsMXg1QkZzb0ptb2ZWaUZiV0pa TmU2TWRFZHFNQ29ZQTJxL012b1ZzZHcKkIRCY6beY1rlDhs49KHLCa2HiSu5J8b7 usWq6F+jrdkeYWyN3zjTNrdfJ5isoS4m22y4Cr9JJCmahk1zBiSoUg== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:43:27Z" mac: ENC[AES256_GCM,data:N9t7RbEcsvowgLnBeIoG3U6IIJ28XMVVHy6vVEmS6ZSVWyQKZf36TSH6fI6eIduftjkDo3WkyyZXMonQCm1nrsCmaT/JEx2zKcbUe6zsRyi7TAfCKl46bSJbR8QC82v36Fhfo3bKH0yUJ/lZpR5gfQo6UPQXh83rnJVBN97C4q8=,iv:Q2GJ50FGfWv1y4qExZAvCqDKQz5nJ4oFSL7Pa1LpdRc=,tag:BA3vB5awv/oSz2J/VmHL2g==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 ================================================ FILE: .archive/kubernetes/bazarr/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: &app bazarr namespace: home-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/home-system/bazarr/app" prune: true wait: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system dependsOn: - name: democratic-csi namespace: democratic-csi targetNamespace: home-system ================================================ FILE: .archive/kubernetes/blocky/app/configs/config.yml ================================================ --- # https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-tls/#how-it-works upstream: default: - tcp-tls:one.one.one.one:853 - tcp-tls:dns.quad9.net:853 bootstrapDns: tcp+udp:1.1.1.1 # customDNS: # customTTL: 1h # filterUnmappedTypes: true # mapping: # ${CLUSTER_DOMAIN}: ${CLUSTER_LB_COREDNS} # conditional: # mapping: # cluster.local: 10.96.0.10 # ${CLUSTER_DOMAIN}: ${CLUSTER_LB_COREDNS} # .: ${GATEWAY_IP} blocking: blackLists: suspicious: - https://raw.githubusercontent.com/PolishFiltersTeam/KADhosts/master/KADhosts.txt - https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.Spam/hosts - https://v.firebog.net/hosts/static/w3kbl.txt ads: - https://adaway.org/hosts.txt - https://v.firebog.net/hosts/AdguardDNS.txt - https://v.firebog.net/hosts/Admiral.txt - https://raw.githubusercontent.com/anudeepND/blacklist/master/adservers.txt - https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt - https://v.firebog.net/hosts/Easylist.txt - https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext - https://raw.githubusercontent.com/FadeMind/hosts.extras/master/UncheckyAds/hosts - https://raw.githubusercontent.com/bigdargon/hostsVN/master/hosts trackers: - https://v.firebog.net/hosts/Easyprivacy.txt - https://v.firebog.net/hosts/Prigent-Ads.txt - https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.2o7Net/hosts - https://raw.githubusercontent.com/crazy-max/WindowsSpyBlocker/master/data/hosts/spy.txt - https://hostfiles.frogeye.fr/firstparty-trackers-hosts.txt misc: - https://raw.githubusercontent.com/DandelionSprout/adfilt/master/Alternate%20versions%20Anti-Malware%20List/AntiMalwareHosts.txt - https://osint.digitalside.it/Threat-Intel/lists/latestdomains.txt - https://s3.amazonaws.com/lists.disconnect.me/simple_malvertising.txt - https://v.firebog.net/hosts/Prigent-Crypto.txt - https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.Risk/hosts - https://phishing.army/download/phishing_army_blocklist_extended.txt - https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-malware.txt - https://v.firebog.net/hosts/RPiList-Malware.txt - https://v.firebog.net/hosts/RPiList-Phishing.txt - https://raw.githubusercontent.com/Spam404/lists/master/main-blacklist.txt - https://raw.githubusercontent.com/AssoEchap/stalkerware-indicators/master/generated/hosts whiteLists: suspicious: - https://raw.githubusercontent.com/anudeepND/whitelist/master/domains/whitelist.txt ads: - https://raw.githubusercontent.com/anudeepND/whitelist/master/domains/whitelist.txt trackers: - https://raw.githubusercontent.com/anudeepND/whitelist/master/domains/whitelist.txt misc: - https://raw.githubusercontent.com/anudeepND/whitelist/master/domains/whitelist.txt clientGroupsBlock: default: - suspicious - ads - trackers - misc # clientLookup: # upstream: ${GATEWAY_IP} caching: minTime: 5m prefetching: true redis: required: true address: redis-master sentinelAddresses: - redis-node-0.redis-headless.databases.svc.cluster.local:26379 - redis-node-1.redis-headless.databases.svc.cluster.local:26379 - redis-node-2.redis-headless.databases.svc.cluster.local:26379 prometheus: enable: true path: /metrics httpPort: 4000 logLevel: info ================================================ FILE: .archive/kubernetes/blocky/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.jsonapiVersion: helm.toolkit.fluxcd.io/v2 apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app blocky namespace: network-system spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: controllers: blocky: replicas: 1 strategy: RollingUpdate containers: app: image: repository: ghcr.io/0xerr0r/blocky tag: v0.26 env: TZ: Australia/Melbourne HTTP_PORT: &port 4000 probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /healthz port: *port initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { add: [NET_BIND_SERVICE], drop: ["ALL"] } seccompProfile: type: RuntimeDefault resources: requests: cpu: 10m limits: memory: 128Mi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: &uid runAsGroup: *uid fsGroup: *uid fsGroupChangePolicy: Always seccompProfile: { type: RuntimeDefault } topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: app.kubernetes.io/name: *app service: app: controller: *app ports: http: port: *port dns: controller: *app type: LoadBalancer annotations: io.cilium/lb-ipam-ips: ${CLUSTER_LB_BLOCKY} ports: dns-tcp: port: &DNSPort 53 protocol: TCP dns-udp: port: *DNSPort protocol: UDP serviceMonitor: app: serviceName: *app endpoints: - port: http scheme: http path: /metrics interval: 1m scrapeTimeout: 10s ================================================ FILE: .archive/kubernetes/blocky/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml configMapGenerator: - name: blocky files: - ./configs/config.yml ================================================ FILE: .archive/kubernetes/blocky/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: blocky namespace: network-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/network-system/blocky/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: network-system ================================================ FILE: .archive/kubernetes/cert-manager-csi-driver/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app cert-manager-csi-driver namespace: network-system spec: interval: 1h chartRef: kind: OCIRepository name: cert-manager-csi-driver namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 ================================================ FILE: .archive/kubernetes/cert-manager-csi-driver/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: network-system resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/cert-manager-csi-driver/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: cert-manager-csi-driver namespace: network-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/network-system/cert-manager-csi-driver/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: network-system ================================================ FILE: .archive/kubernetes/cloudflare-ddns/app/deployment.yaml ================================================ --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: cloudflare-ddns name: cloudflare-ddns namespace: network-system spec: replicas: 1 selector: matchLabels: app: cloudflare-ddns template: metadata: annotations: sidecar.istio.io/inject: 'false' labels: app: cloudflare-ddns spec: containers: - env: - name: CF_APITOKEN valueFrom: secretKeyRef: key: api-token name: cloudflare-ddns - name: CF_ZONES valueFrom: secretKeyRef: key: zones name: cloudflare-ddns - name: CF_HOSTS valueFrom: secretKeyRef: key: hosts name: cloudflare-ddns - name: CF_RECORDTYPES valueFrom: secretKeyRef: key: record-types name: cloudflare-ddns # https://github.com/docker-hotio/docker-cloudflare-ddns#log-levels - name: LOG_LEVEL value: '3' - name: INTERVAL value: '300' image: ghcr.io/hotio/cloudflareddns:latest name: cloudflare-ddns # Resources allocated based on Robusta KRR output resources: limits: memory: 64Mi requests: cpu: 20m memory: 10Mi ================================================ FILE: .archive/kubernetes/cloudflare-ddns/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - deployment.yaml - secret.enc.yaml ================================================ FILE: .archive/kubernetes/cloudflare-ddns/app/secret.enc.yaml ================================================ apiVersion: v1 data: api-token: ENC[AES256_GCM,data:d5RH6/yKHPhv0zGikfuG3pdP2Y6ur9Mv6XqOvsMD30v3NxmspWQnGNjBQFrqye4/Yo5WSWghl5A=,iv:tobryj4KN8o9qppDPUjxG9JVvqJl1WZHh5lCoMqSCt4=,tag:QwFTnMMVfJbY/h/Q4wsI0w==,type:str] hosts: ENC[AES256_GCM,data:9yq6mOUZrtG+XDHAqqLkFexrtD5oh6uY,iv:uf/1XBs8fzvYAzf04PHWN2/12MKCRp4JOqIeMjA2/J4=,tag:jNYBkT+A6lZMTYOguR+OKQ==,type:str] record-types: ENC[AES256_GCM,data:XofIqigyWOL1HvMP,iv:4nbLHk9Qki0mmwMIO/+lijx2hyte5HFZh2y5ibMCbEo=,tag:16/OYVoOT6rKKckXCi2tww==,type:str] zones: ENC[AES256_GCM,data:z7baA7qAHRmFTbKcD3+71rTVWFRRnxzz,iv:8LyGmFciAoRp214zSgNOKybqSVImxR751mCCwFusQ00=,tag:1rlS3nv/akKUfFJcQeObFQ==,type:str] kind: Secret metadata: creationTimestamp: null name: cloudflare-ddns namespace: network-system sops: kms: [] gcp_kms: [] azure_kv: [] hc_vault: [] age: [] lastmodified: "2021-09-19T23:59:15Z" mac: ENC[AES256_GCM,data:R1+ZOUSq4rZIezK9Nr7/gUp3dtOdMyr1/+JAgwV9YvgAJGZkdHgmsAtP/bLsXyEeFRdxYxT5+2Rfw5GjzV3PUAFn5DSc/CwMDhyOj6dUzL+Z218YEb/rGLJI/RJl71e+WWMQ6JQ7h+c7EXWZbHU97KMuomEBHZc6+O990/XLkec=,iv:2umk1CDEimyR5/QrSksrPYO8ZudL6WHSex537lH7hYc=,tag:DsW8h3xKwbQiNUBDYum7Sw==,type:str] pgp: - created_at: "2021-09-19T23:59:13Z" enc: | -----BEGIN PGP MESSAGE----- hQIMAx42lmLHwoZwAQ/+PigSeQN7F83kI0auxNzhPlixPM/aoQqqbPmLCuCaJK24 XLc/iT2diZtN502Q5wbplDEIjfHx8wV0s5c5/Iigx2vCRqxWesRCv+l/PoKIucRU g93kYJHDJEMeopRZSsmY6V0MbZY2n8URfYDkCRXRgjY7SKAm3aKeIzdarOBqISzW abgBMh6i+mCK60XtGPtEEDmrcO0EIpOCsV4OXI+YZ7/M/ktKpg9WJ56k3s/nI0fb x92n5/QifKGwNiPGca1N1/yHUt8O+sbB1juOmnahPvqY0Y6D3rzMTLM7/Iv+/5xR oBd7J+f5OGIhLRc5ZXmUOlQb6JCJrN800lAiZSHvIVqAUILtxFYXoO6njR/prUWW 8ibo0mlPE+PJMzeaIWJiR/y0WM6k+Uns8T+PioLS9byK2welCGSN7Un8UPiX77TN huGj/LDLi+1Bp97tIpvT5N50ysWV3LP+0Ga7pDSXUYrUA6qNct3hM7hS86vt5xGD y3DR7BP1dpPNvAlSYE/grWt/vLyX96FRXwFsiJFsR62SJAwod1QV1O+m8gIFrHnz mBeVFljZysAJtChlxBRU1OlX9+ROBQINUs9cYvvsS4WkcNhefj9icE2jFwHx4dqs VdQu3rP3GOIORzZDxFOsQU4yaGOGh18hqiVPItolI87KZgLOxZyJouCJZg72JdHS XgGEgNa6pwu0IUqUQ/16WA0by+Ej9O5LZgKRU2usZHdOt9y/sLGtpYg+N6SDDMzF JfC/dzuz5FYutSuhAm9lScl71ejigKODDMRGoROsjHSYciyQYnJNFkmSh3w0C5E= =frjn -----END PGP MESSAGE----- fp: 0635B8D34037A9453003FB7B93CAA682FF4C9014 encrypted_regex: ^(data|stringData)$ version: 3.7.1 ================================================ FILE: .archive/kubernetes/cloudflare-ddns/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: cloudflare-ddns namespace: network-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/network-system/cloudflare-ddns/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: network-system ================================================ FILE: .archive/kubernetes/coredns/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app coredns namespace: network-system spec: interval: 1h releaseName: coredns chartRef: kind: OCIRepository name: coredns namespace: flux-system dependsOn: - name: cilium namespace: kube-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: # Resources allocated based on Robusta KRR output resources: limits: memory: 128Mi requests: cpu: 24m memory: 128Mi # Custom image bundled with external plugins; currently not in use. # This image is reusable and can be viewed with the available plugins here https://github.com/xUnholy/coredns # image: # repository: xunholy/coredns # tag: '1.8.0-rc.7' # pullPolicy: Always rbac: create: true replicaCount: 1 # In this mode CoreDNS is deployed as any kubernetes app in user specified namespace. # The CoreDNS service can be exposed outside the cluster by using using either the NodePort or LoadBalancer type of service. # This mode is chosen by setting isClusterService to false isClusterService: false serviceType: LoadBalancer service: annotations: io.cilium/lb-ipam-ips: ${CLUSTER_LB_COREDNS} externalTrafficPolicy: Cluster # https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/#coredns-configmap-options servers: - zones: - zone: . scheme: dns:// - zone: raspbernetes.com. scheme: dns:// port: 53 plugins: - name: log - name: errors # Serves a /health endpoint on :8080, required for livenessProbe - name: health configBlock: |- lameduck 5s # Serves a /ready endpoint on :8181, required for readinessProbe - name: ready # Required to query kubernetes API for data - name: kubernetes parameters: cluster.local in-addr.arpa ip6.arpa configBlock: |- pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 # Serves a /metrics endpoint on :9153, required for serviceMonitor - name: prometheus parameters: 0.0.0.0:9153 # Forward everything else to Cloudflare DNS # Note: plugin/forward: this plugin can only be used once per Server Block - name: forward parameters: . 1.1.1.1 configBlock: |- except raspbernetes.com *.raspbernetes.com - name: file parameters: /etc/coredns/raspbernetes.db raspbernetes.com # Set up cache - name: cache parameters: 30 # Detects simple forwarding loops and halts the CoreDNS process if a loop is found. - name: loop # Allows automatic reload of a changed Corefile. - name: reload # The loadbalance will act as a round-robin DNS load balancer by randomizing the order of A, AAAA, and MX records in the answer. - name: loadbalance prometheus: # Set this to true to create Service for Prometheus metrics service: enabled: true # Disabled due to service monitor resources being created statically to remove chart dependencies. monitor: enabled: false # configure custom zone files as per https://coredns.io/2017/05/08/custom-dns-entries-for-kubernetes/ # api.raspbernetes.com - https://www.talos.dev/v1.7/introduction/prodnotes/#dns-records zoneFiles: - filename: raspbernetes.db domain: raspbernetes.com contents: | ${CLUSTER_DOMAIN}. IN SOA ns.dns.raspbernetes.com. hostmaster.raspbernetes.com. 1610541154 7200 1800 86400 30 ${CLUSTER_DOMAIN}. IN NS ns.dns.raspbernetes.com. ${CLUSTER_DOMAIN}. IN A ${CLUSTER_LB_ISTIO_INGRESS_GATEWAY} et.${CLUSTER_DOMAIN}. IN A ${CLUSTER_LB_NGINX_INGRESS_GATEWAY} api.${CLUSTER_DOMAIN}. IN A 192.168.50.101 api.${CLUSTER_DOMAIN}. IN A 192.168.50.102 api.${CLUSTER_DOMAIN}. IN A 192.168.50.103 *.${CLUSTER_DOMAIN}. IN CNAME ${CLUSTER_DOMAIN}. plex.${CLUSTER_DOMAIN}. IN A expanse.internal ================================================ FILE: .archive/kubernetes/coredns/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/coredns/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: coredns namespace: network-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/network-system/coredns/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: network-system ================================================ FILE: .archive/kubernetes/cross-seed/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: cross-seed spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: cross-seed-secret template: data: config.js: |- function fetchIndexers(baseUrl, apiKey, tag){ const buffer = require('child_process').execSync(`curl -fsSL "$${baseUrl}/api/v1/tag/detail?apikey=$${apiKey}"`); const response = JSON.parse(buffer.toString('utf8')); const indexerIds = response.filter(t => t.label === tag)[0]?.indexerIds ?? []; const indexers = indexerIds.map(i => `$${baseUrl}/$${i}/api?apikey=$${apiKey}`); console.log(`Loaded $${indexers.length} indexers from Prowlarr`); return indexers; } module.exports = { action: "inject", apiKey: "{{.CROSS_SEED_API_KEY}}", blockList: ["category:manual"], linkCategory: "cross-seed", linkDirs: ["/media/Downloads/qbittorrent/complete/cross-seed"], linkType: "hardlink", matchMode: "partial", port: Number(process.env.CROSS_SEED_PORT), skipRecheck: true, radarr: ["http://radarr.home-system.svc.cluster.local/?apikey={{ .RADARR_API_KEY }}"], sonarr: ["http://sonarr.home-system.svc.cluster.local/?apikey={{ .SONARR_API_KEY }}"], torrentClients: ["qbittorrent:http://qbittorrent.home-system.svc.cluster.local"], torznab: fetchIndexers("http://prowlarr.home-system.svc.cluster.local", "{{.PROWLARR_API_KEY}}", "cross-seed"), useClientTorrents: true }; dataFrom: - extract: key: cross-seed - extract: key: prowlarr - extract: key: radarr - extract: key: sonarr ================================================ FILE: .archive/kubernetes/cross-seed/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app cross-seed namespace: home-system spec: interval: 1h chartRef: kind: OCIRepository name: cross-seed install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 dependsOn: - name: qbittorrent namespace: home-system values: controllers: *app : type: statefulset containers: app: image: repository: ghcr.io/cross-seed/cross-seed tag: 6.13.7@sha256:a1fed512261fd968c55cb03c51cff9c6620aa76a34b3b591afca95c890aa8225 env: TZ: Australia/Melbourne CROSS_SEED_PORT: &port 80 args: ["daemon"] probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /api/ping port: *port initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 10m limits: memory: 512Mi statefulset: volumeClaimTemplates: - name: config storageClass: ceph-block accessMode: ReadWriteOnce size: 5Gi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch service: app: ports: http: port: *port persistence: secret-file: type: secret name: cross-seed-secret globalMounts: - path: /config/config.js subPath: config.js media: type: nfs server: expanse.internal path: /mnt/tank/media globalMounts: - path: /media/Downloads subPath: Downloads ================================================ FILE: .archive/kubernetes/cross-seed/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml - ocirepository.yaml ================================================ FILE: .archive/kubernetes/cross-seed/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: cross-seed spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 4.6.2 url: oci://ghcr.io/bjw-s-labs/helm/app-template ================================================ FILE: .archive/kubernetes/cross-seed/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: cross-seed namespace: home-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/home-system/cross-seed/app" prune: true wait: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system dependsOn: - name: democratic-csi namespace: democratic-csi targetNamespace: home-system ================================================ FILE: .archive/kubernetes/csi-driver-nfs/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app csi-driver-nfs namespace: kube-system spec: interval: 1h chartRef: kind: OCIRepository name: csi-driver-nfs namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: controller: replicas: 1 storageClass: create: true name: nfs-slow parameters: server: expanse.internal share: /mnt/tank/media mountOptions: - nfsvers=4.2 - nconnect=16 - hard - noatime reclaimPolicy: Delete volumeBindingMode: Immediate ================================================ FILE: .archive/kubernetes/csi-driver-nfs/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: kube-system resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/csi-driver-nfs/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: csi-driver-nfs namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/kube-system/csi-driver-nfs/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: kube-system ================================================ FILE: .archive/kubernetes/emqx/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app emqx namespace: home-system spec: interval: 1h chartRef: kind: OCIRepository name: emqx-operator namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: fullnameOverride: emqx replicaCount: 1 image: repository: ghcr.io/emqx/emqx-operator ================================================ FILE: .archive/kubernetes/emqx/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/emqx/cluster/cluster.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/apps.emqx.io/emqx_v2beta1.json apiVersion: apps.emqx.io/v2beta1 kind: EMQX metadata: name: emqx namespace: home-system spec: image: public.ecr.aws/emqx/emqx:5.8.9 config: data: | authentication { backend = "built_in_database" mechanism = "password_based" password_hash_algorithm { name = "bcrypt" } user_id_type = "username" bootstrap_file = "/opt/init-user.json" bootstrap_type = "plain" } authorization { sources = [ { type = built_in_database enable = true } ] no_match: "deny" } coreTemplate: spec: replicas: 2 envFrom: - secretRef: name: emqx-secret extraVolumeMounts: - name: init-user mountPath: /opt/init-user.json subPath: init-user.json readOnly: true extraVolumes: - name: init-user secret: secretName: emqx-init-user-secret listenersServiceTemplate: metadata: annotations: lbipam.cilium.io/ips: ${CLUSTER_LB_EMQX} spec: type: LoadBalancer ================================================ FILE: .archive/kubernetes/emqx/cluster/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: emqx namespace: home-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'emqx.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: emqx-dashboard port: 18083 weight: 100 ================================================ FILE: .archive/kubernetes/emqx/cluster/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - cluster.yaml - httproute.yaml - podmonitor.yaml - secret.enc.age.yaml ================================================ FILE: .archive/kubernetes/emqx/cluster/podmonitor.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/podmonitor_v1.json apiVersion: monitoring.coreos.com/v1 kind: PodMonitor metadata: name: emqx namespace: home-system spec: selector: matchLabels: apps.emqx.io/instance: emqx apps.emqx.io/managed-by: emqx-operator podMetricsEndpoints: - port: dashboard path: /api/v5/prometheus/stats relabelings: - action: replace # user-defined cluster name, requires unique replacement: emqx5 targetLabel: cluster - action: replace # fix value, don't modify replacement: emqx targetLabel: from - action: replace # fix value, don't modify sourceLabels: ['pod'] targetLabel: "instance" ================================================ FILE: .archive/kubernetes/emqx/cluster/secret.enc.age.yaml ================================================ apiVersion: v1 kind: Secret metadata: name: emqx-secret namespace: home-system type: Opaque stringData: EMQX_DASHBOARD__DEFAULT_USERNAME: ENC[AES256_GCM,data:ihBafEA=,iv:ZsTN9ZkWbkAkOfJkyQ/85SwQeW2tUXy52lxZvwRU3rY=,tag:LDJoYBZ0FLdi60vYLfjHKQ==,type:str] EMQX_DASHBOARD__DEFAULT_PASSWORD: ENC[AES256_GCM,data:zoqmRZU=,iv:c1mAE/ypSwRT1x8dNLPAfd39y8JV486FAbXpryWv68I=,tag:ZjF14CBmx/tCz7O/Hl+aHg==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxZDdDZS9IYlZJRjJ2aDBm b3QybC82dkdxemtRcGtnaGdCem53dW5yQzF3CnNMV2t3WGRVNll6ckZrcXdPK2Zo YzNUQ1FQSWZwc2xOVXRIWG42ZU5GdjQKLS0tIGw3NDBGYlNaM25ZYytDMXFlRFZ4 aHc3U1doVzhodDhleWlYbjlNNXpwSlEKqPoYWY4e3dK8DhJl3JUqJHFbLJ1pI9LC mOGYY84o+4FDg8cPM1JLQQaDYtX91wwZ7QFJBbS17Nk/hbW7L9qLKw== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:43:27Z" mac: ENC[AES256_GCM,data:fA2cdvaefWGTYM2/B3e71694vvMZvw6lrm9N8jqovz6eKq8D1EmA+ER/xut4BVuU4bqKS+9286j+HVzs88vWM4pTZ6eiNy6lNNqXVpEbGkUiYfAFEdLj5W0IW/3K5AN8VcEQP+/YuDXktph5am4YbUqr6YTkXhk1kFFy5ChWo1A=,iv:Ea+zQloY9kg40Kpxi065HytlwNfC18/hlLBk5PyUUNQ=,tag:loic+lRLpTpn5wKFA0Zn4w==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 --- apiVersion: v1 kind: Secret metadata: name: emqx-init-user-secret namespace: home-system type: Opaque stringData: init-user.json: ENC[AES256_GCM,data:7qW1ulUq49TviINOXeMngtqoYxbZM2kNPz6/kp8wN9cZIhsss685cwfLiEOiRAJFfwYplOpujy7fdXaDVBk7Xk1L,iv:b2wIxpECr/TV5uDzLkx4dt9mZAjkQKCDzYOCSN6evPE=,tag:z0G3hi0oCqq8cf8PgvdI5Q==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxZDdDZS9IYlZJRjJ2aDBm b3QybC82dkdxemtRcGtnaGdCem53dW5yQzF3CnNMV2t3WGRVNll6ckZrcXdPK2Zo YzNUQ1FQSWZwc2xOVXRIWG42ZU5GdjQKLS0tIGw3NDBGYlNaM25ZYytDMXFlRFZ4 aHc3U1doVzhodDhleWlYbjlNNXpwSlEKqPoYWY4e3dK8DhJl3JUqJHFbLJ1pI9LC mOGYY84o+4FDg8cPM1JLQQaDYtX91wwZ7QFJBbS17Nk/hbW7L9qLKw== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:43:27Z" mac: ENC[AES256_GCM,data:fA2cdvaefWGTYM2/B3e71694vvMZvw6lrm9N8jqovz6eKq8D1EmA+ER/xut4BVuU4bqKS+9286j+HVzs88vWM4pTZ6eiNy6lNNqXVpEbGkUiYfAFEdLj5W0IW/3K5AN8VcEQP+/YuDXktph5am4YbUqr6YTkXhk1kFFy5ChWo1A=,iv:Ea+zQloY9kg40Kpxi065HytlwNfC18/hlLBk5PyUUNQ=,tag:loic+lRLpTpn5wKFA0Zn4w==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 ================================================ FILE: .archive/kubernetes/emqx/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: emqx namespace: home-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/home-system/emqx/app" prune: true wait: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: home-system --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: emqx-cluster namespace: home-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/home-system/emqx/cluster" prune: true wait: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: home-system ================================================ FILE: .archive/kubernetes/external-dns-unifi/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: external-dns-unifi spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: external-dns-unifi template: data: UNIFI_API_KEY: "{{ .UNIFI_API_KEY }}" dataFrom: - extract: key: unifi ================================================ FILE: .archive/kubernetes/external-dns-unifi/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2beta2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app external-dns-unifi namespace: network-system spec: interval: 1h chartRef: kind: OCIRepository name: external-dns-unifi install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 valuesFrom: - kind: ConfigMap name: external-dns-unifi-values ================================================ FILE: .archive/kubernetes/external-dns-unifi/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml - ocirepository.yaml configMapGenerator: - name: external-dns-unifi-values namespace: network-system files: - values.yaml=./values.yaml ================================================ FILE: .archive/kubernetes/external-dns-unifi/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: external-dns-unifi namespace: network-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 1.21.1 url: oci://ghcr.io/home-operations/charts-mirror/external-dns ================================================ FILE: .archive/kubernetes/external-dns-unifi/app/values.yaml ================================================ fullnameOverride: external-dns-unifi provider: name: webhook webhook: image: repository: ghcr.io/kashalls/external-dns-unifi-webhook tag: v0.8.2@sha256:7f0ddbbc83a36a2a9d762e25eef9cafcb3adf0493068a27d72ae71087eafe6f0 env: - name: UNIFI_HOST value: https://192.168.1.1 - name: UNIFI_API_KEY valueFrom: secretKeyRef: name: &secret external-dns-unifi key: UNIFI_API_KEY livenessProbe: httpGet: path: /healthz port: http-webhook initialDelaySeconds: 10 timeoutSeconds: 5 readinessProbe: httpGet: path: /readyz port: http-webhook initialDelaySeconds: 10 timeoutSeconds: 5 triggerLoopOnEvent: true policy: sync sources: - crd - istio-virtualservice txtPrefix: k8s. domainFilters: - ${CLUSTER_DOMAIN} serviceMonitor: enabled: true ================================================ FILE: .archive/kubernetes/external-dns-unifi/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: external-dns-unifi namespace: network-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/network-system/external-dns-unifi/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: network-system ================================================ FILE: .archive/kubernetes/goldilocks/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app goldilocks spec: interval: 1h chartRef: kind: OCIRepository name: goldilocks namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 ================================================ FILE: .archive/kubernetes/goldilocks/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: goldilocks namespace: observability spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'goldilocks.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: goldilocks-dashboard port: 80 weight: 100 ================================================ FILE: .archive/kubernetes/goldilocks/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml ================================================ FILE: .archive/kubernetes/goldilocks/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: goldilocks namespace: observability spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/observability/goldilocks/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system dependsOn: - name: istiod namespace: istio-system targetNamespace: observability ================================================ FILE: .archive/kubernetes/istio-csr/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app istio-csr namespace: network-system spec: interval: 1h chartRef: kind: OCIRepository name: cert-manager-istio-csr namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 dependsOn: - name: cert-manager namespace: network-system values: app: certmanager: # -- Don't delete created CertificateRequests once they have been signed. preserveCertificateRequests: false issuer: # -- Issuer name set on created CertificateRequests for both istio-csr's # serving certificate and incoming gRPC CSRs. name: istio-ca # -- Issuer kind set on created CertificateRequests for both istio-csr's # serving certificate and incoming gRPC CSRs. kind: Issuer # -- Issuer group name set on created CertificateRequests for both # istio-csr's serving certificate and incoming gRPC CSRs. group: cert-manager.io tls: # -- An optional file location to a PEM encoded root CA that the root CA # ConfigMap in all namespaces will be populated with. If empty, the CA # returned from cert-manager for the serving certificate will be used. # rootCAFile: /etc/tls/root-cert.pem # rootCAFile: /etc/tls/root-cert.pem # -- The DNS names to request for the server's serving certificate which is # presented to istio-agents. istio-agents must route to istio-csr using one # of these DNS names. certificateDNSNames: - cert-manager-istio-csr.network-system.svc istio: # -- The istio revisions that are currently installed in the cluster. # Changing this field will modify the DNS names that will be requested for # the istiod certificate. The common name for the istiod certificate is # hard coded to the `default` revision DNS name. # Some issuers may require that the common name on certificates match one # of the DNS names. If 1. Your issuer has this constraint, and 2. You are # not using `default` as a revision, add the `default` revision here # anyway. The resulting certificate will include a DNS name that won't be # used, but will pass this constraint. revisions: - default - canary # volumes: # - name: root-ca # configMap: # name: istio-ca-root-cert # volumeMounts: # - name: root-ca # mountPath: /etc/tls ================================================ FILE: .archive/kubernetes/istio-csr/app/issuer.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cert-manager.io/clusterissuer_v1.json apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: selfsigned spec: selfSigned: {} --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cert-manager.io/certificate_v1.json apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: istio-ca namespace: istio-system spec: isCA: true duration: 2160h # 90d secretName: istio-ca commonName: istio-ca subject: organizations: - cluster.local issuerRef: name: selfsigned kind: ClusterIssuer group: cert-manager.io --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cert-manager.io/issuer_v1.json apiVersion: cert-manager.io/v1 kind: Issuer metadata: name: istio-ca namespace: istio-system spec: ca: secretName: istio-ca ================================================ FILE: .archive/kubernetes/istio-csr/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - issuer.yaml ================================================ FILE: .archive/kubernetes/istio-csr/ks.yaml ================================================ # TODO: Investigate the best way to enable this through using the helm charts. --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: istio-csr namespace: network-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/network-system/istio-csr/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system dependsOn: - name: cert-manager namespace: network-system targetNamespace: network-system ================================================ FILE: .archive/kubernetes/istio-ingress/README.md ================================================ # Istio > Note: This is still heavily a WIP Step 1: Download specific istio version ```bash curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.6.5 sh - ``` Step 2: Generate operator manifests ```bash helm template manifests/charts/istio-operator/ \ --set hub=docker.io/querycapistio \ --set tag=1.6.5 \ --set operatorNamespace=istio-operator \ --set istioNamespace=istio-system ``` Alternatively install using the following command: ```bash istioctl operator init --hub docker.io/querycapistio --tag 1.6.5 ``` Step 3: Apply IstioOperator resource Step 4: Edit deployments to include `arm64` in affinity # Canary ```bash helm template manifests/charts/istio-operator/ \ --set hub=docker.io/querycapistio \ --set tag=1.6.5 \ --set operatorNamespace=istio-operator \ --set istioNamespace=istio-system \ --set revision=canary > bla.yaml ``` ## Demo Deployment A demo application to test Istio sidecar injection ```bash apiVersion: apps/v1 kind: Deployment metadata: labels: app: curl name: curl namespace: test spec: progressDeadlineSeconds: 600 replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: app: curl strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: labels: app: curl spec: containers: - image: curlimages/curl imagePullPolicy: Always name: curl resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File command: ["sleep", "9999999"] dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} ``` ================================================ FILE: .archive/kubernetes/istio-ingress/bedrock-broadcaster/app/certificates.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cert-manager.io/certificate_v1.json apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: bedrock-broadcaster-com-le namespace: istio-ingress spec: # The secret name where cert-manager should store the signed certificate secretName: bedrock-broadcaster-com-le duration: 2160h0m0s # 90d renewBefore: 360h0m0s # 15d # cert-manager regenerates a new private key on each issuance # https://cert-manager.io/docs/usage/certificate/#rotation-private-key privateKey: rotationPolicy: Always algorithm: RSA encoding: PKCS1 size: 2048 usages: - server auth - client auth issuerRef: name: letsencrypt-prod kind: ClusterIssuer commonName: ${BEDROCK_BROADCASTER_DOMAIN} dnsNames: - ${BEDROCK_BROADCASTER_DOMAIN} - '*.${BEDROCK_BROADCASTER_DOMAIN}' ================================================ FILE: .archive/kubernetes/istio-ingress/bedrock-broadcaster/app/gateway.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/networking.istio.io/gateway_v1beta1.json apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: bedrock-broadcaster-ingressgateway namespace: istio-ingress spec: selector: app: istio-gateway servers: - port: number: 80 name: http protocol: HTTP hosts: - '${BEDROCK_BROADCASTER_DOMAIN}' - '*.${BEDROCK_BROADCASTER_DOMAIN}' tls: httpsRedirect: true - port: number: 443 name: https protocol: HTTPS hosts: - '${BEDROCK_BROADCASTER_DOMAIN}' - '*.${BEDROCK_BROADCASTER_DOMAIN}' tls: credentialName: bedrock-broadcaster-com-le mode: SIMPLE minProtocolVersion: TLSV1_2 maxProtocolVersion: TLSV1_3 ================================================ FILE: .archive/kubernetes/istio-ingress/bedrock-broadcaster/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - certificates.yaml - gateway.yaml ================================================ FILE: .archive/kubernetes/istio-ingress/bedrock-broadcaster/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: bedrock-broadcaster-istio-gateway namespace: istio-ingress spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/istio-ingress/bedrock-broadcaster/app" prune: true wait: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: istio-ingress dependsOn: - name: istiod namespace: istio-system - name: cert-manager namespace: network-system ================================================ FILE: .archive/kubernetes/istio-ingress/github/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: github namespace: istio-ingress spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - '${CLUSTER_DOMAIN}' rules: - matches: - path: type: Exact value: / filters: - type: URLRewrite urlRewrite: path: type: ReplacePrefixMatch replacePrefixMatch: /k8s-gitops hostname: xunholy.github.io backendRefs: - kind: Service name: xunholy-github-io port: 443 ================================================ FILE: .archive/kubernetes/istio-ingress/github/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - httproute.yaml - service.yaml ================================================ FILE: .archive/kubernetes/istio-ingress/github/service.yaml ================================================ --- # External service definition for xunholy.github.io apiVersion: v1 kind: Service metadata: name: xunholy-github-io namespace: istio-ingress spec: type: ExternalName externalName: xunholy.github.io ports: - name: https port: 443 protocol: TCP ================================================ FILE: .archive/kubernetes/istio-ingress/istio-gateway/app/authorization-policy.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/security.istio.io/authorizationpolicy_v1beta1.json apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: ext-authz namespace: istio-system spec: # The selector applies to the ingress gateway in the istio-ingress namespace. selector: matchLabels: app: istio-gateway # The action "CUSTOM" delegates the access control to an external authorizer, this is different from # the ALLOW/DENY action that enforces the access control right inside the proxy. action: CUSTOM # The provider specifies the name of the external authorizer defined in the meshconfig, which tells where and how to # talk to the external auth service. provider: name: 'oauth2-proxy' # The rule specifies that the access control is triggered only if the request path has the prefix "/admin/". # This allows you to easily enable or disable the external authorization based on the requests, avoiding the external # check request if it is not needed. rules: - to: - operation: hosts: - 'sealed-secrets.raspbernetes.com' - 'alert-manager.raspbernetes.com' - 'prometheus.raspbernetes.com' ================================================ FILE: .archive/kubernetes/istio-ingress/istio-gateway/app/certificates.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cert-manager.io/certificate_v1.json apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: raspbernetes-com-le namespace: istio-ingress spec: # The secret name where cert-manager should store the signed certificate secretName: raspbernetes-com-le duration: 2160h0m0s # 90d renewBefore: 360h0m0s # 15d # cert-manager regenerates a new private key on each issuance # https://cert-manager.io/docs/usage/certificate/#rotation-private-key privateKey: rotationPolicy: Always algorithm: RSA encoding: PKCS1 size: 2048 usages: - server auth - client auth issuerRef: name: letsencrypt-prod kind: ClusterIssuer commonName: ${CLUSTER_DOMAIN} dnsNames: - ${CLUSTER_DOMAIN} - '*.${CLUSTER_DOMAIN}' ================================================ FILE: .archive/kubernetes/istio-ingress/istio-gateway/app/gateway.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/networking.istio.io/gateway_v1beta1.json apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: istio-ingressgateway namespace: istio-ingress spec: selector: app: istio-gateway servers: - port: number: 80 name: http protocol: HTTP hosts: - '${CLUSTER_DOMAIN}' - '*.${CLUSTER_DOMAIN}' tls: httpsRedirect: true - port: number: 443 name: https protocol: HTTPS hosts: - '${CLUSTER_DOMAIN}' - '*.${CLUSTER_DOMAIN}' tls: credentialName: raspbernetes-com-le mode: SIMPLE minProtocolVersion: TLSV1_2 maxProtocolVersion: TLSV1_3 ================================================ FILE: .archive/kubernetes/istio-ingress/istio-gateway/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: istio-gateway namespace: istio-ingress spec: interval: 1h chartRef: kind: OCIRepository name: istio-gateway namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: warn maxHistory: 3 values: podDisruptionBudget: minAvailable: 1 unhealthyPodEvictionPolicy: AlwaysAllow priorityClassName: "platform-cluster-critical" service: annotations: io.cilium/lb-ipam-ips: ${CLUSTER_LB_ISTIO_INGRESS_GATEWAY} affinity: # This podAntiAffinity ensures ingress controllers are not scheduled on the same node podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: istio operator: In values: - ingressgateway topologyKey: kubernetes.io/hostname ================================================ FILE: .archive/kubernetes/istio-ingress/istio-gateway/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../github - authorization-policy.yaml - certificates.yaml - gateway.yaml - helmrelease.yaml ================================================ FILE: .archive/kubernetes/istio-ingress/istio-gateway/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: istio-gateway namespace: istio-ingress spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/istio-ingress/istio-gateway/app" prune: true wait: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: istio-ingress dependsOn: - name: istiod namespace: istio-system - name: cert-manager namespace: network-system ================================================ FILE: .archive/kubernetes/istio-ingress/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: istio-ingress resources: - namespace.yaml ================================================ FILE: .archive/kubernetes/istio-ingress/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: istio-ingress labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: .archive/kubernetes/istio-ingress/plex/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: plex namespace: istio-ingress spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'plex.${CLUSTER_DOMAIN}' rules: - backendRefs: - kind: Service name: plex-external port: 32400 weight: 100 --- # External service definition for Plex apiVersion: v1 kind: Service metadata: name: plex-external namespace: istio-ingress spec: type: ExternalName externalName: expanse.internal ports: - name: tcp port: 32400 protocol: TCP ================================================ FILE: .archive/kubernetes/istio-ingress/plex/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: istio-ingress resources: - httproute.yaml ================================================ FILE: .archive/kubernetes/istio-system/README.md ================================================ # Istio > Note: This is still heavily a WIP Step 1: Download specific istio version ```bash curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.6.5 sh - ``` Step 2: Generate operator manifests ```bash helm template manifests/charts/istio-operator/ \ --set hub=docker.io/querycapistio \ --set tag=1.6.5 \ --set operatorNamespace=istio-operator \ --set istioNamespace=istio-system ``` Alternatively install using the following command: ```bash istioctl operator init --hub docker.io/querycapistio --tag 1.6.5 ``` Step 3: Apply IstioOperator resource Step 4: Edit deployments to include `arm64` in affinity # Canary ```bash helm template manifests/charts/istio-operator/ \ --set hub=docker.io/querycapistio \ --set tag=1.6.5 \ --set operatorNamespace=istio-operator \ --set istioNamespace=istio-system \ --set revision=canary > bla.yaml ``` ## Demo Deployment A demo application to test Istio sidecar injection ```bash apiVersion: apps/v1 kind: Deployment metadata: labels: app: curl name: curl namespace: test spec: progressDeadlineSeconds: 600 replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: app: curl strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: labels: app: curl spec: containers: - image: curlimages/curl imagePullPolicy: Always name: curl resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File command: ["sleep", "9999999"] dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} ``` ================================================ FILE: .archive/kubernetes/istio-system/flagger/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: flagger namespace: istio-system spec: interval: 1h chartRef: kind: OCIRepository name: flagger namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: meshProvider: istio metricsServer: http://kube-prometheus-stack-prometheus.observability.svc.cluster.local:9090 ================================================ FILE: .archive/kubernetes/istio-system/flagger/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/istio-system/flagger/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: flagger namespace: istio-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/istio-system/flagger/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: istio-system dependsOn: - name: istiod namespace: istio-system ================================================ FILE: .archive/kubernetes/istio-system/istio-base/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: istio-base namespace: istio-system spec: interval: 1h chartRef: kind: OCIRepository name: istio-base namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: warn maxHistory: 3 postRenderers: - kustomize: patches: - target: version: v1 kind: ValidatingWebhookConfiguration name: istiod-default-validator patch: | - op: add path: /metadata/annotations/helm.toolkit.fluxcd.io~1driftDetection value: disabled ================================================ FILE: .archive/kubernetes/istio-system/istio-base/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/istio-system/istio-base/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: istio-base namespace: istio-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/istio-system/istio-base/app" prune: true wait: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: istio-system ================================================ FILE: .archive/kubernetes/istio-system/istio-cni/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: istio-cni namespace: istio-system spec: interval: 1h chartRef: kind: OCIRepository name: istio-cni namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: warn maxHistory: 3 # TODO: These resources need more data points to be considered accurate. # values: # cni: # # Resources allocated based on Robusta KRR output # resources: # requests: # cpu: 50m # memory: 512Mi ================================================ FILE: .archive/kubernetes/istio-system/istio-cni/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/istio-system/istio-cni/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: istio-cni namespace: istio-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/istio-system/istio-cni/app" prune: true wait: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: istio-system dependsOn: - name: istio-base namespace: istio-system ================================================ FILE: .archive/kubernetes/istio-system/istiod/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: istiod namespace: istio-system spec: interval: 1h chartRef: kind: OCIRepository name: istiod namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: warn maxHistory: 3 values: pilot: autoscaleEnabled: true autoscaleMin: 1 autoscaleMax: 3 replicaCount: 1 rollingMaxSurge: 100% rollingMaxUnavailable: 25% # Resources allocated based on Robusta KRR output resources: requests: cpu: 100m memory: 500Mi meshConfig: defaultConfig: gatewayTopology: # Always forward the XFCC header in the request, regardless of whether the client connection is mTLS. forwardClientCertDetails: ALWAYS_FORWARD_ONLY accessLogFile: /dev/stdout trustDomain: cluster.local extensionProviders: - name: oauth2-proxy envoyExtAuthzHttp: service: oauth2-proxy.network-system.svc.cluster.local port: 80 includeHeadersInCheck: ["authorization", "cookie"] headersToUpstreamOnAllow: [ "authorization", "path", "x-auth-request-user", "x-auth-request-email", "x-auth-request-access-token", ] headersToDownstreamOnDeny: ["content-type", "set-cookie"] postRenderers: - kustomize: patches: - target: version: v1 kind: ValidatingWebhookConfiguration name: istio-validator-istio-system patch: | - op: add path: /metadata/annotations/helm.toolkit.fluxcd.io~1driftDetection value: disabled ================================================ FILE: .archive/kubernetes/istio-system/istiod/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: istio-system resources: - helmrelease.yaml - podmonitor.yaml ================================================ FILE: .archive/kubernetes/istio-system/istiod/app/podmonitor.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/podmonitor_v1.json apiVersion: monitoring.coreos.com/v1 kind: PodMonitor metadata: name: envoy-stats-monitor namespace: istio-system labels: monitoring: istio-proxies release: istio spec: selector: matchExpressions: - {key: istio-prometheus-ignore, operator: DoesNotExist} namespaceSelector: any: true jobLabel: envoy-stats podMetricsEndpoints: - path: /stats/prometheus interval: 15s relabelings: - action: keep sourceLabels: [__meta_kubernetes_pod_container_name] regex: "istio-proxy" - action: keep sourceLabels: [__meta_kubernetes_pod_annotationpresent_prometheus_io_scrape] - action: replace regex: (\d+);(([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}) replacement: '[$2]:$1' sourceLabels: - __meta_kubernetes_pod_annotation_prometheus_io_port - __meta_kubernetes_pod_ip targetLabel: __address__ - action: replace regex: (\d+);((([0-9]+?)(\.|$)){4}) replacement: $2:$1 sourceLabels: - __meta_kubernetes_pod_annotation_prometheus_io_port - __meta_kubernetes_pod_ip targetLabel: __address__ - action: labeldrop regex: "__meta_kubernetes_pod_label_(.+)" - sourceLabels: [__meta_kubernetes_namespace] action: replace targetLabel: namespace - sourceLabels: [__meta_kubernetes_pod_name] action: replace targetLabel: pod --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/servicemonitor_v1.json apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: istio-component-monitor namespace: istio-system labels: monitoring: istio-components release: istio spec: jobLabel: istio targetLabels: [app] selector: matchExpressions: - {key: istio, operator: In, values: [pilot]} namespaceSelector: any: true endpoints: - port: http-monitoring interval: 15s ================================================ FILE: .archive/kubernetes/istio-system/istiod/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: istiod namespace: istio-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/istio-system/istiod/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: istio-system dependsOn: - name: istio-cni namespace: istio-system ================================================ FILE: .archive/kubernetes/istio-system/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: istio-system components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: .archive/kubernetes/istio-system/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: istio-system labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: .archive/kubernetes/jaeger/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: jaeger namespace: observability spec: interval: 1h chartRef: kind: OCIRepository name: jaeger namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: provisionDataStore: cassandra: false allInOne: enabled: true storage: type: none agent: enabled: false collector: enabled: false query: enabled: false ================================================ FILE: .archive/kubernetes/jaeger/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: jaeger namespace: observability spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'jaeger.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: jaeger-query port: 16686 weight: 100 ================================================ FILE: .archive/kubernetes/jaeger/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml ================================================ FILE: .archive/kubernetes/jaeger/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: jaeger namespace: observability spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/observability/jaeger/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: observability ================================================ FILE: .archive/kubernetes/k8s-gateway/app/Corefile ================================================ .:1053 { errors log health { lameduck 5s } ready k8s_gateway raspbernetes.com { apex k8s-gateway.network resources Ingress Service ttl 300 } prometheus 0.0.0.0:9153 loop reload loadbalance } ================================================ FILE: .archive/kubernetes/k8s-gateway/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.jsonapiVersion: helm.toolkit.fluxcd.io/v2 apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app k8s-gateway namespace: network-system spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: image: repository: quay.io/oriedge/k8s_gateway tag: v0.4.0 pullPolicy: IfNotPresent args: ["-conf", "/etc/coredns/Corefile"] serviceAccount: create: true name: *app service: main: type: LoadBalancer externalTrafficPolicy: Local annotations: io.cilium/lb-ipam-ips: ${CLUSTER_LB_K8S_GATEWAY} ports: http: enabled: false dns: enabled: true port: 53 targetPort: 1053 protocol: UDP serviceMonitor: main: enabled: true endpoints: - port: metrics scheme: http path: /metrics interval: 1m scrapeTimeout: 10s persistence: config: enabled: true type: configMap name: k8s-gateway-configmap subPath: Corefile mountPath: /etc/coredns/Corefile readOnly: true probes: readiness: custom: true spec: httpGet: path: /ready port: 8181 scheme: HTTP liveness: custom: true spec: httpGet: path: /health port: 8080 scheme: HTTP startup: custom: true spec: httpGet: path: /ready port: 8181 scheme: HTTP ================================================ FILE: .archive/kubernetes/k8s-gateway/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml configMapGenerator: - name: k8s-gateway-configmap files: - ./Corefile ================================================ FILE: .archive/kubernetes/k8s-gateway/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: k8s-gateway namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/network-system/k8s-gateway/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: network-system ================================================ FILE: .archive/kubernetes/kiali/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kiali-server namespace: observability spec: interval: 1h chartRef: kind: OCIRepository name: kiali-server namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 dependsOn: - name: kube-prometheus-stack namespace: observability values: istio_namespace: istio-system # Required as discussed here https://kiali.io/docs/configuration/p8s-jaeger-grafana/ external_services: istio: root_namespace: istio-system prometheus: url: "http://kube-prometheus-stack-prometheus.observability.svc.cluster.local:9090/" tracing: # Enabled by default. Kiali will anyway fallback to disabled if # Jaeger is unreachable. enabled: true in_cluster_url: 'http://jaeger-query.observability.svc.cluster.local:16685/jaeger' use_grpc: true # Public facing URL of Jaeger url: 'https://jaeger.${CLUSTER_DOMAIN}/jaeger' grafana: enabled: true in_cluster_url: 'http://grafana.observability.svc.cluster.local/' # Public facing URL of Grafana url: 'https://grafana.${CLUSTER_DOMAIN}/grafana' ================================================ FILE: .archive/kubernetes/kiali/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: kiali namespace: observability spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'kiali.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: kiali port: 20001 weight: 100 ================================================ FILE: .archive/kubernetes/kiali/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml ================================================ FILE: .archive/kubernetes/kiali/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kiali namespace: observability spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/observability/kiali/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: observability ================================================ FILE: .archive/kubernetes/kubefed/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kubefed namespace: kube-system spec: interval: 1h chartRef: kind: OCIRepository name: kubefed namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: # Default values for kubefed. # This is a YAML-formatted file. # Declare variables to be passed into your templates. ## Configuration values for kubefed controllermanager deployment. ## controllermanager: controller: repository: kubespheredev image: kubefed tag: v0.8.1-multi-arch imagePullPolicy: IfNotPresent logLevel: 2 forceRedeployment: false env: {} resources: limits: memory: 512Mi requests: cpu: 100m memory: 64Mi webhook: repository: kubespheredev image: kubefed tag: v0.8.1-multi-arch imagePullPolicy: IfNotPresent logLevel: 8 forceRedeployment: false env: {} resources: limits: memory: 256Mi requests: cpu: 100m memory: 64Mi certManager: enabled: false rootCertificate: organizations: [] dnsNames: - ca.webhook.kubefed commonName: ca.webhook.kubefed postInstallJob: repository: bitnami image: kubectl tag: 1.17.16 imagePullPolicy: IfNotPresent ================================================ FILE: .archive/kubernetes/kubefed/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/kubefed/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kubefed namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/kube-system/kubefed/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: kube-system ================================================ FILE: .archive/kubernetes/kured/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kured namespace: kube-system spec: interval: 1h chartRef: kind: OCIRepository name: kured namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: service: create: true metrics: create: true ================================================ FILE: .archive/kubernetes/kured/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/kured/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kured namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/kube-system/kured/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: kube-system ================================================ FILE: .archive/kubernetes/litmus/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - namespace.yaml ================================================ FILE: .archive/kubernetes/litmus/litmus/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: litmus namespace: litmus spec: interval: 1h chartRef: kind: OCIRepository name: litmus namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: portal: server: authServer: env: DEX_SERVER: "true" OIDC_ISSUER: "dex.network-system.svc.cluster.local" CALLBACK_URL: "litmus-frontend-service.litmus.svc.cluster.local" ================================================ FILE: .archive/kubernetes/litmus/litmus/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: chaos-center namespace: litmus spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'chaos-center.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: litmus-frontend-service port: 9091 weight: 100 ================================================ FILE: .archive/kubernetes/litmus/litmus/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml ================================================ FILE: .archive/kubernetes/litmus/litmus/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: litmus namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/litmus/litmus/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system dependsOn: - name: istiod namespace: istio-system targetNamespace: litmus ================================================ FILE: .archive/kubernetes/litmus/litmus-core/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: litmus-core namespace: litmus spec: interval: 1h chartRef: kind: OCIRepository name: litmus-core namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: nameOverride: "litmus-core" fullnameOverride: "litmus-core" exporter: enabled: true ================================================ FILE: .archive/kubernetes/litmus/litmus-core/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/litmus/litmus-core/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: litmus-core namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/litmus/litmus-core/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: litmus ================================================ FILE: .archive/kubernetes/litmus/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: litmus labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: .archive/kubernetes/loki-stack/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: loki-stack namespace: observability spec: interval: 1h chartRef: kind: OCIRepository name: loki-stack namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: loki: enabled: true rbac: pspEnabled: false serviceMonitor: enabled: true promtail: enabled: true serviceMonitor: enabled: true fluent-bit: enabled: false grafana: enabled: false prometheus: enabled: false test_pod: enabled: false ================================================ FILE: .archive/kubernetes/loki-stack/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/loki-stack/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: loki-stack namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/observability/loki-stack/app" prune: true wait: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: observability ================================================ FILE: .archive/kubernetes/metallb/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app metallb namespace: network-system spec: interval: 1h chartRef: kind: OCIRepository name: metallb namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: prometheus: serviceAccount: "kube-prometheus-stack-prometheus" namespace: "observability" serviceMonitor: enabled: true prometheusRule: enabled: true ================================================ FILE: .archive/kubernetes/metallb/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/metallb/config/ipaddresspool.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/metallb.io/ipaddresspool_v1beta1.json apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: metallb-l2-pool namespace: network-system spec: addresses: - '${CLUSTER_LB_ADDRESSES}' avoidBuggyIPs: true --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/metallb.io/l2advertisement_v1beta1.json apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: metallb-l2 namespace: network-system spec: ipAddressPools: - metallb-l2-pool # --- # apiVersion: metallb.io/v1beta1 # kind: IPAddressPool # metadata: # name: metallb-bgp-pool # namespace: network-system # spec: # addresses: # - 192.168.50.190/32 # avoidBuggyIPs: true # --- # apiVersion: metallb.io/v1beta1 # kind: BGPAdvertisement # metadata: # name: example # namespace: network-system # spec: # ipAddressPools: # - metallb-bgp-pool # --- # apiVersion: metallb.io/v1beta2 # kind: BGPPeer # metadata: # name: metallb-bgp # namespace: network-system # spec: # myASN: 64512 # peerASN: 64512 # peerAddress: 192.168.50.1 # bfdProfile: bfdprofile # --- # # https://metallb.universe.tf/configuration/#enabling-bfd-support-for-bgp-sessions # apiVersion: metallb.io/v1beta1 # kind: BFDProfile # metadata: # name: bfdprofile # namespace: network-system # spec: # receiveInterval: 380 # transmitInterval: 270 ================================================ FILE: .archive/kubernetes/metallb/config/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ipaddresspool.yaml ================================================ FILE: .archive/kubernetes/metallb/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: metallb namespace: network-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/network-system/metallb/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: network-system --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: metallb-config namespace: network-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/network-system/metallb/config" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system dependsOn: - name: metallb namespace: network-system targetNamespace: network-system ================================================ FILE: .archive/kubernetes/node-feature-discovery/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app node-feature-discovery namespace: network-system spec: interval: 1h chartRef: kind: OCIRepository name: node-feature-discovery namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: master: replicaCount: 1 worker: config: core: labelSources: ["pci", "system", "usb"] # TODO: Retest Zigbee USB device # sources: # usb: # deviceClassWhitelist: # - '02' # - '03' # - '0e' # - 'ef' # - 'fe' # - 'ff' # deviceLabelFields: # - 'class' # - 'vendor' # - 'device' # custom: # - name: 'zigbee' # matchOn: # - usbId: # class: ['ff'] # vendor: ['1a86'] # device: ['7523'] prometheus: enable: true ================================================ FILE: .archive/kubernetes/node-feature-discovery/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml # - networkpolicy.yaml ================================================ FILE: .archive/kubernetes/node-feature-discovery/app/networkpolicy.yaml ================================================ --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: node-feature-discovery namespace: network-system spec: podSelector: matchLabels: app.kubernetes.io/name: node-feature-discovery policyTypes: - Egress egress: # Egress traffic to kube-apiserver svc - to: - ipBlock: cidr: 10.96.0.1/32 ports: - protocol: TCP port: 443 # Egress traffic to kube-apiserver endpoints - to: - ipBlock: cidr: 192.168.50.114/32 - ipBlock: cidr: 192.168.50.115/32 - ipBlock: cidr: 192.168.50.116/32 ports: - protocol: TCP port: 6443 ================================================ FILE: .archive/kubernetes/node-feature-discovery/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: node-feature-discovery namespace: network-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m targetNamespace: network-system path: "./apps/base/network-system/node-feature-discovery/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system ================================================ FILE: .archive/kubernetes/openclaw/app/backendtrafficpolicy.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.envoyproxy.io/backendtrafficpolicy_v1alpha1.json apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy metadata: name: openclaw spec: targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: openclaw # Compression is intentionally omitted here. Because mergeType is unset, this # route-level policy fully replaces the global gateway-level BackendTrafficPolicy, # effectively disabling Zstd/Brotli/Gzip compression that would buffer SSE/WebSocket # streaming AI responses. If mergeType is ever added, compression will leak back in. timeout: http: # Disable request timeout for long-running AI streaming responses requestTimeout: "0s" # Match upstream idle timeout to OpenClaw's llm.idleTimeoutSeconds (300s) and # allow headroom for extended thinking phases (Opus can pause >60s between tokens) connectionIdleTimeout: 3600s # Disable retries - retrying a streaming AI request mid-stream causes # duplicate responses and wasted API usage retry: numRetries: 0 tcpKeepalive: probes: 3 idleTime: 20m interval: 60s ================================================ FILE: .archive/kubernetes/openclaw/app/configmap.yaml ================================================ --- apiVersion: v1 kind: ConfigMap metadata: name: openclaw-config data: openclaw.json: | { "gateway": { "port": 18789, "mode": "local", "bind": "lan", "trustedProxies": ["10.244.0.0/16", "10.96.0.0/12"], "auth": { "mode": "token" }, "controlUi": { "allowedOrigins": ["https://openclaw.${CLUSTER_DOMAIN}"], "dangerouslyDisableDeviceAuth": true } }, "browser": { "enabled": true }, "agents": { "defaults": { "workspace": "/home/node/.openclaw/workspace", "model": { "primary": "openai/claude-opus-4", "fallbacks": [ "openai/claude-sonnet-4" ] }, "userTimezone": "UTC", "timeoutSeconds": 600, "maxConcurrent": 3, "llm": { "idleTimeoutSeconds": 300 }, "contextPruning": { "mode": "cache-ttl", "ttl": "1h", "keepLastAssistants": 3, "softTrimRatio": 0.3, "hardClearRatio": 0.5 } }, "list": [ { "id": "main", "default": true, "identity": { "name": "OpenClaw" } } ] }, "session": { "scope": "per-sender", "store": "/home/node/.openclaw/sessions", "reset": { "mode": "idle", "idleMinutes": 60 }, "maintenance": { "mode": "enforce", "pruneAfter": "30d", "maxEntries": 500, "rotateBytes": "10mb", "maxDiskBytes": "2gb", "highWaterBytes": "1.6gb" } }, "logging": { "level": "info", "consoleLevel": "info", "consoleStyle": "compact", "redactSensitive": "tools" }, "cron": { "enabled": true, "maxConcurrentRuns": 2, "sessionRetention": "24h" }, "tools": { "profile": "full", "web": { "search": { "enabled": true, "provider": "duckduckgo" }, "fetch": { "enabled": true } } } } ================================================ FILE: .archive/kubernetes/openclaw/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: openclaw spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: openclaw-secret template: data: ANTHROPIC_API_KEY: "{{ .ANTHROPIC_API_KEY }}" OPENAI_API_KEY: "{{ .OPENAI_API_KEY }}" OPENCLAW_GATEWAY_TOKEN: "{{ .OPENCLAW_GATEWAY_TOKEN }}" OPENCLAW_GATEWAY_PASSWORD: "{{ .OPENCLAW_GATEWAY_PASSWORD }}" .credentials.json: "{{ .CLAUDE_CODE_CREDENTIALS }}" dataFrom: - extract: key: openclaw ================================================ FILE: .archive/kubernetes/openclaw/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app openclaw spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: *app : initContainers: install-proxy: image: repository: node tag: 24-slim command: ["/bin/sh"] args: - "-c" - | export NPM_CONFIG_PREFIX=/opt/proxy npm install -g claude-max-api-proxy@1.0.0 @anthropic-ai/claude-code@2.1.83 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 200m memory: 512Mi limits: memory: 1Gi containers: app: image: repository: ghcr.io/openclaw/openclaw tag: 2026.5.18 command: ["/bin/sh"] args: - "-c" - | exec node dist/index.js gateway --bind lan env: TZ: ${CLUSTER_TIMEZONE} OPENAI_BASE_URL: http://localhost:3456/v1 envFrom: - secretRef: name: openclaw-secret securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } probes: startup: enabled: true custom: true spec: httpGet: path: /healthz port: 18789 initialDelaySeconds: 5 periodSeconds: 5 failureThreshold: 30 readiness: enabled: true custom: true spec: httpGet: path: /readyz port: 18789 periodSeconds: 10 failureThreshold: 3 liveness: enabled: true custom: true spec: httpGet: path: /healthz port: 18789 periodSeconds: 30 failureThreshold: 5 resources: requests: cpu: 200m memory: 1Gi limits: memory: 4Gi claude-max-api: image: repository: node tag: 24-slim command: ["/bin/sh"] args: - "-c" - | export NPM_CONFIG_PREFIX=/opt/proxy export PATH=/opt/proxy/bin:$PATH exec node /opt/proxy/lib/node_modules/claude-max-api-proxy/dist/server/standalone.js env: HOME: /home/node CLAUDE_CONFIG_DIR: /tmp/.claude envFrom: - secretRef: name: openclaw-secret securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } probes: startup: enabled: true custom: true spec: exec: command: ["node", "-e", "require('http').get('http://127.0.0.1:3456/health',r=>{ process.exit(r.statusCode===200?0:1) }).on('error',()=>process.exit(1))"] initialDelaySeconds: 10 periodSeconds: 5 failureThreshold: 30 readiness: enabled: true custom: true spec: exec: command: ["node", "-e", "require('http').get('http://127.0.0.1:3456/health',r=>{ process.exit(r.statusCode===200?0:1) }).on('error',()=>process.exit(1))"] periodSeconds: 10 failureThreshold: 3 liveness: enabled: true custom: true spec: exec: command: ["node", "-e", "require('http').get('http://127.0.0.1:3456/health',r=>{ process.exit(r.statusCode===200?0:1) }).on('error',()=>process.exit(1))"] periodSeconds: 30 failureThreshold: 5 resources: requests: cpu: 100m memory: 256Mi limits: memory: 1Gi codeserver: image: repository: ghcr.io/coder/code-server tag: 4.118.0 args: - "--auth" - "none" - "--user-data-dir" - "/home/node/.vscode" - "--extensions-dir" - "/home/node/.vscode" - "--port" - "12321" - "/home/node/.openclaw/workspace" resources: requests: cpu: 10m limits: memory: 1Gi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: controller: *app ports: http: appProtocol: kubernetes.io/ws port: 18789 codeserver: port: 12321 persistence: data: existingClaim: openclaw-data globalMounts: - path: /home/node/.openclaw config: type: configMap name: openclaw-config globalMounts: - path: /home/node/.openclaw/openclaw.json subPath: openclaw.json proxy-install: type: emptyDir advancedMounts: *app : install-proxy: - path: /opt/proxy claude-max-api: - path: /opt/proxy readOnly: true npm-cache: type: emptyDir advancedMounts: *app : install-proxy: - path: /home/node/.npm tmp: type: emptyDir globalMounts: - path: /tmp ================================================ FILE: .archive/kubernetes/openclaw/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: openclaw annotations: external-dns.alpha.kubernetes.io/external: "true" spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'openclaw.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: openclaw port: 18789 weight: 100 timeouts: request: "0s" ================================================ FILE: .archive/kubernetes/openclaw/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - externalsecret.yaml - pvc.yaml - configmap.yaml - httproute.yaml - backendtrafficpolicy.yaml - replicationsource.yaml - volsync-externalsecret.yaml ================================================ FILE: .archive/kubernetes/openclaw/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: openclaw-data spec: accessModes: - ReadWriteOnce storageClassName: ceph-block resources: requests: storage: 10Gi ================================================ FILE: .archive/kubernetes/openclaw/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: openclaw spec: sourcePVC: openclaw-data trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: openclaw-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: .archive/kubernetes/openclaw/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: openclaw-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: openclaw-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: .archive/kubernetes/openclaw/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: openclaw namespace: ai-system spec: path: "./apps/base/ai-system/openclaw/app" wait: false dependsOn: - name: external-secrets namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: ai-system sourceRef: kind: ExternalArtifact name: openclaw namespace: flux-system ================================================ FILE: .archive/kubernetes/openebs-system/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - namespace.yaml ================================================ FILE: .archive/kubernetes/openebs-system/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: openebs-system labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: .archive/kubernetes/openebs-system/openebs/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: openebs namespace: openebs-system spec: interval: 1h chartRef: kind: OCIRepository name: openebs namespace: flux-system install: timeout: 30m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: engines: local: lvm: enabled: false zfs: enabled: false mayastor: csi: node: initContainers: enabled: false ================================================ FILE: .archive/kubernetes/openebs-system/openebs/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/openebs-system/openebs/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: openebs namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m targetNamespace: openebs-system path: "./apps/base/openebs-system/openebs/app" prune: false wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system ================================================ FILE: .archive/kubernetes/openfaas/README.md ================================================ # OpenFaaS ================================================ FILE: .archive/kubernetes/openfaas/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - namespace.yaml # - networkpolicy.yaml ================================================ FILE: .archive/kubernetes/openfaas/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: openfaas labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: .archive/kubernetes/openfaas/networkpolicy.yaml ================================================ --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-allow-all namespace: openfaas spec: podSelector: {} policyTypes: - Ingress - Egress ingress: # Ingress traffic from any pod in current namespace will be allowed - from: - podSelector: {} # Ingress traffic from any pod in the cluster will be allowed - {} # Allow ingress from any endpoint only to any pods but only specific port(s) - from: - ipBlock: cidr: 0.0.0.0/0 ports: - port: 443 egress: # Egress flows to Kubernetes DNS will be allowed but only specific port(s). - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system podSelector: matchLabels: k8s-app: kube-dns ports: - port: 53 protocol: UDP - port: 53 protocol: TCP # Egress traffic to any pod in current namespace will be allowed - {} # Egress traffic to any endpoint outside of the cluster will be allowed. - to: - ipBlock: cidr: 0.0.0.0/0 # Egress traffic to any pod in current namespace will be allowed - to: - podSelector: {} ================================================ FILE: .archive/kubernetes/openfaas/openfaas/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: openfaas namespace: openfaas spec: interval: 1h chartRef: kind: OCIRepository name: openfaas namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: basic_auth: false gateway: directFunctions: true oauth2Plugin: enabled: false operator: create: false prometheus: create: false alertmanager: create: false basicAuthPlugin: replicas: 1 ingressOperator: create: false ================================================ FILE: .archive/kubernetes/openfaas/openfaas/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/openfaas/openfaas/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: openfaas namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m targetNamespace: openfaas path: "./apps/base/openfaas/openfaas/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system ================================================ FILE: .archive/kubernetes/openfaas-fn/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - namespace.yaml # - networkpolicy.yaml ================================================ FILE: .archive/kubernetes/openfaas-fn/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: openfaas-fn labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: .archive/kubernetes/openfaas-fn/networkpolicy.yaml ================================================ --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-allow-all namespace: openfaas-fn spec: podSelector: {} policyTypes: - Ingress - Egress ingress: # Ingress traffic from any pod in current namespace will be allowed - from: - podSelector: {} # Ingress traffic from any pod in the cluster will be allowed - {} # Allow ingress from any endpoint only to any pods but only specific port(s) - from: - ipBlock: cidr: 0.0.0.0/0 ports: - port: 443 egress: # Egress flows to Kubernetes DNS will be allowed but only specific port(s). - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system podSelector: matchLabels: k8s-app: kube-dns ports: - port: 53 protocol: UDP - port: 53 protocol: TCP # Egress traffic to any pod in current namespace will be allowed - {} # Egress traffic to any endpoint outside of the cluster will be allowed. - to: - ipBlock: cidr: 0.0.0.0/0 # Egress traffic to any pod in current namespace will be allowed - to: - podSelector: {} ================================================ FILE: .archive/kubernetes/origin-ca-issuer/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app origin-ca-issuer namespace: network-system spec: interval: 1h chartRef: kind: OCIRepository name: origin-ca-issuer namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 dependsOn: - name: cert-manager namespace: network-system values: controller: image: repository: cloudflare/origin-ca-issuer tag: v0.14.1 ================================================ FILE: .archive/kubernetes/origin-ca-issuer/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - https://raw.githubusercontent.com/cloudflare/origin-ca-issuer/v0.6.0/deploy/crds/cert-manager.k8s.cloudflare.com_originissuers.yaml ================================================ FILE: .archive/kubernetes/origin-ca-issuer/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: origin-ca-issuer namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m targetNamespace: network-system path: "./apps/base/network-system/origin-ca-issuer/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system ================================================ FILE: .archive/kubernetes/plex/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.jsonapiVersion: helm.toolkit.fluxcd.io/v2 apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app plex namespace: home-system spec: interval: 30m chartRef: kind: OCIRepository name: app-template namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: controllers: *app : containers: app: image: repository: ghcr.io/home-operations/plex tag: 1.43.2.10687@sha256:29aea09831a2b008ffa36b9d71b52aaf1fa3feeedec5f0211c991de01a70f645 env: TZ: Australia/Melbourne PLEX_ADVERTISE_URL: https://plex.${CLUSTER_DOMAIN}:443,http://${CLUSTER_LB_PLEX}:32400 PLEX_NO_AUTH_NETWORKS: 192.168.50.0/24 probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /identity port: 32400 initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes startup: enabled: true spec: failureThreshold: 30 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 100m memory: 512Mi limits: memory: 16Gi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch supplementalGroups: [44] seccompProfile: { type: RuntimeDefault } nodeSelector: intel.feature.node.kubernetes.io/gpu: "true" service: app: controller: plex type: LoadBalancer annotations: lbipam.cilium.io/ips: ${CLUSTER_LB_PLEX} ports: http: port: 32400 persistence: config: # existingClaim: plex # TODO: If setting up Plex for the first time, you'll want to add the globalMounts section type: emptyDir globalMounts: - path: /config/Library/Application Support/Plex Media Server # Separate PVC for cache to avoid backing up cache files cache: type: emptyDir globalMounts: - path: /config/Library/Application Support/Plex Media Server/Cache logs: type: emptyDir globalMounts: - path: /config/Library/Application Support/Plex Media Server/Logs tmp: type: emptyDir transcode: type: emptyDir media: type: nfs server: expanse.internal path: /mnt/tank/media globalMounts: - path: /media readOnly: true ================================================ FILE: .archive/kubernetes/plex/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: plex namespace: home-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'plex.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: plex port: 32400 weight: 100 ================================================ FILE: .archive/kubernetes/plex/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml ================================================ FILE: .archive/kubernetes/plex/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: plex namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m targetNamespace: home-system path: "./apps/base/home-system/plex/app" prune: true wait: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system ================================================ FILE: .archive/kubernetes/reloader/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app reloader namespace: kube-system spec: interval: 1h chartRef: kind: OCIRepository name: reloader namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: reloader: readOnlyRootFileSystem: true ================================================ FILE: .archive/kubernetes/reloader/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/reloader/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: reloader namespace: kube-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m targetNamespace: kube-system path: "./apps/base/kube-system/reloader/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system ================================================ FILE: .archive/kubernetes/sealed-secrets/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: sealed-secrets namespace: kube-system spec: interval: 1h chartRef: kind: OCIRepository name: sealed-secrets namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: networkPolicy: enabled: true metrics: serviceMonitor: enabled: true ================================================ FILE: .archive/kubernetes/sealed-secrets/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: sealed-secrets namespace: kube-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'sealed-secrets.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: sealed-secrets port: 8080 weight: 100 ================================================ FILE: .archive/kubernetes/sealed-secrets/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml ================================================ FILE: .archive/kubernetes/sealed-secrets/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: sealed-secrets namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m targetNamespace: kube-system path: "./apps/base/kube-system/sealed-secrets/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system dependsOn: - name: istiod namespace: istio-system ================================================ FILE: .archive/kubernetes/secret-store-csi-driver/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: secret-store-csi-driver namespace: kube-system spec: interval: 1h chartRef: kind: OCIRepository name: secret-store-csi-driver namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: logFormatJSON: true ## Install RBAC roles and bindings required for K8S Secrets syncing if true syncSecret: enabled: true ## Enable secret rotation feature [alpha] enableSecretRotation: true ================================================ FILE: .archive/kubernetes/secret-store-csi-driver/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/secret-store-csi-driver/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: secret-store-csi-driver namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m targetNamespace: kube-system path: "./apps/base/kube-system/secret-store-csi-driver/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system ================================================ FILE: .archive/kubernetes/snmp-exporter/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app snmp-exporter namespace: observability spec: interval: 1h chartRef: kind: OCIRepository name: snmp-exporter namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 dependsOn: - name: kube-prometheus-stack namespace: observability values: fullnameOverride: *app ================================================ FILE: .archive/kubernetes/snmp-exporter/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: observability resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/snmp-exporter/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: snmp-exporter namespace: observability spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m targetNamespace: observability path: "./apps/base/observability/snmp-exporter/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system ================================================ FILE: .archive/kubernetes/speedtest/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.jsonapiVersion: helm.toolkit.fluxcd.io/v2 apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: speedtest namespace: observability spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: image: repository: ghcr.io/miguelndecarvalho/speedtest-exporter tag: v3.5.4 resources: requests: cpu: 15m memory: 64M limits: memory: 128M service: main: ports: http: enabled: false metrics: enabled: true protocol: TCP port: 9798 ================================================ FILE: .archive/kubernetes/speedtest/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/speedtest/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: speedtest namespace: observability spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m targetNamespace: observability path: "./apps/base/observability/speedtest/app" prune: true wait: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system ================================================ FILE: .archive/kubernetes/tf-controller/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: tf-controller namespace: flux-system spec: interval: 1h chartRef: kind: OCIRepository name: tf-controller namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: beta.kubernetes.io/arch operator: In values: - amd64 ================================================ FILE: .archive/kubernetes/tf-controller/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/tf-controller/ks.yaml ================================================ --- # Note: Arm64 support is currently not supported https://github.com/weaveworks/tf-controller/issues/453 apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: tf-controller namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/flux-system/tf-controller/app" prune: true wait: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: flux-system ================================================ FILE: .archive/kubernetes/tf-controller/terraform/gcp/secret.enc.age.yaml ================================================ apiVersion: v1 kind: Secret metadata: name: gcp-creds namespace: flux-system data: key: ENC[AES256_GCM,data:qdGhNr5VLi+zCbeBzVwXo+ppH3wjWw6GJLHVDAfR0PFoD4yWi4B70tFiRTVujZDX1bariGS70e9L+HzI3q3LtZsMa3p/68HjPrEtLhjUxm7HiSpep0bJMbwhc/um+FZ3v4inoMK24UC54QP+nr0qXhqww3HYvqtkD7w2QriekYsfM0q8KgprZubvx6ZoAKUbSUKHsuUmSDL+79AfTV7pmQImU6eUawsJHGGkaoHybhJzT/fxrUlktV2fduY9Sf04wotGGQJ2SdeOlLAJonF1oquzGUfTUiO9cYiA69kM1oRn2VhF/OQIvfvG6ExkxvbGJP0jyEftlSF/F567RILI7PTRfIf8DIf8qN47TSzu3mbvMBcDLKPO5JzTuK6Vry+xcx7GsVouUvhSMaB3UkzxgkbhSXNfk9QR6M2m8RpIIBpbyWUECwH6xbCfAinSYGhgwIN18fOjdkmdXp9olwbfge+ksyH69ONNVvOzoA36gFeSD6MlXjOXKohXe7VQXzEkpdm3bP7dmVVAyBxHd7aBfcjNroPBuhgeFNtj4uG3GgKaB0MI+gHwx5kdXPzhywVHnDqgsRyZ6ru5FsGzX/aeIvtnSNd5Okp7Mm+YbZvF8JvBa6IRaMXRjE0VMuET3LnN0fYs8W9ChvPHD3ZLXeGBrzmM2UBAi55HMqtrrMKXY9ahVXDIxrkoFKxIkSEqw1Q3DeI4MJKQoKE8h1U73Jy2liUwiPl4sPC5HiFsR7cu2LkaD1YM9j4ps/edYHZjl7uSPBk2HgGXP6SaMoYRM1ZlgfXIGbJx74+8gm3gl6Db01KCJALIhcJ6sw8z/AZBMmO8lmxrV4iTYU9VaJjiYnZXGTgFZlrr56Z8PVbTok+PE0A08YRLPouBwuW2eSkhmwGSdX/Qp4End9sGseURYJf+LDPMdqaTBmW8KTZJ+3MgOXcJYKOQmjG5QCkP1CQDacVVyaBFGKELEHr0wD2bwVzokluC2z3OPEOvTbaE/kMlCXafTwq08fgN6pvNrqam1DXrEq1O4X3TZE3qfJagePYWg/tF+nbmA1HrZyNvO8IwHreaNA2BhX+MQDOJ9Qumu++7F9oIzwahv9eoSZJCeFynOcooEIEt4RW6GeZE2GGmFGsexGWbeeL1eXoS5SW8cs+Z7JF+kNmwABHyXnAPDKU1Z1GYQ+FMmqPVLWtaQU7u5In8DwrwhUbzsKaBzIAslwtEUJDA/6CTbUMfvYbY7J3EfwyssXun0Wl+SkEWEWHkwybQQvSWn2mjM7XWAfNk9iA9XBVBnnHwZG97Zjq6ozWnyw++Zi3/EFTyrrGiQNyqMZa5UHGgumVd2ArLCsoNZR8jdwYKfJJ/6KGutrJEosaJ1TUiNE9UHKX/4PA0qz7c27t71JhqckDJNtZd7ShXXlmLWO6cGuCtMeasFpOD7W8USEppC+JEOMtE+mQ9qdgLMu49z+FWuDl8w0dun8ZZxBlhv9ePIwZiGOnXnS2t7EQeSO8FEoTiKXwgfZOLt8hs8sFPF55Xz6GwaGytakuFniFpZru/cUM6DFh6lYy+2xrwznJ3rVSZYTf/zXO2YhjUY53v5EptOKgICaZKGgZ14KPNT9eH3j+YrGuCCinxDk3UKUTIz0UGtVaYp+g6bxTcNqYOgeAHaStbqh3eqvfyboSRrPFipH6HpEJgVVWuPF3b2UOjIO4m1Hj4F9gQ20SKoeKg8ZzTTrA6iMgPwICZ95aMpS425MrCzZYjInaWYeT9bGNBcGhbAJgHnkHWooMgW3+0OrXEJMM/rkLdCt3iFifp+lbhg6i1VZ22p0IDIhtybfCJpiJJdIaeTVEhU2xi4xbF0w2ZKb/p6eR+LUm9mlmbrXZMhauMG9gMCLqXPUrihX+v5TiauAB4Wu8/tQdS7SfHhc79xunCcvWI9c/NijMKgJOvRMjo/eNQDKvV9kWhNhj5IuIzh7i1XKRtQzIx1CM/uBfzd04DF2RdMUKguc1L9ryyUMnBGF8ly0xTfhciOU25tCk9MaPoSOyPEYy1nBu+80LS5sl7PnrrEEPGGBr5+hvU90UEY+62zINnrpPb3bkdTtkwOuna/j2tNCsgu31AomMXTFdWzDzgZhvXZ82I0Tvg+9YS2NO9MV5BglAfczBhRKSjY/AdoCp2kylk4k0ybdTNjAhqLpoinorKBT3/x9r1uvspxhhCnmk7preQzyVUkFqRw5WIT5eKvVb3tO6RN8rl6wVzsEtrTZJMHmQrHNu6G9w8/e4ildA2pFVhIBJH/Dq3A8ZV5BaYHfsclLqRfdsPJPBqCPvr+s3I66JDjKi2XmWa58htYPPN8iOuFxvrCszHoaRMksSl9EU11QVMUtfYCe6jEhJKp6xeetolhlgbQKvoIrOUXcXfOAF00IqyspCNwVXNeSvlMbKkpt7BP3qncITpCqiAyTYTC/cgS+nuk9LAoGkcr9XIqXaeZ0hdQBHKB4B7Au9//803aN+KFO5dBrcbaKpE1QyZrqVt6YLOEGrcNWAVmndBHL9MPM6KwJgWFePe+H8thfGqHKl6z18/cEeVYNG8A9vXpkmIDb82FxbsL5ZnfXKBZQoNnT8Vc21mITBsaqL0/F4rMMTle0Q9ws9TVa6ObKhf3U+B65QjwhycQedA/2yI+62eDvbSwI9t6yZBtiTJklRQXGyN+SJdnbRrf1rU+jKzSa5aefGw+yCq+JHRCv7/yXHfMLtT99k1mFsXBSpBOVu39I/6Sq36srCFija6uQAirdIy0XRWjEWQ5WqB/wef53wYuB2Xlx2J6+Gg7+rI8PW2COc6gnfB87LQM9VPfuuEKjTlXc09UkL0xzTCW1wXZgxBkXqHDecdjALgHvA4kkGMTZmX0lgvbLxZ2Z6ntRWZdf37ZED4E5+OTnW5w/3jfOoeQCbXYr0GQBWjd+iZzBFL4G0YXjmioDBuRyZkTSp944LiaiRgwryIYPqg0mlFa/OLCRN+XfIpTqmG378GQbrVFaqNLRbjHo3a5Qzeq6cIt1cXL/n47HPT8OMKM0oJXaP62/bfWWpXoDEpxNttc84tWh/ahS4SsSFQqtP03bohxwRG6zDXHH8JMV5JRU6heeV2q6/sGF2Hw79Yi/OnmWQl9O1fbQ5VSH9e3Ewh5rvI18ig3ZcXoXtUiqInlvNMJaLq/SKuDptYEyW3J3s+BU3Kjro7V9rrLn3g8kawjjN5ghrXfa84Jc0tvCoMSRF7toxaHNhFSIwiNkXSdVUOQVOyyXd72AdHr6Q94JF0/Z8oC6JaL/f4XyGLWyBtxn5lAG1Kq3F38eA5X1RsjOYZaMCqg07VmqEWOldqvFtelNQMUmv5u+zGRxeasVt3r1UPF2/cppCLo1qLitblDgzCAG+Nud2RR9C/KiC4O6M82G6VXt5akpkXbmBmSPY9dfHBPi4dcD7P6BXanZnmUFA1xaD4/6gNzco33IVaH+lDkF18hLZQf26TgrH7OTc7us/vytmCNkTfjMErASzKLyGBsSLpPhjkpcMRfURg47DIF8n8UoJOZzAF/gvBJjCye8YdFIQ0ZDJlLJ68rBcEAc5EzfQzh1Ipkz7N7GYfhs9L5TD0VCxzV6wyMi1InexmSwPfha15ULnbZ7qbs0REsDEYE6lkOWJJqd1WeMKJkU4/mqDu4+Y3EXWmKpEVsLBd+ZpkzqK+MPH5OHjzjR9nFjoVeYFes+vcPRE3Vs+fpEaxc5XccdAHYYkraihh3biM2N1KFSyqRAcscK5I7d80lF8gR6fS0Yf4wBeH7/RSFqBgLYX1mxGsYHDb75Kn3aa+t0cZRMpCQ8asbhilJ/AXgsM65AjaasSTR3SZUqwrMlkI9x4iVrHUuqWNM8tXlPP3fZ3SsyKmWAsokrPBSBIiMZOszfDSb/tCmL4+lajXkPl9YToB+yBe8t2Sgd2ED/eGQmE4I4kTK9CHj2P0LfMyMxq9STnmd5TCzvnqVE1GLfXf5uRbrSBHFtwUtW+KdGvgycYPAAnjrQhOcNTplHwMAvpzCNc238OUuILJnI6/oswzI8hwyiYImbR/AaKxpxcaGhjN3nIUc2+aE/YidWU8tIJQc049vSeKjEv1egMTWrejMd6rrFEPjhgdN2O20uM=,iv:GqDvJ/YmQ3d5UWclUb45nWT29fxBd/UFKA6dNZYW/tM=,tag:KZF6B10+fA69KRfgpJJEmw==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaMUplWU5qaCtnTFZQUFRq T0xRWWFuMmlqemt6YSswdCs1WnVrQlVIMGpNCndwQ3QweXRUb09TQjhTQ01wTldn djZzRXAwMU9kYmhRL1hmVDFlcVpIYUUKLS0tIHZ1YXF6RXVManZJMHVZK1FJV3d2 cG56R1VxS2JWVzViZkQrNjNUMEZ0Mk0KeFmBCFu3ZMXo0gU+3hK+AGvQzo0GOcLB JboZWaQRDbETJR9YL3k+Lyg6S7+7ab2wHuayRrEAN3l7rvvfqxSkAA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:43:27Z" mac: ENC[AES256_GCM,data:1AjpdP2JMhQAD5hby0FaTmX4P3wnwAFUd1od7I18hfqI8MJ39VITpvH8eEMBs8CBKnrLQ0cDTcmxj/sVpBKFKIzjJ3g11ZY/9U3/W4g3xKdZcIA3gmDwmLGh7X8WNtRmGmCIygs2I4jBCD+ZIILw5GEmXgAlzO1rjgPBiGpPil8=,iv:PlFJtVew4s4Sf8eVRvCQbg0XhpCy1bQnkE3tUo1iH5g=,tag:Dz9fA6KajDrYgOrHEJ2hEQ==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 ================================================ FILE: .archive/kubernetes/tf-controller/terraform/gcp/terraform.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/infra.contrib.fluxcd.io/terraform_v1alpha1.json apiVersion: infra.contrib.fluxcd.io/v1alpha1 kind: Terraform metadata: name: storage namespace: flux-system spec: interval: 12h path: ./terraform sourceRef: kind: OCIRepository name: flux-system namespace: flux-system runnerPodTemplate: spec: env: - name: GOOGLE_APPLICATION_CREDENTIALS valueFrom: secretKeyRef: name: gcp-creds key: key affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: beta.kubernetes.io/arch operator: In values: - amd64 ================================================ FILE: .archive/kubernetes/thanos/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: thanos namespace: observability spec: interval: 1h chartRef: kind: OCIRepository name: thanos namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: image: repository: thanosio/thanos tag: v0.41.0 queryFrontend: enabled: false query: replicaCount: 3 podAntiAffinityPreset: hard replicaLabel: - __replica__ dnsDiscovery: sidecarsService: kube-prometheus-stack-thanos-discovery sidecarsNamespace: observability # TODO: Re-enable once OpenEBS is configured on Talos compactor: enabled: false metrics: enabled: true serviceMonitor: enabled: true objstoreConfig: type: GCS config: bucket: 'thanos-raspbernetes-storage' valuesFrom: - kind: Secret name: thanos-objstore-config ================================================ FILE: .archive/kubernetes/thanos/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: thanos namespace: observability spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'thanos.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: thanos-query port: 9090 weight: 100 ================================================ FILE: .archive/kubernetes/thanos/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml - secret.enc.age.yaml ================================================ FILE: .archive/kubernetes/thanos/app/secret.enc.age.yaml ================================================ apiVersion: v1 kind: Secret metadata: name: thanos-objstore-config namespace: observability data: values.yaml: ENC[AES256_GCM,data:ZgEeR/6rpXeRz1EvAH7D4WX7CXL6z2zLWqmU4T4qfa/qVyRJTvVaRL+EmbbSsKlsDQ4+gSHpWg6aEUVz2I9qmuDfgb0aSfGNk55G3OMqv9d0c3D8/HmuiCBjFASn2e1VRMdhoD/PyhKVZR+HpNJVG5ZxZtwRpKfgRcF/EFgUNPW88lkhucEIoo6nrF7A9vQgkIbQ9Mw+EJGSayGIz96juPLY7etvMvRNKlxV9zG3WJxnack3iAQsj6a7K6M8gbhDycYnpdGCzNDcxHz481qLmWUGPArf3fS67hRU/NAJRHf2XicH2dkfL7IosddISGGusRTUA2DpRkvm3WuorGeE70Q3gFav4pKwz4SLekdKT3lxubVUHj9tmcwSCkuixi4DJWxXMEQr25i1Q0xNV1YcFsX7NYqwgLK3NujACIyHIBAa2lDEjoWZGe1qwDqZf63ZJvVIwfL9gZXI3JmP31AaZqdUX9kXatQP6cUs8MH7Se4B9pniqv7anbjxngsrhcjt+JI+alPQPRcBHSQWNik0Gg25TgyjS7dLx9g39TRy5RxtQpRhvjvri3ARb+GlUqKC+PohvvhnUTYNdqpKWB51B2+zngW/guLWlRYkq+wpEbu3quvjRnrOlfHVm0zrEMmIQFKS+tAc0Z99qC+Ai7N1cqmIqEDOhbBvn0+P+bA+XuzPaGHYCC3aK4MbruMiWl30e/pnjOxVI/1OpDgRghLPe4Mo3p3urwXT2Be42O2QvRkg3sz05pwLNcK9XvFpRQOoLvYAOLAsCva3WuytuHvxP6JDSeIsbTNTWeGz10KoOcZp2u6j4mrE+zHBxCxl2zkXhRVngueukee6cTRpLbJwfAzR2tvjswCN9UI1pJ9zmutuQbUrjbbuYxa1OC7BLBpBhMNRGL8LkwvZ7aFJa8Bp/L6Z5M3tr+T9tDibbLGNLKNXHhIwQ2eowUkRSegGZjT1zooolz5fNyINJeXZjw1p+PEQ08zHI4LxHUrEz/eII1ipeoRsukGvu5H9Ry+6vPXf7qE2ILR1G+yg+uIzh9bHnC4t1OIIo4udTOes5tQCdgNWFN/0GnCXHFt24pZ9hhovCukbiMTBiuA8/iUeyFa+G4Ott/jwz++1MjiwXAaVZ9Y6sxqpBbEbVLJ7liUJUZArQFxhJaECBMrhB5/A2Ce2VB0a7/zrDeHaFOPFIdoRDKUBjpia6VZl99QkSCDj6InzxsoOR1G0EjXEZ1FuNisB948kjh2hW1TFzU9wR+/EFQCWxaT7+rKNjjclpQto/3vlwl2V4qBwU0qAQgKrI/aUdDh7LpU2ml8toFj7aE/eLTFg6H0IEfFxGpaUeTTvCraqEWhiS5aePCB2g0xoqEQRIXoiXixnKsqVhar3KhlLgRTR0vRpcRtSAsrCPzbqZ1DdoErajzrhuslzyH2tflmoUtGA2/7soD3ut5ubQGoK7t7zEOfH2YmQcWbf5/9BCFXXXXxqFIiQ47TNpj1eIZ1n+2ZpfqDn4EIp6P6uRUWCSQf6YGbK3aBfdp6clys+4icPQeeEJO/1omlz3Vnm7cInP9vcnrU7kr/EJFyUiNtQANJ940KCTOk9gaDYcUSoxiLS3tSjYAahnIjJH/g53t88bMAhlV3vxVWfvveZA2svOyvGdiytDRbQtfoiRnQhB9fIOSuuQiICzaHTCrQrraifBsqZRehdRZ3yBSJqbpZUTeb5HlBpyaYBJxwT1CEyq+iMqyf6HK48T2EeGd88NN+ZpZbY/CP7wvLI4OCUqs6OqndY+DZU96RQO+9DI8BCtktDWXnbCJYUk/jWmoVSaYqq+hiSWp869r/M/0Owhn7o6q54H6/raT1sGUVu5ncla032EnmpRcU/r1gJ/ttoBaxO3R/mgdl/S7uKDQswJK/VeacxNd0aPNBAyY9Xf483spDuvoNOPirZ1XQuSy0VwQOFBvEm9w040dYYwnqLX7UxwKt3Jylzjd7FmibLGdJt6ZktV6UzA+X5tA65o+yz0j5m8GuiYHvTUDJoTenYlOK7eLJ4Sud6ynWHeUEoBbUVPHcu5n77F8Gwp7JUYFOfUAZRF2XABMjCljBs3VxsJfjkEq/34Ls3OIW2YYLPBxTtrCEnAuRIXk51eSDvrS62ndCZjyvetriM5ZPB1vW7gKtwRhyzi3iWCLDKPdp1/LQDN4WryfLTK+Dylh4SCGjdv8i5+x92eJNMk0IAdCiNaMrpcyN+SH32ias1h/sCGZzvm7ivxdyyCF/PuCNrj+dFtVZ7rtbaI6zbLsV5zgCdF+ccm/dGFdhPzsQT2f5fvOv2oaj1sM7aNrndwfOzhy5YnAlXtkZrVAleNd31CKywbD3UnukTct97pAjTXf6tcZ5OCeVlpRvAcybeMXvm8f0qq6TWgSslKRJ87Xa+I2abad43W5r0yduFiWQRVB81BzhPmiMqZbWf8HQSy3EZRZTOqxAZj1sl5LMUMuAyVw3rxxmfsX5YWfNOlCuqgcSbpCYqRB5D0UpFuCcvo5PYMpgdcrm8NEOSOFN2gVRKEPYO3sqOTGmMDBIK6ZTuMwd7NN9ED+bm5N7DmC0ci0Ubvj4YFbOVwU4pBRZejJs/nFS3D6dM4JTOaYdWnFfp6upYhpSzy+ysOurIocl2v0HTv2c0jlWvioFEh+HgDNzxQVK1gzn4WiGpBHE/t3vGHRb5NPz54TXSTPnfDe36sYzjNlNgWBrDuKNKSepLkfjHUpbZqVUPW6R9ltJ6Vm42TlqKEXA2F3ZGG1N0beDdSszTxmKZsohgHTDb8XZQzhs7bhiqVe2FMIwl9LMhj9hOVxLNgvVSfv9ynwDOzFVIb00lw7awco8h9ZCshJmY7X5zUtL9nrIYktj5Yl30u7sndYAeHufC4+q47cWYzYVFJ+xJcE09jEGlVrxQy0QEvU6+0y0JAEvljd5BvqvMewtZ0+fD6Hn0lGP5jSxmmjGmhfRIfB+TkEvdNkGlxI6bBWYx+mtDlBuMt4/qdNx+D9/WPxjOdPfm+bNAt36Z+JVeM2QDUJxOmeiJngIM/Jm7ZQImtvvgN9k/bGp36fOho10odZ/8ukJ09fx4bHTn8JqiB25VVEXBtxr3cLIffqsUAdDgfNki/OOg1Ccf7XXzvF7OZzQU3x2dzNGrRtU1r84ycE4hEu7xJm6laIEIAF8l6XTZW0sbtjx2bOuErC0WfG0UTwipvFt26SL++2ReRufDNs5A3o12Fdgcmk7C8p05oSgDMKm2tqDOKiYJGJmsbojAfuSM1YITiSOruGc7aUMQ2gH4qERA2w4YZOT01ZHETCtJNLkiTOVx0eOxdh8DSaBq6uE2eaJVURbar4PspoBym1XNdnku+YQrdlv1y5ahFYJh+JzgoDfGOXD7CZBVLh2Hvi7jtj8lO+c5edLWsDvinZLpsei0acSG5NC4IQMdZz4YYiuM/EGKD2EL3+kuSNYH1WAamwIMYKxRz7ItYPz2l1pPnpzSp283hhr2leklPL8w5WpXpmKLiho//Rbm+RKmep7B4c682ty2QIOaOPbfEACaRhCeBYSiQFHIh5O3hvFolI9FWPGlNBwvlJaNiXszgzycZBuhoBntcaLtDdAvrM1e/C6yfxxuZZ+j64/LZ8YDxcm9QmUxM0cUnm/CiJJT2Ks1hpEXjI33ILpduEjRXlK9vaurWvGMh3zOiMnUdfcUm7LEtFny7qT7Z8f6mefOfcFmGkAX+EdA/1XcPj+2zV0dmD5TakhJLE5hKIr8be5ECuYdR7HQY+xHUPTTtBiFB8GSCZGKUtxj3YNwJB7vEz10UE3EAvkwUGF8q01rvURiSr4fEv/O5owItd/lpBYtj2ciH7d1V518yvo+/H0VSsb+fbsfdOoSEnD6zjABgS2TWEGtOKzxEclkC9/2LEdJpb9YX548yqT9JEY5uiBxqyoL5dLADQvZ4wCj0zZSXWLFaWqTzCUmgnBCqpMpPh1t3cyBTWhQ8ovP5ThzKlD/OSvjZK+Abw9H6fQU3oug+cRFyaliSApL9Np9SD4qvTlO+0q3/Iy+JnnFCTHxIoTCxzbzH7d59Xfx81uiAgqkLp8xn/KrX+FJHxFtM0uVOhuaHjNkhWnnSfFlzgiTDW3JPfteYK1VMN7MSclxFajOlwYnr8JuJ0OQsM4jnV7GKOezgBnAESXrCNFgeKs1/lAE0V0YXzD37d4vVCiPFiLkGi22yGIMYkwTr/fes7jT+m3A1QQxfFvatHEPdWd3OqkbiBkDAn0BjV0SRSbsba7/Krnc21r7ZWM6d9YExJpTwCrjt0bkYAlk71Qkmqykxg5Kz836YcwJlbpYaA==,iv:nCNui8aF2uHeg3/8u5OPIR6kbxTz9khRz0Fa5JGpmu0=,tag:FtwpNID7fp67UQZdfO5JUA==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1QllRbktLampSbFp5OXpV RWJES2pQZDJ6MGlFaDVQSmtlRDhwUkUxSjFzClBlRzA4L0duc2JiWFhIVHBQQ290 ZFY4NWh4TVdxSzFrQ1M1Vzh2V0VrYmcKLS0tIGFQTTNZSldGeFJBMkppTjZlNjhr MEN6bnE5a2NGWUladXAwYWhNWjZrdzgKOuSYD9Vxwq5wrzHzaOnfpWG1ywGb9b+g 6Ee9jlkLjqmL+O6HJwKmhxLBpJ3kDPtQpitof2wOhza5sWRBho2ltA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:43:27Z" mac: ENC[AES256_GCM,data:OGGLV9DK9wyr6KA3+vEd1ONgxKkCVndosu82brHriHQT/TIFggQqquX09u+6IscNxhNv+7k1Z/p1Bryz2+f4QyHkSQSES0gF+w3bZQN4z226ct8b1w3SEt91PfkO5ZKbxCCV3zwT9JrsXlLQj1tNuIFkwOk4a8iD0/a6DGMtiNM=,iv:1Lc9MaSd7A0Vt7PhT5BmRESeAZAUGRa0iF5wwSJzbU4=,tag:R/b8A62o9B0doE0Ligyn1Q==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 ================================================ FILE: .archive/kubernetes/thanos/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: thanos namespace: observability spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/observability/thanos/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: observability dependsOn: - name: istiod namespace: istio-system ================================================ FILE: .archive/kubernetes/traefik-ingress/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - namespace.yaml ================================================ FILE: .archive/kubernetes/traefik-ingress/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: traefik-ingress labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: .archive/kubernetes/traefik-ingress/traefik/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: traefik namespace: traefik-ingress spec: interval: 1h chartRef: kind: OCIRepository name: traefik namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 dependsOn: - name: cert-manager namespace: network-system values: deployment: enabled: true replicas: 1 service: annotations: io.cilium/lb-ipam-ips: ${CLUSTER_LB_TRAEFIK_GATEWAY} spec: externalTrafficPolicy: Local autoscaling: enabled: true minReplicas: 1 maxReplicas: 3 logs: general: format: json level: INFO access: enabled: true format: json ingressClass: enabled: true isDefaultClass: false fallbackApiVersion: v1 tlsOptions: default: minVersion: VersionTLS12 maxVersion: VersionTLS13 sniStrict: true pilot: enabled: false experimental: plugins: enabled: true providers: kubernetesCRD: enabled: true allowCrossNamespace: true allowExternalNameServices: true resources: requests: memory: 128Mi cpu: 100m limits: memory: 512Mi ================================================ FILE: .archive/kubernetes/traefik-ingress/traefik/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: .archive/kubernetes/traefik-ingress/traefik/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: traefik namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/traefik-ingress/traefik/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: traefik-ingress ================================================ FILE: .archive/kubernetes/velero/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - namespace.yaml ================================================ FILE: .archive/kubernetes/velero/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: velero labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: .archive/kubernetes/velero/velero/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: velero namespace: velero spec: interval: 1h chartRef: kind: OCIRepository name: velero namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: # Resources allocated based on Robusta KRR output resources: requests: cpu: 100m memory: 128Mi limits: memory: 256Mi # Init containers to add to the Velero deployment's pod spec. At least one plugin provider image is required. initContainers: - name: velero-plugin-for-gcp image: velero/velero-plugin-for-gcp:v1.14.1@sha256:b92b9cc55947eb7e570c47643b37dc8de99686dfdf912a08c1462aa10f53e2f5 imagePullPolicy: IfNotPresent volumeMounts: - mountPath: /target name: plugins - name: velero-plugin-for-openebs image: openebs/velero-plugin:3.6.0 imagePullPolicy: IfNotPresent volumeMounts: - mountPath: /target name: plugins # Disable updateCRDs using the velero image # Upstream bitnami/kubectl doesn't support ARM64 images upgradeCRDs: false # Info about the secret to be used by the Velero deployment, which # should contain credentials for the cloud provider IAM account you've # set up for Velero. credentials: # Name of a pre-existing secret (if any) in the Velero namespace # that should be used to get IAM account credentials. Optional. existingSecret: cloud-credentials # Parameters for the `default` BackupStorageLocation and VolumeSnapshotLocation, # and additional server settings. configuration: # Parameters for the `default` BackupStorageLocation. See # https://velero.io/docs/v1.5/api-types/backupstoragelocation/ backupStorageLocation: - name: default provider: gcp bucket: raspbernetes-velero-backups # Backup schedules to create. schedules: daily-backup: schedule: "0 6 * * *" template: ttl: "120h" postRenderers: - kustomize: patches: - target: kind: BackupStorageLocation name: default patch: | - op: add path: /metadata/annotations/meta.helm.sh~1release-name value: velero - op: add path: /metadata/annotations/meta.helm.sh~1release-namespace value: velero ================================================ FILE: .archive/kubernetes/velero/velero/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - secret.enc.age.yaml ================================================ FILE: .archive/kubernetes/velero/velero/app/secret.enc.age.yaml ================================================ apiVersion: v1 kind: Secret metadata: name: cloud-credentials namespace: velero data: cloud: ENC[AES256_GCM,data:VGVj5ZuzhFqQZ+aUZ3cjkPjGw/J0ASclWErxTwhFAVoSGX902bOJ8X9Qw72hWr1EYReoZNJ60IEE0Q7YyfRn2XnOb89glteFvUeL2eZD5Wup94pCcwIgHXbf/XTrNsfKaSOHD/ioqQXgZ+AnSA14eVauf+fwjz3NKiRkx9rB7ik48Y+vnal6/4WeX07eQe/EAdJ0ZHb5CD2RcbC1Dy0EXowxk8dFMq8S0Jop56COf3PrBdaMzkvz4xgtRC4t8KxuVyW/GC68ZaOxYo4AMC5/KapmcCEHTQdXsv7eo5bf0b2tXCgUO/LVKM3ZVUcYmpmmClM2cRnDg5M0oRrsNAbdPDm5/lFRe8XNgNiPhxZ5dhcs1P4cza9nljjLFHtsvzjF9YqpQrmjmHvSKBHs9YbL16owK49uc2/TmQDjVsaMDEKhah0Y7D/2185XNUz1Jypw0VsTVFr/BgZOpQXAaipez5oUQmE5VQw3UcyYIkzXLGqEl1lNKorCB9uA/6nyYPnBemHwhtAovXCODGeR+eq8uWXRyZ9Cb0PCdDWJhooD957p2PY+K2hZU8RFlqFokpgAmi/grfxVAmAcIIQ7840Gdx/ICTaUN8g/K4YLFzdSGzocNGCcivMIbqev4Oc8M0aalt36UD/TLcqM3fvq45I3K+olMzwrJCct27MHv9NHZjkfdwgDzAUT1PdUO7FNnKFFL+JHh8pUXhzdSsC1NW90bMM/Q1M8hkTMj4PX42N7a4/Nen3UUb3x5IzTjS1y5P9z3MBQB1ns8V73FvGlDt5p/iggAAuZd9Jy1+WMmdkIbY3+3KZl6m4EVh2xp/5mw4xJUX/xeTZl2kyuYw66kQufyvE4BW4Vc+QtRHoCiTNkkHdRm4Ycv01wNl7OOkqVv8mKo1cJNEVyjwTHsvbv31oAa/6UVbn3Meb2lAUv2lH2+qTTdFIGJzehwtxQkeOPR8Wffe6m+CuN9xJ/8dF80T8HnU4P6nX0UgrHIserPW9V6BKExVdzsKc3cGn3dWYZDsvbqozw6BxvjcMYY51gNfhIf7MS6PwxDzilJND4T5+pN6d0RyvG094liR/CdtVRrw5GnEwlv4Nn6Z5a3WENhnrErQKO//PeHGiiVb6Cni2SFibJBv4gm53MC6TqOUi4iXzD6ghntEvoRq4gtEUlhpXOhd6yJjQ3mTk4KMak1iYS0oqRUumy1j9pNsYxPMiu65WU7LEi3Zu5xxkF7OmpDL6PMCH/NEz/92QX5OXyjNooTV+p9GTzs8SfuXgqRF5AGG4WnhUM4Oop9rsaOhz74l9Ln9BtX2olEDAvPKazu9bQoCle6AnmloZ/qXr0A2ZcTVTVksrg15oR00iLVkny/PON9duaE89wNJtVh360RiyTJuR8sAU0TB5lmHrmwaDtjG0dZ0kWePwHwUkSr5B6/4K5xKi8KE8Q5wdApGTpI8JjvjTkD19aFFfu4vTUJ14/2q2byLzvzj+EjzHt1dr5hkQb25JHolIFWPQLQI28YlPJBkU9OdGaJiVtCLAwIOOMX7Y8yrPRQN29Jn0SvafQoSAYG65RmPyGHF8o6UzwtzY1b8oJaFrM/A3X8h9BL1xYR6/cxanQLZ1IDLDXvmBtvdt1gcRKNNYytDT0M7BzGS/eRgddoPh5qr+KGTHBHTYWph8hltdv4UC6zgcRCaY3O4oCSNnLiruc6mHORHwtVq7ydCgaj3JKW6fwHVybPpgpvROc65YA6ozqNknYzRNfx+jU6gPFaCEPUa/yEFkIyIHjhA6hem0XmRzjU2E03laFFp8agTUX463V949zjiA6UQxLimn/87H3YRMwZJ7Rs5m2+hYQH4bOSNSGYlowuXkNYzyAelkmDFD5k9sMBnFJITxFrGDoP6lRHrjAEFN0NC3ibJmy8Z8S4quRO9trOczzl9lDOJpIGm1SRRymOQg7CDM76Z3SWHVw0psfh6iNCf91mtl4JEuigRfIUhxURaIcb33w9KM5m/eEzQdLrreMcp8L/2erRZyJhkg85AE2nBWp/iBaJX6bSJUg6100AmyFkEVoYHQBt/q782hACQWx5wf5zf8i4uL5Woi48aHODgd7dF5mNCJXcxILwImfO7oktRQGbgmClIZ4iETYheFcsNgteNK0+lzKVSCCD5iFrKseIFA3fvxxWdG8WXJe8AZ6Dop8/+ohYdzP7v1V9tsa9Fvqhe6xYhoPOwF9DTK6Fcpbq5HTI3MNS7/r1J4e1QRUg+2lQNYhUgaTpS7HmTOT54klKomugx+UhDCnRuI8I0feKg7seVrJEP23on3Fl+JYwiZJMiYAaAdEI6RjbjbQaoQJkrEMWfmUmmcTRTgXaFG59MOpK9K6D3v2MyYDlGSE5ME2xJgEEX5UPLjhItj+cL17j+x2SBnpi1RvvqrDdER+NtZlM8Sv91oESUNE4cH+UzfMGFjKqPZ1S4Xf5pC5esP0vtb4aOqf/xL2fZo9rzuqxlWk/VxADDKOP8lzgfvZErfNtjqCopA2md1gsnevvHxElH+99ow2y2W5qOh6wefwc3EjjSQMqbh4uJMtyKG6yTmqcYThwwto+4yLu4l3jacV2WO30PHPCHPZf4W7I8SIVdcxBB9oHxf5Jq8mNKa5uh8J65fmb5cLBN25NVqBZc+iPfsPU1GvrFmIUlXsR2CtWIlt9CTuujhqxP6MOIldYY7ZPoDfPApf2PL4V2WgTZ7g+0YNefpvjJVqWeDYXIdOsDcK6s2gbY9q4C/bQttj/z0spWsLFa7cdn4bNY3dCmKAl7C0Mjnpr4dYkDQ/ailxZbZYVTHm4KooV5uLAUNRRPL+fVVq2sf7+9Og6JzvR2NW3CoCejTstaZpgVXv/xcqLwb/B6YHe2JFpk+zXvEZIlllqt6z/SdhJPHKE6yayczW/kruXdyP2n7xW2V+yVoLfGQd4a6fAC0k4+85Dsk10KLX5F4RW23xc5iqC5jqPtqCWi2l60lP0DK+S3R+zAxaEq2QNoHwjwwqARfer9w8vx6DteO1qUCjt/K2wNQd0kTxMCFDAlBySpWlZKCqq2YXLuoo2IF7+zlQuDq0lGUh12Gj7ULqfvtALl9JpBpuB9SCDjznTuh/iJlDFeR7JyaPB1BFqpqerrmDzz0S3/q84KcMxvulprKyoJ9qq9B8RrQHdIt3WU2eR0Tvav8ugG9gnI67dyaKVEPQEqjwImotbIVTGyDI7ZXOM2lJtJwmagLjGUaEFwecmaBSFQlvgWF4ZsXj3dUD6jBfV/7kFdSY7fOPlIWGaHIQBwy5Ot4scsV5FY5wviwM8DnTlYkUkcLwfeMMo4tpg9CLasG5DUJGcbynFabwzklftjiZKSAuIFnWePloWVq+vWJCLbQHqYKsOl+L+4oDW6uFvddHfQJPh6WRQiQCe5z3JN4v3d6Trk0f3jbUI01ml7oXOC4YwnVbMBrNzglSgxHeUCIqU7kOEANgVfVVT2laaT1KztfRj2DNEmDxKhn+T6EqFEzmr4oO1O8Lem9OLxnolRXdi6b+fFIytJVjfuXof7H50OPuy1jN0G8NjjeuK7QGsD+q3EnOOcxc2jZfIlvq6B61TjJ27ENCr58YXknK62T6717aLu7jmqQDpyyQzOa/JSrgbBIZRbeE3AIHT+x8vJzcr56ucMB9ZT6p65t1OWiZr6R578iWYJSgQmZv7v9/HRBJWBPpkGBlnqvWDaanhjX6D43IW8HIWFmcWirehIETfU3Llg3yID1lJVLbsjWTlVhRF9+UK6adG4CAcHrqFprCpzuUO0IizQz6tVlqPg9hNz+gjFLUIbRFTMkpQMTaM5ZB4MKvrUl7oZxD6Z6vwdmMmsNGDguBhU29IANA8hTfOx/OaJmXvMjhsuObVgqiP+yoDiBey8DCSWpVBEkV27To6T0IBs+8PlxXCUb22+jp7APPwlUsJ9hi4kD0Mpf7M63ag+Yf2v+wHhP1plj6VZkV1lSsfA3HHnG4U8+GmQ/bt3IiCA0/iNLg8rjCq5PgxIYveI7sIK8UyfEy1n7f2y0pUtTe3j2owQ9SKrZ3qgwhEx7F5ZFSJIUOajEuuapucmibWX2+LAWBQbTUIkTAiBYsxfBtNOOn,iv:Un7Jm8IihNb1irOtGpfYTJLRZPtW/qEmDs3dEV0E2kE=,tag:bwZQ7/6DHwvPpN0z7UA5cw==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRUDNaazM0dm5Pc25HWkVy SHphZGd6MHh4eFdXS2JkRXpIR1RnOXJXU1M0CmpiKzlYcHhRZkFHaC9KdGl2d3Yy bkREZ0dva3U2TTZ5RGFOa1dQYmpDTzQKLS0tIDVrWmRubmtCTjVGMzAxQzRaWm5P WXRuTkUwUjI1Wno1VXNTTkttOEt3ZmsK1Fb/pr9i4uwHjsBJb1FR1kbHcgSky5f4 ug0n2v0el4MYUvEh9BrWQY7FkB78p1OsQVHo0gsRsiE/l4c3UbHVRQ== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:43:27Z" mac: ENC[AES256_GCM,data:1ZDxHHqd9RpOjlZKSDM5RQ/KtywK6f0uiQexNTFKQqVhKBNNP9zklcIXFsv98NLEZp19+aO7NDZVc+lRNr8neYczr/ugOvgZjD2WFfYJPKtBgS7vaPBOAydZaZdFkTmrzxLWXGrdprHCt1KA9wpS5uZH+hkoAnLd9mkgj6KK+Po=,iv:Cqf7PUwyuVg72ZBZ6bL2Cx8sB2EiGQZyaqWUSu4uV/s=,tag:esI9hD7XLMZthA0CDC9kiw==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 ================================================ FILE: .archive/kubernetes/velero/velero/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: velero namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./apps/base/velero/velero/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: velero ================================================ FILE: .archive/kubernetes/vmangos/README.md ================================================ # VMaNGOS - Vanilla WoW Server (1.12.1) ## Server Configuration - `mangosd.conf` and `realmd.conf` are managed as ConfigMaps in the HelmRelease - The realm address is set via `VMANGOS_REALMLIST_ADDRESS` env var on the database container - Game settings (player limit, max level, etc.) are in `mangosd.conf` ## Managing Users Accounts are managed via the mangosd server console. Attach to the running pod: ```bash kubectl attach -it -n game-servers deploy/vmangos-mangosd -c app ``` ### Creating an Account In the mangos console: ``` account create ``` ### Granting GM Privileges ``` account set gmlevel 3 ``` To detach from the console, press `Ctrl+P` then `Ctrl+Q`. ## Account Registration A web-based registration page is available at `https://emberstone.owncloud.ai`. Players can create accounts without needing console access. The registration page is deployed separately in `vmangos-registration/`. ## Connecting ### Requirements - World of Warcraft **1.12.1** client (patch 5875) - An account on the server ### Client Setup 1. Edit `WoW/Data/enUS/realmlist.wtf` (or `enGB`): ``` set realmlist wow.owncloud.ai ``` 2. Launch WoW and log in ================================================ FILE: .archive/kubernetes/vmangos/app/dnsendpoint.yaml ================================================ --- apiVersion: externaldns.k8s.io/v1alpha1 kind: DNSEndpoint metadata: name: vmangos-wow annotations: external-dns.alpha.kubernetes.io/external: "true" spec: endpoints: - dnsName: "wow.${CLUSTER_DOMAIN}" recordType: A targets: - "${EXTERNAL_IP}" ================================================ FILE: .archive/kubernetes/vmangos/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: vmangos namespace: game-servers spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 values: controllers: database: containers: app: image: repository: ghcr.io/mserajnik/vmangos-database tag: latest env: TZ: Australia/Melbourne MARIADB_USER: mangos MARIADB_PASSWORD: mangos MARIADB_ROOT_PASSWORD: password VMANGOS_REALMLIST_NAME: Emberstone VMANGOS_REALMLIST_ADDRESS: ${CLUSTER_LB_ENVOY_EXT_GATEWAY_API} VMANGOS_REALMLIST_PORT: "8085" VMANGOS_REALMLIST_ICON: "1" VMANGOS_REALMLIST_TIMEZONE: "0" VMANGOS_REALMLIST_ALLOWED_SECURITY_LEVEL: "0" VMANGOS_ENABLE_AUTOMATIC_WORLD_DB_CORRECTIONS: "1" VMANGOS_PROCESS_CUSTOM_SQL: "1" probes: liveness: enabled: true custom: true spec: exec: command: ['healthcheck.sh', '--connect', '--innodb_initialized'] periodSeconds: 30 timeoutSeconds: 3 failureThreshold: 3 readiness: enabled: true custom: true spec: exec: command: ['healthcheck.sh', '--connect', '--innodb_initialized'] periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 startup: enabled: true custom: true spec: exec: command: ['healthcheck.sh', '--connect', '--innodb_initialized'] periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 30 resources: requests: cpu: 100m memory: 512Mi limits: memory: 2Gi realmd: initContainers: wait-db: image: repository: busybox tag: latest command: ['sh', '-c', 'until nc -z vmangos-database 3306; do sleep 2; done'] containers: app: image: repository: ghcr.io/mserajnik/vmangos-server tag: "5875" command: ["realmd"] env: TZ: Australia/Melbourne probes: liveness: enabled: true custom: true spec: tcpSocket: port: 3724 periodSeconds: 30 timeoutSeconds: 3 failureThreshold: 3 readiness: enabled: true custom: true spec: tcpSocket: port: 3724 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 startup: enabled: true custom: true spec: tcpSocket: port: 3724 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 30 resources: requests: cpu: 10m memory: 64Mi limits: memory: 256Mi mangosd: pod: terminationGracePeriodSeconds: 120 initContainers: wait-db: image: repository: busybox tag: latest command: ['sh', '-c', 'until nc -z vmangos-database 3306; do sleep 2; done'] containers: app: image: repository: ghcr.io/mserajnik/vmangos-server tag: "5875" command: ["mangosd"] tty: true stdin: true env: TZ: Australia/Melbourne probes: liveness: enabled: true custom: true spec: tcpSocket: port: 8085 periodSeconds: 30 timeoutSeconds: 3 failureThreshold: 3 readiness: enabled: true custom: true spec: tcpSocket: port: 8085 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 startup: enabled: true custom: true spec: tcpSocket: port: 8085 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 30 resources: requests: cpu: 500m memory: 1Gi limits: memory: 4Gi service: database: controller: database ports: mysql: port: 3306 auth: controller: realmd ports: auth: port: 3724 world: controller: mangosd ports: world: port: 8085 soap: controller: mangosd ports: soap: port: 7878 configMaps: mangosd-config: data: mangosd.conf: | DataDir = "/opt/vmangos/storage/data" LogsDir = "/opt/vmangos/storage/logs" HonorDir = "/opt/vmangos/storage/honor" LoginDatabase.Info = "vmangos-database;3306;mangos;mangos;realmd" WorldDatabase.Info = "vmangos-database;3306;mangos;mangos;mangos" CharacterDatabase.Info = "vmangos-database;3306;mangos;mangos;characters" LogsDatabase.Info = "vmangos-database;3306;mangos;mangos;logs" RealmID = 1 WorldServerPort = 8085 BindIP = "0.0.0.0" WowPatch = 10 PlayerLimit = 100 MaxPlayerLevel = 60 CharactersPerRealm = 10 WorldAvailable = 1 Anticheat.Enable = 0 Rate.XP.Kill = 3 Rate.XP.Quest = 3 Rate.XP.Explore = 3 Rate.Drop.Item.Poor = 3 Rate.Drop.Item.Normal = 3 Rate.Drop.Item.Uncommon = 3 Rate.Drop.Item.Rare = 2 Rate.Drop.Item.Epic = 1 Rate.Drop.Money = 3 Rate.Reputation.Gain = 3 MailDeliveryDelay = 0 SOAP.Enabled = 1 SOAP.IP = 0.0.0.0 SOAP.Port = 7878 PlayerBot.UpdateMs = 1000 PlayerBot.ShowInWhoList = 1 PartyBot.AutoEquip = 1 BattleBot.AutoJoin = 1 AHBot.Enable = 1 realmd-config: data: realmd.conf: | [RealmdConf] ConfVersion=2024091701 LoginDatabaseInfo = "vmangos-database;3306;mangos;mangos;realmd" LogsDir = "/opt/vmangos/storage/logs" PatchesDir = "./patches" MaxPingTime = 30 RealmServerPort = 3724 BindIP = "0.0.0.0" TrustedProxyServers = "" PidFile = "" LogLevel.Console = 2 LogLevel.File = 2 LogTime = 0 LogFile = "Realmd.log" LogTimestamp = 0 LogFileLevel = 0 UseProcessors = 0 ProcessPriority = 1 WaitAtStartupError = 0 MinRealmListDelay = 1 RealmsStateUpdateDelay = 20 WrongPass.MaxCount = 0 WrongPass.BanTime = 600 WrongPass.BanType = 0 ReqEmailVerification = 0 ReqEmailSince = 0 GeoLocking = 0 StrictVersionCheck = 1 SendMail = 0 MailFrom = "" MailCertChecks = 1 SendGridKey = "" GeolockGUID = "" MaxSessionDuration = 300 persistence: database: existingClaim: vmangos-database advancedMounts: database: app: - path: /var/lib/mysql data: existingClaim: vmangos-data advancedMounts: mangosd: app: - path: /opt/vmangos/storage/data readOnly: true mangosd-config: type: configMap name: vmangos-mangosd-config advancedMounts: mangosd: app: - path: /opt/vmangos/config/mangosd.conf subPath: mangosd.conf realmd-config: type: configMap name: vmangos-realmd-config advancedMounts: realmd: app: - path: /opt/vmangos/config/realmd.conf subPath: realmd.conf mangosd-logs: type: emptyDir advancedMounts: mangosd: app: - path: /opt/vmangos/storage/logs realmd-logs: type: emptyDir advancedMounts: realmd: app: - path: /opt/vmangos/storage/logs honor: type: emptyDir advancedMounts: mangosd: app: - path: /opt/vmangos/storage/honor ================================================ FILE: .archive/kubernetes/vmangos/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - pvc-database.yaml - pvc-data.yaml - tcproutes.yaml - dnsendpoint.yaml - replicationsource.yaml - volsync-externalsecret.yaml ================================================ FILE: .archive/kubernetes/vmangos/app/pvc-data.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: vmangos-data namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: ceph-block ================================================ FILE: .archive/kubernetes/vmangos/app/pvc-database.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: vmangos-database namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: ceph-block ================================================ FILE: .archive/kubernetes/vmangos/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: vmangos-database spec: sourcePVC: vmangos-database trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: vmangos-database-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: .archive/kubernetes/vmangos/app/tcproutes.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/tcproute_v1alpha2.json apiVersion: gateway.networking.k8s.io/v1alpha2 kind: TCPRoute metadata: name: vmangos-auth spec: parentRefs: - name: envoy-external namespace: network-system sectionName: vmangos-auth rules: - backendRefs: - name: vmangos-auth port: 3724 --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/tcproute_v1alpha2.json apiVersion: gateway.networking.k8s.io/v1alpha2 kind: TCPRoute metadata: name: vmangos-world spec: parentRefs: - name: envoy-external namespace: network-system sectionName: vmangos-world rules: - backendRefs: - name: vmangos-world port: 8085 ================================================ FILE: .archive/kubernetes/vmangos/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: vmangos-database-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: vmangos-database-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: .archive/kubernetes/vmangos/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: vmangos namespace: game-servers spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 10m path: "./apps/base/game-servers/vmangos/app" prune: true wait: true sourceRef: kind: OCIRepository name: flux-system namespace: flux-system dependsOn: - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: game-servers ================================================ FILE: .claude/agents/README.md ================================================ # Claude Agents for GitOps Operations This directory contains specialized Claude agent definitions for Kubernetes and DevOps/Platform engineering tasks in this FluxCD GitOps repository. ## Available Agents | Agent | File | Purpose | |-------|------|---------| | **Flux Troubleshooter** | [flux-troubleshooter.md](./flux-troubleshooter.md) | Diagnose and resolve FluxCD resource issues | | **GitOps Deployer** | [gitops-deployer.md](./gitops-deployer.md) | Deploy applications following repository patterns | | **Security Auditor** | [security-auditor.md](./security-auditor.md) | Security review of manifests and configurations | | **Dependency Mapper** | [dependency-mapper.md](./dependency-mapper.md) | Map and validate Flux dependency chains | | **Resource Optimizer** | [resource-optimizer.md](./resource-optimizer.md) | Optimize resource requests/limits and autoscaling | ## How to Use These Agents ### Method 1: Reference Agent in Prompts When working with Claude Code, reference an agent by name: ``` "As the Flux Troubleshooter agent, diagnose why the prometheus HelmRelease in the observability namespace is failing to reconcile." ``` ``` "As the GitOps Deployer agent, deploy Grafana Tempo to the observability namespace using the official Grafana OCI Helm chart." ``` ### Method 2: Use Agent Context Claude Code will automatically use agent context when the task matches the agent's expertise: ``` "Why is my prometheus HelmRelease failing?" → Claude may automatically use Flux Troubleshooter agent context ``` ``` "Add Redis to the database namespace" → Claude may automatically use GitOps Deployer agent context ``` ### Method 3: Explicit Agent Mode Some Claude Code interfaces may support explicit agent selection: ``` /agent flux-troubleshooter Diagnose prometheus reconciliation failure ``` ## Quick Start Examples ### Deploy New Application ``` As the GitOps Deployer agent: Deploy Grafana Mimir to the observability namespace. - Use official Grafana OCI Helm chart - Configure S3 backend (use existing thanos bucket) - Enable distributed mode with 3 replicas - Create SOPS-encrypted secret for S3 credentials ``` **Expected Output:** - Complete directory structure - All required YAML manifests - SOPS encryption commands - Deployment instructions ### Troubleshoot Flux Issue ``` As the Flux Troubleshooter agent: The kube-prometheus-stack HelmRelease is stuck in "Upgrade Failed". Diagnose the root cause and provide remediation steps. ``` **Expected Output:** - Status analysis - Root cause identification - Step-by-step remediation - Verification commands ### Security Audit ``` As the Security Auditor agent: Audit all manifests in the network-system namespace for security issues. Focus on secret management, pod security standards, and RBAC. ``` **Expected Output:** - Structured security report - Severity-rated issues - Remediation steps for each issue - Compliance summary ### Map Dependencies ``` As the Dependency Mapper agent: Map the complete dependency chain for all applications in the istio-system and istio-ingress namespaces. ``` **Expected Output:** - Dependency tree visualization - Reconciliation order - Validation results - Optimization recommendations ### Optimize Resources ``` As the Resource Optimizer agent: Analyze the observability namespace and recommend resource optimizations. Provide cost savings estimates and HPA configurations. ``` **Expected Output:** - Current vs actual usage analysis - Optimized resource recommendations - HPA configurations - Cost savings estimates ## Common Workflows ### 1. Complete Application Deployment Chain multiple agents for end-to-end deployment: ``` Step 1 - Deploy: As the GitOps Deployer agent, deploy to Step 2 - Secure: As the Security Auditor agent, audit / Step 3 - Validate: As the Dependency Mapper agent, verify dependencies Step 4 - Monitor: As the Flux Troubleshooter agent, verify reconciliation ``` ### 2. Incident Response ``` Step 1 - Diagnose: As the Flux Troubleshooter agent, diagnose Step 2 - Dependencies: As the Dependency Mapper agent, check if dependencies are healthy Step 3 - Optimize: As the Resource Optimizer agent, check for resource exhaustion ``` ### 3. Security Hardening ``` Step 1 - Audit: As the Security Auditor agent, audit all namespaces Step 2 - Validate: Review and apply security recommendations ``` ## Agent Capabilities Summary ### Flux Troubleshooter ✅ Diagnose HelmRelease failures ✅ Diagnose Kustomization failures ✅ Check controller health ✅ Trace dependency issues ✅ Provide remediation steps ### GitOps Deployer ✅ Create application directory structure ✅ Generate HelmRelease + OCIRepository ✅ Configure Flux Kustomizations ✅ Set up SOPS secrets ✅ Create cluster overlays ✅ Follow repository conventions ### Security Auditor ✅ Scan for unencrypted secrets ✅ Validate pod security standards ✅ Review RBAC configurations ✅ Check network policies ✅ Identify privilege escalation ✅ Verify SOPS encryption ### Dependency Mapper ✅ Build dependency graphs ✅ Detect circular dependencies ✅ Calculate reconciliation order ✅ Validate cross-namespace refs ✅ Suggest optimizations ✅ Identify critical path ### Resource Optimizer ✅ Analyze resource usage ✅ Recommend requests/limits ✅ Configure HPA ✅ Calculate cost savings ✅ Right-size workloads ✅ Identify over/under-provisioning ## Repository Context All agents have access to repository-specific context: - **Cluster**: cluster-00 (default) - **Branch**: main (auto-reconciled by Flux) - **Bootstrap**: Flux Operator (not traditional `flux bootstrap`) - **Charts**: OCIRepository (not HelmRepository) - **Secrets**: SOPS with PGP + Age + GCP KMS - **SOPS PGP**: `0635B8D34037A9453003FB7B93CAA682FF4C9014` - **SOPS Age**: `age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t` ## Agent Development ### Creating New Agents To create a new agent: 1. **Create agent file**: `.claude/agents/my-agent.md` 2. **Define expertise**: List capabilities and focus area 3. **Document workflow**: Step-by-step process the agent follows 4. **Provide examples**: Commands, YAML snippets, expected outputs 5. **Include context**: Repository-specific patterns and conventions 6. **Test**: Validate agent with real repository tasks ### Agent Template ```markdown # [Agent Name] Agent You are a [domain] expert specializing in [specific focus]. ## Expertise - List capabilities - Specific skills - Tools and technologies ## Workflow When [task description], follow this approach: 1. **Step 1**: Description 2. **Step 2**: Description 3. **Step 3**: Description ## Common Patterns [Provide patterns, examples, code snippets] ## Repository-Specific Context [Repository conventions and specifics] ## Output Format [Expected output structure] ``` ## Best Practices 1. **Be Specific**: Provide clear context (namespace, app name, requirements) 2. **Iterate**: Review agent output, refine with follow-up questions 3. **Validate**: Always validate agent-generated code before applying 4. **Chain Agents**: Use multiple agents for complex workflows 5. **Learn**: Study agent outputs to understand GitOps patterns 6. **Customize**: Fork and modify agents for your specific needs ## Limitations Agents are guidance tools, not autonomous actors: - ⚠️ **Always review** generated YAML manifests - ⚠️ **Test in staging** before production - ⚠️ **Validate** against cluster policies - ⚠️ **Understand** the recommendations before applying - ⚠️ **Monitor** after applying changes ## Integration Points ### With FluxCD - Agents understand Flux Operator patterns - Generate FluxCD-compatible manifests - Follow repository's Flux conventions ### With SOPS - Agents use repository SOPS configuration - Generate properly encrypted secrets - Configure Flux decryption automatically ### With Kustomize - Agents follow base/overlay pattern - Generate valid Kustomize patches - Respect repository structure ### With Helm - Agents use OCIRepository (not HelmRepository) - Follow HelmRelease conventions - Apply repository-wide defaults ## Support - **Repository Guide**: See [/CLAUDE.md](../../CLAUDE.md) - **Documentation**: See [/docs](../../docs/) - **Task Automation**: See [/.taskfiles](../../.taskfiles/) - **FluxCD Docs**: https://fluxcd.io ## Contributing Improvements welcome: 1. Enhance existing agent workflows 2. Add new agents for common tasks 3. Improve examples and documentation 4. Share success stories and patterns Submit PRs with agent updates or create issues for new agent ideas. ================================================ FILE: .claude/agents/dependency-mapper.md ================================================ # Dependency Mapper Agent You are a FluxCD dependency analysis expert specializing in mapping and validating Kustomization dependency chains. ## Expertise - Build dependency directed acyclic graphs (DAGs) - Detect circular dependencies - Validate dependency order and reconciliation sequences - Suggest optimal dependency chains - Identify missing or incorrect dependencies - Calculate reconciliation timing ## Analysis Workflow ### 1. Extract Dependencies Get all Kustomizations and their dependencies: ```bash # List all Kustomizations with dependencies kubectl get kustomization -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.namespace}{"\t"}{.spec.dependsOn[*].name}{"\n"}{end}' | column -t # Get specific Kustomization dependencies kubectl get kustomization -n flux-system -o yaml | yq '.spec.dependsOn' ``` ### 2. Build Dependency Graph Create a directed graph where: - **Nodes**: Kustomization resources - **Edges**: `dependsOn` relationships - **Direction**: A → B means "B depends on A" ### 3. Validate Graph Properties Check for: - **Circular dependencies**: Invalid, will prevent reconciliation - **Missing dependencies**: Referenced Kustomization doesn't exist - **Cross-namespace references**: Valid but ensure namespace in `dependsOn` - **Orphaned resources**: Kustomizations with no dependents or dependencies ### 4. Calculate Reconciliation Order Use topological sort to determine: 1. **Level 0**: No dependencies (can reconcile immediately) 2. **Level 1**: Depends only on Level 0 3. **Level N**: Depends on Level N-1 or lower Resources at the same level can reconcile in parallel. ## Common Dependency Patterns ### Core Infrastructure Dependencies ``` cert-manager (network-system) └── Ingress Controllers └── Applications with Ingress kube-prometheus-stack CRDs (observability) └── kube-prometheus-stack Operator └── ServiceMonitor/PodMonitor resources Istio Base (istio-system) └── Istio Istiod └── Istio Gateway └── VirtualServices/DestinationRules ``` ### Storage Dependencies ``` Rook-Ceph Operator (rook-ceph) └── Rook-Ceph Cluster └── StorageClass/CephBlockPool └── Applications with PVCs ``` ### Common Patterns by System **Network System:** - cert-manager (no deps) - external-dns (depends on cert-manager) - ingress-nginx (depends on cert-manager) - oauth2-proxy (depends on cert-manager, ingress-nginx) **Observability:** - prometheus-operator-crds (no deps) - kube-prometheus-stack (depends on CRDs) - grafana (depends on prometheus) - loki (no deps, independent) - thanos (depends on prometheus) **Security System:** - kyverno-crds (no deps) - kyverno (depends on CRDs) - gatekeeper (no deps) - falco (no deps) **Istio:** - istio-base (no deps) - istio-istiod (depends on istio-base) - istio-gateway (depends on istio-istiod) - kiali (depends on istio-istiod, prometheus) ## Dependency Validation Rules ### Valid Dependencies ✅ **Namespace before resources:** ```yaml # Good: namespace created first dependsOn: - name: observability-namespace ``` ✅ **CRDs before operators:** ```yaml # Good: CRDs installed first dependsOn: - name: prometheus-operator-crds ``` ✅ **Operators before instances:** ```yaml # Good: operator ready before creating instances dependsOn: - name: kube-prometheus-stack ``` ### Invalid Dependencies ❌ **Circular dependency:** ```yaml # App A depends on App B # App B depends on App A # Result: Neither can reconcile ``` ❌ **Missing dependency:** ```yaml # References non-existent Kustomization dependsOn: - name: non-existent-kustomization ``` ❌ **Wrong namespace:** ```yaml # Missing namespace field for cross-namespace dep dependsOn: - name: cert-manager # Incorrect # Should be: dependsOn: - name: cert-manager namespace: flux-system ``` ### Unnecessary Dependencies ⚠️ **Over-specification:** ```yaml # Grafana doesn't need to depend on Loki # They can reconcile independently dependsOn: - name: loki # Unnecessary ``` ## Analysis Commands ### View Dependency Status ```bash # Check if dependencies are ready flux get kustomization -A # Watch reconciliation order flux get kustomization -A --watch # Check specific dependency kubectl get kustomization -n flux-system -o yaml | yq '.status.conditions' ``` ### Find Blocking Dependencies ```bash # Find Kustomizations that are not ready kubectl get kustomization -A -o json | jq -r '.items[] | select(.status.conditions[] | select(.type=="Ready" and .status!="True")) | .metadata.name' # Check what's waiting kubectl get kustomization -A -o json | jq -r '.items[] | select(.status.conditions[] | select(.reason=="DependencyNotReady")) | "\(.metadata.name) waiting on \(.status.conditions[].message)"' ``` ## Output Format Provide dependency analysis in this format: ``` DEPENDENCY TREE: [namespace/system] ================================ Level 0 (No dependencies - can reconcile immediately): - cert-manager (network-system) - prometheus-operator-crds (observability) - istio-base (istio-system) Level 1 (Depends on Level 0): - kube-prometheus-stack (observability) → depends on: prometheus-operator-crds - istio-istiod (istio-system) → depends on: istio-base - external-dns (network-system) → depends on: cert-manager Level 2 (Depends on Level 1 or below): - prometheus (observability) → depends on: kube-prometheus-stack - istio-gateway (istio-ingress) → depends on: istio-istiod RECONCILIATION ORDER: 1. [Parallel] cert-manager, prometheus-operator-crds, istio-base 2. [Parallel] kube-prometheus-stack, istio-istiod, external-dns 3. [Parallel] prometheus, istio-gateway VALIDATION RESULTS: ✓ No circular dependencies detected ✓ All referenced Kustomizations exist ✓ Cross-namespace dependencies valid ⚠ Warning: [specific warning] RECOMMENDATIONS: 1. [Specific recommendation with justification] 2. [Another recommendation] CRITICAL PATH: istio-base → istio-istiod → istio-gateway (longest chain: 3 levels) ``` ## Optimization Recommendations ### Reduce Unnecessary Dependencies If two resources can reconcile independently, don't create a dependency: ```yaml # Bad: Grafana and Loki are independent grafana: dependsOn: - name: loki # Good: Let them reconcile in parallel grafana: dependsOn: - name: kube-prometheus-stack # Only if Grafana needs Prometheus datasource loki: dependsOn: [] # No dependencies ``` ### Parallelize Reconciliation Group independent resources to reconcile simultaneously: ```yaml # All these can start in parallel if they share dependencies - prometheus - grafana - loki - jaeger # All depend on cert-manager, can reconcile together after cert-manager is ready ``` ### Critical Path Optimization Identify the longest dependency chain (critical path) and optimize: 1. Remove unnecessary dependencies in the chain 2. Ensure critical path components have higher reconciliation frequency 3. Consider pre-installing critical path components during bootstrap ## Troubleshooting Dependency Issues ### Kustomization Stuck on DependencyNotReady ```bash # Check which dependency is not ready kubectl get kustomization -n flux-system -o yaml | yq '.status.conditions[] | select(.reason=="DependencyNotReady")' # Check the dependency's status kubectl get kustomization -n flux-system -o yaml | yq '.status.conditions' ``` ### Circular Dependency Detection If Kustomizations are never becoming ready: 1. Map all `dependsOn` relationships 2. Look for cycles: A → B → C → A 3. Break the cycle by removing one dependency 4. Force reconcile: `flux reconcile kustomization -n flux-system` ### Missing Dependency ```bash # List all Kustomizations kubectl get kustomization -A # Check if referenced dependency exists kubectl get kustomization -n flux-system ``` ## Repository-Specific Context This repository: - Uses **flux-system** namespace for all Kustomization resources - Follows pattern: `[system-name]-[app-name]` for Kustomization names - Common base dependencies: cert-manager, CRD kustomizations - Bootstrap order defined in `kubernetes/clusters/cluster-00/` Always reference resources with `namespace/name` format for clarity. ================================================ FILE: .claude/agents/flux-troubleshooter.md ================================================ # Flux Troubleshooter Agent You are a FluxCD troubleshooting expert specializing in diagnosing and resolving FluxCD resource issues. ## Expertise - Analyze Flux resource status and conditions (HelmReleases, Kustomizations, OCIRepositories, GitRepositories) - Check controller health and logs - Trace dependency chains - Identify common reconciliation failures - Suggest remediation steps ## Troubleshooting Workflow When analyzing Flux issues, follow this systematic approach: 1. **Check Resource Status** - Get resource with `kubectl get -n -o yaml` - Examine `.status.conditions` for error messages - Check `.status.lastAttemptedRevision` vs `.status.lastAppliedRevision` 2. **Verify Dependencies** - Review `spec.dependsOn` in Kustomizations - Ensure all dependencies are healthy and ready - Check if dependency chain is correct 3. **Validate Source Resources** - For HelmReleases: Check referenced OCIRepository or HelmRepository - For Kustomizations: Check referenced GitRepository or OCIRepository - Verify source is reconciling successfully 4. **Check SOPS Decryption** - If secrets involved, verify decryption config in Kustomization - Ensure `sops-gpg` or `sops-age` secret exists in namespace - Check for decryption errors in kustomize-controller logs 5. **Review Controller Logs** - `kubectl logs -n flux-system deploy/helm-controller --since=30m` - `kubectl logs -n flux-system deploy/kustomize-controller --since=30m` - `kubectl logs -n flux-system deploy/source-controller --since=30m` 6. **Examine Managed Resources** - Check `.status.inventory` for list of managed resources - Verify each managed resource exists and is healthy - Look for resource conflicts or stuck finalizers 7. **Provide Root Cause Analysis** - Identify the specific failure point - Explain why it's failing - Provide actionable remediation steps with exact commands ## Common Issues & Solutions ### HelmRelease Failures **CRD Version Mismatch:** - Update CRDs to required version - Force reconcile: `flux reconcile helmrelease -n ` **Values Validation Error:** - Check values.yaml against chart schema - Verify variable substitution is working **Chart Not Found:** - Verify OCIRepository URL is correct - Check chart version exists: `helm show chart oci://` ### Kustomization Failures **Decryption Failed:** - Verify SOPS secret exists: `kubectl get secret -n flux-system sops-gpg` - Check encryption fingerprints match **Dependency Not Ready:** - Check dependency status - Ensure dependency order is correct **Source Not Found:** - Verify GitRepository is reconciling - Check branch/tag/commit exists ## Repository-Specific Context This repository uses: - **Flux Operator** (not traditional `flux bootstrap`) - **OCIRepository** for Helm charts (not HelmRepository) - **SOPS** encryption with PGP + Age + GCP KMS - **Cluster**: cluster-00 (default) - **Branch**: main (auto-reconciled) ## Output Format Always provide: 1. **Status Summary**: Current state of the resource 2. **Root Cause**: Specific reason for failure 3. **Remediation Steps**: Exact commands to fix the issue 4. **Verification**: How to confirm the fix worked Use code references with `file:line` format when referencing manifests. ================================================ FILE: .claude/agents/gitops-deployer.md ================================================ # GitOps Application Deployer Agent You are a GitOps application deployment expert specializing in FluxCD-based deployments following this repository's patterns. ## Expertise - Generate complete application structures following repository conventions - Create HelmRelease + OCIRepository manifests - Set up SOPS-encrypted secrets - Configure Kustomizations with proper dependencies - Create overlays for cluster-specific customization - Apply repository naming and labeling conventions ## Deployment Workflow When deploying a new application: 1. **Create Directory Structure** ``` kubernetes/apps/base/[system-name]/[app-name]/ ├── app/ │ ├── helmrelease.yaml │ ├── kustomization.yaml │ ├── ocirepository.yaml │ ├── values.yaml │ └── secret.enc.yaml (if needed) ├── ks.yaml └── namespace.yaml (if new namespace) ``` 2. **System Categories** - `kube-system`: Core Kubernetes components - `network-system`: Networking (cert-manager, external-dns, ingress) - `observability`: Monitoring stack (Prometheus, Grafana, Loki, Thanos) - `security-system`: Security (Kyverno, Falco, Gatekeeper) - `istio-system` & `istio-ingress`: Service mesh - `home-system`: Home automation & media apps - `rook-ceph`: Storage cluster - `database`: Database workloads 3. **Create OCIRepository** ```yaml apiVersion: source.toolkit.fluxcd.io/v1beta2 kind: OCIRepository metadata: name: [app-name]-chart namespace: [namespace] spec: url: oci://[registry]/[chart-name] interval: 1h ref: semver: ">=X.Y.Z" # or tag: "X.Y.Z" ``` 4. **Create HelmRelease** ```yaml apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: [app-name] spec: chartRef: kind: OCIRepository name: [app-name]-chart namespace: [namespace] interval: 30m timeout: 10m valuesFrom: - kind: ConfigMap name: [app-name]-values optional: true - kind: Secret name: [app-name]-secrets optional: true values: # Minimal required values ``` 5. **Create Flux Kustomization (ks.yaml)** ```yaml apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: [system-name]-[app-name] namespace: flux-system labels: substitution.flux/enabled: "true" spec: interval: 10m path: ./kubernetes/apps/base/[system-name]/[app-name] prune: true sourceRef: kind: GitRepository name: flux-system dependsOn: - name: [dependency-name] namespace: flux-system decryption: # If secrets exist provider: sops secretRef: name: sops-age postBuild: substituteFrom: - kind: ConfigMap name: cluster-config optional: false - kind: Secret name: cluster-secrets optional: false ``` 6. **Create Namespace (if new)** ```yaml apiVersion: v1 kind: Namespace metadata: name: [namespace] labels: pod-security.kubernetes.io/enforce: privileged # or restricted/baseline pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/warn: privileged goldilocks.fairwinds.com/enabled: "true" ``` 7. **Create Secret (if needed)** - Create unencrypted secret first - Encrypt with SOPS: `sops -e secret.yaml > secret.enc.yaml` - Delete unencrypted version - Add `.enc.yaml` suffix 8. **Update Parent Kustomization** Add to `kubernetes/apps/base/[system-name]/kustomization.yaml`: ```yaml resources: - [app-name]/ks.yaml ``` ## Repository Conventions ### File Naming - `ks.yaml`: Flux Kustomization resources (how to apply) - `kustomization.yaml`: Kustomize configuration (what to apply) - `*.enc.yaml`: SOPS-encrypted files - `helmrelease.yaml`: Helm release definitions - `ocirepository.yaml`: OCI chart sources - `namespace.yaml`: Namespace with pod security labels ### HelmRelease Global Defaults All HelmReleases automatically inherit these defaults: ```yaml install: crds: CreateReplace createNamespace: true replace: true strategy: RetryOnFailure timeout: 10m rollback: recreate: true force: true cleanupOnFail: true upgrade: cleanupOnFail: true crds: CreateReplace remediation: remediateLastFailure: true retries: 3 strategy: rollback ``` ### Common Dependencies - CRDs → Operators → Applications - Namespaces → RBAC → Applications - cert-manager → Ingress controllers → Apps - Storage → Databases → Applications ## OCI Registry Locations Common OCI registries: - **Prometheus Community**: `oci://ghcr.io/prometheus-community/charts/[chart]` - **Grafana**: `oci://ghcr.io/grafana/charts/[chart]` - **Bitnami**: `oci://registry-1.docker.io/bitnamicharts/[chart]` - **GitLab**: `oci://registry.gitlab.com/[project]/charts/[chart]` - **CNCF**: Check ArtifactHub for OCI support ## Output Format Provide: 1. **Complete directory structure** with all files 2. **All YAML manifests** properly formatted 3. **Instructions** for encryption and application 4. **Verification steps** to confirm deployment 5. **File references** using `file:line` format After generating manifests, recommend: - Security audit with Security Auditor agent - Validation with Manifest Validator agent - Dependency check with Dependency Mapper agent ================================================ FILE: .claude/agents/resource-optimizer.md ================================================ # Resource Optimizer Agent You are a Kubernetes resource optimization expert specializing in right-sizing resource requests/limits and configuring autoscaling. ## Expertise - Analyze actual resource usage from metrics - Recommend optimal resource requests and limits - Configure Horizontal Pod Autoscaler (HPA) - Configure Vertical Pod Autoscaler (VPA) recommendations - Identify over-provisioned and under-provisioned workloads - Calculate cost savings and efficiency improvements - Balance performance, cost, and reliability ## Optimization Workflow ### 1. Gather Current State ```bash # Current resource usage kubectl top pods -n kubectl top nodes # Current resource requests/limits kubectl get pods -n -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].resources}{"\n"}{end}' # HPA status kubectl get hpa -n # VPA recommendations (if deployed) kubectl get vpa -n -o yaml ``` ### 2. Analyze Historical Metrics Use Prometheus queries to get historical data: ```promql # CPU usage over 30 days (P50, P90, P99) quantile_over_time(0.50, container_cpu_usage_seconds_total{namespace=""}[30d]) quantile_over_time(0.90, container_cpu_usage_seconds_total{namespace=""}[30d]) quantile_over_time(0.99, container_cpu_usage_seconds_total{namespace=""}[30d]) # Memory usage over 30 days quantile_over_time(0.90, container_memory_working_set_bytes{namespace=""}[30d]) # Request vs actual usage sum(rate(container_cpu_usage_seconds_total{namespace=""}[5m])) by (pod) / on(pod) sum(kube_pod_container_resource_requests{resource="cpu", namespace=""}) by (pod) ``` ### 3. Calculate Recommendations #### CPU Requests - **Base on P90 usage** with 20-30% headroom for bursts - Align to node capacity for efficient bin-packing - Consider workload type: - **Latency-sensitive**: Higher headroom (30-40%) - **Batch jobs**: Lower headroom (10-20%) - **Bursty workloads**: Lower requests, rely on limits #### CPU Limits - **Option 1**: 2-4x requests (allows bursting) - **Option 2**: No limit (avoid CPU throttling, use QoS Burstable) - **Never set limits** below actual P95 usage #### Memory Requests - **Base on P90 usage** with 20-30% headroom - Memory is incompressible - ensure adequate requests - Account for heap growth (Java, Node.js) #### Memory Limits - **Set 1.5-2x requests** to handle spikes - **Avoid limits for JVM apps** (can cause OOM instead of graceful GC) - **Set limits** for memory leak protection ### 4. QoS Classes Choose appropriate Quality of Service class: **Guaranteed** (requests == limits): - Critical workloads - Predictable resource usage - Last to be evicted ```yaml resources: requests: cpu: 500m memory: 1Gi limits: cpu: 500m memory: 1Gi ``` **Burstable** (requests < limits or only requests): - Most applications (recommended) - Can use extra resources when available ```yaml resources: requests: cpu: 500m memory: 1Gi limits: cpu: 2000m memory: 2Gi ``` **BestEffort** (no requests/limits): - Non-critical batch jobs - First to be evicted - Not recommended for production ## Horizontal Pod Autoscaler (HPA) ### CPU-Based HPA ```yaml apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: example-hpa namespace: example-namespace spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: example-app minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 # Target 70% CPU utilization behavior: scaleDown: stabilizationWindowSeconds: 300 # Wait 5min before scaling down policies: - type: Percent value: 50 # Scale down max 50% of pods at once periodSeconds: 60 scaleUp: stabilizationWindowSeconds: 0 # Scale up immediately policies: - type: Percent value: 100 # Scale up max 100% (double) at once periodSeconds: 15 ``` ### Memory-Based HPA ```yaml metrics: - type: Resource resource: name: memory target: type: Utilization averageUtilization: 80 ``` ### Custom Metrics HPA ```yaml metrics: - type: Pods pods: metric: name: http_requests_per_second target: type: AverageValue averageValue: "1000" ``` ### HPA Configuration Guidelines **Min Replicas:** - At least 2 for high availability - Consider failure domains (zones) **Max Replicas:** - Based on peak traffic capacity - Consider backend capacity (database connections) - Cost constraints **Target Utilization:** - **CPU**: 70-80% (allows headroom for bursts) - **Memory**: 80-85% (less bursty than CPU) **Behavior:** - **Scale up quickly** (seconds to minutes) - **Scale down slowly** (minutes to hours) to avoid flapping ## Resource Optimization Patterns ### Over-Provisioned (Wasteful) **Symptoms:** - Actual usage << requests (e.g., 10% utilization) - Many idle resources - High cost-to-usage ratio **Action:** - Reduce requests to P90 + 20% - Consider reducing replicas - Add HPA for elasticity ### Under-Provisioned (Risky) **Symptoms:** - Actual usage ≥ requests/limits - Frequent OOM kills - CPU throttling - Performance degradation **Action:** - Increase requests/limits immediately - Add HPA to handle demand spikes - Investigate memory leaks if memory keeps growing ### Right-Sized (Optimal) **Target:** - Actual usage: 60-80% of requests - 20-40% headroom for bursts - No CPU throttling - No OOM kills - Cost-effective ## Cost Optimization Strategies ### 1. Reduce Over-Provisioning - Lower requests for under-utilized pods - Use smaller instance types - **Estimated savings**: 20-50% of compute costs ### 2. Implement HPA - Scale to zero (or min replicas) during low traffic - Auto-scale during peak hours - **Estimated savings**: 30-70% for variable workloads ### 3. Use Spot/Preemptible Nodes - For fault-tolerant workloads - Combine with node affinity - **Estimated savings**: 60-80% vs on-demand ### 4. Bin-Packing Efficiency - Align resource requests to node capacity - Use pod topology spread constraints - **Estimated savings**: 10-30% through better utilization ## Repository Integration ### Update HelmRelease Values Add to `values.yaml`: ```yaml resources: requests: cpu: 500m memory: 1Gi limits: cpu: 2000m memory: 2Gi autoscaling: enabled: true minReplicas: 2 maxReplicas: 10 targetCPUUtilizationPercentage: 75 targetMemoryUtilizationPercentage: 80 ``` ### Create Cluster Overlay For cluster-specific resource tuning: ```yaml # kubernetes/apps/overlays/cluster-00/observability/prometheus/resources-patch.yaml apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: prometheus spec: values: server: resources: requests: cpu: 1000m memory: 4Gi limits: cpu: 4000m memory: 8Gi ``` ## Output Format Provide optimization report: ``` RESOURCE OPTIMIZATION REPORT: [namespace] ========================================== WORKLOAD: [name] ---------------- Current Configuration: Replicas: 3 Requests: {cpu: 1000m, memory: 2Gi} Limits: {cpu: 2000m, memory: 4Gi} HPA: Not configured Actual Usage (30-day P90): CPU: 450m (45% of requests) Memory: 1.2Gi (60% of requests) Utilization Analysis: ⚠ Over-provisioned CPU by 55% ✓ Memory usage appropriate Recommendations: Requests: {cpu: 500m, memory: 1.5Gi} # Reduce CPU by 50%, memory by 25% Limits: {cpu: 1500m, memory: 3Gi} Add HPA: minReplicas: 2 maxReplicas: 5 targetCPUUtilization: 75% Expected Impact: - Cost savings: $XX/month (XX% reduction) - Improved bin-packing: +2 pods per node - Risk: LOW (maintains 20% headroom) YAML Configuration: --- [Provide complete YAML] ``` ## Monitoring & Validation After optimization: ```bash # Monitor resource usage kubectl top pods -n --watch # Check for OOM kills kubectl get events -n | grep OOM # Check for CPU throttling kubectl get pods -n -o json | jq '.items[] | select(.status.containerStatuses[].state.waiting.reason == "CrashLoopBackOff")' # Monitor HPA kubectl get hpa -n --watch # Check pod evictions kubectl get events -n | grep Evicted ``` ## Best Practices 1. **Start conservative**: Better to over-provision initially 2. **Iterate**: Adjust based on actual usage over weeks 3. **Test**: Validate in staging before production 4. **Monitor**: Set alerts for high resource usage 5. **Document**: Note assumptions and expected patterns 6. **Review**: Quarterly resource optimization reviews Always provide before/after YAML, expected impact, and validation steps. ================================================ FILE: .claude/agents/security-auditor.md ================================================ # Security Auditor Agent You are a Kubernetes security expert specializing in auditing GitOps configurations for security best practices. ## Expertise - Scan for unencrypted secrets - Validate pod security standards - Review RBAC configurations - Identify privilege escalation risks - Verify network policies - Review SOPS encryption patterns - Check for CVE-prone configurations ## Audit Workflow When reviewing configurations, systematically check: ### 1. Secret Management **Critical Checks:** - All secrets MUST use `.enc.yaml` suffix (SOPS encrypted) - No base64-encoded secrets without SOPS encryption - Verify SOPS fingerprints match repository config: - PGP: `0635B8D34037A9453003FB7B93CAA682FF4C9014` - Age: `age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t` **Commands:** ```bash # Find unencrypted secrets grep -r "kind: Secret" kubernetes/apps/ | grep -v ".enc.yaml" # Verify SOPS encryption sops -d path/to/secret.enc.yaml ``` ### 2. Pod Security Standards **Critical Checks:** - Namespaces MUST have `pod-security.kubernetes.io/enforce` label - No `privileged: true` unless absolutely required - No `hostNetwork: true`, `hostPID: true`, `hostIPC: true` - No `runAsUser: 0` (root) unless required - `allowPrivilegeEscalation: false` should be set - Capabilities should be dropped: `drop: [ALL]` - Read-only root filesystem when possible **Acceptable Security Contexts:** ```yaml securityContext: allowPrivilegeEscalation: false runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 seccompProfile: type: RuntimeDefault capabilities: drop: [ALL] readOnlyRootFilesystem: true ``` **Commands:** ```bash # Check namespace labels grep -r "pod-security.kubernetes.io" kubernetes/apps/ # Find privileged pods grep -r "privileged: true" kubernetes/apps/ # Find host namespace usage grep -rE "host(Network|PID|IPC): true" kubernetes/apps/ ``` ### 3. RBAC Configuration **Critical Checks:** - Principle of least privilege applied - No wildcard (`*`) permissions on resources or verbs - ServiceAccounts properly scoped - No `cluster-admin` binding unless required - Token auto-mounting disabled when not needed: `automountServiceAccountToken: false` **Risky Permissions:** - `create` on `pods/exec` (remote code execution) - `*` on `secrets` (credential access) - `*` on `*` (full cluster access) - `escalate` or `bind` on roles (privilege escalation) **Commands:** ```bash # Find wildcard permissions grep -rE "- \"\*\"" kubernetes/apps/ # Check ServiceAccount usage grep -r "serviceAccountName:" kubernetes/apps/ ``` ### 4. Network Security **Critical Checks:** - NetworkPolicies exist for namespaces with sensitive workloads - Default deny policies where appropriate - Ingress/egress restrictions defined - Service mesh policies (Istio AuthorizationPolicy) configured **Recommended NetworkPolicy:** ```yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-ingress spec: podSelector: {} policyTypes: - Ingress ``` ### 5. Supply Chain Security **Critical Checks:** - Images should use digest pinning: `image@sha256:...` - Images from trusted registries only - Chart sources verified (OCIRepository with semver) - Renovate automation configured for updates **Trusted Registries:** - `ghcr.io` (GitHub Container Registry) - `gcr.io`, `registry.k8s.io` (Google/Kubernetes) - `quay.io` (Red Hat Quay) - Internal registry if configured **Commands:** ```bash # Find tag-based images (not digest) grep -rE "image:.*:[^@]*$" kubernetes/apps/ ``` ### 6. Resource Limits **Critical Checks:** - Resource requests and limits defined - No unbounded resource consumption - QoS class appropriate (Guaranteed for critical workloads) **Recommended:** ```yaml resources: requests: cpu: 100m memory: 128Mi limits: cpu: 500m memory: 512Mi ``` ### 7. Admission Control **Critical Checks:** - Kyverno or OPA policies applied - Pod Security Admission enabled - Image verification policies active - Mutation webhooks for security defaults ## Severity Ratings Use these severity levels: - **CRITICAL**: Immediate security risk (unencrypted secrets, privileged containers) - **HIGH**: Significant risk (missing RBAC, no network policies, root user) - **MEDIUM**: Moderate risk (no resource limits, tag-based images) - **LOW**: Best practice violation (missing labels, verbose logging) - **INFO**: Recommendations for improvement ## Output Format Provide structured audit report: ``` SECURITY AUDIT REPORT: [namespace/app] ========================================= CRITICAL: [CRIT-1] Issue title - File: path/to/file.yaml:line - Issue: Detailed description - Risk: Impact explanation - Fix: Exact remediation steps HIGH: [HIGH-1] Issue title ... MEDIUM: ... LOW: ... PASSED: ✓ Check description ✓ Check description SUMMARY: - Total issues: X - Critical: X, High: X, Medium: X, Low: X - Files scanned: X - Compliance: X% ``` ## Repository-Specific Context - **SOPS Keys**: PGP `0635B8D...`, Age `age19gj...` - **Pod Security**: Most namespaces use `privileged` enforcement - **Service Mesh**: Istio deployed, use AuthorizationPolicy - **Policy Engines**: Kyverno and OPA Gatekeeper available - **Runtime Security**: Falco and Tetragon for detection ## Remediation Priority 1. **Immediate** (Critical): Unencrypted secrets, privileged containers 2. **Within 24h** (High): Missing RBAC, root users, host namespaces 3. **Within week** (Medium): Resource limits, network policies 4. **Next sprint** (Low): Image digests, labels, documentation Always reference files with `file:line` format for easy navigation. ================================================ FILE: .gitattributes ================================================ .secrets/git-crypt/** filter=git-crypt diff=git-crypt *.enc.yaml diff=sopsdiffer ================================================ FILE: .github/CODEOWNERS ================================================ # https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners * @xUnholy ================================================ FILE: .github/CODE_OF_CONDUCT.md ================================================ # Code of Conduct We follow the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). Please contact info@owncloud.ai to report an issue. ================================================ FILE: .github/CONTRIBUTING.md ================================================ # Contributing Guide [Instructions](https://contribute.cncf.io/maintainers/github/templates/required/contributing/#introduction) - [Contributing Guide](#contributing-guide) - [Ways to Contribute](#ways-to-contribute) - [Find an Issue](#find-an-issue) - [Ask for Help](#ask-for-help) - [Sign Your Commits](#sign-your-commits) - [DCO](#dco) - [Pull Request Checklist](#pull-request-checklist) Welcome! We are glad that you want to contribute to our project! 💖 As you get started, you are in the best position to give us feedback on areas of our project that we need help with including: * Gaps in our Guide or documentation * Bugs in our automation scripts If anything doesn't make sense, or doesn't work when you run it, please open a bug report and let us know! ## Ways to Contribute We welcome many different types of contributions including: * New features * Builds, CI/CD * Bug fixes * Documentation * Issue Triage * Answering questions on Discord * Web design * Communications / Social Media / Blog Posts * Release management Not everything happens through a GitHub pull request. Please contact us and let's discuss how we can work together - Email: info@owncloud.ai ## Find an Issue We have good first issues for new contributors and help wanted issues suitable for any contributor. [good first issue]([TODO](https://github.com/xUnholy/k8s-gitops/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)) has extra information to help you make your first contribution. [help wanted]([TODO](https://github.com/xUnholy/k8s-gitops/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)) are issues suitable for someone who isn't a core maintainer and is good to move onto after your first pull request. Sometimes there won’t be any issues with these labels. That’s ok! There is likely still something for you to work on. If you want to contribute but you don’t know where to start or can't find a suitable issue, you can ask for an issue to work on. Once you see an issue that you'd like to work on, please post a comment saying that you want to work on it. Something like "I want to work on this" is fine. ## Ask for Help The best way to reach us with a question when contributing is to ask on: * The original github issue * Our Discord channel ## Sign Your Commits [Instructions](https://contribute.cncf.io/maintainers/github/templates/required/contributing/#sign-your-commits) ### DCO Licensing is important to open source projects. It provides some assurances that the software will continue to be available based under the terms that the author(s) desired. We require that contributors sign off on commits submitted to our project's repositories. The [Developer Certificate of Origin (DCO)](https://probot.github.io/apps/dco/) is a way to certify that you wrote and have the right to contribute the code you are submitting to the project. You sign-off by adding the following to your commit messages. Your sign-off must match the git user and email associated with the commit. This is my commit message Signed-off-by: Your Name Git has a `-s` command line option to do this automatically: git commit -s -m 'This is my commit message' If you forgot to do this and have not yet pushed your changes to the remote repository, you can amend your commit with the sign-off by running git commit --amend -s ## Pull Request Checklist When you submit your pull request, or you push new commits to it, our automated systems will run some checks on your new code. We require that your pull request passes these checks, but we also have more criteria than just that before we can accept and merge it. ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.yaml ================================================ --- name: Bug Report description: Report a problem with the cluster or an application labels: ["bug"] body: - type: dropdown id: system attributes: label: System description: Which system is affected? options: - kube-system - network-system - observability - security-system - home-system - game-servers - ai-system - rook-ceph - flux-system - other validations: required: true - type: input id: application attributes: label: Application description: Which application is affected? placeholder: e.g. cert-manager, home-assistant validations: required: true - type: textarea id: description attributes: label: Description description: What happened? validations: required: true - type: textarea id: expected attributes: label: Expected Behavior description: What should have happened? validations: required: true - type: textarea id: logs attributes: label: Relevant Logs description: Paste relevant logs or Flux events render: shell ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.yaml ================================================ --- name: Feature Request description: Propose a new application or cluster enhancement labels: ["enhancement"] body: - type: textarea id: description attributes: label: Description description: What would you like to add or change? validations: required: true - type: textarea id: rationale attributes: label: Rationale description: Why is this needed? validations: required: true - type: textarea id: implementation attributes: label: Implementation Notes description: Any thoughts on how to implement this? ================================================ FILE: .github/pull_request_template.md ================================================ ## Summary ## Changes - ## Test Plan - [ ] `pre-commit run --all-files` passes - [ ] Flux Local diff reviewed in PR comments - [ ] Secrets are encrypted (`.enc.yaml` / `.enc.age.yaml`) ## Checklist - [ ] YAML is valid and passes yamllint - [ ] No unencrypted secrets committed - [ ] Dependencies updated in `ks.yaml` if needed - [ ] Relevant documentation updated ================================================ FILE: .github/renovate.json5 ================================================ { $schema: "https://docs.renovatebot.com/renovate-schema.json", extends: [ "config:recommended", // TODO: Consider using best-practices once OCI sha256 digests are supported // "config:best-practices", "docker:enableMajor", "security:openssf-scorecard", ":automergeBranch", ":automergeDigest", ":disableRateLimiting", ":dependencyDashboard", ":semanticCommits", ":timezone(Australia/Melbourne)", "github>xunholy/k8s-gitops//.renovate/autoMerge.json5", "github>xunholy/k8s-gitops//.renovate/changelogs.json5", "github>xunholy/k8s-gitops//.renovate/customManagers.json5", "github>xunholy/k8s-gitops//.renovate/grafanaDashboards.json5", "github>xunholy/k8s-gitops//.renovate/groups.json5", "github>xunholy/k8s-gitops//.renovate/labels.json5", "github>xunholy/k8s-gitops//.renovate/semanticCommits.json5", ], dependencyDashboardTitle: "Renovate Dashboard 🤖", suppressNotifications: ["prEditedNotification", "prIgnoreNotification"], "pre-commit": { enabled: true, }, ignorePaths: ["**/*.enc.*", "**/resources/**"], flux: { managerFilePatterns: ["/(^|/)kubernetes/.+\\.ya?ml$/"], }, "helm-values": { managerFilePatterns: ["/(^|/)kubernetes/.+\\.ya?ml$/"], }, kubernetes: { managerFilePatterns: ["/(^|/)kubernetes/.+\\.ya?ml$/"], }, } ================================================ FILE: .github/workflows/azerothcore.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json name: "Build AzerothCore WotLK" on: workflow_dispatch: {} push: branches: - main paths: - .github/workflows/azerothcore.yaml - kubernetes/apps/base/game-servers/azerothcore/app/resources/** permissions: write-all env: CONTEXT: kubernetes/apps/base/game-servers/azerothcore/app/resources WORLDSERVER_IMAGE: ghcr.io/xunholy/azerothcore-wotlk-worldserver AUTHSERVER_IMAGE: ghcr.io/xunholy/azerothcore-wotlk-authserver DB_IMPORT_IMAGE: ghcr.io/xunholy/azerothcore-wotlk-db-import jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Login to GHCR uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 - name: Build and push worldserver uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7 with: context: ${{ env.CONTEXT }} target: worldserver push: true tags: | ${{ env.WORLDSERVER_IMAGE }}:${{ github.sha }} ${{ env.WORLDSERVER_IMAGE }}:latest build-args: THREADS=2 cache-from: type=gha,scope=azerothcore cache-to: type=gha,mode=max,scope=azerothcore - name: Build and push authserver uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7 with: context: ${{ env.CONTEXT }} target: authserver push: true tags: | ${{ env.AUTHSERVER_IMAGE }}:${{ github.sha }} ${{ env.AUTHSERVER_IMAGE }}:latest build-args: THREADS=2 cache-from: type=gha,scope=azerothcore cache-to: type=gha,mode=max,scope=azerothcore - name: Build and push db-import uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7 with: context: ${{ env.CONTEXT }} target: db-import push: true tags: | ${{ env.DB_IMPORT_IMAGE }}:${{ github.sha }} ${{ env.DB_IMPORT_IMAGE }}:latest build-args: THREADS=2 cache-from: type=gha,scope=azerothcore cache-to: type=gha,mode=max,scope=azerothcore ================================================ FILE: .github/workflows/cmangos-registration.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json name: "Build CMaNGOS Registration" on: workflow_dispatch: {} push: branches: - main paths: - .github/workflows/cmangos-registration.yaml - kubernetes/apps/base/game-servers/cmangos-registration/app/resources/** permissions: write-all env: IMAGE: ghcr.io/xunholy/cmangos-registration jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Login to GHCR uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 - name: Build and push uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7 with: context: kubernetes/apps/base/game-servers/cmangos-registration/app/resources push: true tags: | ${{ env.IMAGE }}:${{ github.sha }} ${{ env.IMAGE }}:latest cache-from: type=gha cache-to: type=gha,mode=max ================================================ FILE: .github/workflows/cmangos.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json name: "Build CMaNGOS Classic" on: workflow_dispatch: {} push: branches: - main paths: - .github/workflows/cmangos.yaml - kubernetes/apps/base/game-servers/cmangos/app/resources/** permissions: write-all env: BUILDER_IMAGE: ghcr.io/xunholy/cmangos-classic-builder RUNNER_IMAGE: ghcr.io/xunholy/cmangos-classic jobs: build-builder: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Login to GHCR uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 - name: Build and push builder uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7 with: context: kubernetes/apps/base/game-servers/cmangos/app/resources target: builder push: true tags: | ${{ env.BUILDER_IMAGE }}:${{ github.sha }} ${{ env.BUILDER_IMAGE }}:latest build-args: | THREADS=4 COMMIT_SHA=${{ github.sha }} cache-from: | type=gha,scope=builder type=registry,ref=${{ env.BUILDER_IMAGE }}:latest cache-to: type=gha,mode=max,scope=builder build-runner: runs-on: ubuntu-latest needs: build-builder steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Login to GHCR uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 - name: Build and push runner uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7 with: context: kubernetes/apps/base/game-servers/cmangos/app/resources target: runner push: true tags: | ${{ env.RUNNER_IMAGE }}:${{ github.sha }} ${{ env.RUNNER_IMAGE }}:latest build-args: | THREADS=4 COMMIT_SHA=${{ github.sha }} cache-from: | type=gha,scope=builder type=gha,scope=runner type=registry,ref=${{ env.RUNNER_IMAGE }}:latest cache-to: type=gha,mode=max,scope=runner ================================================ FILE: .github/workflows/dex-k8s-authenticator.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json name: "Build dex-k8s-authenticator" on: workflow_dispatch: {} push: branches: - main paths: - .github/workflows/dex-k8s-authenticator.yaml - kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/** permissions: write-all env: IMAGE: ghcr.io/xunholy/dex-k8s-authenticator jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Login to GHCR uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 - name: Build and push uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7 with: context: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources push: true tags: | ${{ env.IMAGE }}:${{ github.sha }} ${{ env.IMAGE }}:latest cache-from: type=gha cache-to: type=gha,mode=max ================================================ FILE: .github/workflows/flux-local.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json name: Flux Local on: pull_request: branches: - main concurrency: group: ${{ github.workflow }}-${{ github.event.number || github.ref }} cancel-in-progress: true permissions: contents: read jobs: filter: name: Flux Local - Filter runs-on: ubuntu-latest outputs: changed-files: ${{ steps.changed-files.outputs.changed_files }} steps: - name: Get Changed Files id: changed-files uses: bjw-s-labs/action-changed-files@a9a36fb08ce06db9b02fbd8026cc2c0945eb9841 # v0.6.0 with: patterns: kubernetes/**/* test: if: ${{ needs.filter.outputs.changed-files != '[]' }} needs: filter name: Flux Local - Test runs-on: ubuntu-latest strategy: matrix: cluster: ["cluster-00"] steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Run flux-local test uses: docker://ghcr.io/allenporter/flux-local:v8.2.0@sha256:9c77739d8d7c71b808311693ea52d603d1ddb5190d3d4f23e47f6f33d5254602 with: args: >- test --all-namespaces --enable-helm --path /github/workspace/kubernetes/clusters/${{ matrix.cluster }} --sources "flux-system=kubernetes/" --verbose --skip-invalid-kustomization-paths diff: if: ${{ needs.filter.outputs.changed-files != '[]' }} needs: filter name: Flux Local - Diff runs-on: ubuntu-latest permissions: contents: read pull-requests: write strategy: matrix: cluster: ["cluster-00"] resource: ["helmrelease", "kustomization"] fail-fast: false steps: - name: Checkout Pull Request Branch uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: path: pull - name: Checkout Default Branch uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.event.repository.default_branch }} path: default - name: Run flux-local diff uses: docker://ghcr.io/allenporter/flux-local:v8.2.0@sha256:9c77739d8d7c71b808311693ea52d603d1ddb5190d3d4f23e47f6f33d5254602 with: args: >- diff ${{ matrix.resource }} --unified 6 --path /github/workspace/pull/kubernetes/clusters/${{ matrix.cluster }} --path-orig /github/workspace/default/kubernetes/clusters/${{ matrix.cluster }} --strip-attrs "helm.sh/chart,checksum/config,app.kubernetes.io/version,chart" --limit-bytes 10000 --all-namespaces --sources "flux-system=kubernetes/" --output-file diff.patch --skip-invalid-kustomization-paths - name: Generate Diff id: diff run: |- echo 'diff<> $GITHUB_OUTPUT [ -f diff.patch ] && cat diff.patch >> $GITHUB_OUTPUT echo 'EOF' >> $GITHUB_OUTPUT - if: ${{ steps.diff.outputs.diff != '' }} name: Generate Token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 id: app-token with: app-id: ${{ secrets.BOT_APP_ID }} private-key: ${{ secrets.BOT_APP_PRIVATE_KEY }} - if: ${{ steps.diff.outputs.diff != '' }} name: Add Comment continue-on-error: true uses: marocchino/sticky-pull-request-comment@0ea0beb66eb9baf113663a64ec522f60e49231c0 # v3.0.4 with: GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} header: ${{ github.event.pull_request.number }}/kubernetes/${{ matrix.resource }} message: |- ```diff ${{ steps.diff.outputs.diff }} ``` success: if: ${{ !cancelled() }} needs: ["test", "diff"] name: Flux Local - Success runs-on: ubuntu-latest steps: - name: Any jobs failed? if: ${{ contains(needs.*.result, 'failure') }} run: exit 1 - name: All jobs passed or skipped? if: ${{ !(contains(needs.*.result, 'failure')) }} run: echo "All jobs passed or skipped" && echo "${{ toJSON(needs.*.result) }}" ================================================ FILE: .github/workflows/oci.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json name: "Publish OCI artifact" on: workflow_dispatch: {} push: branches: - main paths: - .github/workflows/oci.yaml - kubernetes/** # Default GITHUB_TOKEN token permissions do NOT support cosign and must be enabled. # This is to set the package and id_token permissions to read|write. # Current default permissions can be viewed here: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token permissions: write-all env: OCI_REPO: "oci://ghcr.io/xunholy/manifests/${{ github.event.repository.name }}" GHCR_REPO: "ghcr.io/xunholy/manifests/${{ github.event.repository.name }}" jobs: publish: runs-on: ubuntu-latest env: COSIGN_EXPERIMENTAL: "true" COSIGN_YES: "true" steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Setup Flux CLI uses: fluxcd/flux2/action@main with: token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Crane uses: imjasonh/setup-crane@6da1ae018866400525525ce74ff892880c099987 # v0.5 - name: Setup Cosign uses: sigstore/cosign-installer@main - name: Login to GHCR uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Create OCI artifact run: | flux push artifact "$OCI_REPO:$(git rev-parse --short HEAD)" \ --path="./kubernetes" \ --source="$(git config --get remote.origin.url)" \ --revision="$(git branch --show-current)@sha1:$(git rev-parse HEAD)" \ --ignore-paths="sops-gpg.encrypted.yaml,sops-age.encrypted.yaml,.sops.pub.asc" \ --reproducible - name: Create OCI artifact tag run: | flux tag artifact "$OCI_REPO:$(git rev-parse --short HEAD)" --tag main - name: Get the digest of the OCI artifact id: crane run: | DIGEST=$(crane digest "$GHCR_REPO:$(git rev-parse --short HEAD)") echo "DIGEST=$DIGEST" >> $GITHUB_OUTPUT - name: Sign the OCI artifact run: cosign sign "$GHCR_REPO@${{ steps.crane.outputs.DIGEST }}" -y ================================================ FILE: .github/workflows/oidc.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json name: "Example: GCP Workload identity Federation" on: workflow_dispatch: {} jobs: connect: runs-on: ubuntu-latest permissions: id-token: 'write' # Required for requesting the JWT contents: 'read' # Required for actions/checkout steps: # actions/checkout MUST come before auth - uses: 'actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd' # v6 # Checkout your repository # Authenticate to Google Cloud using the workload identity federation - id: 'auth' name: 'Authenticate to Google Cloud' uses: 'google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093' # v3 with: create_credentials_file: 'true' # Create a credentials file # Set the workload identity provider and service account workload_identity_provider: 'projects/970557914270/locations/global/workloadIdentityPools/raspbernetes-oidc-pool/providers/github-provider' service_account: 'raspbernetes-oidc-sa@raspbernetes.iam.gserviceaccount.com' - name: 'Set up Cloud SDK' uses: 'google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db' # v3 - id: 'gcloud' name: 'gcloud' run: |- gcloud auth login --brief --cred-file="${{ steps.auth.outputs.credentials_file_path }}" gcloud services list ================================================ FILE: .github/workflows/render-talos-manifests.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json name: "Render Talos Integration Manifests" on: push: branches: - main paths: - kubernetes/apps/base/kube-system/kubelet-csr-approver/app/values.yaml - kubernetes/apps/base/kube-system/kubelet-csr-approver/app/ocirepository.yaml workflow_dispatch: {} permissions: contents: write jobs: render: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Setup Helm uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5 - name: Extract chart version from OCIRepository id: chart run: | VERSION=$(grep -A2 'ref:' kubernetes/apps/base/kube-system/kubelet-csr-approver/app/ocirepository.yaml | grep 'tag:' | awk '{print $2}') echo "version=$VERSION" >> "$GITHUB_OUTPUT" echo "Chart version: $VERSION" - name: Pull chart env: CHART_VERSION: ${{ steps.chart.outputs.version }} run: | helm pull oci://ghcr.io/postfinance/charts/kubelet-csr-approver \ --version "$CHART_VERSION" \ --untar \ --destination /tmp/chart - name: Render manifest run: | helm template kubelet-csr-approver /tmp/chart/kubelet-csr-approver \ --namespace kube-system \ --values kubernetes/apps/base/kube-system/kubelet-csr-approver/app/values.yaml \ --no-hooks \ > /tmp/rendered.yaml - name: Setup yq uses: mikefarah/yq@751d8ad57b84f1794661bc70c0afb92a22ad7b3c # v4.53.2 - name: Build final manifest with header and annotations env: CHART_VERSION: ${{ steps.chart.outputs.version }} run: | { cat < talos/integrations/cert-approver/cert-approver.yaml - name: Update kustomization version env: CHART_VERSION: ${{ steps.chart.outputs.version }} run: | sed -i "s/version: .*/version: $CHART_VERSION/" \ talos/integrations/cert-approver/kustomization.yaml - name: Check for changes id: diff run: | git diff --quiet talos/integrations/cert-approver/ && echo "changed=false" >> "$GITHUB_OUTPUT" || echo "changed=true" >> "$GITHUB_OUTPUT" - name: Commit and push if: steps.diff.outputs.changed == 'true' env: CHART_VERSION: ${{ steps.chart.outputs.version }} run: | git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add talos/integrations/cert-approver/ git commit -m "chore(talos): re-render kubelet-csr-approver manifest v${CHART_VERSION}" git push ================================================ FILE: .github/workflows/renovate.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json name: "Renovate" on: merge_group: workflow_dispatch: inputs: dryRun: description: Dry Run default: false type: boolean required: true logLevel: description: Log Level default: info type: choice options: - debug - info - warn - error - fatal required: false version: description: Renovate Version default: latest required: false schedule: - cron: "0 * * * *" push: branches: - main paths: - .github/workflows/renovate.yaml - .github/renovate.json5 - .github/renovate/**.json5 concurrency: group: ${{ github.workflow }}-${{ github.event.number || github.ref }} cancel-in-progress: true jobs: renovate: name: Renovate runs-on: ubuntu-latest steps: - name: Generate Token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3 id: app-token with: app-id: "${{ secrets.BOT_APP_ID }}" private-key: "${{ secrets.BOT_APP_PRIVATE_KEY }}" - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false token: "${{ steps.app-token.outputs.token }}" - name: Renovate uses: renovatebot/github-action@693b9ef15eec82123529a37c782242f091365961 # v46.1.14 env: LOG_LEVEL: "${{ inputs.logLevel || 'debug' }}" RENOVATE_DRY_RUN: "${{ inputs.dryRun }}" RENOVATE_PLATFORM: github RENOVATE_PLATFORM_COMMIT: true RENOVATE_AUTODISCOVER: true RENOVATE_AUTODISCOVER_FILTER: "${{ github.repository }}" RENOVATE_INTERNAL_CHECKS_FILTER: strict with: configurationFile: .github/renovate.json5 token: "x-access-token:${{ steps.app-token.outputs.token }}" renovate-version: "${{ inputs.version || 'latest' }}" ================================================ FILE: .github/workflows/terraform.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json name: "Terraform: Plan And Apply" on: workflow_dispatch: {} pull_request: branches: - main paths: - '.github/workflows/terraform.yaml' - 'terraform/**' env: tf_actions_working_dir: terraform/gcp terraform_version: 1.9.8 jobs: plan: runs-on: ubuntu-latest defaults: run: working-directory: ${{ env.tf_actions_working_dir }} steps: - name: checkout id: checkout_code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: 'google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093' # v3 with: credentials_json: ${{ secrets.GCP_SA_KEY }} - uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3.0.1 with: project_id: ${{ secrets.GCP_PROJECT_ID }} export_default_credentials: true - uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4 with: terraform_version: ${{ env.terraform_version }} - name: Terraform fmt id: fmt run: terraform fmt -check continue-on-error: false - name: Terraform Lint uses: reviewdog/action-tflint@master with: github_token: ${{ secrets.github_token }} reporter: github-pr-review fail_on_error: 'true' filter_mode: 'nofilter' - name: Terraform Init id: init run: terraform init continue-on-error: false - name: Terraform Validate id: validate run: terraform validate -no-color continue-on-error: false - name: Terraform Plan id: plan run: terraform plan -no-color continue-on-error: false - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 if: github.event_name == 'pull_request' env: PLAN: "terraform\n${{ steps.plan.outputs.stdout }}" with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const output = `#### Terraform Format and Style 🖌 \`${{ steps.fmt.outcome }}\` #### Terraform Initialization ⚙️ \`${{ steps.init.outcome }}\` #### Terraform Validation 🤖 ${{ steps.validate.outputs.stdout }} #### Terraform Plan 📖 \`${{ steps.plan.outcome }}\`
Show Plan \`\`\`${process.env.PLAN}\`\`\`
*Pusher: @${{ github.actor }}, Action: \`${{ github.event_name }}\`, Working Directory: \`${{ env.tf_actions_working_dir }}\`, Workflow: \`${{ github.workflow }}\`*`; github.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: output } apply: runs-on: ubuntu-latest if: github.event_name != 'pull_request' needs: ["plan"] defaults: run: working-directory: ${{ env.tf_actions_working_dir }} steps: - name: checkout id: checkout_code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: 'google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093' # v3 with: credentials_json: ${{ secrets.GCP_SA_KEY }} - uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3.0.1 with: project_id: ${{ secrets.GCP_PROJECT_ID }} export_default_credentials: true - uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4 with: terraform_version: ${{ env.terraform_version }} - name: Terraform Init id: init run: terraform init continue-on-error: false - name: Terraform Apply id: apply run: terraform apply -no-color -auto-approve -input=false continue-on-error: false ================================================ FILE: .github/workflows/test-e2e.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json name: "Flux: Run E2E Tests In KIND" on: workflow_dispatch: {} env: DEFAULT_BRANCH: main # TODO: Fine-grained scope # permissions: # contents: write # (REQUIRED): [read] Used for actions/checkout - [write] Used for FluxCD bootstrap # pull-requests: write # (REQUIRED): [write] Used for FluxCD bootstrap # id-token: 'write' # (REQUIRED): Used for requesting the JWT permissions: write-all jobs: kubernetes: runs-on: ubuntu-latest steps: # Checkout the repository - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Setup Homebrew uses: Homebrew/actions/setup-homebrew@master - name: Setup Tools run: | brew install fluxcd/tap/flux go-task/tap/go-task sops kubernetes-cli - name: Setup Kubernetes Kind uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0 with: version: "v0.18.0" - name: 'Set up Cloud SDK' uses: 'google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db' # v3 - id: 'auth' name: 'Authenticate to Google Cloud' uses: 'google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093' # v3 with: create_credentials_file: 'true' # Create a credentials file # Set the workload identity provider and service account workload_identity_provider: 'projects/970557914270/locations/global/workloadIdentityPools/raspbernetes-oidc-pool/providers/github-provider' service_account: 'raspbernetes-oidc-sa@raspbernetes.iam.gserviceaccount.com' - name: Run task flux env: CLUSTER: e2e GITHUB_USER: ${{ github.repository_owner }} GITHUB_REPO: ${{ github.event.repository.name }} GITHUB_BRANCH: ${{ github.head_ref || env.DEFAULT_BRANCH }} GITHUB_TOKEN: ${{ secrets.FLUX_FINE_GRAINED_E2E_PAT }} run: | task core:gpg CLUSTER="$CLUSTER" task flux CLUSTER="$CLUSTER" GITHUB_USER="$GITHUB_USER" GITHUB_REPO="$GITHUB_REPO" GITHUB_BRANCH="$GITHUB_BRANCH" ================================================ FILE: .gitignore ================================================ # Ignore the following repositories and files .DS_Store # Local .terraform directories **/.terraform/* # .tfstate files *.tfstate *.tfstate.* # Crash log files crash.log crash.*.log # Exclude all .tfvars files, which are likely to contain sensitive data, such as # password, private keys, and other secrets. These should not be part of version # control as they are data points which are potentially sensitive and subject # to change depending on the environment. *.tfvars *.tfvars.json # Ignore override files as they are usually used to override resources locally and so # are not checked in override.tf override.tf.json *_override.tf *_override.tf.json # Ignore CLI configuration files .terraformrc terraform.rc # Ignore tf lock files **/.terraform.lock.hcl # Ignore VSCODE SOPS decrypted files **/.decrypted~* # If you prefer the allow list template instead of the deny list, see community template: # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore # # Binaries for programs and plugins *.exe *.exe~ *.dll *.so *.dylib # Test binary, built with `go test -c` *.test # Output of the go coverage tool, specifically when used with LiteIDE *.out # Dependency directories (remove the comment below to include it) # vendor/ # Go workspace file go.work # Ignore the hacks directory containing the scripts to run locally hacks/** # Ignore crossplane packages that have been built locally *.xpkg # Ignore Kubernetes configs kubeconfig # Ignore Talos configs talosconfig # Ignore sensitive files *.agekey *.pub *.key *.pem ================================================ FILE: .pre-commit-config.yaml ================================================ # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v6.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-added-large-files - id: check-merge-conflict - id: detect-private-key - id: check-yaml args: [--allow-multiple-documents] exclude: ^kubernetes/apps/base/home-system/recyclarr/app/resources/recyclarr\.yml$ - id: check-json - id: check-toml # Only enable this if we want to prevent commits directly to the main branch # - id: no-commit-to-branch # args: [--branch, main] - repo: https://github.com/adrienverge/yamllint.git rev: v1.38.0 hooks: - id: yamllint args: [-c=.yamllint.yaml] # TODO: Enable this once we have a markdownlint config # - repo: https://github.com/igorshubovych/markdownlint-cli # rev: v0.44.0 # hooks: # - id: markdownlint # args: [--fix] - repo: https://github.com/koalaman/shellcheck-precommit rev: v0.11.0 hooks: - id: shellcheck args: [--severity=warning] ================================================ FILE: .renovate/autoMerge.json5 ================================================ { $schema: "https://docs.renovatebot.com/renovate-schema.json", packageRules: [ { description: "Auto-merge GitHub Actions", matchManagers: ["github-actions"], automerge: true, automergeType: "branch", matchUpdateTypes: ["minor", "patch", "digest"], ignoreTests: true, }, { description: "Auto-merge Helm / Docker minor + patch", matchDatasources: ["helm", "docker"], automerge: true, automergeType: "pr", matchUpdateTypes: ["minor", "patch"], ignoreTests: true, }, { description: "Disable auto-merge for stateful home-system + game-servers apps (manual review required)", matchFileNames: [ "kubernetes/apps/base/home-system/**", "kubernetes/apps/base/game-servers/**", ], automerge: false, }, { description: "Auto-merge everything under .archive (unmaintained, lifecycle-only)", matchFileNames: [".archive/**"], automerge: true, automergeType: "branch", ignoreTests: true, }, ], } ================================================ FILE: .renovate/changelogs.json5 ================================================ { $schema: "https://docs.renovatebot.com/renovate-schema.json", packageRules: [ { description: "Changelog URL for 1Password Connect", matchPackageNames: ["/1password/"], changelogUrl: "https://github.com/1Password/connect/blob/main/CHANGELOG.md", }, { description: "Changelog URL for Cloudflared", matchPackageNames: ["cloudflared"], changelogUrl: "https://github.com/cloudflare/cloudflared/blob/master/RELEASE_NOTES", }, { description: "Changelog URL for Spegel", matchPackageNames: ["/spegel/"], changelogUrl: "https://github.com/spegel-org/spegel/blob/main/CHANGELOG.md", }, ], } ================================================ FILE: .renovate/customManagers.json5 ================================================ { $schema: "https://docs.renovatebot.com/renovate-schema.json", customManagers: [ { customType: "regex", description: "Process annotated dependencies", managerFilePatterns: [ "/(^|/).+\\.env$/", "/(^|/).+\\.sh$/", "/(^|/).+\\.ya?ml(?:\\.j2)?$/", ], matchStrings: [ // # renovate: datasource=github-releases depName=k3s-io/k3s // k3s_release_version: &version v1.29.0+k3s1 // # renovate: datasource=helm depName=cilium repository=https://helm.cilium.io // version: 1.15.1 // # renovate: datasource=docker depName=ghcr.io/siderolabs/kubelet // KUBERNETES_VERSION=v1.31.1 "datasource=(?\\S+) depName=(?\\S+)( repository=(?\\S+))?\\n.+(:\\s|=)(&\\S+\\s)?(?\\S+)", // # renovate: datasource=docker depName=ghcr.io/prometheus-operator/prometheus-operator // https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/v0.80.0/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagerconfigs.yaml "datasource=(?\\S+) depName=(?\\S+)\\n.+/(?(v|\\d)[^/]+)", ], datasourceTemplate: "{{#if datasource}}{{{datasource}}}{{else}}github-releases{{/if}}", }, { customType: "regex", description: "Process OCI dependencies", managerFilePatterns: ["/\\.yaml(?:\\.j2)?$/"], matchStrings: ["oci://(?[^:]+):(?\\S+)"], datasourceTemplate: "docker", }, ], } ================================================ FILE: .renovate/grafanaDashboards.json5 ================================================ { $schema: "https://docs.renovatebot.com/renovate-schema.json", customDatasources: { "grafana-dashboards": { defaultRegistryUrlTemplate: "https://grafana.com/api/dashboards/{{packageName}}", format: "json", transformTemplates: ['{"releases":[{"version": $string(revision)}], "sourceDirectory": name}'], }, }, customManagers: [ { description: "Process Grafana dashboards", customType: "regex", managerFilePatterns: ["/grafanadashboard\\.yaml(?:\\.j2)?$/",], matchStrings: [ "dashboards\\/(?\\d+)\\/revisions\\/(?\\d+)\\/download", ], datasourceTemplate: "custom.grafana-dashboards", versioningTemplate: "regex:^(?\\d+)$", autoReplaceStringTemplate: "dashboards/{{depName}}/revisions/{{newValue}}/download", }, ], packageRules: [ { addLabels: ["renovate/grafana-dashboard"], automerge: true, automergeType: "branch", commitMessageExtra: "({{currentVersion}} ➔ {{newVersion}})", commitMessageTopic: "dashboard {{sourceDirectory}}", ignoreTests: true, matchDatasources: ["custom.grafana-dashboards"], matchUpdateTypes: ["major"], semanticCommitScope: "grafana-dashboards", semanticCommitType: "chore", }, ], } ================================================ FILE: .renovate/groups.json5 ================================================ { $schema: "https://docs.renovatebot.com/renovate-schema.json", packageRules: [ { description: "Actions Runner Controller Group", groupName: "Actions Runner Controller", matchDatasources: ["docker"], matchPackageNames: [ "/gha-runner-scale-set-controller/", "/gha-runner-scale-set/", ], group: { commitMessageTopic: "{{{groupName}}} group", }, minimumGroupSize: 2, }, { description: "Talos Group", groupName: "talos", matchDatasources: ["docker"], matchPackageNames: ["/installer/"], group: { commitMessageTopic: "{{{groupName}}} group", }, minimumGroupSize: 2, }, { description: "Cilium Group", groupName: "Cilium", matchDatasources: ["docker"], matchPackageNames: ["/cilium/"], group: { commitMessageTopic: "{{{groupName}}} group", }, }, { description: "Flux Operator Group", groupName: "Flux Operator", matchDatasources: ["docker"], matchPackageNames: [ "/flux-operator/", "/flux-instance/", "/flux-operator-manifests/", ], group: { commitMessageTopic: "{{{groupName}}} group", }, minimumGroupSize: 3, }, { description: "Cert-Manager Group", groupName: "Cert-Manager", matchDatasources: ["docker"], matchPackageNames: ["/cert-manager/"], group: { commitMessageTopic: "{{{groupName}}} group", }, }, { description: "kagent Group", groupName: "kagent", matchDatasources: ["docker", "helm"], matchPackagePatterns: ["kagent", "kagent-crds"], group: { commitMessageTopic: "{{{groupName}}} group", }, minimumGroupSize: 2, }, { description: "kgateway Group", groupName: "kgateway", matchDatasources: ["helm"], matchPackagePatterns: ["kgateway", "kgateway-crds"], group: { commitMessageTopic: "{{{groupName}}} group", }, minimumGroupSize: 2, }, { description: "Rook-Ceph Group", groupName: "rook-ceph", matchDatasources: ["docker"], matchPackageNames: ["/rook-ceph/", "/rook-ceph-cluster/"], group: { commitMessageTopic: "{{{groupName}}} group", }, minimumGroupSize: 2, }, { description: "Kubernetes Group", groupName: "kubernetes", matchDatasources: ["docker"], matchPackageNames: [ "/kube-apiserver/", "/kube-controller-manager/", "/kube-proxy/", "/kube-scheduler/", "/kubelet/", ], group: { commitMessageTopic: "{{{groupName}}} group", }, minimumGroupSize: 5, }, { description: "Open WebUI Group", groupName: "Open WebUI", matchDatasources: ["helm"], matchPackageNames: ["open-webui"], separateMajorMinor: false, group: { commitMessageTopic: "{{{groupName}}} group", }, }, { description: "1Password Connect Group", groupName: "1password-connect", matchDatasources: ["docker"], matchPackageNames: ["/1password/"], group: { commitMessageTopic: "{{{groupName}}} group", }, minimumGroupSize: 2, }, ], } ================================================ FILE: .renovate/labels.json5 ================================================ { $schema: "https://docs.renovatebot.com/renovate-schema.json", packageRules: [ { matchUpdateTypes: ["major"], labels: ["type/major"], }, { matchUpdateTypes: ["minor"], labels: ["type/minor"], }, { matchUpdateTypes: ["patch"], labels: ["type/patch"], }, { matchUpdateTypes: ["digest"], labels: ["type/digest"], }, { matchDatasources: ["docker"], addLabels: ["renovate/container"], }, { matchDatasources: ["helm"], addLabels: ["renovate/helm"], }, { matchManagers: ["github-actions"], addLabels: ["renovate/github-action"], }, { matchDatasources: ["github-releases"], addLabels: ["renovate/github-release"], }, ], } ================================================ FILE: .renovate/semanticCommits.json5 ================================================ { $schema: "https://docs.renovatebot.com/renovate-schema.json", packageRules: [ { matchUpdateTypes: ["major"], semanticCommitType: "feat", commitMessagePrefix: "{{semanticCommitType}}({{semanticCommitScope}})!:", commitMessageExtra: "( {{currentVersion}} → {{newVersion}} )", }, { matchUpdateTypes: ["minor"], semanticCommitType: "feat", commitMessageExtra: "( {{currentVersion}} → {{newVersion}} )", }, { matchUpdateTypes: ["patch"], semanticCommitType: "fix", commitMessageExtra: "( {{currentVersion}} → {{newVersion}} )", }, { matchUpdateTypes: ["digest"], semanticCommitType: "chore", commitMessageExtra: "( {{currentDigestShort}} → {{newDigestShort}} )", }, { matchDatasources: ["docker"], semanticCommitScope: "container", commitMessageTopic: "image {{depName}}", }, { matchDatasources: ["helm"], semanticCommitScope: "helm", commitMessageTopic: "chart {{depName}}", }, { matchManagers: ["github-actions"], semanticCommitType: "ci", semanticCommitScope: "github-action", commitMessageTopic: "action {{depName}}", }, { matchDatasources: ["github-releases"], semanticCommitScope: "github-release", commitMessageTopic: "release {{depName}}", }, ], } ================================================ FILE: .sops.yaml ================================================ --- # creation rules are evaluated sequentially, the first match wins creation_rules: # secret files using GCP KMS to encrypt the stored PGP keys - path_regex: kubernetes/clusters/.*/secrets/sops-gpg.encrypted.ya?ml encrypted_regex: ^(data|stringData)$ unencrypted-regex: ^(description|metadata)$ gcp_kms: projects/raspbernetes/locations/global/keyRings/sops/cryptoKeys/sops-key mac_only_encrypted: true # AGE encrypted Kubernetes secret files - path_regex: kubernetes/.*/.*\.enc\.age\.ya?ml encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true age: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t # AGE encrypted Talos secret files - path_regex: talos/.*/.*\.enc\.age\.ya?ml encrypted_regex: '((?i)(pass|secret($|[^N])|ca|crt|key|token|^data$|^stringData$))' mac_only_encrypted: true age: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t stores: yaml: indent: 2 ================================================ FILE: .sourceignore ================================================ ## Used by Fluxv2 Source Controller https://toolkit.fluxcd.io/components/source/gitrepositories/#excluding-files # Exclude all by default /* # Include the following explicit folder(s) !/kubernetes # Exclude sub-foler(s) and file(s) /kubernetes/clusters/**/secrets/ # Include sub-foler(s) and file(s) !/kubernetes/clusters/**/secrets/cluster-config.yaml !/kubernetes/clusters/**/secrets/cluster-secrets.enc.age.yaml !/kubernetes/clusters/**/secrets/github-auth.enc.age.yaml ================================================ FILE: .taskfiles/bootstrap/Taskfile.yaml ================================================ --- version: '3.41.0' vars: CLUSTER_ID: '{{.CLUSTER_ID| default "cluster-00"}}' env: CLUSTER_ID: '{{.CLUSTER_ID}}' ROOT_DIR: '{{.ROOT_DIR}}' tasks: setup: desc: "Ensure required CLIs are installed and initialized" summary: | This task checks if the required dependencies are installed on your system. It then initializes the Helmfile environment to ensure it's ready for use. platforms: [darwin, linux] cmd: helmfile init preconditions: - which helmfile helm kubectl silent: true interactive: true bootstrap: desc: "Bootstrap the FluxCD operator" summary: | Bootstraps the FluxCD operator in the Kubernetes cluster. The command applies the FluxCD operator configuration using Helm. Make sure the necessary environment variables (`CLUSTER_ID`) are set before proceeding. prompt: You're bootstraping FluxCD operator configuration "kubernetes/clusters/{{.CLUSTER_ID}}" ... Do you want to continue? deps: [setup, secrets] cmd: helmfile apply --file {{.ROOT_DIR}}/kubernetes/bootstrap/helmfile.yaml --skip-diff-on-install {{.CLI_ARGS}} requires: vars: [CLUSTER_ID] preconditions: - test -f kubernetes/bootstrap/helmfile.yaml - test -f {{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}/flux-system/flux-operator/app/values.yaml - test -f {{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}/flux-system/flux-instance/app/values.yaml silent: true diff: desc: "Display the differences between the current and desired FluxCD operator configurations" summary: | This task compares the current state of the FluxCD operator with the desired state specified in the Helmfile. Use this to preview changes before applying them to the cluster. cmds: - echo "Comparing FluxCD operator configurations... {{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}" - helmfile diff -f {{.ROOT_DIR}}/kubernetes/bootstrap/helmfile.yaml requires: vars: [CLUSTER_ID] preconditions: - test -f kubernetes/bootstrap/helmfile.yaml - test -f {{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}/flux-system/flux-operator/app/values.yaml - test -f {{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}/flux-system/flux-instance/app/values.yaml silent: true secrets: desc: "Install cluster secrets and configs; Only to be used when updating secrets manually" env: GOOGLE_APPLICATION_CREDENTIALS: '{{.HOME}}/keys/raspbernetes-d72f2d61e4ac.json' cmds: - kubectl create namespace flux-system --dry-run=client -oyaml | kubectl apply -f - - kubectl create namespace external-secrets --dry-run=client -oyaml | kubectl apply -f - - sops --decrypt "{{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}/secrets/sops-gpg.encrypted.yaml" | kubectl apply -f - - sops --decrypt "{{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}/secrets/sops-age.encrypted.yaml" | kubectl apply -f - - sops --decrypt "{{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}/secrets/cluster-secrets.enc.age.yaml" | kubectl apply -f - - sops --decrypt "{{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}/secrets/github-auth.enc.age.yaml" | kubectl apply -f - - kubectl apply -f {{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}/secrets/cluster-config.yaml preconditions: - test -f {{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}/secrets/sops-gpg.encrypted.yaml - test -f {{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}/secrets/sops-age.encrypted.yaml - test -f {{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}/secrets/github-auth.enc.age.yaml - test -f {{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}/secrets/cluster-secrets.enc.age.yaml - test -f {{.ROOT_DIR}}/kubernetes/clusters/{{.CLUSTER_ID}}/secrets/cluster-config.yaml requires: vars: [CLUSTER_ID] silent: true ================================================ FILE: .taskfiles/core/Taskfile.yaml ================================================ --- version: '3.41.0' tasks: gpg: desc: "Import the public and private gpg keys locally" cmds: - gpg --import kubernetes/clusters/cluster-00/secrets/.sops.pub.asc - gpg --import <(sops --decrypt "kubernetes/clusters/cluster-00/secrets/sops-gpg.encrypted.yaml" | yq e '.data[]' - | base64 -d) status: - gpg --list-secret-keys --keyid-format=long | grep production.owncloud.ai lint: desc: "Example: task core:lint -- --no-warnings" cmds: - yamllint -c .yamllint.yaml . {{.CLI_ARGS}} ================================================ FILE: .taskfiles/flux/Taskfile.yaml ================================================ --- version: '3.41.0' tasks: secrets: desc: "Install cluster secrets and configs; Only to be used when updating secrets manually" env: GOOGLE_APPLICATION_CREDENTIALS: ~/raspbernetes-d72f2d61e4ac.json cmds: - cmd: | kubectl create namespace flux-system --dry-run=client -oyaml | kubectl apply -f - sops --decrypt "kubernetes/clusters/{{.CLUSTER}}/secrets/sops-gpg.encrypted.yaml" | kubectl apply -f - sops --decrypt "kubernetes/clusters/{{.CLUSTER}}/secrets/cluster-secrets.enc.age.yaml" | kubectl apply -f - kubectl apply -f kubernetes/clusters/{{.CLUSTER}}/secrets/cluster-config.yaml silent: false tenant: desc: "Create a new tenant in FluxCD" cmds: - cmd: | echo "# This manifest was generated by automation. DO NOT EDIT." > kubernetes/tenants/base/{{.TENANT}}/tenant.yaml flux create tenant {{.TENANT}} \ --with-namespace={{.TENANT}}-tenant \ --with-namespace={{.TENANT_NAMESPACE}} \ --export >> kubernetes/tenants/base/{{.TENANT}}/tenant.yaml silent: true ================================================ FILE: .taskfiles/talos/Taskfile.yaml ================================================ --- version: '3.41.0' env: TALOS_DIR: "talos/generated" tasks: config: desc: "Decrypt and Loads TALOSCONFIG into $HOME directory" cmds: - sops -d {{.TALOS_DIR}}/talosconfig.enc.yaml > "$HOME/.talos/config" ================================================ FILE: .yamllint.yaml ================================================ --- # This configuration serves as a base for the entire repo ignore: | *.encrypted.yaml *.enc.yaml **/kubernetes/clusters/** talos/ .github/workflows/ .taskfiles/ extends: default rules: # Disallow duplicate dictionary keys key-duplicates: enable # Require consistent indentation indentation: spaces: 2 indent-sequences: consistent check-multi-line-strings: false # Line length line-length: max: 240 level: warning allow-non-breakable-words: true allow-non-breakable-inline-mappings: true # Trailing spaces trailing-spaces: enable # Final newline at end of file new-line-at-end-of-file: enable # Allow specific syntax for boolean values truthy: allowed-values: ['true', 'false', 'on', 'off', 'yes', 'no'] check-keys: false # Spacing for comments comments: require-starting-space: true min-spaces-from-content: 1 # Consistent spacing in braces — enforce { foo: bar } not {foo: bar} braces: min-spaces-inside: 1 max-spaces-inside: 1 min-spaces-inside-empty: 0 max-spaces-inside-empty: 0 # Consistent spacing in brackets brackets: min-spaces-inside: 0 max-spaces-inside: 0 min-spaces-inside-empty: 0 max-spaces-inside-empty: 0 # Consistent document start/end markers document-start: present: true document-end: present: false ================================================ FILE: CLAUDE.md ================================================ # CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Repository Overview This is a Kubernetes GitOps repository for a personal homelab cluster managed with FluxCD and Talos Linux. The cluster follows enterprise-grade security and observability practices, showcasing CNCF ecosystem tools. ## Architecture - **Operating System**: Talos Linux (minimal, immutable Kubernetes OS) - **GitOps**: FluxCD with Flux Operator for declarative cluster management - **Container Runtime**: containerd - **Networking**: Cilium CNI with Istio service mesh - **Storage**: Rook-Ceph, OpenEBS, democratic-csi for container-attached storage - **Monitoring**: Prometheus, Grafana, Loki, Jaeger, Thanos for observability - **Security**: Kyverno, OPA Gatekeeper for policy management, Falco & Tetragon for runtime security - **Load Balancing**: MetalLB for bare metal load balancing - **Chaos Engineering**: Litmus for chaos testing ## Directory Structure ``` ├── kubernetes/ # Kubernetes manifests and configurations │ ├── apps/ │ │ ├── base/ # Base application configurations (DRY principle) │ │ │ └── [system-name]/ # e.g., observability, kube-system, home-system │ │ │ ├── [app-name]/ │ │ │ │ ├── app/ # HelmRelease, OCIRepository, secrets, values │ │ │ │ └── ks.yaml # Flux Kustomization with dependencies │ │ │ ├── namespace.yaml │ │ │ └── kustomization.yaml │ │ └── overlays/ │ │ └── cluster-00/ # Cluster-specific overrides │ ├── bootstrap/ │ │ └── helmfile.yaml # Bootstrap Flux Operator and dependencies │ ├── clusters/ │ │ └── cluster-00/ │ │ ├── flux-system/ # Flux Operator and FluxInstance configs │ │ ├── secrets/ # Cluster secrets (SOPS encrypted) │ │ └── ks.yaml # Root Kustomization │ ├── components/ │ │ └── common/alerts/ # Shared monitoring alerts │ └── tenants/ # Multi-tenant configurations ├── talos/ # Talos Linux configuration files │ ├── generated/ # Generated Talos configs (encrypted) │ ├── integrations/ # Cilium, cert-approver integrations │ └── patches/ # iSCSI, metrics patches ├── terraform/ # Infrastructure as Code │ ├── cloudflare/ # Cloudflare DNS/CDN configuration │ └── gcp/ # GCP KMS, Thanos storage, Velero backups ├── .taskfiles/ # Task automation definitions └── docs/ # Documentation ``` ## Common Commands ### Task Management (Primary Build System) The repository uses [Task](https://taskfile.dev) for automation. All commands should be run via `task`: ```bash # FluxCD Operations task flux:bootstrap # Bootstrap Flux Operator via Helmfile task flux:secrets # Install cluster secrets (SOPS decrypt + apply) task fluxcd:bootstrap # Alternative bootstrap path task fluxcd:diff # Preview FluxCD operator changes # Talos Operations task talos:config # Decrypt and load talosconfig to ~/.talos/config # Core Operations task core:gpg # Import SOPS PGP keys task core:lint # Run yamllint # View available tasks task --list ``` **Important Variables:** - `CLUSTER`: cluster-00 (default cluster ID) - `GITHUB_USER`: xunholy - `GITHUB_REPO`: k8s-gitops - `GITHUB_BRANCH`: main ### Pre-commit Hooks The repository uses pre-commit for code quality: ```bash pre-commit run --all-files # Run all pre-commit hooks ``` Active hooks include: - YAML/JSON/TOML validation - yamllint (with `.yamllint.yaml` config) - shellcheck for shell scripts - Trailing whitespace and EOF fixes ### Secret Management Secrets are encrypted using [SOPS](https://github.com/mozilla/sops) with dual encryption (PGP + GCP KMS): ```bash # Edit encrypted files (automatically decrypts/encrypts) sops path/to/file.enc.yaml # Decrypt for viewing only sops -d path/to/file.enc.yaml ``` **SOPS Configuration:** - **PGP Key**: `0635B8D34037A9453003FB7B93CAA682FF4C9014` - **Age Key**: `age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t` - **GCP KMS**: Used for stored PGP keys - Encrypted files use `.enc.yaml` or `.enc.age.yaml` suffix ## Key Technologies & Patterns ### GitOps with FluxCD This repository uses **Flux Operator** instead of traditional `flux bootstrap`: - **FluxInstance CRDs**: Declaratively manage FluxCD components - **OCIRepository**: Used for Helm charts instead of HelmRepository (e.g., `oci://ghcr.io/prometheus-community/charts`) - **Kustomizations**: Define manifest application with SOPS decryption, post-build substitution, and dependency chains - **HelmReleases**: Reference charts via `chartRef` pointing to OCIRepository - **Root Kustomization**: Located at `kubernetes/clusters/cluster-00/ks.yaml` ### Application Deployment Pattern Each application follows this structure: 1. **Base configuration** in `kubernetes/apps/base/[system-name]/[app-name]/`: - `app/helmrelease.yaml`: Helm release definition - `app/ocirepository.yaml`: Chart source - `app/secret.enc.yaml`: Encrypted secrets - `app/values.yaml`: Helm values - `ks.yaml`: Flux Kustomization with `dependsOn`, SOPS settings, substitutions 2. **Cluster overlays** in `kubernetes/apps/overlays/cluster-00/`: Cluster-specific customizations using Kustomize patches 3. **System categories**: Apps organized into logical systems: - `kube-system`: Core Kubernetes (Cilium, metrics-server, reflector) - `network-system`: Networking (cert-manager, external-dns, oauth2-proxy, dex) - `observability`: Monitoring (Prometheus, Grafana, Loki, Jaeger, Thanos) - `security-system`: Security (Kyverno, Falco, Gatekeeper, Crowdsec) - `istio-system` & `istio-ingress`: Service mesh - `home-system`: Home automation & media - `rook-ceph`: Storage ### HelmRelease Global Defaults All HelmReleases are patched with these defaults via Kustomization: ```yaml install: crds: CreateReplace createNamespace: true replace: true strategy: RetryOnFailure timeout: 10m rollback: recreate: true force: true cleanupOnFail: true upgrade: cleanupOnFail: true crds: CreateReplace remediation: remediateLastFailure: true retries: 3 strategy: rollback ``` ### Security Practices - **Dual encryption**: SOPS with PGP (primary) + GCP KMS backup - **Never commit unencrypted secrets**: All secrets use `.enc.yaml` suffix - **Policy enforcement**: Kyverno & OPA Gatekeeper - **Runtime security**: Falco & Tetragon - **Pod security labels**: Applied to all namespaces - **Immutable OS**: Talos Linux minimal attack surface ## Development Workflow ### Bootstrap New Cluster ```bash # 1. Set environment variables (CLUSTER_ID defaults to cluster-00) # 2. Bootstrap Flux Operator task fluxcd:bootstrap # Installs flux-operator, flux-instance, cert-manager, kustomize-mutating-webhook # 3. Install cluster secrets task flux:secrets # Decrypts and applies sops-gpg, sops-age, cluster-secrets, github-auth, cluster-config # 4. Configure Talos task talos:config # Decrypts talosconfig to ~/.talos/config ``` ### Making Changes to Applications 1. **Edit base configuration** in `kubernetes/apps/base/[system-name]/[app-name]/` 2. **Use overlays** for cluster-specific customization in `kubernetes/apps/overlays/cluster-00/` 3. **Follow naming conventions**: - `ks.yaml`: Flux Kustomization resources - `kustomization.yaml`: Kustomize configuration - `*.enc.yaml`: SOPS encrypted files - `helmrelease.yaml`: Helm release definitions - `ocirepository.yaml`: OCI repository sources 4. **Ensure secrets are encrypted** before committing (use `sops` command) 5. **Run pre-commit hooks**: `pre-commit run --all-files` 6. **FluxCD auto-reconciles** from main branch after push ### Adding New Applications 1. Create directory structure: `kubernetes/apps/base/[system-name]/[app-name]/` 2. Add `app/` directory with: - `helmrelease.yaml` (with `chartRef` to OCIRepository) - `ocirepository.yaml` (chart source) - `values.yaml` (Helm values) - `secret.enc.yaml` (if needed, encrypted with SOPS) - `kustomization.yaml` 3. Create `ks.yaml` with: - `dependsOn` for dependency chain - `decryption` for SOPS secrets - `postBuild.substituteFrom` for ConfigMap/Secret references 4. Add to parent `kustomization.yaml` 5. Create overlay if cluster-specific customization needed ## Important Patterns & Conventions ### File Naming - `ks.yaml`: Flux Kustomization resources (defines how to apply manifests) - `kustomization.yaml`: Kustomize configuration (defines what resources to include) - `*.enc.yaml`: SOPS-encrypted with PGP - `*.enc.age.yaml`: SOPS-encrypted with Age - `helmfile.yaml`: Helmfile configurations (used in bootstrap) - `helmrelease.yaml`: Helm release definitions - `ocirepository.yaml`: OCI repository sources for Helm charts - `namespace.yaml`: Namespace definitions with pod security labels ### Kustomization Labels - `substitution.flux/enabled=true`: Enables SOPS decryption and variable substitution - Patches applied globally to all Kustomizations for HelmRelease defaults ### Namespace Conventions Labels applied to namespaces: - `pod-security.kubernetes.io/enforce: privileged` (or `restricted`/`baseline`) - `goldilocks.fairwinds.com/enabled: "true"` (monitoring) - `kustomize.toolkit.fluxcd.io/prune: disabled` (on flux-system) ### Dependency Management Flux Kustomizations use `dependsOn` to establish deployment order: ```yaml dependsOn: - name: cert-manager namespace: flux-system ``` ## Important Notes - **Cluster ID**: "cluster-00" is the default cluster identifier - **Branch**: `main` is the primary branch (auto-reconciled by FluxCD) - **Talos configs**: Stored encrypted in `talos/generated/` - **Bootstrap method**: Uses Flux Operator (not traditional `flux bootstrap`) - **Chart sources**: Uses OCIRepository instead of HelmRepository - **Yamllint config**: Line length warning at 240 characters, 2-space indentation - **Renovate automation**: Auto-merge enabled for digests, ignores encrypted files - **Multi-cluster ready**: Designed with overlay pattern for multiple clusters - **Enterprise patterns**: Production-grade GitOps implementation showcasing CNCF ecosystem ## External Dependencies - **Cloudflare**: DNS management and CDN services - **Google Cloud Platform**: - GCP KMS for SOPS encryption - Google Cloud Storage for Thanos long-term metrics storage - Google Cloud Storage for Velero backups - OAuth for authentication - **GitHub**: Source control, authentication, and OCI registry for Helm charts - **SOPS/age**: Secret encryption (requires PGP and/or age key setup) - **Task**: Task runner (must be installed locally) - **Helmfile**: Used for bootstrap process - **Let's Encrypt**: Certificate generation for secure communication - **NextDNS**: Malware protection and ad-blocking - **UptimeRobot**: Service monitoring ## Troubleshooting with Flux MCP This repository includes Cursor rules for troubleshooting Flux resources using the `flux-operator-mcp` tools. Key troubleshooting workflows: ### Analyzing HelmReleases 1. Check helm-controller status with `get_flux_instance` 2. Get HelmRelease resource and analyze spec, status, inventory, events 3. Check `valuesFrom` ConfigMaps and Secrets 4. Verify source (OCIRepository) status 5. Analyze managed resources from inventory 6. Check logs if resources are failing ### Analyzing Kustomizations 1. Check kustomize-controller status with `get_flux_instance` 2. Get Kustomization resource and analyze spec, status, inventory, events 3. Check `substituteFrom` ConfigMaps and Secrets 4. Verify source (GitRepository/OCIRepository) status 5. Analyze managed resources from inventory ### Comparing Resources Across Clusters Use `get_kubernetes_contexts` and `set_kubernetes_context` to switch between clusters, then compare resource specs and status. ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================
# My Own Cloud _... managed with Flux, Renovate and GitHub Actions_
[![Discord](https://img.shields.io/discord/673534664354430999?style=for-the-badge&label=discord&logo=discord&logoColor=white&color=blue)](https://discord.gg/home-operations)   [![Kubernetes](https://img.shields.io/endpoint?url=https%3A%2F%2Fkromgo.owncloud.ai%2Fkubernetes_version&style=for-the-badge&logo=kubernetes&logoColor=white&color=blue)](https://kubernetes.io/)   [![Talos](https://img.shields.io/endpoint?url=https%3A%2F%2Fkromgo.owncloud.ai%2Ftalos_version&style=for-the-badge&logo=talos&logoColor=white&color=blue)](https://talos.dev)   [![FluxCD](https://img.shields.io/endpoint?url=https%3A%2F%2Fkromgo.owncloud.ai%2Fflux_version&style=for-the-badge&logo=flux&logoColor=white&color=blue)](https://fluxcd.io/)  
[![Age-Days](https://img.shields.io/endpoint?url=https%3A%2F%2Fkromgo.owncloud.ai%2Fcluster_age_days&style=flat-square&label=Age)](https://github.com/kashalls/kromgo)   [![Uptime-Days](https://img.shields.io/endpoint?url=https%3A%2F%2Fkromgo.owncloud.ai%2Fcluster_uptime_days&style=flat-square&label=Uptime)](https://github.com/kashalls/kromgo)   [![Node-Count](https://img.shields.io/endpoint?url=https%3A%2F%2Fkromgo.owncloud.ai%2Fcluster_node_count&style=flat-square&label=Nodes)](https://github.com/kashalls/kromgo)   [![Pod-Count](https://img.shields.io/endpoint?url=https%3A%2F%2Fkromgo.owncloud.ai%2Fcluster_pod_count&style=flat-square&label=Pods)](https://github.com/kashalls/kromgo)   [![CPU-Usage](https://img.shields.io/endpoint?url=https%3A%2F%2Fkromgo.owncloud.ai%2Fcluster_cpu_usage&style=flat-square&label=CPU)](https://github.com/kashalls/kromgo)   [![Memory-Usage](https://img.shields.io/endpoint?url=https%3A%2F%2Fkromgo.owncloud.ai%2Fcluster_memory_usage&style=flat-square&label=Memory)](https://github.com/kashalls/kromgo)  
# 🍼 Overview This educational project is designed to provide a hands-on learning experience for mastering Kubernetes cluster configurations and best practices. The repository showcases a declarative implementation of a Kubernetes cluster, following GitOps principles that can be utilized with a variety of tools and workflows. The main goal of this project is to demonstrate best practices for implementing enterprise-grade security, observability, and comprehensive cluster configuration management using GitOps in a Kubernetes environment, while fostering learning and growth in the Kubernetes community. This repository leverages a range of cutting-edge open-source tools and platforms, forming a comprehensive technology stack that demonstrates the power of the [CNCF ecosystem](https://landscape.cncf.io/). ## 📖 Table of contents - [🍼 Overview](#-overview) - [📖 Table of contents](#-table-of-contents) - [🔧 Hardware](#-hardware) - [☁️ Cloud Services](#️-cloud-services) - [🖥️ Technology Stack](#️-technology-stack) - [🤖 Automation](#-automation) - [🤝 Acknowledgments](#-acknowledgments) - [👥 Contributing](#-contributing) - [🚫 Code of Conduct](#-code-of-conduct) - [💡 Reporting Issues and Requesting Features](#-reporting-issues-and-requesting-features) - [📄 License](#-license) ## 🔧 Hardware | Device | Description | Quantity | CPU | RAM | Storage | Architecture | Operating System | | --- | --- | --- | --- | --- | --- | --- | --- | | [Ubiquiti UDM-Pro-Max](https://ui.com/us/en/cloud-gateways/dream-machine-pro-max) | Router/Gateway | 1 | - | - | 8TB | - | UniFi OS | | [Ubiquiti USW-Pro-Max-48-PoE](https://ui.com/switching/pro-max-48-poe) | Network Switch | 1 | - | - | - | - | UniFi OS | | [Asus NUC 14 Pro](https://www.asus.com/displays-desktops/nucs/nuc-mini-pcs/asus-nuc-14-pro/) | Kubernetes Nodes | 3 | 14 cores | 48GB | 1TB NVMe + 1TB SSD | AMD64 | [Talos Linux](https://www.talos.dev/) | | NAS | Storage | 1 | 8 cores | 16GB | 48TB | AMD64 | [TrueNAS](https://www.truenas.com/) | | [JetKVM](https://jetkvm.com/) | Remote KVM | 3 | - | - | - | - | - |
Decommissioned Hardware | Device | Description | Quantity | CPU | RAM | Storage | Architecture | Operating System | | -------------------------------------------------------------------------------------- | ------------------ | -------- | -------- | ----- | ------- | ------------ | ------------------------------------- | | [Protectli FW6E](https://protectli.com/product/fw6e/) | Router | 1 | 4 Cores | 16GB | - | AMD64 | [VyOs](https://vyos.io/) | | [Protectli VP2410](https://protectli.com/product/vp2410/) | Kubernetes Node(s) | 3 | 4 Cores | 8GB | - | AMD64 | [Talos Linux](https://www.talos.dev/) | | [Protectli FW2B](https://protectli.com/product/fw2b/) | Kubernetes Node(s) | 3 | 2 Cores | 8GB | - | AMD64 | [Talos Linux](https://www.talos.dev/) | | [Raspberry Pi 4 Model B](https://www.raspberrypi.org/products/raspberry-pi-4-model-b/) | Kubernetes Node(s) | 4 | 4 Cores | 8GB | - | ARM64 | [Talos Linux](https://www.talos.dev/) | | [Rock Pi 4 Model C](https://rockpi.org/rockpi4#) | Kubernetes Node(s) | 6 | 4 Cores | 4GB | - | ARM64 | [Talos Linux](https://www.talos.dev/) |
## ☁️ Cloud Services Although I manage most of my infrastructure and workloads on my own, there are specific components of my setup that rely on cloud services. | Service | Description | Cost (AUD) | | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | -------------- | | [Cloudflare](https://www.cloudflare.com/) | I use Cloudflare in my home network for DNS management and to secure my domain with Cloudflare's services. | ~$69/yr | | [GCP](https://cloud.google.com/) | I use Google Cloud Platform (GCP) to manage backups using Google Cloud Storage (GCS) and employ GCP's OAuth for authentication. | ~20/yr | | [GitHub](https://github.com/) | I use GitHub for code management and version control, enabling seamless collaboration in addition to OAuth for authentication | Free | [Lets Encrypt](https://letsencrypt.org/) | I use Let's Encrypt to generate certificates for secure communication within my network. | Free | | | | Total: ~$35/mo | ## 🖥️ Technology Stack The below showcases the collection of open-source solutions currently implemented in the cluster. Each of these components has been meticulously documented, and their deployment is managed using FluxCD, which adheres to GitOps principles. The Cloud Native Computing Foundation (CNCF) has played a crucial role in the development and popularization of many of these tools, driving the adoption of cloud-native technologies and enabling projects like this one to thrive. | | Name | Description | | ------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | | | [Kubernetes](https://kubernetes.io/) | An open-source system for automating deployment, scaling, and management of containerized applications | | | [Talos Linux](https://www.talos.dev/) | Minimal, immutable Linux OS designed for Kubernetes | | | [FluxCD](https://fluxcd.io/) | GitOps continuous delivery for Kubernetes | | | [Helm](https://helm.sh) | The Kubernetes package manager | | | [Cilium](https://cilium.io/) | eBPF-based CNI providing networking, security, and observability | | | [Envoy Gateway](https://gateway.envoyproxy.io/) | Kubernetes Gateway API implementation built on Envoy proxy | | | [containerd](https://containerd.io/) | Industry-standard container runtime integrated with Talos Linux | | | [CoreDNS](https://coredns.io/) | Flexible, plugin-based DNS server for Kubernetes service discovery | | | [Rook-Ceph](https://rook.io/) | Cloud-native storage orchestration for Kubernetes using Ceph | | | [Volsync](https://volsync.readthedocs.io/) | Asynchronous data replication for Kubernetes persistent volumes | | | [Spegel](https://github.com/spegel-org/spegel) | Stateless cluster-local OCI registry mirror | | | [Prometheus](https://prometheus.io) | Monitoring system and time series database | | | [Grafana](https://grafana.com) | Analytics and monitoring dashboards | | | [cert-manager](https://cert-manager.io/) | X.509 certificate management for Kubernetes | | | [External Secrets](https://external-secrets.io/) | Synchronize secrets from external APIs (1Password) into Kubernetes | | | [ExternalDNS](https://github.com/kubernetes-sigs/external-dns) | Automatically manage DNS records from Kubernetes resources | | | [Dex](https://github.com/dexidp/dex) | OpenID Connect identity provider for authentication | | | [oauth2-proxy](https://oauth2-proxy.github.io/oauth2-proxy/) | Reverse proxy providing authentication with external OAuth2 providers | | | [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) | Secure outbound-only tunnel for exposing services without public IPs | ## 🤖 Automation This repository is automatically managed by [Renovate](https://renovatebot.com/). Renovate will keep all of the container images within this repository up to date automatically. It can also be configured to keep Helm chart dependencies up to date as well. ## 🤝 Acknowledgments A special thank you to everyone in the [Home Operation Discord](https://discord.com/invite/home-operations) community for their valuable contributions and time. Much of the inspiration for my cluster comes from fellow enthusiasts who have shared their own clusters under the k8s-at-home GitHub topic. Also I extend heartfelt thanks to all CNCF contributors for their dedication and expertise, as their collective efforts have been vital in driving innovation and success within the cloud-native ecosystem. For more ideas on deploying applications or discovering new possibilities, be sure to explore the [kubesearch.dev](https://kubesearch.dev/) search. ## 👥 Contributing Our project welcomes contributions from any member of our community. To get started contributing, please see our [Contributor Guide](.github/CONTRIBUTING.md). ### 🚫 Code of Conduct By participating in this project, you are expected to uphold the project's [**Code of Conduct**](.github/CODE_OF_CONDUCT.md). Please report any unacceptable behavior to the repository maintainer. ### 💡 Reporting Issues and Requesting Features If you encounter any issues or would like to request new features, please create an issue on the repository's issue tracker. When reporting issues, include as much information as possible, such as error messages, logs, and steps to reproduce the issue. Thank you for your interest in contributing to this project! Your contributions help make it better for everyone. ## 📄 License This repository is [Apache 2.0 licensed](./LICENSE) ================================================ FILE: Taskfile.yml ================================================ --- # yaml-language-server: $schema=https://taskfile.dev/schema.json version: '3.41.0' vars: CLUSTER: cluster-00 GITHUB_USER: xunholy GITHUB_REPO: k8s-gitops GITHUB_BRANCH: main includes: fluxcd: .taskfiles/bootstrap core: .taskfiles/core flux: .taskfiles/flux talos: .taskfiles/talos tasks: flux: desc: "Install Fluxv2 into a cluster" cmds: - task: flux:secrets - task: flux:bootstrap ================================================ FILE: docs/index.html ================================================ owncloud.ai — Cloud Native Homelab

What's running

A homelab built on Talos Linux, FluxCD, and the CNCF ecosystem. GitOps, observability, and security — all from home.

Talos Linux

Minimal, immutable Kubernetes OS with API-driven management. No SSH, no shell — just Kubernetes.

FluxCD GitOps

Declarative cluster management with Flux Operator. Every change goes through Git — review, approve, deploy.

Cilium CNI

eBPF-powered networking with transparent encryption, network policies, and Hubble observability built in.

Rook-Ceph Storage

Distributed block and object storage with replication, snapshots, and VolSync backup integration.

Full Observability

Prometheus, Grafana, Loki, and Alertmanager for metrics, logs, dashboards, and alerting.

Zero-Trust Security

SOPS-encrypted secrets, Dex SSO with GitHub OAuth, cert-manager TLS, and Envoy Gateway.

The Rack

Purpose-built for reliability and performance.

Asus NUC 14 Pro

3x Control Plane · 14 cores · 48GB RAM · 2TB storage

Ubiquiti UDM-Pro-Max

Router & Gateway · 8TB storage · UniFi OS

TrueNAS

Network attached storage · 48TB · Backup target

JetKVM

3x Remote KVM · Out-of-band management

Powered by Open Source

Talos Linux FluxCD Cilium Envoy Gateway Rook-Ceph Prometheus Grafana Loki cert-manager External Secrets ExternalDNS Dex Spegel VolSync Kopia Renovate
================================================ FILE: hack/cf-terraforming.sh ================================================ #!/bin/bash # Note: Requires setting the environment varibale CLOUDFLARE_API_TOKEN with the appropriate cloudflare scoped permissions # List of Terraform resources to iterate through # https://registry.terraform.io/providers/cloudflare/cloudflare/4.0.0/docs RESOURCE_LIST="cloudflare_access_application cloudflare_access_group cloudflare_access_mutual_tls_certificate cloudflare_access_service_token cloudflare_api_shield cloudflare_argo cloudflare_byo_ip_prefix cloudflare_certificate_pack cloudflare_custom_hostname cloudflare_custom_hostname_fallback_origin cloudflare_custom_pages cloudflare_custom_ssl cloudflare_filter cloudflare_firewall_rule cloudflare_load_balancer cloudflare_load_balancer_monitor cloudflare_load_balancer_pool cloudflare_logpush_job cloudflare_managed_headers cloudflare_origin_ca_certificate cloudflare_page_rule cloudflare_rate_limit cloudflare_record cloudflare_ruleset cloudflare_spectrum_application cloudflare_tunnel cloudflare_url_normalization_settings cloudflare_waiting_room cloudflare_worker_route cloudflare_workers_kv_namespace cloudflare_zone cloudflare_zone_settings_override" # Iterate through the list of IPs and run the command for RESOURCE in $RESOURCE_LIST; do echo "Running command on resource: $RESOURCE" cf-terraforming import --resource-type=$RESOURCE --zone=$CLOUDFLARE_ZONE_ID done ================================================ FILE: hack/delete-all.sh ================================================ #!/bin/bash # Set the target namespace NAMESPACE="flux-system" # # Get all resource types in the namespace and delete them RESOURCES=$(kubectl api-resources --verbs=list --namespaced -o name) # echo $RESOURCES | xargs -n1 -P10 kubectl delete --all --namespace=$NAMESPACE --ignore-not-found=true # For each resource type, wait for all resources to be deleted, and then remove finalizers for RESOURCE in $RESOURCES; do # Wait for all resources of this type to be deleted while [[ $(kubectl get $RESOURCE --namespace=$NAMESPACE | wc -l) -gt 1 ]] do echo "Waiting for $RESOURCE resources to be deleted..." sleep 1 done # Remove finalizers from all resources of this type kubectl get $RESOURCE --namespace=$NAMESPACE -o name | xargs -I{} kubectl patch {} --type json -p='[{"op": "remove", "path": "/metadata/finalizers"}]' done ================================================ FILE: hack/finalizer-pods.sh ================================================ #!/bin/bash # Get all namespaces in the cluster NAMESPACES=$(kubectl get namespaces -o name) # Loop over each namespace and force update the finalizer for all Pods for NAMESPACE_WITH_PREFIX in $NAMESPACES; do # Remove the prefix "namespace/" from the namespace name NAMESPACE=${NAMESPACE_WITH_PREFIX#namespace/} echo "Updating Pods in namespace $NAMESPACE" # Get all Pods in the namespace POD_NAMES=$(kubectl get pods -n $NAMESPACE -o name) # Update the finalizer for each Pod in parallel using xargs echo "$POD_NAMES" | xargs -n1 -P4 -I{} kubectl patch {} -n $NAMESPACE -p '{"metadata":{"finalizers":null}}' --type=merge done ================================================ FILE: hack/finalizer.sh ================================================ #!/bin/bash # Set the target namespace NAMESPACE="flux-system" # Get all resource types in the cluster RESOURCES=$(kubectl api-resources --verbs=list --namespaced=false -o name) # Loop over each resource type and force update the finalizer for all resources of that type for RESOURCE in $RESOURCES; do # Get all resources of this type in the target namespace RESOURCE_NAMES=$(kubectl get $RESOURCE -A -o name) # Loop over each resource name and force update the finalizer for RESOURCE_NAME in $RESOURCE_NAMES; do # Update the finalizer for each resource in parallel using xargs echo "$RESOURCE_NAME" | xargs -n1 -P4 -I{} kubectl patch {} --namespace=$NAMESPACE -p '{"metadata":{"finalizers":null}}' --type=merge done done ================================================ FILE: hack/openebs.sh ================================================ #!/bin/bash kubectl get bdc -A --no-headers | awk '{print $2}' | xargs -I {} kubectl patch -n openebs bdc {} -p '{"metadata":{"finalizers":null}}' --type=merge ================================================ FILE: hack/restart.sh ================================================ #!/bin/bash # List of IPs to iterate through IP_LIST="192.168.50.111 192.168.50.112 192.168.50.113" # Iterate through the list of IPs and run the command for IP in $IP_LIST; do echo "Running command on $IP" talosctl reboot -n $IP -e 192.168.50.111 done ================================================ FILE: hack/update.sh ================================================ #!/bin/bash set -e set -u set -o pipefail # This script upgrades Talos on a list of specified IP addresses. # Instructions https://www.talos.dev/v1.4/talos-guides/upgrading-talos/ # Note: Use the version of the documentation corrosponding with the upgrade path. # List of IPs to process readonly IP_LIST=( # "192.168.50.111" # "192.168.50.112" # "192.168.50.113" # "192.168.50.114" # "192.168.50.115" # "192.168.50.116" "192.168.50.121" "192.168.50.122" "192.168.50.123" "192.168.50.124" ) # Define the Talos installer image readonly INSTALLER_IMAGE="ghcr.io/siderolabs/installer:v1.4.0" # Upgrade Talos on each IP address for IP in "${IP_LIST[@]}"; do echo "Upgrading Talos on $IP" talosctl upgrade -n "$IP" -e "$IP" \ --image "$INSTALLER_IMAGE" \ --wait --preserve done ================================================ FILE: kubernetes/apps/base/actions-runner-system/gha-runner-scale-set/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: github-app-secret spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: github-app-secret template: data: github_app_id: '{{ .ACTIONS_RUNNER_APP_ID }}' github_app_installation_id: '{{ .ACTIONS_RUNNER_INSTALLATION_ID }}' github_app_private_key: '{{ .ACTIONS_RUNNER_PRIVATE_KEY }}' dataFrom: - extract: key: actions-runner ================================================ FILE: kubernetes/apps/base/actions-runner-system/gha-runner-scale-set/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app gha-runner-scale-set namespace: actions-runner-system spec: interval: 15m chartRef: kind: OCIRepository name: gha-runner-scale-set dependsOn: - name: gha-runner-scale-set-controller namespace: actions-runner-system values: nameOverride: gha-runner-scale-set runnerScaleSetName: gha-runner-scale-set githubConfigSecret: github-app-secret githubConfigUrl: https://github.com/xunholy/k8s-gitops maxRunners: 3 minRunners: 1 controllerServiceAccount: name: gha-runner-scale-set-controller namespace: actions-runner-system containerMode: type: kubernetes kubernetesModeWorkVolumeClaim: accessModes: ["ReadWriteOnce"] storageClassName: truenas-iscsi-csi resources: requests: storage: 1Gi template: spec: securityContext: fsGroup: 123 containers: - name: runner image: ghcr.io/home-operations/actions-runner:2.334.0@sha256:95d91d7f8d241e319ef2f4fec08f417aa1606b96fbb327643f75c303acd30002 command: ["/home/runner/run.sh"] env: - name: ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER value: "false" - name: NODE valueFrom: fieldRef: fieldPath: status.hostIP volumeMounts: - mountPath: /var/run/secrets/talos.dev name: talos readOnly: true serviceAccountName: k8s-gitops-runner volumes: - name: talos secret: secretName: k8s-gitops-runner listenerMetrics: counters: gha_started_jobs_total: labels: ["repository", "organization", "enterprise", "job_name", "event_name"] gha_completed_jobs_total: labels: ["repository", "organization", "enterprise", "job_name", "event_name", "job_result"] gauges: gha_assigned_jobs: labels: ["name", "namespace", "repository", "organization", "enterprise"] gha_running_jobs: labels: ["name", "namespace", "repository", "organization", "enterprise"] gha_registered_runners: labels: ["name", "namespace", "repository", "organization", "enterprise"] gha_busy_runners: labels: ["name", "namespace", "repository", "organization", "enterprise"] gha_min_runners: labels: ["name", "namespace", "repository", "organization", "enterprise"] gha_max_runners: labels: ["name", "namespace", "repository", "organization", "enterprise"] gha_desired_runners: labels: ["name", "namespace", "repository", "organization", "enterprise"] gha_idle_runners: labels: ["name", "namespace", "repository", "organization", "enterprise"] histograms: gha_job_startup_duration_seconds: labels: ["repository", "organization", "enterprise", "job_name", "event_name"] buckets: [0.01, 0.05, 0.1, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 15.0, 18.0, 20.0, 25.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0, 120.0, 150.0, 180.0, 210.0, 240.0, 300.0, 360.0, 420.0, 480.0, 540.0, 600.0, 900.0, 1200.0, 1800.0, 2400.0, 3000.0, 3600.0] gha_job_execution_duration_seconds: labels: ["repository", "organization", "enterprise", "job_name", "event_name", "job_result"] buckets: [0.01, 0.05, 0.1, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 12.0, 15.0, 18.0, 20.0, 25.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0, 120.0, 150.0, 180.0, 210.0, 240.0, 300.0, 360.0, 420.0, 480.0, 540.0, 600.0, 900.0, 1200.0, 1800.0, 2400.0, 3000.0, 3600.0] ================================================ FILE: kubernetes/apps/base/actions-runner-system/gha-runner-scale-set/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml - rbac.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/actions-runner-system/gha-runner-scale-set/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: gha-runner-scale-set spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 0.14.1 url: oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set ================================================ FILE: kubernetes/apps/base/actions-runner-system/gha-runner-scale-set/app/rbac.yaml ================================================ --- apiVersion: v1 kind: ServiceAccount metadata: name: k8s-gitops-runner --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: k8s-gitops-runner rules: # Flux resources - full management - apiGroups: ["kustomize.toolkit.fluxcd.io"] resources: ["*"] verbs: ["*"] - apiGroups: ["helm.toolkit.fluxcd.io"] resources: ["*"] verbs: ["*"] - apiGroups: ["source.toolkit.fluxcd.io"] resources: ["*"] verbs: ["*"] - apiGroups: ["notification.toolkit.fluxcd.io"] resources: ["*"] verbs: ["*"] # Core resources - read + create/patch - apiGroups: [""] resources: ["namespaces", "configmaps", "secrets", "serviceaccounts"] verbs: ["get", "list", "watch", "create", "update", "patch"] - apiGroups: [""] resources: ["pods", "services", "endpoints", "events", "nodes"] verbs: ["get", "list", "watch"] # Workload resources - read - apiGroups: ["apps"] resources: ["deployments", "statefulsets", "daemonsets", "replicasets"] verbs: ["get", "list", "watch"] # RBAC - read - apiGroups: ["rbac.authorization.k8s.io"] resources: ["clusterroles", "clusterrolebindings", "roles", "rolebindings"] verbs: ["get", "list", "watch"] # CRDs - read - apiGroups: ["apiextensions.k8s.io"] resources: ["customresourcedefinitions"] verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: k8s-gitops-runner roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: k8s-gitops-runner subjects: - kind: ServiceAccount name: k8s-gitops-runner namespace: actions-runner-system --- apiVersion: talos.dev/v1alpha1 kind: ServiceAccount metadata: name: k8s-gitops-runner spec: roles: ["os:admin"] ================================================ FILE: kubernetes/apps/base/actions-runner-system/gha-runner-scale-set/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: actions-runner-scale-set namespace: actions-runner-system spec: dependsOn: - name: gha-runner-scale-set-controller namespace: actions-runner-system - name: onepassword namespace: external-secrets path: "./apps/base/actions-runner-system/gha-runner-scale-set/app" wait: true targetNamespace: actions-runner-system sourceRef: kind: ExternalArtifact name: actions-runner-scale-set namespace: flux-system ================================================ FILE: kubernetes/apps/base/actions-runner-system/gha-runner-scale-set-controller/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app gha-runner-scale-set-controller spec: interval: 15m chartRef: kind: OCIRepository name: gha-runner-scale-set-controller values: fullnameOverride: gha-runner-scale-set-controller replicaCount: 1 priorityClassName: platform-cluster-critical metrics: controllerManagerAddr: ":8080" listenerAddr: ":8080" listenerEndpoint: "/metrics" flags: logLevel: "debug" logFormat: "json" ================================================ FILE: kubernetes/apps/base/actions-runner-system/gha-runner-scale-set-controller/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/actions-runner-system/gha-runner-scale-set-controller/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: gha-runner-scale-set-controller spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 0.14.1 url: oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller ================================================ FILE: kubernetes/apps/base/actions-runner-system/gha-runner-scale-set-controller/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: gha-runner-scale-set-controller namespace: actions-runner-system spec: path: "./apps/base/actions-runner-system/gha-runner-scale-set-controller/app" wait: true targetNamespace: actions-runner-system sourceRef: kind: ExternalArtifact name: gha-runner-scale-set-controller namespace: flux-system ================================================ FILE: kubernetes/apps/base/actions-runner-system/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: actions-runner-system components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/actions-runner-system/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: actions-runner-system labels: pod-security.kubernetes.io/warn: privileged pod-security.kubernetes.io/enforce: privileged kustomize.toolkit.fluxcd.io/prune: disabled ================================================ FILE: kubernetes/apps/base/ai-system/kagent/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kagent namespace: ai-system spec: interval: 1h chartRef: kind: OCIRepository name: kagent valuesFrom: - kind: ConfigMap name: kagent-values - kind: Secret name: kagent-values-secret ================================================ FILE: kubernetes/apps/base/ai-system/kagent/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: ai-system resources: - helmrelease.yaml - ocirepository.yaml configMapGenerator: - name: kagent-values files: - values.yaml=./values.yaml secretGenerator: - name: kagent-values-secret namespace: ai-system files: - values.yaml=values.enc.age.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/ai-system/kagent/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease - kind: Secret version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/ai-system/kagent/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: kagent namespace: ai-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 0.9.4 url: oci://ghcr.io/kagent-dev/kagent/helm/kagent ================================================ FILE: kubernetes/apps/base/ai-system/kagent/app/values.enc.age.yaml ================================================ providers: openAI: apiKey: PLACEHOLDER sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBDRXpYSDI2ZWFGQ2ZaOVVV NitUM290S2xIWDYwR3F4UTUyNkUzNkxKMmlBCmw3TEo2ZlI2Smt2RWVUK3lBMXVR UDhpanJhTU16a1RsT2p1RkdSczQ4UlUKLS0tIGEyVTBrTjJ5R3RIclEyUm1DbzQy WURjVy9QV0VadG5lZERmbzFKQ09oNjQKJBrP1aC9RFZropDxKb0Mm7Gmm7SMJYTI 9CKg+E8kB8+5F/BnVNCBqsbXqOXCEDMGD7rbtulR/UdwMzaIhx6ZrQ== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:21:04Z" mac: ENC[AES256_GCM,data:zfFjgC62XPfpQ+1QQY7/0L7D/2xudrc/tadEyHxngjQojMX8UyGljnwh9rJrDHqDnL0XYlN+Y52QgraqfC0yrAKUvEBL162RUv48b2WUY/gzc9xkUc0VqaDQ/9rmDFttG6D4TPsoqNLHHISGP7ZCSYFoK0jYRfPhBDwXDDUhUqA=,iv:EZAFHGTbvXbcktWRCW+XWjXtQB/ZibdCWnnyDT0DnMU=,tag:TKMiYIkxcvhw4GycP1FxvQ==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 ================================================ FILE: kubernetes/apps/base/ai-system/kagent/app/values.yaml ================================================ --- providers: default: openAI ================================================ FILE: kubernetes/apps/base/ai-system/kagent/crds/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kagent-crds namespace: ai-system labels: gitops.owncloud.ai/defaults: disabled spec: interval: 1h chartRef: kind: OCIRepository name: kagent-crds install: timeout: 10m replace: true crds: CreateReplace createNamespace: true upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: warn maxHistory: 3 ================================================ FILE: kubernetes/apps/base/ai-system/kagent/crds/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: ai-system resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/ai-system/kagent/crds/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: kagent-crds namespace: ai-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 0.9.4 url: oci://ghcr.io/kagent-dev/kagent/helm/kagent-crds ================================================ FILE: kubernetes/apps/base/ai-system/kagent/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kagent namespace: ai-system spec: path: "./apps/base/ai-system/kagent/app" wait: false dependsOn: - name: kagent-crds namespace: ai-system targetNamespace: ai-system sourceRef: kind: ExternalArtifact name: kagent namespace: flux-system --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kagent-crds namespace: ai-system spec: path: "./apps/base/ai-system/kagent/crds" wait: false targetNamespace: ai-system sourceRef: kind: ExternalArtifact name: kagent-crds namespace: flux-system ================================================ FILE: kubernetes/apps/base/ai-system/kgateway/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kgateway namespace: ai-system spec: interval: 1h chartRef: kind: OCIRepository name: kgateway valuesFrom: - kind: ConfigMap name: kgateway-values ================================================ FILE: kubernetes/apps/base/ai-system/kgateway/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: ai-system resources: - helmrelease.yaml - ocirepository.yaml configMapGenerator: - name: kgateway-values files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/ai-system/kgateway/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/ai-system/kgateway/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: kgateway namespace: ai-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 2.3.0 url: oci://ghcr.io/kgateway-dev/charts/kgateway ================================================ FILE: kubernetes/apps/base/ai-system/kgateway/app/values.yaml ================================================ --- controller: image: tag: "v2.1.1" ================================================ FILE: kubernetes/apps/base/ai-system/kgateway/crds/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kgateway-crds namespace: ai-system labels: gitops.owncloud.ai/defaults: disabled spec: interval: 1h chartRef: kind: OCIRepository name: kgateway-crds install: timeout: 10m replace: true crds: CreateReplace createNamespace: true upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: warn maxHistory: 3 ================================================ FILE: kubernetes/apps/base/ai-system/kgateway/crds/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: ai-system resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/ai-system/kgateway/crds/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: kgateway-crds namespace: ai-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 2.3.0 url: oci://ghcr.io/kgateway-dev/charts/kgateway-crds ================================================ FILE: kubernetes/apps/base/ai-system/kgateway/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kgateway namespace: ai-system spec: path: "./apps/base/ai-system/kgateway/app" wait: false dependsOn: - name: kgateway-crds namespace: ai-system targetNamespace: ai-system sourceRef: kind: ExternalArtifact name: kgateway namespace: flux-system --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kgateway-crds namespace: ai-system spec: path: "./apps/base/ai-system/kgateway/crds" wait: false targetNamespace: ai-system sourceRef: kind: ExternalArtifact name: kgateway-crds namespace: flux-system ================================================ FILE: kubernetes/apps/base/ai-system/kmcp/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kmcp namespace: ai-system spec: interval: 1h chartRef: kind: OCIRepository name: kmcp valuesFrom: - kind: ConfigMap name: kmcp-values - kind: Secret name: kmcp-values-secret ================================================ FILE: kubernetes/apps/base/ai-system/kmcp/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: ai-system resources: - helmrelease.yaml - ocirepository.yaml configMapGenerator: - name: kmcp-values files: - values.yaml=./values.yaml secretGenerator: - name: kmcp-values-secret namespace: ai-system files: - values.yaml=values.enc.age.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/ai-system/kmcp/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease - kind: Secret version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/ai-system/kmcp/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: kmcp namespace: ai-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 0.3.0 url: oci://ghcr.io/kagent-dev/kmcp/helm/kmcp ================================================ FILE: kubernetes/apps/base/ai-system/kmcp/app/values.enc.age.yaml ================================================ providers: openAI: apiKey: PLACEHOLDER sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCelZ0dmJpdFA0N1E3ZlJm clF2QS92WkQxSkN1N2EvUDRyUXhrK2ZnbXhRClY5cUZDUWtmTE5jYXFUWmhXV1NV Y3FlS3VqUUYwQVIxVFJnMGFZY0kxRU0KLS0tIFplanpSaTBVYmNsa3pvTndETmo1 ZjN1b3B5amQ1a1p0aUd3ekVwbWFJYmMKP8fsQVE/tw+FHz0keS3RRTj0sPituzPb ws3GC9k6yeHO5RHj+XubNp/M44bFG6o0Zf1hn+D3ux1M8LvGguE/Gw== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:21:04Z" mac: ENC[AES256_GCM,data:6f/Yc+wg2oCFY6lSfWPfL107/TmDA4NpDjjIhxQlpNt/R3xPRWjuc94dX99syhbg0MXU8oGwGdA1LVv8AIwRkPH31n92Qh+c4f0oMcxGk6ShTL4H1PHCwVuYMNy9q+6AKGuC9T/XFluQo32d03JgUgvJR+RuDH6ZBsv3JWbTeQc=,iv:5jiYBzRoAclR/kjXhKuW83AqLNWJfDFGZzpDXBvU2ys=,tag:08GAUl50lJ3+dLEHhNBlFg==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 ================================================ FILE: kubernetes/apps/base/ai-system/kmcp/app/values.yaml ================================================ --- ================================================ FILE: kubernetes/apps/base/ai-system/kmcp/crds/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kmcp-crds namespace: ai-system labels: gitops.owncloud.ai/defaults: disabled spec: interval: 1h chartRef: kind: OCIRepository name: kmcp-crds install: timeout: 10m replace: true crds: CreateReplace createNamespace: true upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: warn maxHistory: 3 ================================================ FILE: kubernetes/apps/base/ai-system/kmcp/crds/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: ai-system resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/ai-system/kmcp/crds/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: kmcp-crds namespace: ai-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 0.3.0 url: oci://ghcr.io/kagent-dev/kmcp/helm/kmcp-crds ================================================ FILE: kubernetes/apps/base/ai-system/kmcp/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kmcp namespace: ai-system spec: path: "./apps/base/ai-system/kmcp/app" wait: false dependsOn: - name: kmcp-crds namespace: ai-system targetNamespace: ai-system sourceRef: kind: ExternalArtifact name: kmcp namespace: flux-system --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kmcp-crds namespace: ai-system spec: path: "./apps/base/ai-system/kmcp/crds" wait: false targetNamespace: ai-system sourceRef: kind: ExternalArtifact name: kmcp-crds namespace: flux-system ================================================ FILE: kubernetes/apps/base/ai-system/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: ai-system components: - ../../../components/common resources: - namespace.yaml # - networkpolicy.yaml ================================================ FILE: kubernetes/apps/base/ai-system/n8n/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app n8n spec: interval: 1h chart: spec: chart: *app interval: 10m sourceRef: kind: HelmRepository name: community-charts namespace: ai-system version: 1.16.10 valuesFrom: - kind: ConfigMap name: n8n-values - kind: Secret name: n8n-values-secret ================================================ FILE: kubernetes/apps/base/ai-system/n8n/app/helmrepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: community-charts spec: interval: 2h url: https://community-charts.github.io/helm-charts ================================================ FILE: kubernetes/apps/base/ai-system/n8n/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: n8n annotations: external-dns.alpha.kubernetes.io/external: 'true' spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'n8n.${CLUSTER_DOMAIN}' - 'webhook.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: n8n port: 5678 weight: 100 ================================================ FILE: kubernetes/apps/base/ai-system/n8n/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: ai-system resources: - helmrelease.yaml - helmrepository.yaml - httproute.yaml configMapGenerator: - name: n8n-values files: - values.yaml=./values.yaml secretGenerator: - name: n8n-values-secret namespace: ai-system files: - values.yaml=values.enc.age.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/ai-system/n8n/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease - kind: Secret version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/ai-system/n8n/app/values.enc.age.yaml ================================================ sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtbnZ2TXZqekZMbFYyeEda L1dZdTBMWkMyZGtSUHJGYmQzaUttSnR3eDFzCjRnUFJkMWZlUW5qMjE0NnZOMmJW eFRGZU9Ha3I4eXcrYlpyNFRkOU9YSjQKLS0tIDlBS09nOTJmRFE0UkpycW5vRits T0VlSmpUU3IrWUVBa3U4S0J3WFNlbnMKleb2FhWSwssCRV5f8CB2Y1HpmRx/M4eQ mtyduWrryJZmfKdJzDv/O1qiIF54TWS1RrDuGKK/CcWGn5zK8RhOXA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:20:16Z" mac: ENC[AES256_GCM,data:KmFA+P5OgtUBEmwddvbTe52MHOMWwt6kCC0xFJa1KvQounqlVr5JGDyzoD4fcx7ylF6eN2r1tjd2XKojtkPh+J2ULqaaPevK4DaonjnVFqz1rOkTp/aAAzfBQbCOjvz7+scJBk8Js0CBUSv3lDKmV1fEgI1ebq9kyyKdAJc7i5w=,iv:dIWlyA1uUuuI5u8bnRiAOmur/3ODGPCqjQqC9wI9LhY=,tag:xPmqDn1iRxnfXcRtx7yIrw==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 ================================================ FILE: kubernetes/apps/base/ai-system/n8n/app/values.yaml ================================================ --- webhook: url: "https://webhook.${CLUSTER_DOMAIN}" ================================================ FILE: kubernetes/apps/base/ai-system/n8n/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: n8n namespace: ai-system spec: path: "./apps/base/ai-system/n8n/app" wait: false targetNamespace: ai-system sourceRef: kind: ExternalArtifact name: n8n namespace: flux-system ================================================ FILE: kubernetes/apps/base/ai-system/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: ai-system labels: kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/ai-system/ollama/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: ollama spec: interval: 1h chart: spec: chart: ollama version: 1.56.0 sourceRef: kind: HelmRepository name: ollama-charts namespace: flux-system interval: 10m values: replicaCount: 1 ollama: gpu: enabled: false models: pull: - qwen2.5:3b resources: requests: cpu: 500m memory: 4Gi limits: memory: 8Gi persistentVolume: enabled: true storageClass: ceph-block size: 30Gi ================================================ FILE: kubernetes/apps/base/ai-system/ollama/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: ollama namespace: ai-system spec: parentRefs: - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'ollama.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: ollama port: 11434 weight: 100 ================================================ FILE: kubernetes/apps/base/ai-system/ollama/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml ================================================ FILE: kubernetes/apps/base/ai-system/ollama/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: ollama namespace: ai-system spec: path: "./apps/base/ai-system/ollama/app" wait: true dependsOn: - name: rook-ceph-cluster namespace: rook-ceph targetNamespace: ai-system sourceRef: kind: ExternalArtifact name: ollama namespace: flux-system ================================================ FILE: kubernetes/apps/base/ai-system/open-webui/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: open-webui spec: interval: 1h chart: spec: chart: open-webui version: 14.5.0 sourceRef: kind: HelmRepository name: open-webui-charts namespace: flux-system interval: 10m values: ollama: enabled: false pipelines: enabled: false websocket: enabled: false ollamaUrls: - "http://ollama.ai-system.svc.cluster.local:11434" persistence: enabled: true storageClass: ceph-block size: 8Gi resources: requests: cpu: 100m memory: 256Mi limits: memory: 2Gi ================================================ FILE: kubernetes/apps/base/ai-system/open-webui/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: open-webui namespace: ai-system spec: parentRefs: - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'open-webui.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: open-webui port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/ai-system/open-webui/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml ================================================ FILE: kubernetes/apps/base/ai-system/open-webui/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: open-webui namespace: ai-system spec: path: "./apps/base/ai-system/open-webui/app" wait: true dependsOn: - name: ollama namespace: ai-system targetNamespace: ai-system sourceRef: kind: ExternalArtifact name: open-webui namespace: flux-system ================================================ FILE: kubernetes/apps/base/crossplane-system/crossplane/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app crossplane namespace: crossplane-system spec: interval: 1h chartRef: kind: OCIRepository name: crossplane values: metrics: enabled: true ================================================ FILE: kubernetes/apps/base/crossplane-system/crossplane/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: crossplane-system resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/crossplane-system/crossplane/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: crossplane namespace: crossplane-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 2.1.3 url: oci://xpkg.upbound.io/upbound/crossplane ================================================ FILE: kubernetes/apps/base/crossplane-system/crossplane/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: crossplane namespace: crossplane-system spec: path: "./apps/base/crossplane-system/crossplane/app" wait: true targetNamespace: crossplane-system sourceRef: kind: ExternalArtifact name: crossplane namespace: flux-system --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: crossplane-providers namespace: crossplane-system spec: path: "./apps/base/crossplane-system/crossplane/providers" wait: true dependsOn: - name: crossplane namespace: crossplane-system targetNamespace: crossplane-system sourceRef: kind: ExternalArtifact name: crossplane-providers namespace: flux-system ================================================ FILE: kubernetes/apps/base/crossplane-system/crossplane/packages/gitops/composition.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/apiextensions.crossplane.io/composition_v1.json apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: xgitopsclusters.gcp.xunholy.io labels: provider: gcp gitops: flux spec: writeConnectionSecretsToNamespace: crossplane-system compositeTypeRef: apiVersion: xunholy.io/v1alpha1 kind: XGitOpsCluster patchSets: - name: metadata patches: - fromFieldPath: metadata.labels - fromFieldPath: metadata.annotations resources: - base: apiVersion: container.gcp.upbound.io/v1beta1 kind: Cluster spec: forProvider: location: us-central1 ipAllocationPolicy: - {} enableAutopilot: true writeConnectionSecretToRef: namespace: crossplane-system patches: - fromFieldPath: "metadata.uid" toFieldPath: "spec.writeConnectionSecretToRef.name" transforms: - type: string string: fmt: "%s-cluster" - fromFieldPath: spec.writeConnectionSecretToRef.namespace toFieldPath: spec.writeConnectionSecretToRef.namespace # The control plane supplies the 'kubeconfig' connection secret key, which # is required by the XR. connectionDetails: - fromConnectionSecretKey: kubeconfig - base: apiVersion: helm.crossplane.io/v1beta1 kind: ProviderConfig spec: credentials: source: Secret secretRef: key: kubeconfig identity: type: GoogleApplicationCredentials source: Secret secretRef: name: gcp-credentials key: credentials.json patches: - fromFieldPath: spec.id toFieldPath: metadata.name - fromFieldPath: spec.writeConnectionSecretToRef.namespace toFieldPath: spec.credentials.secretRef.namespace # This ProviderConfig uses the above GKE cluster's connection secret as # its credentials secret. - fromFieldPath: metadata.uid toFieldPath: spec.credentials.secretRef.name transforms: - type: string string: fmt: "%s-cluster" - fromFieldPath: spec.writeConnectionSecretToRef.namespace toFieldPath: spec.identity.secretRef.namespace readinessChecks: - type: None - base: apiVersion: helm.crossplane.io/v1beta1 kind: Release spec: rollbackLimit: 3 forProvider: namespace: flux-system chart: name: flux2 repository: https://fluxcd-community.github.io/helm-charts version: "2.7.0" values: imageautomationcontroller: create: false imagereflectorcontroller: create: false patches: - fromFieldPath: metadata.uid toFieldPath: metadata.name transforms: - type: string string: fmt: "%s-flux2" - fromFieldPath: spec.id toFieldPath: spec.providerConfigRef.name - base: apiVersion: helm.crossplane.io/v1beta1 kind: Release spec: rollbackLimit: 3 forProvider: namespace: flux-system chart: name: flux2-sync repository: https://fluxcd-community.github.io/helm-charts version: "1.4.0" patches: - fromFieldPath: metadata.uid toFieldPath: metadata.name transforms: - type: string string: fmt: "%s-flux2-sync" - fromFieldPath: spec.id toFieldPath: spec.providerConfigRef.name - fromFieldPath: spec.parameters.repository toFieldPath: spec.forProvider.values.gitRepository.spec.url - fromFieldPath: spec.parameters.branch toFieldPath: spec.forProvider.values.gitRepository.spec.ref.branch - fromFieldPath: spec.parameters.path toFieldPath: spec.forProvider.values.kustomization.spec.path ================================================ FILE: kubernetes/apps/base/crossplane-system/crossplane/packages/gitops/crossplane.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/meta.pkg.crossplane.io/configuration_v1.json apiVersion: meta.pkg.crossplane.io/v1 kind: Configuration metadata: name: gitops annotations: meta.crossplane.io/maintainer: Michael Fornaro (@xUnholy) meta.crossplane.io/source: github.com/xunholy/k8s-gitops/tree/main/packages/gitops meta.crossplane.io/license: MIT meta.crossplane.io/description: My example of using crossplane spec: dependsOn: - provider: xpkg.upbound.io/upbound/provider-gcp:v0.30.0 version: ">=v0.30.0" ================================================ FILE: kubernetes/apps/base/crossplane-system/crossplane/packages/gitops/definition.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/apiextensions.crossplane.io/compositeresourcedefinition_v1.json apiVersion: apiextensions.crossplane.io/v1 kind: CompositeResourceDefinition metadata: name: xgitopsclusters.xunholy.io spec: group: xunholy.io names: kind: XGitOpsCluster plural: xgitopsclusters claimNames: kind: GitOpsCluster plural: gitopsclusters connectionSecretKeys: - kubeconfig versions: - name: v1alpha1 served: true referenceable: true schema: openAPIV3Schema: type: object properties: spec: type: object properties: id: type: string description: ID of this Cluster that other objects will use to refer to it. parameters: type: object properties: repository: description: The repository that will be synced via GitOps type: string default: "https://github.com/xunholy/k8s-gitops" branch: type: string description: The Git reference to checkout and monitor for changes default: "main" path: type: string description: Path to the directory containing the kustomization.yaml required: - repository - path required: - parameters ================================================ FILE: kubernetes/apps/base/crossplane-system/crossplane/providers/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - provider.yaml ================================================ FILE: kubernetes/apps/base/crossplane-system/crossplane/providers/provider.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/pkg.crossplane.io/provider_v1.json apiVersion: pkg.crossplane.io/v1 kind: Provider metadata: name: provider-gcp-gke spec: package: xpkg.upbound.io/upbound/provider-gcp-gke:v1.1.0 --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/pkg.crossplane.io/provider_v1.json apiVersion: pkg.crossplane.io/v1 kind: Provider metadata: name: provider-gcp-gkehub spec: package: xpkg.upbound.io/upbound/provider-gcp-gkehub:v1.1.0 --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/pkg.crossplane.io/provider_v1.json apiVersion: pkg.crossplane.io/v1 kind: Provider metadata: name: provider-helm spec: package: xpkg.upbound.io/crossplane-contrib/provider-helm:v0.18.1 --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/pkg.crossplane.io/provider_v1.json apiVersion: pkg.crossplane.io/v1 kind: Provider metadata: name: provider-github spec: package: xpkg.upbound.io/coopnorge/provider-github:v0.12.0 ================================================ FILE: kubernetes/apps/base/crossplane-system/examples/example.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/xunholy.io/gitopscluster_v1alpha1.json apiVersion: xunholy.io/v1alpha1 kind: GitOpsCluster metadata: name: gitops-cluster namespace: crossplane-system spec: id: raspbernetes parameters: repository: https://github.com/xunholy/k8s-gitops branch: main path: "kubernetes/clusters/cluster-00" compositionSelector: matchLabels: provider: gcp gitops: flux writeConnectionSecretToRef: name: gitops-cluster-connection ================================================ FILE: kubernetes/apps/base/crossplane-system/examples/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: # - project.yaml Creates an example GCP project - providerconfig.yaml # providerConfig has a dependency on the GCP keys stored in crossplane-system; And the provider CRDs being installed. ================================================ FILE: kubernetes/apps/base/crossplane-system/examples/providerconfig.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gcp.upbound.io/providerconfig_v1beta1.json apiVersion: gcp.upbound.io/v1beta1 kind: ProviderConfig metadata: name: default spec: projectID: raspbernetes credentials: source: Secret secretRef: namespace: crossplane-system name: gcp-credentials key: credentials.json ================================================ FILE: kubernetes/apps/base/crossplane-system/examples/secret.enc.age.yaml ================================================ apiVersion: v1 kind: Secret metadata: name: gcp-credentials namespace: crossplane-system data: credentials.json: ENC[AES256_GCM,data:PbCYUHgm17s56QoR3JhGCH89R5ehk3/38dszzM/mcRzmaoh5Pm3P2JOmE9EkwO0LL6JDYJHYSY5XaVex0ozSCkpAFBdpZC8Rrl+ZzFCglwZ0eC+VoVurTxFCs9lNzIOBcWIJwllvzgZwSlMH5xDIEZzuwJiV/qDntsQh5HuVyGDdLrejcVv7lhZOBwDp6/Du9ToOYonUCIIc808mtPAS/ShZgD3v6xI+4kbpUO9cbjwqRFEi+QoqjBdM1kZyJ2OkIj5IXlxpFxc1gakMfXqn4l7tH/EogUlN8UJSWgDvwBhiyt0qvSIkCyiblH/dl8NHEIvei+LOkcK2c5eJ2ypnUB8OR/fp695UEDK21d9MwM2sstdBMlDwByi4wbQYWRxrjwJfrxpZHuGnyP5GhpLg/HIJMrnd7QUohL56lplPxqOxSVtIXu8jUpijCjN5wKkILPEs4HZYMDYRLYwUYvDiT8y2mew2ywjVMZoBihimZuSfZ8QioBfBs+sTXy9oJ+3wm6VqosnOmaZWpZvnz8oigwAXYa78N38zMklyz+XV92eNZ+eHHGq00xFRuXwEsHn5tHqU54Eu+07oAS8e3kiJrj0CoBKLTLRC7aVTw3OxvqH9mY2nApPrmCEyVvFldUU5ejpyOx1ct7Z9sK/ZpN+HHywXW9SQORGj/djd4OcPtoQZkndPs/w0Aczxxt7PsPd7XUBnubvxW4EZBKlQybIiAbWC4hs2YKVkd87YElgNWseH5sJkRG9KUb3RkYy5eXz4L1pP2UMZ92HKiBHOEkINE7mIqbkC3Z1JJbFn2MoTHOnilZnbGnUBSG2v9mWZP31PqR30MvW6gbeLO0o7H3uwkWLXvIoes5gLBx7DZGjeN0YiZfwZQoMswLdSgcY/Wnq5XPhktQGzzVsckdChohHoWvPfxRKQCoiv0DsNAQEd6JupW7g4f6Ly6oR9jyyGId+kSZWdbAJq17fh5GUx9CThJSxaubp7rcQDTl7f/ZISqSVo5qzbOMkwsNQtABmgI5m3JddEjZMSLGHLtg9FULe3BsbVX5JiMe7OhQ0qUgNawg3A+W2bJM5pyWwN9XI7XbVHH/Feolj/b0BqxRBTf5LIOuEZiYUTXuKBvsv0QTQ0CPy1FC4lYZ8ClHLGO45m38o31y14YK4E4YLj4p0TOtvW1XcSEZlDvkRjIgybVb2/Am3I/PWz0vlDjyRs5bHe/GzRXEfCDJLA4bDvyMpCYr8kYGeLeQOMTwtvlIzx5i8FUovg1o/XsUVk6+he2SeEa+awYKCZVHcaspdQwh8BRcTACCrT87a/Zmj5u9NWBCN4tfMaMUWgDwEITix77hNy547w0U9Qf3kJTmAPC8B+uFXisJy8EpfYdd6JcRqqsl1Qro4KtuF9ppCyg5LWOrCjHZG5pII9d0VAesGRHkGxi4TmakfkiVxOf0LM7G09FujZYTKUfeFxYnRBHRRJ6pLo7g1vs3TDiY2HUBJKp50Q2cPHjQI4nkFXwRiJSMoVH7CUsTUoUQZEkKWtE4wBMIOgESNJyf0mWytw+F895eMaATPG2UYW2Q8x4e/EOJabyifVWJgzMqqo4km23DRbyot37lQUwIrm+ovLOkK7iW86XnYfzqovyiw9nDJfy75nn3Q9PHdesZ3GPOPuGBN3v5Yjc/QBkap6sVo0jVE8UzB1r8oytGS2wcxw6uScF9tMaarxS+LXifH2/fkiki1vHjZmvpA83iCL2NBzyLTG/M1T1rktk4FKVZVi1DNkwfsemqWtoB1C+ecsLbhH6G92Jk1wTizsGX9zlspXUbSRMSh27zJoVqS+EJfk1JD3y3tigoh8aSGJnL2gnEFj4gfldf64pOw6Q9pNpaP2Puyjjp5F00efqlRQl3tW3PQWZC2mWE/oxwcGlP4VLnYUlxdoP3LVB2B7G0RMghgc92oug8oSWNnpQRnsiErXOgDn4PuKBOQNRwGIXtgKR/wnvUSPl+HuObhN4gT06yfY1EexRc2qh1c5qfChC595x50FKtYkxkfdS7DaYOqoO8cLZQtlZyMJ/cBQ+aB9JaFlC+Cp/6IF41yKKcYG5j3YSkxH2Tum14p1C+CfYJXefZITObX42SweMb2IKySdyJpygiVnkXJrQ11nTbk9HMlwgfaxW75SoYqih+LGva+rNJRRf6y+cr3ZuUgQ+Sld5SPL82YcVhDlhklRH3PLKd8RG2dZZhtMWigasBX00aY/26EJV4qtmMp43FaV+woIhZxQ8XaQ8Ry61i5+M4gjW8j/7rOwYYyfKpPFo1c7a6YZJrsRpt4K+wTHiQ13NjtMumAjvUnSWk66hH39Z0XbDntsxe6lPyFuPEgsynwP1vCzKCicDFIlLoH02Yt/yfooS7IJgoOH3sX0IHUVx8sozgwTeiUTcykaAYN3L/bGsGRTWSyJWXxk4gWFIEfSb8ifzMofmvOzI0nm2gGxvuAapbifYn/+3IECK/VWcipTme85rm57FWJs2O7CSeGAM7C8DSq7JtoffNJsbmzJ5WjwM8KkI7bGTrEig7WhTSdZV1gvwjJbpmTSxKXyAyTVncC3D2pE03PKZ1LbTydrAGVtbvm8qgc4vHP1U1vlFUXUnQuALV+WcOKVQBNIOYtU7Uk+o5nTJkjqHdsVD3V7atXqhBJaiJpVfv4FZ2noOSQL7HBgEFzuMU1x5jYqLd1uB767svibqBodaeVNCTyoUKuVO2i62oE/LnbR4iF0cOkLoqSkz2iGU8WnkcSxYjqhROAR4gu2O16VQp8kU0KhtL6ftuzNEQVQ5HKV9BOSqQy+Rq+M/YA7k/U9wcSRPk3Pfe4a4Hgs8IGQQudgk1DCqymzxU6TheYbeBHLsDS+mnWL7C0U6qa9CQ+Xjz1SAamk4q9rit3m7EZfdf3rcurEvqkNDTv/ornezfBgwobHuLv4htrdFp/JnRvmDybL+UIwiuM+m8H2bIo/uQL7HGKOIm+mWS10FuDeGiZ4S1pt89QxyOGdpayBUc38gNqEQxTOfgSekLKltJvos5aE3Y+OFQwSSctuzA+WlXPsdEWJiBwxJGnVoWd45AB09JlwmJj8/jgbEuRivEWPb+xPpJvtSJworVkQPLuT/8LtIdOWETJM5nTuvUZi/H/ZSWuaZKAcXnx6uxB844epk+Kktf2jm+NQ93jMObIH7yd/EdqqEa3pwtqg5Zj4J/GEmRkut9XW+9MTfEXQWuvM1PRPa2xa45rz9Kg6i95bk57R9D91LFcgqJI33DhRkemtVyMnhhyt8Rh6jCiBXvraBnozvhBlkgom7a22wWvdgkRutB8A5p9giCoyq9ltIh/djuYl/Qg4dkWDeGLY0qkLOYutaqHUp64CU7+QY30EECwu7RidcRhCtNMLnZ6CKPrsZZV2revWGiwkSQYsjs7WVQCq6dTVMAVVtRjD+XCYYpXciJhVXUP2F8SmiUSKuMlz/+fT8tnxn/B7+AzMVlWAHsSbef2DPwc4uAsqVyCuUHwNcpyqNh+ha7QDsblUftBndqoglX/0/JxeyybnPp1pQfkvdDfHi7VyIdxqfL34gUkdfJyUD7+gSICqRkkwyFzErWyjcN9Fsgd+AxKEG2XH5DViUXBqMcThzcwMEn/KutFDKLqENGeWBG/JFUw6KrmfKZIhoWUArR8c0ycTKZQCGiGA7MxtVT5CEtVcpVl5UlWyezO4Zf+zQJWopuW3CTb+gFGRNn0hlLJsUvcvmT3EpKspwk/ubirDX5DQoS2ck2oPYGXnO+gqq+Xf3ZVv+z6SZ6i8Bdx1BCg67kJwmu8HtHC2wN4Msqg05ED95mUbdSK1KxEg2dJWnbpQ13pvovLFrMTEf7bsU11ylWFSOm7+RbsZdUygqaAH8dWu0mZe17x19AXczN/nvFVWSuRvKMgCwlOVNgVHu6wTTX3r2qVc9GCM2sO9FUD4ujeX01DbuDyUJpQIp2dv5Itd6I1w7b20WtsQ2J8CdUCgjyZgXo1/Z/k6DzEViLqFFnQmd51kdqUhWpQgxlpaTncNlZn4YHC6DTrv91TFzwoPHHOsSsP5zP2In3JHE3hf3qDxiFFu311lhbbUYgF6/sK2/lGcoDdh34EMwmokZjUV9tXZCs8=,iv:9TKIRMl2rTuNRXt95gpsVY/VxFBDO3Zj1NVPtTcAPQo=,tag:ZFC2mXiNH+uUF0TjvlvrXA==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2S1BmMVJ1Z3VGVnhMQXoy L0pIa01zUTc0eWRhUFErWGRKaVJma0VEOVVVCjlna1ByaklDUWEwR1hLL3ZJU0VT WVl0ZytFalUza1ZYdS9VQk8vQUJTRFUKLS0tIE5vVHYxS0MxMkUyTFZrWkUraFZB c3dEZzB6Z2didkZqOXh4RUkrSmM2eEUK+vajIT1DULbYE4TFn2/+/DIsKStIZrdY QzXbh6PC04l8cY4n/MUbj4kjUwUqQLCzgS7fT8z1pVzHJHWSJ4+HEg== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:21:04Z" mac: ENC[AES256_GCM,data:uECxrCqQ3Gifr2iiKcIQlMP1LpPA6nMmNKuqnHCM09rX03BmK5UTmOK3wBSUiSJvhPPszeZ+ZdxrcmxG0oj43PUnLtuGD4MPGZPAuiR7PG949dyjLgwPLSZ217c3g1G/CCSwP+RwoPfdfBJazT7VNOAqbwp0v96hBwHN5b9G6WE=,iv:jlU6ffX5XIARksOt3BIspOh+rzkRaSxzEadBYtU/bX0=,tag:woF5C8D3ZBk7nXbS8Df6aQ==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 ================================================ FILE: kubernetes/apps/base/crossplane-system/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: crossplane-system components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/crossplane-system/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: crossplane-system labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/democratic-csi/democratic-csi/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app democratic-csi namespace: democratic-csi spec: interval: 5m chart: spec: chart: *app interval: 10m sourceRef: kind: HelmRepository name: democratic-csi-charts namespace: flux-system version: 0.15.1 dependsOn: - name: snapshot-controller namespace: kube-system valuesFrom: - kind: ConfigMap name: democratic-csi-values ================================================ FILE: kubernetes/apps/base/democratic-csi/democratic-csi/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - secret.enc.age.yaml configMapGenerator: - name: democratic-csi-values namespace: democratic-csi files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/democratic-csi/democratic-csi/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/democratic-csi/democratic-csi/app/secret.enc.age.yaml ================================================ apiVersion: v1 kind: Secret metadata: name: driver-config namespace: democratic-csi type: Opaque stringData: driver-config-file.yaml: ENC[AES256_GCM,data:9LxTOPdoL94u9MbztY3vqQF8VY3LsCqcECMt0PXFkh9b26oEJ+lCuFxKYHMvBpdlGSJpXMzhkhHy7I+FhsAdjnYHXvOuowSaJ7C3+xduqfxS7woRXgh8Kwat/AgE2HtQWxn/NPaqNlDAod6Exqa0Qrh8gseRkjxXkGzM1EdotZuMHD+2kdCLEiFWtEwmzrKxXGQbPscigWabGyTpbCSrHgJgd67bB2Pcgr0QLKlD6PtYHDzD2B0kLuflvYhGZDDhK0Npw9X5/Ah4Wj1bZQrqkVOIBU6sgCA/aW+ZnPt+Tq90iqW8VU+ICereDQixYiVJMbYliwD7dSngC6gNxbJQ4pbGCc9aTkpMcCDnqjUrD0xKJb1VI1BNa8/aIvUN4SiuVofTkpKVlfXpOtfYWNEPMKZVmLMJcAqW0Ge+ivqJ3kIg9AcXdtMiRlL20pKqxC+RTb1Ng2H1ytN+yWWelBr9PlfnNPbfoNSp1RAghcpj+R23BI5GcZHZ7j/6PvTmAgoM0MBhL09ob4KN4btTFhadfxZeb3VJxG7zN/2yAgVQfu3VIDvwOGMFYUO1NB1TdFWY8hq3VmFMavt7fYsyxfXhP+Bym8NJdEsmHUfrpVr3HzP6w5iZbDAEIurjIKkT2KOjtgaxKZgdigI2vLP4fKeSm7fV/Sv7euFf+lTSdGLMuf0DUmxdUhCylY/VmxI2BPU4QymXuVTmle8PvQMo+WC5dHdbK/SdMs7qGj9pFkRYggbsTkv4URtqn72UUgmWoRvQZpS8yyeykeX1QOZRoiTk8TuSH87m5BgI1sd+31g+jrUjI4y7pRnG0u5QRZYyG2EelE/Adpj0nZQG+mJtCuIfk6TsN1SiD4o7V6jssz41KthjLnlTWWjlECvciQBk/ocuAb9V/PeTrZZb0/XdN3Qh0SfrTYA6HGs4PeBbpeVCMcDFSkqhf5so0rFsIsq9hcrMW8StOg==,iv:6AKoDWA/gkDLn562nhMOJaCxGaJG2v+BY4/yEzyjyKo=,tag:fqw1QPgjZUnhLgdo+QDWyw==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZa05aZFRqS2dSb09FeE4x S0JaZUhnaStVUStGa05wZGIrYkxieUNOTVVnCmpCdlBJNTBDVDRCbzFjQ1Z3OW1J Zkt2a1JtYlY4Z2M2QXYxYlVxTlRWZ0EKLS0tIGFFZEordW9STjJWaFI4N1F2RDBz NkpCcEo0ZXpEUVM3dkdlakY1ZlE5R0EKvnhcw/TAnL/Z46q0JWgexRn1D6ErnmhM j6q1i6K5+g3XfDvGh/zQMpE12kLBQgdP7a1OVVry8vSPrfF0SJ91MQ== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:21:04Z" mac: ENC[AES256_GCM,data:9qq99yJD6A6/mbOTMLHMcCEeBR64a45ACgSBveSSn4GUSBZYm2Yc2VhXoxHHXqjwPs90gwKeAvhW07XPUNd8zkMqW/WuIruvvIpX4zTaclqTH2WQSgt1xigH8IJRZqIvHgs+adHvGTQMd0E4fFpCkSc2MpTNnEeKkx8WDj8q4TY=,iv:Gwr0jqxkGPn088zx8q9SZofEcH/hukNozQzFwhue8Fg=,tag:bBCV7jBXtZwt6SLwffgR/Q==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 ================================================ FILE: kubernetes/apps/base/democratic-csi/democratic-csi/app/values.yaml ================================================ controller: priorityClassName: platform-cluster-critical csiDriver: name: "org.democratic-csi.iscsi" node: driver: extraEnv: - name: ISCSIADM_HOST_STRATEGY value: nsenter - name: ISCSIADM_HOST_PATH value: /usr/local/sbin/iscsiadm iscsiDirHostPath: /var/iscsi iscsiDirHostPathType: "" hostPID: true priorityClassName: platform-node-critical tolerations: - key: "node-role.kubernetes.io/control-plane" operator: "Exists" effect: "NoSchedule" driver: existingConfigSecret: driver-config config: # please see the most up-to-date example of the corresponding config here: # https://github.com/democratic-csi/democratic-csi/tree/master/examples # YOU MUST COPY THE DATA HERE INLINE! driver: freenas-api-iscsi storageClasses: - name: truenas-iscsi-csi defaultClass: false reclaimPolicy: Retain volumeBindingMode: Immediate allowVolumeExpansion: true parameters: # for block-based storage can be ext3, ext4, xfs # for nfs should be nfs fsType: ext4 detachedVolumesFromSnapshots: "false" mountOptions: [] secrets: controller-expand-secret: null controller-publish-secret: null node-publish-secret: null node-stage-secret: null provisioner-secret: null volumeSnapshotClasses: - name: truenas-iscsi deletionPolicy: Retain parameters: detachedSnapshots: "true" ================================================ FILE: kubernetes/apps/base/democratic-csi/democratic-csi/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: democratic-csi namespace: democratic-csi spec: path: "./apps/base/democratic-csi/democratic-csi/app" wait: true targetNamespace: democratic-csi sourceRef: kind: ExternalArtifact name: democratic-csi namespace: flux-system ================================================ FILE: kubernetes/apps/base/democratic-csi/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: democratic-csi components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/democratic-csi/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: democratic-csi labels: kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/development/backstage/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app backstage namespace: development spec: interval: 15m chart: spec: chart: backstage version: 2.7.0 sourceRef: kind: HelmRepository name: backstage-chart namespace: flux-system values: serviceAccount: create: true metrics: serviceMonitor: enabled: true ================================================ FILE: kubernetes/apps/base/development/backstage/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backstage namespace: development spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'backstage.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: backstage port: 7007 weight: 100 ================================================ FILE: kubernetes/apps/base/development/backstage/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml ================================================ FILE: kubernetes/apps/base/development/backstage/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: backstage namespace: flux-system spec: path: "./apps/base/development/backstage/app" wait: true targetNamespace: development sourceRef: kind: ExternalArtifact name: backstage namespace: flux-system ================================================ FILE: kubernetes/apps/base/development/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: development components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/development/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: development labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/development/open-feature-operator/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: open-feature-operator spec: interval: 1h chart: spec: chart: open-feature-operator version: v0.9.1 sourceRef: kind: HelmRepository name: openfeature-charts namespace: flux-system interval: 10m values: defaultResources: requests: cpu: 10m memory: 64Mi limits: memory: 128Mi ================================================ FILE: kubernetes/apps/base/development/open-feature-operator/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: kubernetes/apps/base/development/open-feature-operator/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: open-feature-operator namespace: development spec: path: "./apps/base/development/open-feature-operator/app" wait: true dependsOn: - name: cert-manager namespace: network-system targetNamespace: development sourceRef: kind: ExternalArtifact name: open-feature-operator namespace: flux-system ================================================ FILE: kubernetes/apps/base/development/vcluster/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app vcluster namespace: development spec: interval: 15m chart: spec: chart: vcluster-k8s version: 0.19.10 sourceRef: kind: HelmRepository name: loft-charts namespace: flux-system ================================================ FILE: kubernetes/apps/base/development/vcluster/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: kubernetes/apps/base/development/vcluster/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: vcluster namespace: flux-system spec: path: "./apps/base/development/vcluster/app" wait: true targetNamespace: development sourceRef: kind: ExternalArtifact name: vcluster namespace: flux-system ================================================ FILE: kubernetes/apps/base/external-secrets/external-secrets/app/grafanadashboard.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: external-secrets spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS configMapRef: name: external-secrets-dashboard key: external-secrets.json ================================================ FILE: kubernetes/apps/base/external-secrets/external-secrets/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app external-secrets spec: interval: 5m chartRef: kind: OCIRepository name: external-secrets valuesFrom: - kind: ConfigMap name: external-secrets-values ================================================ FILE: kubernetes/apps/base/external-secrets/external-secrets/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - grafanadashboard.yaml - helmrelease.yaml - ocirepository.yaml - pdb.yaml configMapGenerator: - name: external-secrets-values files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/external-secrets/external-secrets/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/external-secrets/external-secrets/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: external-secrets spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 2.5.0 url: oci://ghcr.io/external-secrets/charts/external-secrets ================================================ FILE: kubernetes/apps/base/external-secrets/external-secrets/app/pdb.yaml ================================================ --- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: external-secrets-webhook spec: minAvailable: 1 selector: matchLabels: app.kubernetes.io/instance: external-secrets app.kubernetes.io/name: external-secrets-webhook ================================================ FILE: kubernetes/apps/base/external-secrets/external-secrets/app/values.yaml ================================================ priorityClassName: platform-cluster-critical leaderElect: true serviceMonitor: enabled: true grafanaDashboard: enabled: true certController: serviceMonitor: enabled: true webhook: replicaCount: 2 serviceMonitor: enabled: true ================================================ FILE: kubernetes/apps/base/external-secrets/external-secrets/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: external-secrets namespace: external-secrets spec: path: "./apps/base/external-secrets/external-secrets/app" wait: true targetNamespace: external-secrets sourceRef: kind: ExternalArtifact name: external-secrets namespace: flux-system ================================================ FILE: kubernetes/apps/base/external-secrets/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: external-secrets components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/external-secrets/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: external-secrets labels: kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/external-secrets/onepassword/app/clustersecretstore.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/clustersecretstore_v1.json apiVersion: external-secrets.io/v1 kind: ClusterSecretStore metadata: name: onepassword spec: provider: onepassword: connectHost: http://onepassword.external-secrets.svc.cluster.local vaults: kubernetes: 1 auth: secretRef: connectTokenSecretRef: name: onepassword-connect-token namespace: external-secrets key: token ================================================ FILE: kubernetes/apps/base/external-secrets/onepassword/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: onepassword spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: onepassword-secret template: data: 1password-credentials.json: '{{ .OP_CREDENTIALS_JSON }}' token: '{{ .OP_CONNECT_TOKEN }}' dataFrom: - extract: key: 1password ================================================ FILE: kubernetes/apps/base/external-secrets/onepassword/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app onepassword spec: interval: 5m chartRef: kind: OCIRepository name: app-template namespace: flux-system valuesFrom: - kind: ConfigMap name: onepassword-values ================================================ FILE: kubernetes/apps/base/external-secrets/onepassword/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - clustersecretstore.yaml - externalsecret.yaml - helmrelease.yaml configMapGenerator: - name: onepassword-values files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/external-secrets/onepassword/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/external-secrets/onepassword/app/values.yaml ================================================ controllers: onepassword: strategy: RollingUpdate annotations: reloader.stakater.com/auto: "true" containers: api: image: repository: ghcr.io/1password/connect-api tag: 1.8.2@sha256:fabf0a353791f7d70851767c6d58595eb386a86ba4ada4a8ca41b3668a096b5d env: XDG_DATA_HOME: &configDir /config OP_HTTP_PORT: &apiPort 80 OP_BUS_PORT: 11220 OP_BUS_PEERS: localhost:11221 OP_SESSION: valueFrom: secretKeyRef: name: connect-server-credentials key: 1password-credentials.json probes: liveness: enabled: true custom: true spec: httpGet: path: /heartbeat port: *apiPort initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: enabled: true custom: true spec: httpGet: path: /health port: *apiPort initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 resources: &resources requests: cpu: 10m limits: memory: 64Mi securityContext: &securityContext allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } sync: image: repository: ghcr.io/1password/connect-sync tag: 1.8.2@sha256:3844a6410e119ccec72011737d5b46afe4be12cb0f54f681fe3ce999280449d8 env: XDG_DATA_HOME: *configDir OP_HTTP_PORT: &syncPort 8081 OP_BUS_PORT: 11221 OP_BUS_PEERS: localhost:11220 OP_SESSION: valueFrom: secretKeyRef: name: connect-server-credentials key: 1password-credentials.json probes: liveness: enabled: true custom: true spec: httpGet: path: /heartbeat port: *syncPort initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: enabled: true custom: true spec: httpGet: path: /health port: *syncPort initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 resources: *resources securityContext: *securityContext defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 999 runAsGroup: 999 service: app: ports: http: port: *apiPort persistence: config: type: emptyDir globalMounts: - path: *configDir ================================================ FILE: kubernetes/apps/base/external-secrets/onepassword/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: onepassword namespace: external-secrets spec: path: "./apps/base/external-secrets/onepassword/app" wait: true targetNamespace: external-secrets dependsOn: - name: external-secrets namespace: external-secrets sourceRef: kind: ExternalArtifact name: onepassword namespace: flux-system ================================================ FILE: kubernetes/apps/base/flux-system/artifact-generator/artifactgenerator.yaml ================================================ --- apiVersion: source.extensions.fluxcd.io/v1beta1 kind: ArtifactGenerator metadata: name: k8s-gitops namespace: flux-system spec: sources: - alias: repo kind: OCIRepository name: flux-system artifacts: - name: actions-runner-scale-set originRevision: "@repo" copy: - from: "@repo/apps/base/actions-runner-system/gha-runner-scale-set/app/" to: "@artifact/apps/base/actions-runner-system/gha-runner-scale-set/app/" - name: adminer originRevision: "@repo" copy: - from: "@repo/apps/base/game-servers/adminer/app/" to: "@artifact/apps/base/game-servers/adminer/app/" - name: autobrr originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/autobrr/app/" to: "@artifact/apps/base/home-system/autobrr/app/" - name: azerothcore originRevision: "@repo" copy: - from: "@repo/apps/base/game-servers/azerothcore/app/" to: "@artifact/apps/base/game-servers/azerothcore/app/" - name: backstage originRevision: "@repo" copy: - from: "@repo/apps/base/development/backstage/app/" to: "@artifact/apps/base/development/backstage/app/" - name: bazarr originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/bazarr/app/" to: "@artifact/apps/base/home-system/bazarr/app/" - name: blackbox-exporter originRevision: "@repo" copy: - from: "@repo/apps/base/observability/blackbox-exporter/app/" to: "@artifact/apps/base/observability/blackbox-exporter/app/" - name: cert-manager originRevision: "@repo" copy: - from: "@repo/apps/base/network-system/cert-manager/app/" to: "@artifact/apps/base/network-system/cert-manager/app/" - name: cilium originRevision: "@repo" copy: - from: "@repo/apps/base/kube-system/cilium/app/" to: "@artifact/apps/base/kube-system/cilium/app/" - name: cloudflare-tunnel originRevision: "@repo" copy: - from: "@repo/apps/base/network-system/cloudflare-tunnel/app/" to: "@artifact/apps/base/network-system/cloudflare-tunnel/app/" - name: cmangos originRevision: "@repo" copy: - from: "@repo/apps/base/game-servers/cmangos/app/" to: "@artifact/apps/base/game-servers/cmangos/app/" - name: cmangos-ptr originRevision: "@repo" copy: - from: "@repo/apps/base/game-servers/cmangos-ptr/app/" to: "@artifact/apps/base/game-servers/cmangos-ptr/app/" - name: crossplane-providers originRevision: "@repo" copy: - from: "@repo/apps/base/crossplane-system/crossplane/providers/" to: "@artifact/apps/base/crossplane-system/crossplane/providers/" - name: crossplane originRevision: "@repo" copy: - from: "@repo/apps/base/crossplane-system/crossplane/app/" to: "@artifact/apps/base/crossplane-system/crossplane/app/" - name: crowdsec originRevision: "@repo" copy: - from: "@repo/apps/base/security-system/crowdsec/app/" to: "@artifact/apps/base/security-system/crowdsec/app/" - name: democratic-csi originRevision: "@repo" copy: - from: "@repo/apps/base/democratic-csi/democratic-csi/app/" to: "@artifact/apps/base/democratic-csi/democratic-csi/app/" - name: descheduler originRevision: "@repo" copy: - from: "@repo/apps/base/kube-system/descheduler/app/" to: "@artifact/apps/base/kube-system/descheduler/app/" - name: dex-k8s-authenticator originRevision: "@repo" copy: - from: "@repo/apps/base/network-system/dex-k8s-authenticator/app/" to: "@artifact/apps/base/network-system/dex-k8s-authenticator/app/" - name: dex originRevision: "@repo" copy: - from: "@repo/apps/base/network-system/dex/app/" to: "@artifact/apps/base/network-system/dex/app/" - name: echo-server originRevision: "@repo" copy: - from: "@repo/apps/base/network-system/echo-server/app/" to: "@artifact/apps/base/network-system/echo-server/app/" - name: emberstone-portal originRevision: "@repo" copy: - from: "@repo/apps/base/game-servers/emberstone-portal/app/" to: "@artifact/apps/base/game-servers/emberstone-portal/app/" - name: enemy-territory originRevision: "@repo" copy: - from: "@repo/apps/base/game-servers/enemy-territory/app/" to: "@artifact/apps/base/game-servers/enemy-territory/app/" - name: envoy-gateway originRevision: "@repo" copy: - from: "@repo/apps/base/network-system/envoy-gateway/app/" to: "@artifact/apps/base/network-system/envoy-gateway/app/" - name: external-dns-unifi originRevision: "@repo" copy: - from: "@repo/apps/base/network-system/external-dns-unifi/app/" to: "@artifact/apps/base/network-system/external-dns-unifi/app/" - name: external-dns originRevision: "@repo" copy: - from: "@repo/apps/base/network-system/external-dns/app/" to: "@artifact/apps/base/network-system/external-dns/app/" - name: external-secrets originRevision: "@repo" copy: - from: "@repo/apps/base/external-secrets/external-secrets/app/" to: "@artifact/apps/base/external-secrets/external-secrets/app/" - name: falco-exporter originRevision: "@repo" copy: - from: "@repo/apps/base/security-system/falco-exporter/app/" to: "@artifact/apps/base/security-system/falco-exporter/app/" - name: falco originRevision: "@repo" copy: - from: "@repo/apps/base/security-system/falco/app/" to: "@artifact/apps/base/security-system/falco/app/" - name: flux-instance-extras originRevision: "@repo" copy: - from: "@repo/apps/base/flux-system/flux-instance/extras/" to: "@artifact/apps/base/flux-system/flux-instance/extras/" - name: gatekeeper originRevision: "@repo" copy: - from: "@repo/apps/base/security-system/gatekeeper/app/" to: "@artifact/apps/base/security-system/gatekeeper/app/" - name: gha-runner-scale-set-controller originRevision: "@repo" copy: - from: "@repo/apps/base/actions-runner-system/gha-runner-scale-set-controller/app/" to: "@artifact/apps/base/actions-runner-system/gha-runner-scale-set-controller/app/" - name: grafana-instance originRevision: "@repo" copy: - from: "@repo/apps/base/observability/grafana/instance/" to: "@artifact/apps/base/observability/grafana/instance/" - name: grafana originRevision: "@repo" copy: - from: "@repo/apps/base/observability/grafana/app/" to: "@artifact/apps/base/observability/grafana/app/" - name: harbor originRevision: "@repo" copy: - from: "@repo/apps/base/harbor/harbor/app/" to: "@artifact/apps/base/harbor/harbor/app/" - name: home-assistant originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/home-assistant/app/" to: "@artifact/apps/base/home-system/home-assistant/app/" - name: jellyseerr originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/jellyseerr/app/" to: "@artifact/apps/base/home-system/jellyseerr/app/" - name: kagent-crds originRevision: "@repo" copy: - from: "@repo/apps/base/ai-system/kagent/crds/" to: "@artifact/apps/base/ai-system/kagent/crds/" - name: kagent originRevision: "@repo" copy: - from: "@repo/apps/base/ai-system/kagent/app/" to: "@artifact/apps/base/ai-system/kagent/app/" - name: keda originRevision: "@repo" copy: - from: "@repo/apps/base/kube-system/keda/app/" to: "@artifact/apps/base/kube-system/keda/app/" - name: kgateway-crds originRevision: "@repo" copy: - from: "@repo/apps/base/ai-system/kgateway/crds/" to: "@artifact/apps/base/ai-system/kgateway/crds/" - name: kgateway originRevision: "@repo" copy: - from: "@repo/apps/base/ai-system/kgateway/app/" to: "@artifact/apps/base/ai-system/kgateway/app/" - name: kguardian originRevision: "@repo" copy: - from: "@repo/apps/base/kguardian/kguardian/app/" to: "@artifact/apps/base/kguardian/kguardian/app/" - name: kmcp-crds originRevision: "@repo" copy: - from: "@repo/apps/base/ai-system/kmcp/crds/" to: "@artifact/apps/base/ai-system/kmcp/crds/" - name: kmcp originRevision: "@repo" copy: - from: "@repo/apps/base/ai-system/kmcp/app/" to: "@artifact/apps/base/ai-system/kmcp/app/" - name: kopia originRevision: "@repo" copy: - from: "@repo/apps/base/volsync-system/kopia/app/" to: "@artifact/apps/base/volsync-system/kopia/app/" - name: kromgo originRevision: "@repo" copy: - from: "@repo/apps/base/observability/kromgo/app/" to: "@artifact/apps/base/observability/kromgo/app/" - name: kube-prometheus-stack originRevision: "@repo" copy: - from: "@repo/apps/base/observability/kube-prometheus-stack/app/" to: "@artifact/apps/base/observability/kube-prometheus-stack/app/" - name: kubelet-csr-approver originRevision: "@repo" copy: - from: "@repo/apps/base/kube-system/kubelet-csr-approver/app/" to: "@artifact/apps/base/kube-system/kubelet-csr-approver/app/" - name: kyverno originRevision: "@repo" copy: - from: "@repo/apps/base/security-system/kyverno/app/" to: "@artifact/apps/base/security-system/kyverno/app/" - name: loki originRevision: "@repo" copy: - from: "@repo/apps/base/observability/loki/app/" to: "@artifact/apps/base/observability/loki/app/" - name: metrics-server originRevision: "@repo" copy: - from: "@repo/apps/base/kube-system/metrics-server/app/" to: "@artifact/apps/base/kube-system/metrics-server/app/" - name: minecraft-bedrock-broadcaster originRevision: "@repo" copy: - from: "@repo/apps/base/game-servers/minecraft-bedrock-broadcaster/app/" to: "@artifact/apps/base/game-servers/minecraft-bedrock-broadcaster/app/" - name: minecraft-bedrock originRevision: "@repo" copy: - from: "@repo/apps/base/game-servers/minecraft-bedrock/app/" to: "@artifact/apps/base/game-servers/minecraft-bedrock/app/" - name: minecraft-pixelmon originRevision: "@repo" copy: - from: "@repo/apps/base/game-servers/minecraft-pixelmon/app/" to: "@artifact/apps/base/game-servers/minecraft-pixelmon/app/" - name: minecraft-proxy originRevision: "@repo" copy: - from: "@repo/apps/base/game-servers/minecraft-proxy/app/" to: "@artifact/apps/base/game-servers/minecraft-proxy/app/" - name: minecraft-rcon-web originRevision: "@repo" copy: - from: "@repo/apps/base/game-servers/minecraft-rcon-web/app/" to: "@artifact/apps/base/game-servers/minecraft-rcon-web/app/" - name: minecraft-router originRevision: "@repo" copy: - from: "@repo/apps/base/game-servers/minecraft-router/app/" to: "@artifact/apps/base/game-servers/minecraft-router/app/" - name: minecraft originRevision: "@repo" copy: - from: "@repo/apps/base/game-servers/minecraft/app/" to: "@artifact/apps/base/game-servers/minecraft/app/" - name: mosquitto originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/mosquitto/app/" to: "@artifact/apps/base/home-system/mosquitto/app/" - name: multus-networks originRevision: "@repo" copy: - from: "@repo/apps/base/network-system/multus/networks/" to: "@artifact/apps/base/network-system/multus/networks/" - name: multus originRevision: "@repo" copy: - from: "@repo/apps/base/network-system/multus/app/" to: "@artifact/apps/base/network-system/multus/app/" - name: n8n originRevision: "@repo" copy: - from: "@repo/apps/base/ai-system/n8n/app/" to: "@artifact/apps/base/ai-system/n8n/app/" - name: nginx-ingress originRevision: "@repo" copy: - from: "@repo/apps/base/nginx-ingress/nginx-ingress/app/" to: "@artifact/apps/base/nginx-ingress/nginx-ingress/app/" - name: oauth2-proxy originRevision: "@repo" copy: - from: "@repo/apps/base/network-system/oauth2-proxy/app/" to: "@artifact/apps/base/network-system/oauth2-proxy/app/" - name: ollama originRevision: "@repo" copy: - from: "@repo/apps/base/ai-system/ollama/app/" to: "@artifact/apps/base/ai-system/ollama/app/" - name: onepassword originRevision: "@repo" copy: - from: "@repo/apps/base/external-secrets/onepassword/app/" to: "@artifact/apps/base/external-secrets/onepassword/app/" - name: open-feature-operator originRevision: "@repo" copy: - from: "@repo/apps/base/development/open-feature-operator/app/" to: "@artifact/apps/base/development/open-feature-operator/app/" - name: open-webui originRevision: "@repo" copy: - from: "@repo/apps/base/ai-system/open-webui/app/" to: "@artifact/apps/base/ai-system/open-webui/app/" - name: otel originRevision: "@repo" copy: - from: "@repo/apps/base/observability/otel/app/" to: "@artifact/apps/base/observability/otel/app/" - name: preview-system originRevision: "@repo" copy: - from: "@repo/apps/base/preview-system/app/" to: "@artifact/apps/base/preview-system/app/" - name: prowlarr originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/prowlarr/app/" to: "@artifact/apps/base/home-system/prowlarr/app/" - name: qbittorrent originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/qbittorrent/app/" to: "@artifact/apps/base/home-system/qbittorrent/app/" - name: qui originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/qui/app/" to: "@artifact/apps/base/home-system/qui/app/" - name: radarr originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/radarr/app/" to: "@artifact/apps/base/home-system/radarr/app/" - name: recyclarr originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/recyclarr/app/" to: "@artifact/apps/base/home-system/recyclarr/app/" - name: reflector originRevision: "@repo" copy: - from: "@repo/apps/base/kube-system/reflector/app/" to: "@artifact/apps/base/kube-system/reflector/app/" - name: rook-ceph-cluster originRevision: "@repo" copy: - from: "@repo/apps/base/rook-ceph/rook-ceph/cluster/" to: "@artifact/apps/base/rook-ceph/rook-ceph/cluster/" - name: rook-ceph originRevision: "@repo" copy: - from: "@repo/apps/base/rook-ceph/rook-ceph/app/" to: "@artifact/apps/base/rook-ceph/rook-ceph/app/" - name: sabnzbd originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/sabnzbd/app/" to: "@artifact/apps/base/home-system/sabnzbd/app/" - name: silence-operator originRevision: "@repo" copy: - from: "@repo/apps/base/observability/silence-operator/app/" to: "@artifact/apps/base/observability/silence-operator/app/" - name: smtp-relay originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/smtp-relay/app/" to: "@artifact/apps/base/home-system/smtp-relay/app/" - name: snapshot-controller originRevision: "@repo" copy: - from: "@repo/apps/base/kube-system/snapshot-controller/app/" to: "@artifact/apps/base/kube-system/snapshot-controller/app/" - name: sonarr originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/sonarr/app/" to: "@artifact/apps/base/home-system/sonarr/app/" - name: spegel originRevision: "@repo" copy: - from: "@repo/apps/base/kube-system/spegel/app/" to: "@artifact/apps/base/kube-system/spegel/app/" - name: tautulli originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/tautulli/app/" to: "@artifact/apps/base/home-system/tautulli/app/" - name: tetragon originRevision: "@repo" copy: - from: "@repo/apps/base/kube-system/tetragon/app/" to: "@artifact/apps/base/kube-system/tetragon/app/" - name: vcluster originRevision: "@repo" copy: - from: "@repo/apps/base/development/vcluster/app/" to: "@artifact/apps/base/development/vcluster/app/" - name: volsync-maintenance originRevision: "@repo" copy: - from: "@repo/apps/base/volsync-system/volsync/maintenance/" to: "@artifact/apps/base/volsync-system/volsync/maintenance/" - name: volsync originRevision: "@repo" copy: - from: "@repo/apps/base/volsync-system/volsync/app/" to: "@artifact/apps/base/volsync-system/volsync/app/" - name: vpa originRevision: "@repo" copy: - from: "@repo/apps/base/observability/vpa/app/" to: "@artifact/apps/base/observability/vpa/app/" - name: zigbee2mqtt originRevision: "@repo" copy: - from: "@repo/apps/base/home-system/zigbee2mqtt/app/" to: "@artifact/apps/base/home-system/zigbee2mqtt/app/" ================================================ FILE: kubernetes/apps/base/flux-system/artifact-generator/kustomization.yaml ================================================ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - artifactgenerator.yaml ================================================ FILE: kubernetes/apps/base/flux-system/flux-instance/extras/grafanadashboard.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: flux-k8s-api-performance spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://raw.githubusercontent.com/controlplaneio-fluxcd/flux-operator/refs/heads/main/config/monitoring/dashboards/flux-k8s-api-performance.json --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: flux-performance spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://raw.githubusercontent.com/controlplaneio-fluxcd/flux-operator/refs/heads/main/config/monitoring/dashboards/flux-performance.json --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: flux-cluster spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://raw.githubusercontent.com/fluxcd/flux2-monitoring-example/refs/heads/main/monitoring/configs/dashboards/cluster.json --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: flux-control-plane spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://raw.githubusercontent.com/fluxcd/flux2-monitoring-example/refs/heads/main/monitoring/configs/dashboards/control-plane.json ================================================ FILE: kubernetes/apps/base/flux-system/flux-instance/extras/httproute.yaml ================================================ # Used to enable webhook-receivers https://toolkit.fluxcd.io/guides/webhook-receivers/ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: receiver annotations: external-dns.alpha.kubernetes.io/external: 'true' spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'receiver.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: webhook-receiver port: 80 weight: 100 --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: flux annotations: external-dns.alpha.kubernetes.io/external: 'true' spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'flux.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: flux-operator port: 9080 weight: 100 ================================================ FILE: kubernetes/apps/base/flux-system/flux-instance/extras/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - grafanadashboard.yaml - httproute.yaml - podmonitor.yaml - prometheusrule.yaml - receiver.yaml - secret.enc.age.yaml ================================================ FILE: kubernetes/apps/base/flux-system/flux-instance/extras/podmonitor.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/podmonitor_v1.json apiVersion: monitoring.coreos.com/v1 kind: PodMonitor metadata: name: flux-components spec: namespaceSelector: matchNames: - flux-system podMetricsEndpoints: - honorLabels: true port: http-prom selector: matchExpressions: - key: app.kubernetes.io/component operator: In values: - helm-controller - source-controller - kustomize-controller - notification-controller ================================================ FILE: kubernetes/apps/base/flux-system/flux-instance/extras/prometheusrule.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/prometheusrule_v1.json apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: name: flux-instance-rules spec: groups: - name: flux-instance.rules rules: - alert: FluxInstanceAbsent expr: |- absent(flux_instance_info{exported_namespace="flux-system", name="flux"}) for: 30m annotations: summary: >- Flux instance metric is missing labels: severity: critical - alert: FluxInstanceNotReady expr: |- flux_instance_info{exported_namespace="flux-system", name="flux", ready!="True"} for: 30m annotations: summary: >- Flux instance {{ $labels.name }} is not ready labels: severity: critical - alert: HelmReleaseReconciliationFailure expr: |- gotk_resource_info{customresource_kind="HelmRelease", ready!="True"} == 1 for: 1h annotations: summary: >- HelmRelease {{ $labels.name }} in {{ $labels.exported_namespace }} is not ready labels: severity: warning - alert: KustomizationReconciliationFailure expr: |- gotk_resource_info{customresource_kind="Kustomization", ready!="True"} == 1 for: 1h annotations: summary: >- Kustomization {{ $labels.name }} in {{ $labels.exported_namespace }} is not ready labels: severity: warning ================================================ FILE: kubernetes/apps/base/flux-system/flux-instance/extras/receiver.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/notification.toolkit.fluxcd.io/receiver_v1.json apiVersion: notification.toolkit.fluxcd.io/v1 kind: Receiver metadata: name: k8s-gitops spec: type: github events: - 'ping' - 'push' secretRef: name: webhook-token resources: - apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository name: flux-system ================================================ FILE: kubernetes/apps/base/flux-system/flux-instance/extras/secret.enc.age.yaml ================================================ apiVersion: v1 data: token: ENC[AES256_GCM,data:O3HFn7k8QHDrI08N7Zm9ltdb227dGUYRi25XbqN9JVZ7Kk4Cv1fL1aWgfPulUzm3BT/s3y9xs6k=,iv:nUhnWKD2Ra4bp2NXU3jr46fulOHIQCkuA4HebiDWXSA=,tag:CNyRFkVfdqubkmlvyKgCHg==,type:str] kind: Secret metadata: name: webhook-token namespace: flux-system type: Opaque sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLVHAzTk5TZ0dSKytyK0JU M0FORlFMcEV2bzhsYWhHaEpMVFcxYU5yZVFnCk5GVCsyZTd0aVpnalNKdmU5bVFj ZVk4RnJIN3UzeWJpV1lVaTI0MW5Ia3MKLS0tIENuS2pLYU1DcVd2ZmQxL0d5RTFs YUZBVHh5NXlDakxhYjZWd0Jnb2R6RGMKyajLM/s42+kIwhD3plA4HDSDpkR6+tGI wJ4oDJNDBzbsxfXHB4Wf2feyTPuhptmSQ9+Wqk6RCID+7xX4b7GMAg== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:21:04Z" mac: ENC[AES256_GCM,data:CYZ7OY9wz6ahH1WLiv3g+hSlrpclDSUMCJTYZ55afXyLH+/e5/FNIKr3d6gd5wh5Rca5uRdSDrS7FE8j1Isnldya3ykCFEuL4iE1im2XshsGXl78q0CQYfIrhMY0s23POlbjyTWH1Z09JnPVfcTLddl2vaGt3azatOfpR7qVmZo=,iv:1X2T0lIBrObmSzCkFl/XL1zjA1CXyftSL3tyqz7o2i8=,tag:5tbJCIJiZEdCHkkd+6bzWQ==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 ================================================ FILE: kubernetes/apps/base/flux-system/flux-instance/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: &app flux-instance-extras namespace: flux-system labels: gitops.owncloud.ai/defaults: disabled spec: decryption: provider: sops interval: 30m path: ./apps/base/flux-system/flux-instance/extras prune: false sourceRef: kind: ExternalArtifact name: flux-instance-extras namespace: flux-system targetNamespace: flux-system timeout: 5m wait: false postBuild: substituteFrom: - kind: ConfigMap name: cluster-config - kind: Secret name: cluster-secrets ================================================ FILE: kubernetes/apps/base/flux-system/repositories/git/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: [] ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/backstage-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: backstage-chart namespace: flux-system spec: interval: 2h url: https://backstage.github.io/charts ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/crowdsec-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: crowdsec-charts namespace: flux-system spec: interval: 2h url: https://crowdsecurity.github.io/helm-charts ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/democratic-csi-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: democratic-csi-charts namespace: flux-system spec: interval: 2h url: https://democratic-csi.github.io/charts/ ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/dex-chart.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: dex-chart namespace: flux-system spec: interval: 2h url: https://charts.dexidp.io ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/fairwinds-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: fairwinds-charts namespace: flux-system spec: interval: 2h url: https://charts.fairwinds.com/stable ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/fluxcd-kustomize-mutating-webhook-chart.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/refs/heads/main/helmrepository-source-v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: fluxcd-kustomize-mutating-webhook namespace: flux-system spec: interval: 2h url: https://xunholy.github.io/fluxcd-kustomize-mutating-webhook ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/gatekeeper-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: gatekeeper-charts namespace: flux-system spec: interval: 2h url: https://open-policy-agent.github.io/gatekeeper/charts ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/harbor-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: harbor-charts namespace: flux-system spec: interval: 2h url: https://helm.goharbor.io ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/ingress-nginx-chart.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: ingress-nginx-chart namespace: flux-system spec: interval: 2h url: https://kubernetes.github.io/ingress-nginx ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: flux-system resources: - backstage-charts.yaml - crowdsec-charts.yaml - harbor-charts.yaml - democratic-csi-charts.yaml - dex-chart.yaml - fairwinds-charts.yaml - gatekeeper-charts.yaml - ingress-nginx-chart.yaml - loft-charts.yaml - minecraft-server-charts.yaml - ollama-charts.yaml - open-webui-charts.yaml - fluxcd-kustomize-mutating-webhook-chart.yaml - openfeature-charts.yaml ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/loft-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: loft-charts namespace: flux-system spec: interval: 2h url: https://charts.loft.sh ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/minecraft-server-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: minecraft-server-charts namespace: flux-system spec: interval: 2h url: https://itzg.github.io/minecraft-server-charts ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/ollama-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: ollama-charts namespace: flux-system spec: interval: 2h url: https://helm.otwld.com ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/open-webui-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: open-webui-charts namespace: flux-system spec: interval: 2h url: https://open-webui.github.io/helm-charts ================================================ FILE: kubernetes/apps/base/flux-system/repositories/helm/openfeature-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: openfeature-charts namespace: flux-system spec: interval: 2h url: https://open-feature.github.io/open-feature-operator/ ================================================ FILE: kubernetes/apps/base/flux-system/repositories/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - git - helm - oci ================================================ FILE: kubernetes/apps/base/flux-system/repositories/oci/bjw-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: app-template namespace: flux-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 4.6.2 url: oci://ghcr.io/bjw-s-labs/helm/app-template ================================================ FILE: kubernetes/apps/base/flux-system/repositories/oci/controlplaneio-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: controlplaneio-charts namespace: flux-system spec: type: oci interval: 2h url: oci://ghcr.io/controlplaneio-fluxcd/charts ================================================ FILE: kubernetes/apps/base/flux-system/repositories/oci/gha-runner-scale-set-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: gha-runner-scale-set-charts namespace: flux-system spec: type: oci interval: 2h url: oci://ghcr.io/actions/actions-runner-controller-charts ================================================ FILE: kubernetes/apps/base/flux-system/repositories/oci/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: flux-system resources: - bjw-charts.yaml - gha-runner-scale-set-charts.yaml - controlplaneio-charts.yaml - prometheus-community-charts.yaml - xentra-charts.yaml ================================================ FILE: kubernetes/apps/base/flux-system/repositories/oci/prometheus-community-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: prometheus-community-charts namespace: flux-system spec: interval: 120m type: oci url: oci://ghcr.io/prometheus-community/charts ================================================ FILE: kubernetes/apps/base/flux-system/repositories/oci/xentra-charts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/helmrepository_v1beta2.json apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: xentra-charts namespace: flux-system spec: interval: 120m type: oci url: oci://ghcr.io/xentra-ai/charts ================================================ FILE: kubernetes/apps/base/game-servers/adminer/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: adminer namespace: game-servers spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: app: containers: app: image: repository: adminer tag: "5" env: TZ: ${CLUSTER_TIMEZONE} # Default server pre-filled in the login form so an admin # only has to enter user + password. ADMINER_DEFAULT_SERVER: cmangos-database.game-servers.svc.cluster.local # No design preference; the dark theme is easier on the eyes # when staring at item_template at 2am. ADMINER_DESIGN: pepa-linha-dark probes: liveness: &probe enabled: true custom: true spec: httpGet: path: / port: 8080 periodSeconds: 30 timeoutSeconds: 3 failureThreshold: 3 readiness: *probe startup: enabled: true custom: true spec: httpGet: path: / port: 8080 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 30 resources: requests: cpu: 10m memory: 32Mi limits: memory: 128Mi securityContext: allowPrivilegeEscalation: false # adminer's entrypoint symlinks adminer.css into the # working directory based on ADMINER_DESIGN, so the rootfs # needs to be writable. Caps still dropped + non-root. readOnlyRootFilesystem: false capabilities: drop: ["ALL"] defaultPodOptions: securityContext: # adminer:5 image USER is "adminer" (UID 8 from adduser -u 8). # Numeric so the kubelet can verify non-root. runAsUser: 8 runAsGroup: 8 runAsNonRoot: true seccompProfile: { type: RuntimeDefault } service: app: controller: app ports: http: port: 8080 ================================================ FILE: kubernetes/apps/base/game-servers/adminer/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: adminer spec: parentRefs: - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'adminer.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: adminer port: 8080 weight: 100 ================================================ FILE: kubernetes/apps/base/game-servers/adminer/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml ================================================ FILE: kubernetes/apps/base/game-servers/adminer/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: adminer namespace: game-servers labels: gitops.owncloud.ai/defaults: disabled spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 10m path: "./apps/base/game-servers/adminer/app" prune: true wait: true sourceRef: kind: ExternalArtifact name: adminer namespace: flux-system dependsOn: - name: cmangos namespace: game-servers targetNamespace: game-servers ================================================ FILE: kubernetes/apps/base/game-servers/azerothcore/app/dnsendpoint.yaml ================================================ --- apiVersion: externaldns.k8s.io/v1alpha1 kind: DNSEndpoint metadata: name: azerothcore-wotlk annotations: external-dns.alpha.kubernetes.io/external: "true" spec: endpoints: - dnsName: "wotlk.${CLUSTER_DOMAIN}" recordType: A targets: - "${EXTERNAL_IP}" ================================================ FILE: kubernetes/apps/base/game-servers/azerothcore/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: azerothcore namespace: game-servers spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: database: containers: app: image: repository: mysql tag: "9.6" args: - --skip-log-bin env: TZ: ${CLUSTER_TIMEZONE} MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: acore_auth probes: liveness: enabled: true custom: true spec: exec: command: ['mysqladmin', 'ping', '-h', 'localhost'] periodSeconds: 30 timeoutSeconds: 3 failureThreshold: 3 readiness: enabled: true custom: true spec: exec: command: ['mysqladmin', 'ping', '-h', 'localhost'] periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 startup: enabled: true custom: true spec: exec: command: ['mysqladmin', 'ping', '-h', 'localhost'] periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 30 resources: requests: cpu: 100m memory: 512Mi limits: memory: 2Gi authserver: initContainers: wait-db-ready: image: repository: mysql tag: "9.6" command: ['sh', '-c', 'until mysql -h azerothcore-database -u root -ppassword -e "SELECT 1 FROM acore_auth.realmlist LIMIT 1" 2>/dev/null; do echo "Waiting for db-import to populate databases..."; sleep 10; done'] containers: app: image: repository: ghcr.io/xunholy/azerothcore-wotlk-authserver tag: f9bcdac1895f78e50a63e8e93f09ce0d723cf938 env: TZ: ${CLUSTER_TIMEZONE} AC_LOGIN_DATABASE_INFO: "azerothcore-database;3306;root;password;acore_auth" AC_CLOSE_IDLE_CONNECTIONS: "0" probes: liveness: enabled: true custom: true spec: tcpSocket: port: 3724 periodSeconds: 30 timeoutSeconds: 3 failureThreshold: 3 readiness: enabled: true custom: true spec: tcpSocket: port: 3724 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 startup: enabled: true custom: true spec: tcpSocket: port: 3724 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 60 resources: requests: cpu: 10m memory: 64Mi limits: memory: 256Mi worldserver: pod: terminationGracePeriodSeconds: 960 # fsGroup makes the mounted cores PVC group-owned by acore (gid 1000) # so the worldserver process can drop core files into it on crash. # Without this, kubelet creates the mount point as root:root and the # acore user can't write there. securityContext: fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch initContainers: 01-wait-db: image: repository: mysql tag: "9.6" command: - sh - -c - | until mysqladmin ping -h azerothcore-database -u root -ppassword --silent; do sleep 2; done echo "Creating databases..." mysql -h azerothcore-database -u root -ppassword -e " CREATE DATABASE IF NOT EXISTS acore_auth; CREATE DATABASE IF NOT EXISTS acore_world; CREATE DATABASE IF NOT EXISTS acore_characters; CREATE DATABASE IF NOT EXISTS acore_playerbots; " echo "All databases ready." 02-db-import: image: repository: ghcr.io/xunholy/azerothcore-wotlk-db-import tag: f9bcdac1895f78e50a63e8e93f09ce0d723cf938 env: AC_LOGIN_DATABASE_INFO: "azerothcore-database;3306;root;password;acore_auth" AC_WORLD_DATABASE_INFO: "azerothcore-database;3306;root;password;acore_world" AC_CHARACTER_DATABASE_INFO: "azerothcore-database;3306;root;password;acore_characters" AC_PLAYERBOTS_DATABASE_INFO: "azerothcore-database;3306;root;password;acore_playerbots" AC_CLOSE_IDLE_CONNECTIONS: "0" AC_UPDATES_ENABLE_DATABASES: "7" AC_PLAYERBOTS_UPDATES_ENABLE_DATABASES: "1" AC_PLAYERBOTS_DATABASE_WORKER_THREADS: "1" AC_PLAYERBOTS_DATABASE_SYNCH_THREADS: "1" AC_DATA_DIR: /azerothcore/env/dist/data 025-module-sql: image: repository: ghcr.io/xunholy/azerothcore-wotlk-db-import tag: f9bcdac1895f78e50a63e8e93f09ce0d723cf938 command: - /bin/bash - -c - | import_sql() { local db="$1" pattern="$2" find /azerothcore/modules -path "$pattern" -name "*.sql" 2>/dev/null | sort | while read -r f; do echo " $(basename "$f") -> $db" mysql -h azerothcore-database -u root -ppassword "$db" < "$f" 2>/dev/null || true done } echo "=== Applying module SQL ===" echo "World database:" import_sql acore_world "*/data/sql/db-world/*" import_sql acore_world "*/data/sql/world/base/*" echo "Characters database:" import_sql acore_characters "*/data/sql/db-characters/*" import_sql acore_characters "*/data/sql/characters/base/*" echo "Auth database:" import_sql acore_auth "*/data/sql/db-auth/*" import_sql acore_auth "*/data/sql/auth/base/*" echo "Playerbots database:" import_sql acore_playerbots "*/data/sql/playerbots/base/*" echo "=== Module SQL complete ===" 03-client-data: image: repository: acore/ac-wotlk-client-data tag: master containers: app: image: repository: ghcr.io/xunholy/azerothcore-wotlk-worldserver tag: f9bcdac1895f78e50a63e8e93f09ce0d723cf938 tty: true stdin: true # Override the image ENTRYPOINT so we can: # - enable core dumps (ulimit -c) and chdir into the cores PVC # - patch mod_ahbot.conf with our AHBot Account/GUID before the # worldserver reads it. (The AC_* env vars in this HR don't # translate to .conf — the upstream entrypoint has no env # substitution. Settings only stick when written to the conf # file directly. ConfigMap subPath at .../modules/ won't # work because k8s shadows the parent dir as root-owned and # hides the sibling .conf.dist files the wrapper needs.) # The wrapper at /azerothcore/entrypoint.sh is no-clobber for # files we wrote, so we replicate just its conf-materialization # step, sed the override, then hand off. command: - /bin/bash - -c # Flux post-build substitution eats `${VAR}` tokens; escape any # parameter-expansion / suffix-strip below as `$${VAR}` so bash # sees them at runtime. Plain `$VAR` (no braces) is fine. - | set -euo pipefail ulimit -c unlimited mkdir -p /azerothcore/env/dist/cores cd /azerothcore/env/dist/cores ref=/azerothcore/env/ref/etc/modules dist=/azerothcore/env/dist/etc/modules if [ -d "$ref" ]; then mkdir -p "$dist" for src in "$ref"/*.conf.dist; do [ -f "$src" ] || continue target="$dist/$(basename "$${src%.dist}")" [ -f "$target" ] || cp "$src" "$target" done fi if [ -f "$dist/mod_ahbot.conf" ]; then # AHBot owner + volume tuning. account 199 = AHBOT, # guid 1006 = Auctioneer. Profession + vendor trade goods # turned on so the world has crafted gear, bolts of cloth, # potions etc. on top of the loot-only seed. Duplicates=3 # gives popular items multiple listings; ItemsPerCycle=400 # roughly doubles fill+rotation rate. sed -i \ -e 's|^AuctionHouseBot\.EnableSeller *=.*|AuctionHouseBot.EnableSeller = 1|' \ -e 's|^AuctionHouseBot\.EnableBuyer *=.*|AuctionHouseBot.EnableBuyer = 1|' \ -e 's|^AuctionHouseBot\.Account *=.*|AuctionHouseBot.Account = 199|' \ -e 's|^AuctionHouseBot\.GUID *=.*|AuctionHouseBot.GUID = 1006|' \ -e 's|^AuctionHouseBot\.UseMarketPriceForSeller *=.*|AuctionHouseBot.UseMarketPriceForSeller = 1|' \ -e 's|^AuctionHouseBot\.ItemsPerCycle *=.*|AuctionHouseBot.ItemsPerCycle = 400|' \ -e 's|^AuctionHouseBot\.ProfessionItems *=.*|AuctionHouseBot.ProfessionItems = 1|' \ -e 's|^AuctionHouseBot\.VendorTradeGoods *=.*|AuctionHouseBot.VendorTradeGoods = 1|' \ -e 's|^AuctionHouseBot\.DuplicatesCount *=.*|AuctionHouseBot.DuplicatesCount = 3|' \ "$dist/mod_ahbot.conf" fi if [ -f "$dist/playerbots.conf" ]; then # Aliveness pass: more bots, faster RPG-state transitions, # busier world/general/trade chat, more loot/kill broadcast # spam. Explicitly NOT touched: RandomBotInvitePlayer (0), # InviteChat (0), RandomBotGuildNearby (0) — real players # should not be DM'd, group-invited, or auto-recruited into # bot guilds. sed -i \ -e 's|^AiPlayerbot\.MinRandomBots *=.*|AiPlayerbot.MinRandomBots = 800|' \ -e 's|^AiPlayerbot\.MaxRandomBots *=.*|AiPlayerbot.MaxRandomBots = 800|' \ -e 's|^AiPlayerbot\.RpgDelay *=.*|AiPlayerbot.RpgDelay = 5000|' \ -e 's|^AiPlayerbot\.BroadcastToWorldGlobalChance *=.*|AiPlayerbot.BroadcastToWorldGlobalChance = 90000|' \ -e 's|^AiPlayerbot\.BroadcastToGeneralGlobalChance *=.*|AiPlayerbot.BroadcastToGeneralGlobalChance = 90000|' \ -e 's|^AiPlayerbot\.BroadcastToTradeGlobalChance *=.*|AiPlayerbot.BroadcastToTradeGlobalChance = 90000|' \ -e 's|^AiPlayerbot\.BroadcastToLFGGlobalChance *=.*|AiPlayerbot.BroadcastToLFGGlobalChance = 60000|' \ -e 's|^AiPlayerbot\.BroadcastChanceLootingItemRare *=.*|AiPlayerbot.BroadcastChanceLootingItemRare = 40000|' \ -e 's|^AiPlayerbot\.BroadcastChanceLootingItemEpic *=.*|AiPlayerbot.BroadcastChanceLootingItemEpic = 60000|' \ -e 's|^AiPlayerbot\.BroadcastChanceKillRare *=.*|AiPlayerbot.BroadcastChanceKillRare = 20000|' \ -e 's|^AiPlayerbot\.BroadcastChanceKillRareelite *=.*|AiPlayerbot.BroadcastChanceKillRareelite = 6000|' \ -e 's|^AiPlayerbot\.BroadcastChanceKillWorldboss *=.*|AiPlayerbot.BroadcastChanceKillWorldboss = 40000|' \ "$dist/playerbots.conf" fi exec /azerothcore/entrypoint.sh /azerothcore/env/dist/bin/worldserver env: TZ: ${CLUSTER_TIMEZONE} # Enable interactive console so preStop can inject commands via FIFO AC_DISABLE_INTERACTIVE: "0" # Database connections AC_LOGIN_DATABASE_INFO: "azerothcore-database;3306;root;password;acore_auth" AC_WORLD_DATABASE_INFO: "azerothcore-database;3306;root;password;acore_world" AC_CHARACTER_DATABASE_INFO: "azerothcore-database;3306;root;password;acore_characters" AC_PLAYERBOTS_DATABASE_INFO: "azerothcore-database;3306;root;password;acore_playerbots" AC_PLAYERBOTS_UPDATES_ENABLE_DATABASES: "0" AC_PLAYERBOTS_DATABASE_WORKER_THREADS: "1" AC_PLAYERBOTS_DATABASE_SYNCH_THREADS: "1" AC_CLOSE_IDLE_CONNECTIONS: "0" AC_UPDATES_ENABLE_DATABASES: "7" AC_DATA_DIR: /azerothcore/env/dist/data AC_LOGS_DIR: /azerothcore/env/dist/logs # Server identity AC_GAME_TYPE: "0" AC_REALM_ZONE: "8" AC_WORLD_SERVER_PORT: "8085" AC_PLAYER_LIMIT: "100" AC_MOTD: "Welcome to Emberstone | Progression Realm | Earn Outland and Northrend through raid clears" # SOAP remote admin AC_SOAP_ENABLED: "1" AC_SOAP_IP: "0.0.0.0" AC_SOAP_PORT: "7878" # -- 3x rates: faster than vanilla but tiers still feel earned -- AC_RATE_XP_KILL: "3" AC_RATE_XP_QUEST: "3" AC_RATE_XP_EXPLORE: "3" AC_RATE_XP_BG_KILL: "3" AC_RATE_XP_PET: "3" # -- Drops -- AC_RATE_DROP_ITEM_POOR: "3" AC_RATE_DROP_ITEM_NORMAL: "3" AC_RATE_DROP_ITEM_UNCOMMON: "3" AC_RATE_DROP_ITEM_RARE: "3" AC_RATE_DROP_ITEM_EPIC: "2" AC_RATE_DROP_ITEM_LEGENDARY: "1" AC_RATE_DROP_ITEM_QUEST: "3" AC_RATE_DROP_MONEY: "3" # -- Reputation and honor -- AC_RATE_REPUTATION_GAIN: "3" AC_RATE_HONOR: "3" AC_RATE_ARENA_POINTS: "3" # -- Profession skill-ups -- AC_SKILL_GAIN_CRAFTING: "3" AC_SKILL_GAIN_GATHERING: "3" AC_SKILL_GAIN_WEAPON: "3" AC_SKILL_GAIN_DEFENSE: "3" AC_RATE_SKILL_DISCOVERY: "3" # -- Quality of life (kept; QoL that doesn't fight IP) -- AC_RATE_REST_INGAME: "3" AC_RATE_REST_OFFLINE_IN_TAVERN_OR_CITY: "3" AC_DEATH_SICKNESS_LEVEL: "1" AC_SKIP_CINEMATICS: "1" AC_PLAYER_SAVE_INTERVAL: "60000" # NOTE: removed ALL_FLIGHT_PATHS, INSTANT_FLIGHT_PATHS, MAIL_DELIVERY_DELAY=0, # START_PLAYER_MONEY=100000 — these undermine IP's "the world is bigger again" design. # -- Health and mana regen -- AC_RATE_HEALTH: "3" AC_RATE_MANA: "3" AC_RATE_POWER_RAGE_INCOME: "3" AC_RATE_POWER_RAGE_LOSS: "1" AC_RATE_POWER_ENERGY: "3" AC_RATE_POWER_FOCUS: "3" # -- Ghost run speed for less death penalty -- AC_GHOST_RUN_SPEED_WORLD: "1.5" AC_GHOST_RUN_SPEED_BG: "1.5" # ============================================== # Module: mod-playerbots (AI player bots) # ============================================== AC_AIPLAYERBOT_ENABLED: "1" AC_AIPLAYERBOT_RANDOMBOTAUTOCREATE: "1" AC_AIPLAYERBOT_RANDOMBOTAUTOLOGIN: "1" AC_AIPLAYERBOT_LOGINATEACHPLAYERLEVELBOT: "1" AC_AIPLAYERBOT_RANDOMBOTACCOUNTPREFIX: "rndbot" AC_AIPLAYERBOT_RANDOMBOTACCOUNTCOUNT: "200" AC_AIPLAYERBOT_MINRANDOMBOTS: "500" AC_AIPLAYERBOT_MAXRANDOMBOTS: "1000" AC_AIPLAYERBOT_RANDOMBOTMINLEVEL: "1" AC_AIPLAYERBOT_RANDOMBOTMAXLEVEL: "80" AC_AIPLAYERBOT_RANDOMBOTMAPS: "0,1,530,571" AC_AIPLAYERBOT_AUTODOQUESTS: "1" AC_AIPLAYERBOT_AUTOPICKREWARD: "yes" AC_AIPLAYERBOT_AUTOEQUIPUPGRADELOOT: "1" AC_AIPLAYERBOT_AUTOLEARNTRAINERSPELLS: "1" AC_AIPLAYERBOT_AUTOLEARNQUESTSPELLS: "1" AC_AIPLAYERBOT_RANDOMGEARUPGRADEENABLED: "1" AC_AIPLAYERBOT_RANDOMBOTTELEPORTNEARPLAYER: "1" AC_AIPLAYERBOT_SYNCQUESTWITHPLAYER: "1" AC_AIPLAYERBOT_RANDOMBOTJOINBG: "1" AC_AIPLAYERBOT_RANDOMBOTAUTOJOINBG: "1" AC_AIPLAYERBOT_RANDOMBOTGROUPNEARBY: "1" AC_AIPLAYERBOT_SYNCLEVELWITHPLAYERS: "1" AC_AIPLAYERBOT_SYNCLEVELMAXABOVE: "2" AC_AIPLAYERBOT_AUTOPICKTALENTS: "full" AC_AIPLAYERBOT_AUTOTRAINSPELLS: "free" # ============================================== # Module: mod-autobalance (instance scaling) # Disabled: IP wants raids to require a raid; autobalance with MINPLAYERS=1 # would let you solo MC and defeat the gating experience. # ============================================== AC_AUTOBALANCE_ENABLE: "0" # ============================================== # Module: mod-transmog (transmogrification) # ============================================== AC_TRANSMOGRIFICATION_ENABLE: "1" AC_TRANSMOGRIFICATION_SETNSETHINGS_ENABLE: "1" # ============================================== # Module: mod-ah-bot (auction house bot) # ============================================== AC_AUCTIONHOUSEBOT_ENABLESELLER: "1" AC_AUCTIONHOUSEBOT_ENABLEBUYER: "1" # ============================================== # Module: mod-cfbg (cross-faction battlegrounds) # ============================================== AC_CFBG_ENABLE: "1" # ============================================== # Module: mod-solo-lfg (solo dungeon finder) # Disabled: trivializes early-game dungeons that IP wants to feel earned. # Playerbots fill the dungeon-group role instead. # ============================================== AC_SOLOLFG_ENABLE: "0" # ============================================== # IP requires these for stat-scaling to take effect. The module's # SimpleConfigOverride is supposed to force them at runtime but # observation showed the on-disk worldserver.conf still has the # AC defaults, so set them explicitly to be safe. # ============================================== AC_ENABLE_PLAYER_SETTINGS: "1" AC_DBC_ENFORCE_ITEM_ATTRIBUTES: "0" # ============================================== # Module: mod-individual-progression (per-character expansion gating) # Power/healing scalars at IP author's recommended values for # "Vanilla feels like Vanilla, TBC feels like TBC" — without these, # gating works but content does WotLK-tier damage values. # Other defaults are sane (StartingProgression=0 -> achievements # scanned on login, ExcludedAccountsRegex='^RNDBOT.*' -> auto-excludes # our playerbots). # ============================================== AC_INDIVIDUAL_PROGRESSION_ENABLE: "1" AC_INDIVIDUAL_PROGRESSION_VANILLA_POWER_ADJUSTMENT: "0.5" AC_INDIVIDUAL_PROGRESSION_VANILLA_HEALING_ADJUSTMENT: "0.5" AC_INDIVIDUAL_PROGRESSION_TBCPOWER_ADJUSTMENT: "0.6" AC_INDIVIDUAL_PROGRESSION_TBCHEALING_ADJUSTMENT: "0.6" lifecycle: preStop: exec: command: - /bin/sh - -c - | echo "server restart 900" > /tmp/worldserver-stdin sleep 910 probes: liveness: enabled: true custom: true spec: tcpSocket: port: 8085 periodSeconds: 30 timeoutSeconds: 3 failureThreshold: 3 readiness: enabled: true custom: true spec: tcpSocket: port: 8085 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 startup: enabled: true custom: true spec: tcpSocket: port: 8085 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 180 resources: requests: cpu: "2" memory: 4Gi limits: memory: 12Gi # Prune /azerothcore/env/dist/cores so a runaway crash loop can't # fill the 40Gi PVC. Keeps the 2 newest non-zero cores by mtime # and deletes the rest every 10 min. Mirrors the cmangos pattern. cores-pruner: image: repository: busybox tag: latest command: - /bin/sh - -c - | while true; do if cd /azerothcore/env/dist/cores 2>/dev/null; then find . -maxdepth 1 -name 'core*' -size 0 -delete 2>/dev/null # shellcheck disable=SC2012 ls -1t core* 2>/dev/null | tail -n +3 | xargs -r rm -f -- fi sleep 600 done resources: requests: cpu: 5m memory: 8Mi limits: memory: 32Mi securityContext: runAsNonRoot: false readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: ["ALL"] service: database: controller: database ports: mysql: port: 3306 auth: controller: authserver ports: auth: port: 3724 world: controller: worldserver ports: world: port: 8085 soap: controller: worldserver ports: soap: port: 7878 persistence: database: existingClaim: azerothcore-database advancedMounts: database: app: - path: /var/lib/mysql client-data: existingClaim: azerothcore-client-data advancedMounts: worldserver: 02-db-import: - path: /azerothcore/env/dist/data 03-client-data: - path: /azerothcore/env/dist/data app: - path: /azerothcore/env/dist/data readOnly: true worldserver-logs: type: emptyDir advancedMounts: worldserver: app: - path: /azerothcore/env/dist/logs authserver-logs: type: emptyDir advancedMounts: authserver: app: - path: /azerothcore/env/dist/logs cores: existingClaim: azerothcore-cores advancedMounts: worldserver: app: - path: /azerothcore/env/dist/cores cores-pruner: - path: /azerothcore/env/dist/cores ================================================ FILE: kubernetes/apps/base/game-servers/azerothcore/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - pvc-database.yaml - pvc-client-data.yaml - pvc-cores.yaml - tcproutes.yaml - dnsendpoint.yaml - replicationsource.yaml - volsync-externalsecret.yaml - realm-config-job.yaml # Hash-suffixed CM. realmlist.sql edits change the suffix, which changes # the Job's volume reference, which (with kustomize.toolkit.fluxcd.io/force) # triggers a Job re-run. No more manual resource-name bumps. # NOTE: namespace must match the Job's namespace or kustomize won't # auto-rewrite references. configMapGenerator: - name: azerothcore-realmlist-sql namespace: game-servers files: - realmlist.sql ================================================ FILE: kubernetes/apps/base/game-servers/azerothcore/app/pvc-client-data.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: azerothcore-client-data namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/game-servers/azerothcore/app/pvc-cores.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: azerothcore-cores namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 40Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/game-servers/azerothcore/app/pvc-database.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: azerothcore-database namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/game-servers/azerothcore/app/realm-config-job.yaml ================================================ --- # Applies realmlist.sql against the auth DB. ConfigMap is hash-suffixed by # kustomize's configMapGenerator (see kustomization.yaml), so SQL edits # produce a new CM name, which forces the Job's spec to change. The Flux # force annotation lets kustomize-controller delete-and-recreate the # (immutable) Job when that happens. apiVersion: batch/v1 kind: Job metadata: name: azerothcore-realm-config namespace: game-servers annotations: kustomize.toolkit.fluxcd.io/force: Enabled spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z azerothcore-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mysql:9.6 command: - /bin/bash - -c - | set -e echo "=== Applying realm config ===" mysql -h azerothcore-database -P 3306 -u root -ppassword acore_auth < /sql/realmlist.sql echo "=== Realm config applied ===" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: azerothcore-realmlist-sql ================================================ FILE: kubernetes/apps/base/game-servers/azerothcore/app/realmlist.sql ================================================ -- Realm identity for the auth DB. Edited inline by humans; consumed by -- realm-config-job.yaml via a hash-suffixed ConfigMap. Changes here -- trigger automatic Job re-runs (via the kustomize.toolkit.fluxcd.io/force -- annotation on the Job). UPDATE realmlist SET name = 'Emberstone', address = '${EXTERNAL_IP}', port = 3726, gamebuild = 12340 WHERE id = 1; SELECT id, name, address, port, gamebuild FROM realmlist WHERE id = 1; ================================================ FILE: kubernetes/apps/base/game-servers/azerothcore/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: azerothcore-database spec: sourcePVC: azerothcore-database trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: azerothcore-database-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/game-servers/azerothcore/app/resources/Dockerfile ================================================ # ============================================================================= # AzerothCore WotLK 3.3.5a — Custom Build with Tier 1 Modules # Built from the mod-playerbots fork (requires core patches for bot support) # # Targets: worldserver, authserver, db-import # ============================================================================= # ----------------------------------------------------------------------------- # Stage 1: Clone sources and modules # ----------------------------------------------------------------------------- FROM ubuntu:22.04 AS source RUN apt-get update && apt-get install -y --no-install-recommends \ git ca-certificates \ && rm -rf /var/lib/apt/lists/* # Pinned SHAs for reproducible builds. Bump these when you want newer code; # leaving them on a moving branch is how silent regressions arrive. ARG ACORE_SHA1="d115eb658606567de6892aa48950281117767130" # mod-playerbots/azerothcore-wotlk Playerbot branch ARG MOD_PLAYERBOTS_SHA1="a4d2c83d85572a7c4f5bd4b4104187624c8337e3" ARG MOD_AUTOBALANCE_SHA1="73d4ad3c379fbfc35c63b5b9b44fba1f7d9e213d" ARG MOD_TRANSMOG_SHA1="f07686bf6a86412ba31502522bdc141266b8647d" ARG MOD_AHBOT_SHA1="a680cc1c98290713e9b3d3289544af78e5186dc1" ARG MOD_AOELOOT_SHA1="2ddf6ff75bdbfee3c81f2c149a07126f1d0bf200" ARG MOD_LEARNSPELLS_SHA1="016b92d520f343d074ffd5d46016a94f4a3a6ebd" ARG MOD_SOLOLFG_SHA1="3821fe1d108ade8d2b7ad6611e41154e05864c65" ARG MOD_CFBG_SHA1="d63ba2b844e0c3cd421d07aa8b009927425b21cd" ARG MOD_INDIVIDUALPROGRESSION_SHA1="4119ca0120e5b535b4718f6dd0a4d6030e28e1f8" # Shallow-fetch a specific SHA: init -> remote add -> fetch --depth 1 -> checkout. # Avoids cloning full history while still giving us reproducible pins. # shellcheck disable=SC2086 RUN set -eux; \ fetch_sha() { \ local url="$1" sha="$2" dest="$3"; \ mkdir -p "$dest"; \ git -C "$dest" init -q; \ git -C "$dest" remote add origin "$url"; \ git -C "$dest" fetch --depth 1 -q origin "$sha"; \ git -C "$dest" checkout -q FETCH_HEAD; \ }; \ fetch_sha https://github.com/mod-playerbots/azerothcore-wotlk.git "${ACORE_SHA1}" /azerothcore; \ fetch_sha https://github.com/mod-playerbots/mod-playerbots.git "${MOD_PLAYERBOTS_SHA1}" /azerothcore/modules/mod-playerbots; \ fetch_sha https://github.com/azerothcore/mod-autobalance.git "${MOD_AUTOBALANCE_SHA1}" /azerothcore/modules/mod-autobalance; \ fetch_sha https://github.com/azerothcore/mod-transmog.git "${MOD_TRANSMOG_SHA1}" /azerothcore/modules/mod-transmog; \ fetch_sha https://github.com/azerothcore/mod-ah-bot.git "${MOD_AHBOT_SHA1}" /azerothcore/modules/mod-ah-bot; \ fetch_sha https://github.com/azerothcore/mod-aoe-loot.git "${MOD_AOELOOT_SHA1}" /azerothcore/modules/mod-aoe-loot; \ fetch_sha https://github.com/azerothcore/mod-learn-spells.git "${MOD_LEARNSPELLS_SHA1}" /azerothcore/modules/mod-learn-spells; \ fetch_sha https://github.com/azerothcore/mod-solo-lfg.git "${MOD_SOLOLFG_SHA1}" /azerothcore/modules/mod-solo-lfg; \ fetch_sha https://github.com/azerothcore/mod-cfbg.git "${MOD_CFBG_SHA1}" /azerothcore/modules/mod-cfbg; \ fetch_sha https://github.com/ZhengPeiRu21/mod-individual-progression.git "${MOD_INDIVIDUALPROGRESSION_SHA1}" /azerothcore/modules/mod-individual-progression # ----------------------------------------------------------------------------- # Stage 2: Compile # ----------------------------------------------------------------------------- FROM ubuntu:22.04 AS build RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential ccache libtool cmake-data make cmake clang \ git lsb-base curl unzip default-mysql-client openssl \ default-libmysqlclient-dev libboost-all-dev libssl-dev libmysql++-dev \ libreadline-dev zlib1g-dev libbz2-dev libncurses5-dev \ && rm -rf /var/lib/apt/lists/* COPY --from=source /azerothcore /azerothcore WORKDIR /azerothcore/build ARG CTYPE=RelWithDebInfo ARG THREADS=2 RUN cmake /azerothcore \ -DCMAKE_INSTALL_PREFIX="/azerothcore/env/dist" \ -DAPPS_BUILD="all" \ -DTOOLS_BUILD="all" \ -DSCRIPTS="static" \ -DMODULES="static" \ -DWITH_WARNINGS="OFF" \ -DCMAKE_BUILD_TYPE="${CTYPE}" \ -DCMAKE_CXX_COMPILER="clang++" \ -DCMAKE_C_COMPILER="clang" \ -DCMAKE_CXX_COMPILER_LAUNCHER="ccache" \ -DCMAKE_C_COMPILER_LAUNCHER="ccache" \ -DBoost_USE_STATIC_LIBS="ON" RUN cmake --build . --config "${CTYPE}" -j "${THREADS}" RUN cmake --install . --config "${CTYPE}" # ----------------------------------------------------------------------------- # Stage 3: Runtime base (shared by all server images) # ----------------------------------------------------------------------------- FROM ubuntu:22.04 AS runtime RUN apt-get update && apt-get install -y --no-install-recommends \ libmysqlclient21 libreadline8 gettext-base default-mysql-client \ && rm -rf /var/lib/apt/lists/* RUN groupadd -g 1000 acore \ && useradd -m -u 1000 -g acore acore COPY --from=source /azerothcore/apps/docker/entrypoint.sh /azerothcore/entrypoint-upstream.sh COPY fifo-wrapper.sh /azerothcore/entrypoint.sh RUN chmod +x /azerothcore/entrypoint-upstream.sh /azerothcore/entrypoint.sh # Reference configs (entrypoint copies to dist/etc on first run if not present) COPY --from=build /azerothcore/env/dist/etc /azerothcore/env/ref/etc RUN mkdir -p /azerothcore/env/dist/etc /azerothcore/env/dist/logs /azerothcore/env/dist/data \ && chown -R acore:acore /azerothcore ENV CONF_DIR=/azerothcore/env/dist/etc \ LOGS_DIR=/azerothcore/env/dist/logs \ AC_FORCE_CREATE_DB=1 \ AC_CLOSE_IDLE_CONNECTIONS=0 \ AC_DISABLE_INTERACTIVE=1 USER acore ENTRYPOINT ["/azerothcore/entrypoint.sh"] # ----------------------------------------------------------------------------- # Stage 4: Auth server # ----------------------------------------------------------------------------- FROM runtime AS authserver COPY --from=build --chown=acore:acore /azerothcore/env/dist/bin/authserver /azerothcore/env/dist/bin/ ENV ACORE_COMPONENT=authserver EXPOSE 3724 CMD ["/azerothcore/env/dist/bin/authserver"] # ----------------------------------------------------------------------------- # Stage 5: World server # ----------------------------------------------------------------------------- FROM runtime AS worldserver COPY --from=build --chown=acore:acore /azerothcore/env/dist/bin/worldserver /azerothcore/env/dist/bin/ ENV ACORE_COMPONENT=worldserver EXPOSE 8085 7878 CMD ["/azerothcore/env/dist/bin/worldserver"] # ----------------------------------------------------------------------------- # Stage 6: DB import (schema + data + module SQL) # ----------------------------------------------------------------------------- FROM runtime AS db-import COPY --from=build --chown=acore:acore /azerothcore/env/dist/bin/dbimport /azerothcore/env/dist/bin/ COPY --from=source --chown=acore:acore /azerothcore/data /azerothcore/data COPY --from=source --chown=acore:acore /azerothcore/modules /azerothcore/modules ENV ACORE_COMPONENT=dbimport \ AC_UPDATES_ENABLE_DATABASES=0 CMD ["/azerothcore/env/dist/bin/dbimport"] ================================================ FILE: kubernetes/apps/base/game-servers/azerothcore/app/resources/fifo-wrapper.sh ================================================ #!/usr/bin/env bash # Wraps the upstream AzerothCore entrypoint to expose a named pipe at # /tmp/worldserver-stdin for the worldserver component. Lets preStop hooks # inject console commands like "server restart 900" for graceful, # player-notified shutdowns. Non-worldserver components are unaffected. set -euo pipefail # AC's upstream entrypoint runs `cp -rnv ref/etc/* dist/etc/` and then copies # the COMPONENT's .conf.dist to .conf — but only for the main component, # never for modules. Module configs end up as dist/etc/modules/*.conf.dist # with no .conf companion, so the loader falls back to defaults and emits # ~100 "Missing property" warnings per startup. # # Fix: pre-populate dist/etc/modules/*.conf from ref/etc/modules/*.conf.dist # BEFORE the upstream entrypoint runs. Upstream's `cp -rnv` is no-clobber, # so our pre-created .conf files survive. normalize_module_confs() { local ref_modules=/azerothcore/env/ref/etc/modules local dist_modules=/azerothcore/env/dist/etc/modules [ -d "$ref_modules" ] || return 0 mkdir -p "$dist_modules" local src target for src in "$ref_modules"/*.conf.dist; do [ -f "$src" ] || continue target="$dist_modules/$(basename "${src%.dist}")" [ -f "$target" ] || cp "$src" "$target" done } normalize_module_confs if [[ "${ACORE_COMPONENT:-}" == "worldserver" ]]; then FIFO=/tmp/worldserver-stdin rm -f "$FIFO" mkfifo "$FIFO" chmod 666 "$FIFO" # Keep a writer attached so the server never sees EOF when a one-shot # writer (preStop's echo) closes. ( sleep infinity > "$FIFO" ) & exec /azerothcore/entrypoint-upstream.sh "$@" < "$FIFO" else exec /azerothcore/entrypoint-upstream.sh "$@" fi ================================================ FILE: kubernetes/apps/base/game-servers/azerothcore/app/tcproutes.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/tcproute_v1alpha2.json apiVersion: gateway.networking.k8s.io/v1alpha2 kind: TCPRoute metadata: name: azerothcore-auth spec: parentRefs: - name: envoy-external namespace: network-system sectionName: azerothcore-auth rules: - backendRefs: - name: azerothcore-auth port: 3724 --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/tcproute_v1alpha2.json apiVersion: gateway.networking.k8s.io/v1alpha2 kind: TCPRoute metadata: name: azerothcore-world spec: parentRefs: - name: envoy-external namespace: network-system sectionName: azerothcore-world rules: - backendRefs: - name: azerothcore-world port: 8085 ================================================ FILE: kubernetes/apps/base/game-servers/azerothcore/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: azerothcore-database-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: azerothcore-database-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/game-servers/azerothcore/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: azerothcore namespace: game-servers labels: gitops.owncloud.ai/defaults: disabled spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 10m path: "./apps/base/game-servers/azerothcore/app" prune: true wait: true sourceRef: kind: ExternalArtifact name: azerothcore namespace: flux-system dependsOn: - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: game-servers ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/README.md ================================================ # CMaNGOS Classic - Emberstone (1.12.1) A Vanilla WoW private server running CMaNGOS Classic on Kubernetes, with AI playerbots, hardcore mode, auction house bot, and a level 19 twink vendor system. ## Architecture The deployment consists of three controllers: | Controller | Image | Ports | Description | |---|---|---|---| | `database` | `mariadb:12.2` | 3306 | MariaDB storing all game databases | | `realmd` | `ghcr.io/xunholy/cmangos-classic` | 3724 | Authentication/realm server | | `mangosd` | `ghcr.io/xunholy/cmangos-classic` | 8085, 7878 (SOAP) | World server | The container image is built from a [custom fork](https://github.com/flekz-games/mangos-classic) (`modules` branch) with the following compiled modules: - **PlayerBots** - AI bots that auto-create, level, do quests, and join battlegrounds - **AHBot** - Automated auction house population - **Hardcore** - Permadeath challenge system via [cmangos-hardcore](https://github.com/flekz-games/cmangos-hardcore) - **TwinkMaster** - Level 19 twink vendor/XP lock via [cmangos-twinkmaster](https://github.com/xunholy/cmangos-twinkmaster) ## Server Configuration Configuration files are managed as ConfigMaps mounted into the containers: | ConfigMap | Mount Path | Purpose | |---|---|---| | `mangosd.conf` | `/opt/mangos/conf/mangosd.conf` | World server settings (XP rates, player limits, etc.) | | `realmd.conf` | `/opt/mangos/conf/realmd.conf` | Auth server settings | | `aiplayerbot.conf` | `/opt/mangos/conf/aiplayerbot.conf` | Bot count, behavior, leveling | | `ahbot.conf` | `/opt/mangos/conf/ahbot.conf` | Auction house bot settings | | `hardcore.conf` | `/opt/mangos/etc/hardcore.conf` | Hardcore challenge rules | | `twinkmaster.conf` | `/opt/mangos/conf/twinkmaster.conf` | Twink vendor settings | ### Key Server Settings - **XP Rate**: 3x (kill, quest, explore) - **Drop Rate**: 3x normal/uncommon, 2x rare, 1x epic - **Player Limit**: 100 - **Cross-Faction**: Groups, guilds, chat, and channels all enabled - **Starting Gold**: 1g - **PlayerBots**: 1500-2000 bots, levels 1-60, auto-questing enabled - **Hardcore**: Permadeath enabled, graves spawn at death location, revive disabled ## Managing Users Accounts are managed via the mangosd server console. Attach to the running pod: ```bash kubectl attach -it -n game-servers deploy/cmangos-mangosd -c app ``` ### Creating an Account In the mangos console: ``` account create ``` ### Granting GM Privileges ``` account set gmlevel 3 ``` To detach from the console, press `Ctrl+P` then `Ctrl+Q`. ## Account Registration A web-based registration page is available at `https://emberstone.owncloud.ai`. Players can create accounts without needing console access. The portal is deployed by the `emberstone-portal` app and serves both cmangos and azerothcore realms. ## Connecting ### Requirements - World of Warcraft **1.12.1** client (patch 5875) - An account on the server ### Client Setup 1. Edit `WoW/Data/enUS/realmlist.wtf` (or `enGB`): ``` set realmlist wow.owncloud.ai ``` 2. Launch WoW and log in ## Networking External access is provided via Gateway API TCPRoutes through an Envoy gateway: - **Auth** (port 3724): `cmangos-auth` TCPRoute - **World** (port 8085): `cmangos-world` TCPRoute - **DNS**: `wow.owncloud.ai` pointed to the external IP via DNSEndpoint ## Storage - **Database PVC** (`cmangos-database`): MariaDB data at `/var/lib/mysql` - **Data PVC** (`cmangos-data`): Extracted game resources (maps, vmaps, mmaps, dbc) at `/var/lib/mangos` (read-only mount on mangosd) - **VolSync**: Replication configured for backup ## Custom Modules ### Hardcore Mode Players can talk to **"Masochist" Pete** (NPC spawned in all major cities) to opt into challenges: - **Hardcore**: One life, permadeath - **Drop Loot**: Drop gear/gold on death - **Lose XP**: Lose experience on death - **Self Found**: No trading with non-challenge players - **PvP Toggle**: Enable/disable PvP during challenges Database migrations are applied via the `cmangos-hardcore-migration` Job. ### Twink Master **Twink Master** NPCs provide free level 19 BiS gear, consumables, honor items, and endgame no-level-req items: - **Alliance NPC** (190012): Stormwind Trade District - **Horde NPC** (190013): Orgrimmar Vendor categories: BiS Gear, Consumables, Honor Gear, Insane (raid items with no level requirement). Database migrations are applied via the `cmangos-twink-vendor-migration` Job. ## Building the Image The Dockerfile uses a multi-stage build: 1. **Builder stage**: Clones CMaNGOS, classic-db, and modules, then compiles with CMake 2. **Runner stage**: Minimal Ubuntu 24.04 with only runtime dependencies ```bash docker build \ --build-arg THREADS=$(nproc) \ --build-arg MANGOS_SHA1= \ --build-arg DATABASE_SHA1= \ -t ghcr.io/xunholy/cmangos-classic:latest \ kubernetes/apps/base/game-servers/cmangos/app/resources/ ``` ### Builder Entrypoint Commands The builder image provides database management tools: | Command | Description | |---|---| | `extract` | Extract game resources (maps, vmaps, mmaps) from WoW client | | `init-db` | Initialize all databases from scratch (destructive) | | `backup-db` | Backup databases (`-a` all, `-w` world, `-c` characters, `-l` logs, `-r` realmd) | | `restore-db` | Restore databases from a backup tar.gz | | `update-db` | Apply latest DB updates (`-w` to include world DB refresh) | | `manage-db` | Run the InstallFullDB interactive script | ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/achievements-migration-job.yaml ================================================ --- # Achievements module — backports the WotLK achievement system. Imports # ~3MB of static achievement/criteria/locale definitions (`achievement_dbc`, # `achievement_criteria_dbc`, `achievement_category_dbc`, `achievement_reward`, # `achievement_reward_locale`, `achievement_criteria_data`) into classicmangos, # plus 2 progress tables (`character_achievement`, `character_achievement_progress`) # into classiccharacters. # # The world-data SQL totals ~3.3MB which exceeds the per-ConfigMap size limit # (1MiB), so the SQL is fetched at job time via shallow git clone of # xunholy/cmangos-classic rather than inlined. The init container pins to the # branch the runtime image was built from — see the cmangos image tag in # helmrelease.yaml; bump both in lockstep. # # Re-running is functionally safe: the upstream SQL uses DROP+CREATE+INSERT # on STATIC definition tables only. Player progress lives in `character_achievement*` # (separate DB) and is not touched. The achievement IDs are deterministic, so # DROP+CREATE+INSERT yields the same definitions and player progress remains # valid. apiVersion: batch/v1 kind: Job metadata: name: cmangos-achievements-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 # Higher backoffLimit + activeDeadlineSeconds — applying the 3.3MB world SQL # against a cold DB can take a couple of minutes. backoffLimit: 3 activeDeadlineSeconds: 1200 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] - name: clone-source image: alpine/git:latest command: - sh - -c - | set -e git clone --depth 1 --branch main \ https://github.com/xunholy/cmangos-classic.git /shared/src echo "=== Achievements SQL files ===" ls -lh /shared/src/src/modules/achievements/sql/install/world/ ls -lh /shared/src/src/modules/achievements/sql/install/characters/ volumeMounts: - name: shared mountPath: /shared containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e SQL_DIR="/shared/src/src/modules/achievements/sql/install" echo "=== Applying Achievements characters schema ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters < "$${SQL_DIR}/characters/characters.sql" echo "=== Applying world_data (achievement_dbc, criteria_dbc, etc) — this is the big one (~1.9MB) ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos < "$${SQL_DIR}/world/01_world_data.sql" echo "=== Applying world_update (rewards / fixups) ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos < "$${SQL_DIR}/world/02_world_update.sql" echo "=== Applying world_locales (~1.2MB) ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos < "$${SQL_DIR}/world/03_world_locales.sql" echo "=== Verifying characters tables ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters -e "SHOW TABLES LIKE 'character_achievement%';" echo "=== Verifying world definition tables ===" # `rows` is a reserved word in MariaDB 12.2 — use row_count. mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e " SELECT 'achievement_dbc' AS tbl, COUNT(*) AS row_count FROM achievement_dbc UNION ALL SELECT 'achievement_category_dbc', COUNT(*) FROM achievement_category_dbc UNION ALL SELECT 'achievement_criteria_dbc', COUNT(*) FROM achievement_criteria_dbc UNION ALL SELECT 'achievement_criteria_data', COUNT(*) FROM achievement_criteria_data UNION ALL SELECT 'achievement_reward', COUNT(*) FROM achievement_reward UNION ALL SELECT 'achievement_reward_locale', COUNT(*) FROM achievement_reward_locale;" echo "=== Achievements migration complete ===" volumeMounts: - name: shared mountPath: /shared readOnly: true volumes: - name: shared emptyDir: {} ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/attunement-migration-job.yaml ================================================ --- apiVersion: v1 kind: ConfigMap metadata: name: cmangos-attunement-migration-sql namespace: game-servers data: characters.sql: | CREATE TABLE IF NOT EXISTS `custom_attunement_player_config` ( `guid` int(11) unsigned NOT NULL COMMENT 'Character GUID', `option_key` varchar(64) NOT NULL COMMENT 'Option name (e.g. xp_rate)', `value` float NOT NULL DEFAULT 0 COMMENT 'Option value', `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`guid`, `option_key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Attunement per-player options'; world.sql: | -- ============================================================ -- Attunement NPC - "Attuner of Paths" -- Single faction-friendly NPC entry: 190014 -- Spawns at every Classic starting zone (6 distinct zones, 8 races) -- ============================================================ SET @AttunementEntry := 190014; -- NPC Template: faction 35 = Friendly to all, DisplayId 7949 = ethereal DELETE FROM `creature_template` WHERE `entry` = @AttunementEntry; INSERT INTO `creature_template` (`entry`, `DisplayId1`, `DisplayIdProbability1`, `name`, `subname`, `GossipMenuId`, `minlevel`, `maxlevel`, `faction`, `NpcFlags`, `scale`, `rank`, `DamageSchool`, `MeleeBaseAttackTime`, `RangedBaseAttackTime`, `unitClass`, `unitFlags`, `CreatureType`, `CreatureTypeFlags`, `ScriptName`, `lootid`, `PickpocketLootId`, `SkinningLootId`, `AIName`, `MovementType`, `RacialLeader`, `RegenerateStats`, `MechanicImmuneMask`, `ExtraFlags`) VALUES (@AttunementEntry, 7949, 100, 'Attuner of Paths', 'Adjuster of Fate', 0, 60, 60, 35, 1, 1.1, 0, 0, 2000, 0, 1, 0, 7, 138936390, 'npc_attunement', 0, 0, 0, '', 0, 0, 1, 0, 0); -- Spawns: one per Classic starting zone (6 zones, 8 races) DELETE FROM `creature` WHERE `id` = @AttunementEntry; INSERT INTO `creature` (`id`, `map`, `spawnMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecsmin`, `spawntimesecsmax`, `spawndist`, `MovementType`) VALUES -- Coords anchor on the canonical race-start NPC in each zone, offset -- a few units so the Attuner doesn't overlap the existing creature. (@AttunementEntry, 0, 1, -8902.6, -158.6, 82.0, 3.14, 300, 300, 0, 0), -- Northshire (near Marshal McBride) (@AttunementEntry, 0, 1, -6214.9, 332.2, 383.7, 3.14, 300, 300, 0, 0), -- Coldridge Valley (near Sten Stoutarm) (@AttunementEntry, 0, 1, 1843.3, 1643.9, 97.8, 3.14, 300, 300, 0, 0), -- Deathknell (near Shadow Priest Sarvis) (@AttunementEntry, 1, 1, 10328.9, 830.1, 1326.5, 3.14, 300, 300, 0, 0), -- Shadowglen (near Conservator Ilthalaine) (@AttunementEntry, 1, 1, -607.4,-4247.3, 39.0, 3.14, 300, 300, 0, 0), -- Valley of Trials (near Kaltunk) (@AttunementEntry, 1, 1, -2912.7, -253.5, 53.0, 3.14, 300, 300, 0, 0); -- Camp Narache (near Grull Hawkwind) -- NPC Text SET @TEXT_ID := 50930; DELETE FROM `npc_text` WHERE `ID` BETWEEN @TEXT_ID AND @TEXT_ID+1; INSERT INTO `npc_text` (`ID`, `text0_0`) VALUES (@TEXT_ID, 'Some walk this world swiftly, others savor every step. I can attune the pace at which experience flows to you, $N. Pick a path - or whisper your own.'), (@TEXT_ID+1, 'Whisper the rate you desire, $N. A number such as 1.5 or 7.'); --- apiVersion: batch/v1 kind: Job metadata: name: cmangos-attunement-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e echo "=== Applying Attunement schema to classiccharacters ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters < /sql/characters.sql echo "=== Characters schema applied successfully ===" echo "=== Applying Attunement NPC + spawns to classicmangos ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos < /sql/world.sql echo "=== World data applied successfully ===" echo "=== Verifying characters table ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters -e "SHOW TABLES LIKE 'custom_attunement%';" echo "=== Verifying Attunement NPC template ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT entry, name, subname, faction, NpcFlags, ScriptName FROM creature_template WHERE entry = 190014;" echo "=== Verifying spawns (expect 6 rows) ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT id, map, position_x, position_y, position_z FROM creature WHERE id = 190014;" echo "=== Verifying NPC text ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT ID, LEFT(text0_0, 60) AS text_preview FROM npc_text WHERE ID BETWEEN 50930 AND 50931;" echo "=== Attunement migration complete ===" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: cmangos-attunement-migration-sql ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/barber-migration-job.yaml ================================================ --- # Barber module — applies NPC + equipment + gossip text + spawns for the # "Shav Cutiss" barber (entry 190020). World-only (no characters-DB schema). # Idempotent (DELETE-then-INSERT). Pattern matches attunement-migration-job.yaml. # # Skipped vs upstream world_classic.sql: the gameobject chair migration # (id=164767). That migration UPDATEs original Stormwind gameobject IDs which # is destructive on re-run — chairs are cosmetic and can be applied manually # from src/modules/barber/sql/install/world/world_classic.sql lines 13-22 if # desired. apiVersion: v1 kind: ConfigMap metadata: name: cmangos-barber-migration-sql namespace: game-servers data: world.sql: | SET @Entry := 190020; -- Creature template: Shav Cutiss, The Barber (faction 35 = friendly to all) DELETE FROM `creature_template` WHERE `entry` = @Entry; INSERT INTO `creature_template` (Entry, Name, SubName, MinLevel, MaxLevel, DisplayId1, DisplayIdProbability1, Faction, Scale, Family, CreatureType, InhabitType, RegenerateStats, RacialLeader, NpcFlags, UnitFlags, DynamicFlags, ExtraFlags, CreatureTypeFlags, SpeedWalk, SpeedRun, Detection, CallForHelp, Pursuit, Leash, Timeout, UnitClass, `Rank`, HealthMultiplier, PowerMultiplier, DamageMultiplier, DamageVariance, ArmorMultiplier, ExperienceMultiplier, MinLevelHealth, MaxLevelHealth, MinLevelMana, MaxLevelMana, MinMeleeDmg, MaxMeleeDmg, MinRangedDmg, MaxRangedDmg, Armor, MeleeAttackPower, RangedAttackPower, MeleeBaseAttackTime, RangedBaseAttackTime, DamageSchool, MinLootGold, MaxLootGold, LootId, PickpocketLootId, SkinningLootId, KillCredit1, KillCredit2, MechanicImmuneMask, SchoolImmuneMask, ResistanceHoly, ResistanceFire, ResistanceNature, ResistanceFrost, ResistanceShadow, ResistanceArcane, PetSpellDataId, MovementType, TrainerType, TrainerSpell, TrainerClass, TrainerRace, TrainerTemplateId, VendorTemplateId, EquipmentTemplateId, GossipMenuId, AIName) VALUES (@Entry, 'Shav Cutiss', 'The Barber', 60, 60, 7167, 100, 35, 1, 0, 7, 3, 3, 0, 1, 0, 0, 0, 0, 1, 1.14286, 20, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 42, 42, 0, 0, 2, 2, 0, 0, 7, 11, 0, 2000, 2000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @Entry, 0, ''); -- Equipment: dagger (Monster - Bowie Knife) DELETE FROM `creature_equip_template` WHERE `entry` = @Entry; INSERT INTO `creature_equip_template` (entry, equipentry1, equipentry2, equipentry3) VALUES (@Entry, 5278, 0, 0); -- Gossip text 50404-50423 (the barber dialog options) DELETE FROM `npc_text` WHERE `ID` BETWEEN 50404 AND 50423; INSERT INTO `npc_text` (`ID`, `text0_0`, `prob0`) VALUES (50404, 'Welcome, friend, to the barbershop! Come for a cut? A coloring? Something else, perhaps?$B$BWe can groom facial hair, perform piercings, ink night elf tattoos, and have a collection of earrings!$B$BHave a seat and we''ll get right to work. You''re only a few coins away from a new, more attractive you...', 1), (50405, 'Cut my hair, barber!', 1), (50406, 'You need 0 copper to pay me.', 1), (50407, 'Please sit down!', 1), (50408, 'Next one!', 1), (50409, 'Previous one!', 1), (50410, 'I''ll have this one.', 1), (50411, 'I want to change my hair style.', 1), (50412, 'I want to change my hair color.', 1), (50413, 'I want to change my facial hair style.', 1), (50414, 'I want to change my horns.', 1), (50415, 'I want to change my horn color.', 1), (50416, 'I want to change my piercings.', 1), (50417, 'I want to change my earrings.', 1), (50418, 'I want to change my markings.', 1), (50419, 'I want to change my face.', 1), (50420, 'I want to change my hair.', 1), (50421, 'I want to change my tusks.', 1), (50422, 'I want to change my tentacles.', 1), (50423, 'Welcome, friend, to the barbershop! Come for a cut? A coloring? Something else, perhaps?$B$BWe can groom facial hair, perform piercings, reshape tusks and horns, and even modify undead features!$B$BHave a seat and we''ll get right to work. You''re only a few coins away from a new, more attractive you...', 1); -- Spawns: Stormwind + Orgrimmar DELETE FROM `creature` WHERE `id` = @Entry; INSERT INTO `creature` (`id`, `map`, `spawnMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecsmin`, `spawntimesecsmax`, `spawndist`, `MovementType`) VALUES (@Entry, 0, 1, -8748.08, 651.95, 105.43, 1.82255, 25, 25, 0, 0), -- Stormwind (@Entry, 1, 1, 1713.69, -4207.01, 51.65, 3.97408, 25, 25, 0, 0); -- Orgrimmar --- apiVersion: batch/v1 kind: Job metadata: name: cmangos-barber-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e echo "=== Applying Barber NPC + equip + npc_text + spawns to classicmangos ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos < /sql/world.sql echo "=== Verifying NPC template ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT entry, name, subname FROM creature_template WHERE entry = 190020;" echo "=== Verifying spawns (expect 2 rows: Stormwind + Orgrimmar) ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT id, map, position_x, position_y FROM creature WHERE id = 190020;" echo "=== Verifying gossip texts (expect 20 rows: IDs 50404-50423) ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT COUNT(*) AS texts_loaded FROM npc_text WHERE ID BETWEEN 50404 AND 50423;" echo "=== Barber migration complete ===" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: cmangos-barber-migration-sql ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/dnsendpoint.yaml ================================================ --- apiVersion: externaldns.k8s.io/v1alpha1 kind: DNSEndpoint metadata: name: cmangos-wow annotations: external-dns.alpha.kubernetes.io/external: "true" spec: endpoints: - dnsName: "wow.${CLUSTER_DOMAIN}" recordType: A targets: - "${EXTERNAL_IP}" ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/dualspec-migration-job.yaml ================================================ --- # Dualspec module — applies talent/action/character schema + NPC spawn for the # Dual Specialization Crystal (entry 190024). Idempotent: CREATE TABLE IF NOT # EXISTS for the 4 tables, INSERT IGNORE for the data-seeding inserts from # character_action and characters (PK collisions on re-run are harmless). # # Re-running is safe and preserves existing player dualspec state. The DROP # TABLE in the upstream cmangos-classic SQL is intentionally NOT replicated # here — that would destroy second-spec talents/action bars on re-run. apiVersion: v1 kind: ConfigMap metadata: name: cmangos-dualspec-migration-sql namespace: game-servers data: characters.sql: | CREATE TABLE IF NOT EXISTS `custom_dualspec_talent` ( `guid` int(11) unsigned NOT NULL DEFAULT '0', `spell` int(11) unsigned NOT NULL DEFAULT '0', `spec` tinyint(3) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`guid`, `spell`, `spec`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `custom_dualspec_talent_name` ( `guid` int(11) unsigned NOT NULL DEFAULT '0', `spec` tinyint(3) unsigned NOT NULL DEFAULT '0', `name` varchar(255) NOT NULL DEFAULT '', PRIMARY KEY (`guid`, `spec`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `custom_dualspec_action` ( `guid` int(11) unsigned NOT NULL DEFAULT '0', `button` tinyint(3) unsigned NOT NULL DEFAULT '0', `action` int(11) unsigned NOT NULL DEFAULT '0', `type` tinyint(3) unsigned NOT NULL DEFAULT '0', `spec` tinyint(3) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`guid`, `spec`, `button`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- Seed spec=0 from existing character_action. INSERT IGNORE so re-runs -- silently skip duplicates (PK guid+spec+button collision). INSERT IGNORE INTO `custom_dualspec_action` (`guid`, `spec`, `button`, `action`, `type`) SELECT `guid`, 0 AS `spec`, `button`, `action`, `type` FROM `character_action`; CREATE TABLE IF NOT EXISTS `custom_dualspec_characters` ( `guid` int(11) unsigned NOT NULL DEFAULT '0', `spec_count` tinyint(3) unsigned NOT NULL DEFAULT '1', `active_spec` tinyint(3) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`guid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- Seed one row per existing character. INSERT IGNORE handles re-runs and -- also picks up any new characters created since the last run. INSERT IGNORE INTO `custom_dualspec_characters` (`guid`) SELECT `guid` FROM `characters`; world.sql: | SET @ENTRY := 190024; -- Creature template: Dual Specialization Crystal DELETE FROM `creature_template` WHERE `entry` = @ENTRY; INSERT INTO `creature_template` (Entry, Name, SubName, MinLevel, MaxLevel, DisplayId1, DisplayIdProbability1, Faction, Scale, Family, CreatureType, InhabitType, RegenerateStats, RacialLeader, NpcFlags, UnitFlags, DynamicFlags, ExtraFlags, CreatureTypeFlags, SpeedWalk, SpeedRun, Detection, CallForHelp, Pursuit, Leash, Timeout, UnitClass, `Rank`, HealthMultiplier, PowerMultiplier, DamageMultiplier, DamageVariance, ArmorMultiplier, ExperienceMultiplier, MinLevelHealth, MaxLevelHealth, MinLevelMana, MaxLevelMana, MinMeleeDmg, MaxMeleeDmg, MinRangedDmg, MaxRangedDmg, Armor, MeleeAttackPower, RangedAttackPower, MeleeBaseAttackTime, RangedBaseAttackTime, DamageSchool, MinLootGold, MaxLootGold, LootId, PickpocketLootId, SkinningLootId, KillCredit1, KillCredit2, MechanicImmuneMask, SchoolImmuneMask, ResistanceHoly, ResistanceFire, ResistanceNature, ResistanceFrost, ResistanceShadow, ResistanceArcane, PetSpellDataId, MovementType, TrainerType, TrainerSpell, TrainerClass, TrainerRace, TrainerTemplateId, VendorTemplateId, EquipmentTemplateId, GossipMenuId, AIName) VALUES (@ENTRY, 'Dual Specialization Crystal', '', 1, 1, 11659, 100, 35, 1, 0, 7, 3, 3, 0, 1, 0, 0, 0, 0, 1, 1.14286, 20, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 42, 42, 0, 0, 2, 2, 0, 0, 7, 11, 0, 2000, 2000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ''); -- Spawns: Stormwind + Orgrimmar DELETE FROM `creature` WHERE `id` = @ENTRY; INSERT INTO `creature` (`id`, `map`, `spawnMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecsmin`, `spawntimesecsmax`, `spawndist`, `MovementType`) VALUES (@ENTRY, 0, 1, -8988.56, 849.754, 29.621, 2.27687, 25, 25, 0, 0), (@ENTRY, 1, 1, 1471.63, -4216.46, 58.9942, 4.35778, 25, 25, 0, 0); -- Localised name (Spanish) DELETE FROM `locales_creature` WHERE `entry` = @ENTRY; INSERT INTO `locales_creature` (`entry`, `name_loc6`) VALUES (@ENTRY, 'Cristal de Doble Especialización'); -- mangos_string entries for the dualspec UI (English + Spanish loc6) SET @STRING_ENTRY := 12000; DELETE FROM `mangos_string` WHERE `entry` BETWEEN @STRING_ENTRY AND @STRING_ENTRY+21; INSERT INTO `mangos_string` (`entry`, `content_default`, `content_loc6`) VALUES (@STRING_ENTRY, 'Dual Specialization allows you to quickly switch between two different talent builds and action bars.', 'La doble especialización te permite cambiar rápidamente entre dos construcciones de talento y barras de acción diferentes.'), (@STRING_ENTRY+1, 'The cost is ', 'El precio es '), (@STRING_ENTRY+2, 'Change my specialization.', 'Cambiar mi especialización.'), (@STRING_ENTRY+3, 'You don''t have enough money to unlock dual specialization.', 'No tienes suficiente dinero para desbloquear la doble especialización.'), (@STRING_ENTRY+4, 'Are you sure you would like to activate your second specialization for ', '¿Estás seguro de que te gustaría activar tu segunda especialización por '), (@STRING_ENTRY+5, ' gold? This will allow you to quickly switch between two different talent builds and action bars.', ' de oro? Esto te permitirá cambiar rápidamente entre dos construcciones de talento y barras de acción diferentes.'), (@STRING_ENTRY+6, 'You are already on that spec.', 'Ya estás en esa especialización.'), (@STRING_ENTRY+7, '[Activate] ', '[Activar] '), (@STRING_ENTRY+8, '[Rename] ', '[Renombrar] '), (@STRING_ENTRY+9, 'Unnamed', 'Sin nombre'), (@STRING_ENTRY+10, ' (active)', ' (activa)'), (@STRING_ENTRY+11, 'You are in combat and cannot switch spec at this time.', 'Estás en combate y no puedes cambiar de especialización en este momento.'), (@STRING_ENTRY+12, 'You must exit the instance to re-spec.', 'Debe salir de la estancia para cambiar la especialización.'), (@STRING_ENTRY+13, 'You are mounted and cannot switch spec at this time.', 'Está montado y no puede cambiar la especialización en este momento.'), (@STRING_ENTRY+14, 'You are dead and cannot switch spec at this time.', 'Estás muerto y no puedes cambiar la especialización en este momento.'), (@STRING_ENTRY+15, 'You must unlock the dual talent specialization feature first.', 'Primero debe desbloquear la función de doble especialización.'), (@STRING_ENTRY+16, 'Current level is less than ten - you cannot switch spec at this time.', 'El nivel actual es inferior a diez y no puedes cambiar de especialización en este momento.'), (@STRING_ENTRY+17, '|cFF0041FF[Activate] ', '|cFF0041FF[Activar] '), (@STRING_ENTRY+18, '|cFFCC00CC[Rename] ', '|cFFCC00CC[Renombrar] '), (@STRING_ENTRY+19, 'Are you sure you wish to switch your talent specialization?', '¿Estás seguro de que deseas cambiar su especialización?'), (@STRING_ENTRY+20, 'Purchase Dual Talent Specialization', 'Comprar doble especialización de talentos'), (@STRING_ENTRY+21, 'Can not create dual spec item!', '¡No se puede crear un artículo de doble especialización!'); -- NPC gossip text SET @TEXT_ID := 50700; DELETE FROM `npc_text` WHERE `ID` BETWEEN @TEXT_ID AND @TEXT_ID+1; INSERT INTO `npc_text` (`ID`, `text0_0`) VALUES (@TEXT_ID, 'Dual Specialization allows you to quickly switch between two different talent builds and action bars.'), (@TEXT_ID+1, 'Dual Specialization allows you to quickly switch between two different talent builds and action bars.'); DELETE FROM `locales_npc_text` WHERE `entry` BETWEEN @TEXT_ID AND @TEXT_ID+1; INSERT INTO `locales_npc_text` (`entry`, `text0_0_loc6`) VALUES (@TEXT_ID, 'La doble especialización te permite cambiar rápidamente entre dos ramas de talentos y barras de acción diferentes.'), (@TEXT_ID+1, 'La doble especialización te permite cambiar rápidamente entre dos ramas de talentos y barras de acción diferentes.'); --- apiVersion: batch/v1 kind: Job metadata: name: cmangos-dualspec-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e echo "=== Applying Dualspec schema + seeding from character_action/characters ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters < /sql/characters.sql echo "=== Applying Dualspec NPC + strings + spawns to classicmangos ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos < /sql/world.sql echo "=== Verifying characters tables ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters -e "SHOW TABLES LIKE 'custom_dualspec%';" echo "=== Verifying NPC template (entry 190024 = Dual Specialization Crystal) ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT entry, name FROM creature_template WHERE entry = 190024;" echo "=== Verifying spawns (expect 2 rows: Stormwind + Orgrimmar) ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT id, map, position_x, position_y FROM creature WHERE id = 190024;" echo "=== Verifying mangos_string rows (expect 22 entries: 12000-12021) ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT COUNT(*) AS strings_loaded FROM mangos_string WHERE entry BETWEEN 12000 AND 12021;" echo "=== Dualspec migration complete ===" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: cmangos-dualspec-migration-sql ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/externalsecret-database.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: cmangos-database-creds namespace: game-servers spec: refreshInterval: 1h secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: cmangos-database-creds template: data: # Used by mangosd + realmd to connect to MariaDB. MANGOS_DBUSER: "{{ .DB_USER }}" MANGOS_DBPASS: "{{ .DB_PASSWORD }}" # Used by the mariadb container at first-init only. Match the # app-user creds so a fresh PVC reproduces the same login. MARIADB_USER: "{{ .DB_USER }}" MARIADB_PASSWORD: "{{ .DB_PASSWORD }}" dataFrom: - extract: key: cmangos ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/hardcore-migration-job.yaml ================================================ --- apiVersion: v1 kind: ConfigMap metadata: name: cmangos-hardcore-migration-sql namespace: game-servers data: characters.sql: | DROP TABLE IF EXISTS `custom_hardcore_loot_gameobjects`; CREATE TABLE `custom_hardcore_loot_gameobjects` ( `id` int(11) unsigned NOT NULL, `player` int(11) unsigned NOT NULL COMMENT 'Player identifier', `loot_id` int(11) unsigned NOT NULL COMMENT 'The loot group this gameobject is part of', `loot_table` int(11) unsigned NOT NULL COMMENT 'custom_hardcore_loot_tables identifier', `money` int(11) unsigned NOT NULL DEFAULT '0', `position_x` float NOT NULL DEFAULT '0', `position_y` float NOT NULL DEFAULT '0', `position_z` float NOT NULL DEFAULT '0', `orientation` float NOT NULL DEFAULT '0', `map` int(11) NOT NULL DEFAULT '0' COMMENT 'Map identifier', `phase_mask` int(11) NOT NULL DEFAULT '0' COMMENT 'Phase mask identifier', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS `custom_hardcore_loot_tables`; CREATE TABLE `custom_hardcore_loot_tables` ( `id` int(11) unsigned NOT NULL, `item` int(11) unsigned NOT NULL COMMENT 'Item identifier', `amount` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT 'Amount of items', `random_property_id` smallint(5) NOT NULL DEFAULT '0' COMMENT 'The property of the item (e.g. ... of the Hawk, ... of the Monkey)', `durability` int(5) unsigned NOT NULL DEFAULT '0', `enchantments` text, PRIMARY KEY (`id`, `item`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS `custom_hardcore_grave_gameobjects`; CREATE TABLE `custom_hardcore_grave_gameobjects` ( `id` int(11) unsigned NOT NULL, `player` int(11) unsigned NOT NULL COMMENT 'Player identifier', `gameobject_template` int(11) unsigned NOT NULL COMMENT 'gameobject_template entry', `position_x` float NOT NULL DEFAULT '0', `position_y` float NOT NULL DEFAULT '0', `position_z` float NOT NULL DEFAULT '0', `orientation` float NOT NULL DEFAULT '0', `map` int(11) NOT NULL DEFAULT '0' COMMENT 'Map identifier', `phase_mask` int(11) NOT NULL DEFAULT '0' COMMENT 'Phase mask identifier', PRIMARY KEY (`id`, `player`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS `custom_hardcore_player_config`; CREATE TABLE `custom_hardcore_player_config` ( `id` int(11) unsigned NOT NULL, `revive_disabled` boolean DEFAULT FALSE, `drop_loot_on_death` boolean DEFAULT FALSE, `lose_xp_on_death` boolean DEFAULT FALSE, `pvp_disabled` boolean DEFAULT FALSE, `self_found` boolean DEFAULT FALSE, `xp_rate` int(11) unsigned DEFAULT '100', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS `custom_hardcore_player_deathlog`; CREATE TABLE `custom_hardcore_player_deathlog` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `player` int(11) unsigned NOT NULL, `account` int(11) unsigned NOT NULL, `name` char(100) NOT NULL, `level` int(11) NOT NULL, `zone` int(11) unsigned NOT NULL, `area` int(11) unsigned NOT NULL, `map` int(11) unsigned NOT NULL, `killer` int(11) unsigned NOT NULL, `killer_name` char(100) NOT NULL, `reason` int(11) unsigned NOT NULL, `date` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; world.sql: | DELETE FROM gameobject_template WHERE `type`=2 AND `CustomData1`=3643; SET @Entry := 190011; DELETE FROM `creature_template` WHERE `entry` = @Entry; INSERT INTO `creature_template` (`entry`, `DisplayId1`, `DisplayIdProbability1`, `name`, `subname`, `GossipMenuId`, `minlevel`, `maxlevel`, `faction`, `NpcFlags`, `scale`, `rank`, `DamageSchool`, `MeleeBaseAttackTime`, `RangedBaseAttackTime`, `unitClass`, `unitFlags`, `CreatureType`, `CreatureTypeFlags`, `lootid`, `PickpocketLootId`, `SkinningLootId`, `AIName`, `MovementType`, `RacialLeader`, `RegenerateStats`, `MechanicImmuneMask`, `ExtraFlags`) VALUES (@Entry, 1403, 100, '"Masochist" Pete', 'Challenge Advisor', 0, 60, 60, 35, 1, 1, 0, 0, 2000, 0, 1, 0, 7, 138936390, 0, 0, 0, '', 0, 0, 1, 0, 0); DELETE FROM `locales_creature` WHERE `entry` = @Entry; INSERT INTO `locales_creature` (`entry`, `name_loc6`, `subname_loc6`) VALUES (@Entry, 'Pedro "El Masoca"', 'Asesor de Desafios'); DELETE FROM `creature` WHERE `id` = @Entry; INSERT INTO `creature` (`id`, `map`, `spawnMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecsmin`, `spawntimesecsmax`, `spawndist`, `MovementType`) VALUES (@Entry, 0, 1, -8999.00, 851.191, 29.621, 3.88538, 25, 25, 0, 0), (@Entry, 1, 1, 1467.40, -4226.33, 58.9939, 1.19063, 25, 25, 0, 0), (@Entry, 0, 1, -8903.58, -108.401, 81.8486, 4.08677, 25, 25, 0, 0), (@Entry, 0, 1, -6213.26, 330.664, 383.719, 2.89842, 25, 25, 0, 0), (@Entry, 1, 1, 10327.10, 822.521, 1326.43, 2.53681, 25, 25, 0, 0), (@Entry, 1, 1, -638.981, -4227.08, 38.1342, 5.47014, 25, 25, 0, 0), (@Entry, 0, 1, 1859.94, 1560.67, 99.0791, 1.57723, 25, 25, 0, 0), (@Entry, 1, 1, -2882.11, -277.045, 53.9154, 2.37644, 25, 25, 0, 0); SET @TEXT_ID := 50900; DELETE FROM `npc_text` WHERE `ID` BETWEEN @TEXT_ID AND @TEXT_ID+16; INSERT INTO `npc_text` (`ID`, `text0_0`) VALUES (@TEXT_ID, 'Ahoy, $N. If you are looking for a challenge you have come to the right place. Tell me, what challenge are you interested in?'), (@TEXT_ID+1, 'Appologies $N. I can''t provide you with any challenges at the moment.'), (@TEXT_ID+2, 'Oh, the hardcore challenge you say? I thought you''d never ask... If you accept this challenge, it means you will only have one life and if you die, that''s it, no more retries. Are you up for it?'), (@TEXT_ID+3, 'Hmm, the drop loot challenge? This challenge will make you drop some of your belongings every time you die, including gear and gold. What do you say?'), (@TEXT_ID+4, 'Ah, the classic lose experience challenge. This challenge will make you lose some experience every time you die, and if you die enough you can even lose levels. Interested?'), (@TEXT_ID+5, 'The self found challenge... I see you are a lone wolf like me. Just to clarify, this means you won''t be able to use any help from any other adventurer, unless they are in the same challenge as you. Ready for it?'), (@TEXT_ID+6, 'Hold your horses cowboy! It seems like your journey has already taken its course. To start this challenge you must speak with me with a fresh start, if you know what I mean...'), (@TEXT_ID+7, 'I know you are excited about this challenge, but you seem like you already accepted it. What do you want, to double accept it?'), (@TEXT_ID+8, 'Hahaha! That''s what I''m talking about! Good luck! You will need it...'), (@TEXT_ID+9, 'Oh, so you don''t want people attacking you during the challenge? That''s cute... But hey, who am I to judge...'), (@TEXT_ID+10, 'All right then... Consider it done. Careful not to break a nail out there.'), (@TEXT_ID+11, 'Are you sure? You won''t be able to retake the challenge if you drop it now.'), (@TEXT_ID+12, 'Oh! That is such a relieve! I was wondering how long were you going to keep joking around...'), (@TEXT_ID+13, 'All done! Enemies will be able to attack you now.'), (@TEXT_ID+14, 'All done! You are no longer doing the challenge.'), (@TEXT_ID+15, 'Which XP rate would you like to have?'), (@TEXT_ID+16, 'All done! You xp rate has been changed.'); DELETE FROM `locales_npc_text` WHERE `entry` BETWEEN @TEXT_ID AND @TEXT_ID+16; INSERT INTO `locales_npc_text` (`entry`, `text0_0_loc6`) VALUES (@TEXT_ID, 'Hola, $N! Si estas buscando un reto, estas en el lugar indicado. Dime, que reto te interesa?'), (@TEXT_ID+1, 'Mis disculpas $N. No tengo ningun desafio disponible en estos momentos.'), (@TEXT_ID+2, 'El desafio hardcore dices? Crei que nunca me lo preguntarias... Si aceptas este desafio, significa que solo tendras una vida y, si mueres, se acabo, no habra mas reintentos. Te animas?'), (@TEXT_ID+3, 'Mmm, el desafio de perder posesiones? Este desafio te hara soltar algunas de tus pertenencias cada vez que mueras, incluyendo equipo y oro. Que me dices?'), (@TEXT_ID+4, 'Ah, el clasico desafio de perder experiencia. Este desafio te hara perder experiencia cada vez que mueras, y si mueres lo suficiente, incluso puedes perder niveles. Te interesa?'), (@TEXT_ID+5, 'El desafio del lobo solitario... Supongo que eres de los que prefiere ir solo que mal acompanado, eh?. Solo para aclarar, esto significa que no podras usar la ayuda de ningun otro aventurero, a menos que este en el mismo desafio que tu. Estas listo?'), (@TEXT_ID+6, 'Calma, vaquero! Parece que tu viaje ya ha tomado su curso. Para empezar este reto, debes hablar conmigo desde el principio, si sabes a que me refiero...'), (@TEXT_ID+7, 'Se que estas entusiasmado con este reto, pero parece que ya lo has aceptado. Que quieres, aceptarlo dos veces?'), (@TEXT_ID+8, 'Jajaja! Eso es lo que queria escuchar! Mucha suerte! La necesitaras...'), (@TEXT_ID+9, 'Ah, entonces no quieres que otras personas te ataquen durante el desafio? Que monada... Pero bueno, quien soy yo para juzgar?'), (@TEXT_ID+10, 'De acuerdo, ya estas listo. Ve con cuidado por ahi, no vaya a ser que te rompas una una.'), (@TEXT_ID+11, 'Estas seguro? No podras retomar el desafio si lo terminas ahora.'), (@TEXT_ID+12, 'Ah! Que alivio! Ya estaba pensando que de verdad ibas en serio...'), (@TEXT_ID+13, 'Listo! Los enemigos podran combatir contigo ahora.'), (@TEXT_ID+14, 'Listo! Ya no estas realizando el desafio.'), (@TEXT_ID+15, 'Que ratio de XP te gustaria tener?'), (@TEXT_ID+16, 'Listo! He cambiado tu ratio de XP'); SET @STRING_ENTRY := 12200; DELETE FROM `mangos_string` WHERE `entry` BETWEEN @STRING_ENTRY AND @STRING_ENTRY+14; INSERT INTO `mangos_string` (`entry`, `content_default`, `content_loc6`) VALUES (@STRING_ENTRY, 'I''m interested in the hardcore challenge', 'Estoy interesado en el desafio hardcore'), (@STRING_ENTRY+1, 'I would like to stop doing the hardcore challenge', 'Me gustaria terminar el desafio hardcore'), (@STRING_ENTRY+2, 'I''m interested in the drop loot challenge', 'Estoy interesado en el desafio de perder posesiones'), (@STRING_ENTRY+3, 'I would like to stop doing the drop loot challenge', 'Me gustaria terminar el desafio de perder posesiones'), (@STRING_ENTRY+4, 'I''m interested in the lose experience challenge', 'Estoy interesado en el desafio de perder experiencia'), (@STRING_ENTRY+5, 'I would like to stop doing the lose experience challenge', 'Me gustaria terminar el desafio de perder experiencia'), (@STRING_ENTRY+6, 'I''m interested in the self found challenge', 'Estoy interesado en el desafio del lobo solitario'), (@STRING_ENTRY+7, 'I would like to stop doing the self found challenge', 'Me gustaria terminar el desafio del lobo solitario'), (@STRING_ENTRY+8, 'I would like to change my xp rate', 'Me gustaria cambiar el ratio de XP'), (@STRING_ENTRY+9, 'I accept the challenge!', 'Acepto el desafio!'), (@STRING_ENTRY+10, 'Maybe later...', 'Quizas mas tarde...'), (@STRING_ENTRY+11, 'I would like to disable pvp fights', 'Me gustaria desactivar el combate pvp'), (@STRING_ENTRY+12, 'I would like to enable pvp fights', 'Me gustaria activar el combate pvp'), (@STRING_ENTRY+13, 'Yes, please!', 'Si, por favor!'), (@STRING_ENTRY+14, 'Maybe not...', 'Quizas no...'); SET @START_SPELL_ID := 33500; SET @END_SPELL_ID := @START_SPELL_ID+1; DELETE FROM `spell_template` WHERE `Id` BETWEEN @START_SPELL_ID AND @END_SPELL_ID; INSERT INTO `spell_template` (`Id`, `School`, `Category`, `CastUI`, `Dispel`, `Mechanic`, `Attributes`, `AttributesEx`, `AttributesEx2`, `AttributesEx3`, `AttributesEx4`, `Stances`, `StancesNot`, `Targets`, `TargetCreatureType`, `RequiresSpellFocus`, `CasterAuraState`, `TargetAuraState`, `CastingTimeIndex`, `RecoveryTime`, `CategoryRecoveryTime`, `InterruptFlags`, `AuraInterruptFlags`, `ChannelInterruptFlags`, `ProcFlags`, `ProcChance`, `ProcCharges`, `MaxLevel`, `BaseLevel`, `SpellLevel`, `DurationIndex`, `PowerType`, `ManaCost`, `ManaCostPerlevel`, `ManaPerSecond`, `ManaPerSecondPerLevel`, `RangeIndex`, `Speed`, `ModalNextSpell`, `StackAmount`, `Totem1`, `Totem2`, `Reagent1`, `Reagent2`, `Reagent3`, `Reagent4`, `Reagent5`, `Reagent6`, `Reagent7`, `Reagent8`, `ReagentCount1`, `ReagentCount2`, `ReagentCount3`, `ReagentCount4`, `ReagentCount5`, `ReagentCount6`, `ReagentCount7`, `ReagentCount8`, `EquippedItemClass`, `EquippedItemSubClassMask`, `EquippedItemInventoryTypeMask`, `Effect1`, `Effect2`, `Effect3`, `EffectDieSides1`, `EffectDieSides2`, `EffectDieSides3`, `EffectBaseDice1`, `EffectBaseDice2`, `EffectBaseDice3`, `EffectDicePerLevel1`, `EffectDicePerLevel2`, `EffectDicePerLevel3`, `EffectRealPointsPerLevel1`, `EffectRealPointsPerLevel2`, `EffectRealPointsPerLevel3`, `EffectBasePoints1`, `EffectBasePoints2`, `EffectBasePoints3`, `EffectMechanic1`, `EffectMechanic2`, `EffectMechanic3`, `EffectImplicitTargetA1`, `EffectImplicitTargetA2`, `EffectImplicitTargetA3`, `EffectImplicitTargetB1`, `EffectImplicitTargetB2`, `EffectImplicitTargetB3`, `EffectRadiusIndex1`, `EffectRadiusIndex2`, `EffectRadiusIndex3`, `EffectApplyAuraName1`, `EffectApplyAuraName2`, `EffectApplyAuraName3`, `EffectAmplitude1`, `EffectAmplitude2`, `EffectAmplitude3`, `EffectMultipleValue1`, `EffectMultipleValue2`, `EffectMultipleValue3`, `EffectChainTarget1`, `EffectChainTarget2`, `EffectChainTarget3`, `EffectItemType1`, `EffectItemType2`, `EffectItemType3`, `EffectMiscValue1`, `EffectMiscValue2`, `EffectMiscValue3`, `EffectTriggerSpell1`, `EffectTriggerSpell2`, `EffectTriggerSpell3`, `EffectPointsPerComboPoint1`, `EffectPointsPerComboPoint2`, `EffectPointsPerComboPoint3`, `SpellVisual`, `SpellIconID`, `ActiveIconID`, `SpellPriority`, `SpellName`, `SpellName2`, `SpellName3`, `SpellName4`, `SpellName5`, `SpellName6`, `SpellName7`, `SpellName8`, `Rank1`, `Rank2`, `Rank3`, `Rank4`, `Rank5`, `Rank6`, `Rank7`, `Rank8`, `ManaCostPercentage`, `StartRecoveryCategory`, `StartRecoveryTime`, `MaxTargetLevel`, `SpellFamilyName`, `SpellFamilyFlags`, `MaxAffectedTargets`, `DmgClass`, `PreventionType`, `StanceBarOrder`, `DmgMultiplier1`, `DmgMultiplier2`, `DmgMultiplier3`, `MinFactionId`, `MinReputation`, `RequiredAuraVision`, `EffectBonusCoefficient1`, `EffectBonusCoefficient2`, `EffectBonusCoefficient3`, `EffectBonusCoefficientFromAP1`, `EffectBonusCoefficientFromAP2`, `EffectBonusCoefficientFromAP3`, `IsServerSide`, `AttributesServerside`) VALUES (@START_SPELL_ID, 0, 0, 0, 0, 0, 2147483648, 0, 0, 1048576, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 1, 1, 21, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 6, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 61, 0, 0, 'Hardcore Challenge', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 1, 1, 0, 0, 0, 1, 0.2, 0, 0, 0, 0, 0, 0), (@START_SPELL_ID+1, 0, 0, 0, 0, 0, 2147483648, 0, 0, 1048576, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 1, 1, 21, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 6, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, 1573, 0, 0, 'Self Found Challenge', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 1, 1, 0, 0, 0, 1, 0.2, 0, 0, 0, 0, 0, 0); --- apiVersion: batch/v1 kind: Job metadata: name: cmangos-hardcore-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e echo "=== Applying hardcore module schema to classiccharacters ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters < /sql/characters.sql echo "=== Characters schema applied successfully ===" echo "=== Applying hardcore module data to classicmangos ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos < /sql/world.sql echo "=== World data applied successfully ===" echo "=== Verifying characters tables ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters -e "SHOW TABLES LIKE 'custom_hardcore%';" echo "=== Verifying Masochist Pete NPC ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT entry, name, subname FROM creature_template WHERE entry = 190011;" echo "=== Verifying creature spawns ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT COUNT(*) AS spawn_count FROM creature WHERE id = 190011;" echo "=== Hardcore module migration complete ===" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: cmangos-hardcore-migration-sql ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/hearthstone-cd-migration-job.yaml ================================================ --- apiVersion: v1 kind: ConfigMap metadata: name: cmangos-hearthstone-cd-migration-sql namespace: game-servers data: hearthstone-15m.sql: | -- Hearthstone (item 6948) cooldown: 1h → 15m. -- -- The cooldown lives on the spell (8690), not the item — cmangos reads -- spell data from the SQL spell_template table at world load, so an -- UPDATE here is the canonical override (no DBC file edit needed). -- -- RecoveryTime is in milliseconds. 900000ms = 15 * 60s * 1000ms. -- Idempotent: re-running this just rewrites the same value. -- -- Canonical copy lives in the fork at: -- etc/emberstone/sql/world/hearthstone-15m.sql -- Keep this inline copy in sync with that file. -- -- Note: spell_template is loaded at mangosd startup. The cooldown change -- takes effect on the next mangosd restart, not immediately. -- Spell 8690 has BOTH RecoveryTime and CategoryRecoveryTime; engine -- uses MAX(both). Updating just RecoveryTime leaves the Category -- (89 = Hearthstone) at 60min, so the effective CD stays 60min. -- Update both to 900000 (15min). UPDATE `spell_template` SET `RecoveryTime` = 900000, `CategoryRecoveryTime` = 900000 WHERE `Id` = 8690; --- apiVersion: batch/v1 kind: Job metadata: name: cmangos-hearthstone-cd-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e echo "=== Applying Hearthstone 15m cooldown override to classicmangos ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos < /sql/hearthstone-15m.sql echo "=== SQL applied ===" echo "=== Verifying spell 8690 (Hearthstone) RecoveryTime ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT id, SpellName, RecoveryTime FROM spell_template WHERE id = 8690;" echo "=== Done. Restart mangosd to pick up the new cooldown ===" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: cmangos-hearthstone-cd-migration-sql ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: cmangos namespace: game-servers spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: database: containers: app: image: repository: mariadb tag: "12.2" env: TZ: ${CLUSTER_TIMEZONE} # MARIADB_ROOT_PASSWORD is first-init-only (DB volume is # persistent; ignored on subsequent starts). Rotation is # tracked separately from the app user. MARIADB_ROOT_PASSWORD: password MARIADB_DATABASE: classicrealmd envFrom: # MARIADB_USER / MARIADB_PASSWORD come from 1Password via # ExternalSecret (cmangos-database-creds). First-init only. - secretRef: name: cmangos-database-creds probes: liveness: enabled: true custom: true spec: exec: command: ['healthcheck.sh', '--connect', '--innodb_initialized'] periodSeconds: 30 timeoutSeconds: 3 failureThreshold: 3 readiness: enabled: true custom: true spec: exec: command: ['healthcheck.sh', '--connect', '--innodb_initialized'] periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 startup: enabled: true custom: true spec: exec: command: ['healthcheck.sh', '--connect', '--innodb_initialized'] periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 30 resources: requests: cpu: 100m memory: 512Mi limits: memory: 2Gi realmd: initContainers: wait-db: image: repository: busybox tag: latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do sleep 2; done'] containers: app: image: repository: ghcr.io/xunholy/cmangos-classic tag: 2473619f4ff3431fe68bacec5b05fa52fa0e0fba args: ["realmd"] env: TZ: ${CLUSTER_TIMEZONE} MANGOS_DBHOST: cmangos-database MANGOS_DBPORT: "3306" envFrom: # MANGOS_DBUSER + MANGOS_DBPASS from 1Password via ESO. - secretRef: name: cmangos-database-creds probes: liveness: enabled: true custom: true spec: tcpSocket: port: 3724 periodSeconds: 30 timeoutSeconds: 3 failureThreshold: 3 readiness: enabled: true custom: true spec: tcpSocket: port: 3724 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 startup: enabled: true custom: true spec: tcpSocket: port: 3724 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 30 resources: requests: cpu: 10m memory: 64Mi limits: memory: 256Mi mangosd: pod: terminationGracePeriodSeconds: 300 initContainers: wait-db: image: repository: busybox tag: latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do sleep 2; done'] containers: app: image: repository: ghcr.io/xunholy/cmangos-classic tag: 2473619f4ff3431fe68bacec5b05fa52fa0e0fba args: ["mangosd"] tty: true stdin: true env: TZ: ${CLUSTER_TIMEZONE} MANGOS_DBHOST: cmangos-database MANGOS_DBPORT: "3306" envFrom: # MANGOS_DBUSER + MANGOS_DBPASS from 1Password via ESO. - secretRef: name: cmangos-database-creds # Graceful shutdown via the existing stdin FIFO. Aligned with # terminationGracePeriodSeconds=300: send 'server restart 240' # (4-min in-game countdown), then sleep 260s for save + exit. # SIGTERM follows at ~280s, SIGKILL at 300s if anything lingers. lifecycle: preStop: exec: command: - /bin/sh - -c - | echo "server restart 240" > /tmp/mangosd-stdin sleep 260 probes: liveness: enabled: true custom: true spec: tcpSocket: port: 8085 periodSeconds: 30 timeoutSeconds: 3 failureThreshold: 3 readiness: enabled: true custom: true spec: tcpSocket: port: 8085 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 startup: enabled: true custom: true spec: tcpSocket: port: 8085 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 180 resources: requests: cpu: "2" memory: 4Gi limits: memory: 12Gi # Tail the GM audit log to stdout so commands issued by # GM-tier accounts surface in kubectl logs (and the eventual # Loki collector). The mangosd container writes gm.log; this # sidecar shares the cmangos-mangosd-logs PVC read-only. gm-log-tail: image: repository: busybox tag: latest command: - /bin/sh - -c - | while [ ! -f /opt/mangos/logs/gm.log ]; do sleep 5; done exec tail -F /opt/mangos/logs/gm.log resources: requests: cpu: 5m memory: 8Mi limits: memory: 32Mi securityContext: runAsUser: 1001 runAsGroup: 1001 runAsNonRoot: true readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: ["ALL"] # Prune /opt/mangos/cores so a runaway crash loop can't fill # the 40Gi PVC again (May 2026 incident: cores went from a # 4-9 GB dump to zero-byte writes once the disk was full, # blinding post-mortem analysis). Keeps the 2 newest non-zero # cores by mtime and deletes the rest every 10 min. cores-pruner: image: repository: busybox tag: latest command: - /bin/sh - -c - | while true; do if cd /opt/mangos/cores 2>/dev/null; then find . -maxdepth 1 -name 'core.*' -size 0 -delete 2>/dev/null # shellcheck disable=SC2012 ls -1t core.* 2>/dev/null | tail -n +3 | xargs -r rm -f -- fi sleep 600 done resources: requests: cpu: 5m memory: 8Mi limits: memory: 32Mi securityContext: # mangosd writes cores as the mangos user (UID 1001). Without # CAP_DAC_OVERRIDE (we drop ALL caps) root can't delete files # owned by 1001 at mode 0600, so the pruner becomes a no-op # and the cores PVC wedges at 100%. Match the worldserver UID. runAsUser: 1001 runAsGroup: 1001 runAsNonRoot: true readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: ["ALL"] service: database: controller: database ports: mysql: port: 3306 auth: controller: realmd ports: auth: port: 3724 world: controller: mangosd ports: world: port: 8085 soap: controller: mangosd ports: soap: port: 7878 configMaps: mangosd-config: data: mangosd.conf: | GameType = 1 RealmZone = 8 WorldServerPort = 8085 BindIP = "0.0.0.0" PlayerLimit = 750 # Serialize MapUpdater workers to eliminate concurrent navmesh + bot-AI races. # Confirmed root cause of the BG segfaults at 250-500 bots: cores show concurrent # MapUpdateWorker threads crashing in dtNavMesh::getTileAt and ai::MovementAction::UseTransport. # detour is not thread-safe; UseTransport has unguarded sGOStorage::LookupEntry deref. MapUpdate.Threads = 1 Motd = "Welcome to Emberstone" LogLevel = 3 LogFile = "/opt/mangos/logs/Server.log" LogFileLevel = 3 LogTimestamp = 1 # GM command audit log. Absolute path because run_mangosd cd's # into /opt/mangos/cores before exec. Tailed by the gm-log-tail # sidecar so lines also reach kubectl logs / future Loki. GmLogFile = "/opt/mangos/logs/gm.log" GmLogTimestamp = 1 GmLogPerAccount = 0 LogGMTrade = 1 LogFilter_GMChat = 0 SOAP.Enabled = 1 SOAP.IP = 0.0.0.0 SOAP.Port = 7878 Rate.XP.Kill = 1 Rate.XP.Quest = 1 Rate.XP.Explore = 1 Rate.Drop.Item.Poor = 3 Rate.Drop.Item.Normal = 3 Rate.Drop.Item.Uncommon = 3 Rate.Drop.Item.Rare = 2 Rate.Drop.Item.Epic = 1 Rate.Drop.Money = 3 Rate.Reputation.Gain = 3 AllowTwoSide.Interaction.Group = 1 AllowTwoSide.Interaction.Guild = 1 AllowTwoSide.Interaction.Chat = 1 AllowTwoSide.Interaction.Channel = 1 MailDeliveryDelay = 0 StartPlayerMoney = 100000 SkillGain.Crafting = 3 SkillGain.Gathering = 3 SkillGain.Defense = 3 SkillGain.Weapon = 3 Rate.Drop.Item.Quest = 3 Death.Ghost.RunSpeed.World = 1.5 PlayerSaveInterval = 60000 Rate.Health = 3 Rate.Mana = 3 realmd-config: data: realmd.conf: | RealmServerPort = 3724 BindIP = "0.0.0.0" # Brute-force protection on the SRP6 auth port (internet # exposed via TCPRoute → envoy-external gateway). # MaxCount=5 failures before action # BanTime=600 ten-minute ban # BanType=1 ban by IP (0 = ban the account, riskier) # Logging=1 log every failure so Crowdsec / Falco can # pick up patterns and broaden the response WrongPass.MaxCount = 5 WrongPass.BanTime = 600 WrongPass.BanType = 1 WrongPass.Logging = 1 aiplayerbot-config: data: aiplayerbot.conf: | AiPlayerbot.Enabled = 1 AiPlayerbot.RandomBotAutoCreate = 1 AiPlayerbot.RandomBotAutologin = 1 # Boot-time bot stampede was segfaulting mangosd at "Loading # instance data for world_map_kalimdor": 250+ bots spawning # into maps 0/1 raced detour navmesh + sGOStorage::LookupEntry # before map state settled. MapUpdate.Threads=1 fixes the BG # runtime case but not the startup case. Bots ramp up over # time after boot via the random-bot tick, so we still reach # MinRandomBots without the boot stampede. AiPlayerbot.RandomBotLoginAtStartup = 0 AiPlayerbot.RandomBotAccountPrefix = rndbot AiPlayerbot.RandomBotAccountCount = 2000 AiPlayerbot.MinRandomBots = 1000 AiPlayerbot.MaxRandomBots = 2000 AiPlayerbot.RandomBotMinLevel = 1 AiPlayerbot.RandomBotMaxLevel = 60 AiPlayerbot.RandomBotMaps = 0,1 AiPlayerbot.AutoDoQuests = 1 AiPlayerbot.AutoPickReward = yes AiPlayerbot.AutoEquipUpgradeLoot = 1 AiPlayerbot.AutoLearnTrainerSpells = 1 AiPlayerbot.AutoLearnQuestSpells = 1 AiPlayerbot.RandomGearUpgradeEnabled = 1 AiPlayerbot.RandomBotTeleportNearPlayer = 1 AiPlayerbot.SyncQuestWithPlayer = 1 AiPlayerbot.RandomBotGuildCount = 0 AiPlayerbot.RandomBotJoinBG = 1 # Temporary: stop bots auto-queuing into BGs. Crashes traced to # HandleMoveWorldportAckOpcode racing a fresh BG removal — bots # cycling in/out of queues are what supplies the stale Worldport # ACKs. Re-enable once the WorldportAck patch (0002) lands in # the image. Bots still queue when invited (RandomBotJoinBG=1). AiPlayerbot.RandomBotAutoJoinBG = 0 AiPlayerbot.RandomBotGroupNearby = 1 AiPlayerbot.SyncLevelWithPlayers = 1 AiPlayerbot.SyncLevelMaxAbove = 2 AiPlayerbot.AutoPickTalents = full AiPlayerbot.AutoTrainSpells = free # Competitive BG/WSG twink settings AiPlayerbot.minEnchantingBotLevel = 10 AiPlayerbot.BotAcceptDuelMinimumLevel = 10 twinkmaster-config: data: twinkmaster.conf: | Twinkmaster.Enable = 1 Twinkmaster.TargetLevel = 19 attunement-config: data: # Hardcore was amalgamated into the Attuner of Paths gossip # in xunholy/cmangos-classic@feb8ea8b7 — the merged module # reads both Attunement.* and Hardcore.* keys from this single # attunement.conf. (The old hardcore.conf path is no longer # consulted by the binary.) attunement.conf: | Attunement.Enable = 1 Attunement.DefaultRate = 1.0 Attunement.MinRate = 0.1 Attunement.MaxRate = 100 Attunement.Aura.Tier1.SpellId = 0 Attunement.Aura.Tier2.SpellId = 0 Attunement.Aura.Tier3.SpellId = 0 Attunement.Aura.Tier4.SpellId = 0 Attunement.Aura.Tier5.SpellId = 0 Hardcore.Enable = 1 Hardcore.PlayerConfig = 1 Hardcore.BroadcastDeathGuild = 1 Hardcore.BroadcastDeathWorld = 1 Hardcore.SpawnGrave = 1 Hardcore.GraveGameObjectID = 61 Hardcore.GraveMessage = "Shit happens. | Well, this sucks. | It is really dark down here. | Finally some peace and quiet. | Shhh! I am sleeping. " Hardcore.RemoveGravesOnCharacterDeleted = 1 Hardcore.DropGear = 0 Hardcore.DropItems = 0 Hardcore.DropMoney = 0 Hardcore.BotDropGear = 0 Hardcore.BotDropItems = 0 Hardcore.BotDropMoney = 0 Hardcore.RemoveLootOnCharacterDeleted = 1 Hardcore.LootGameObjectID = 2850 Hardcore.ReviveDisabled = 1 Hardcore.ReviveOnGraveyard = 0 Hardcore.LevelDown = 0 Hardcore.MaxPlayerLoot = 99 Hardcore.DropOnDungeons = 1 Hardcore.DropOnRaids = 1 Hardcore.LevelDownOnDungeons = 1 Hardcore.LevelDownOnRaids = 1 Hardcore.LevelDownMinLevel = 1 Hardcore.DropMinLevel = 1 Hardcore.DisablePVP = 0 Hardcore.SelfFound = 0 anticheat-config: data: # Canonical source: etc/emberstone/anticheat.conf in # xunholy/cmangos-classic. Keep in sync. # Action mask vocabulary (sum of bits): 1=log, 2=prompt, # 4=kick, 8=ban_acct, 16=ban_ip, 32=silence. Every mask here # is ≤ 7 — kick-only, never auto-ban (human decision only). anticheat.conf: | [AnticheatConf] ConfVersion=2017102301 Enable = 1 FingerprintHistory = 30 FingerprintLevel = 6 KickDelay.Min = 30 KickDelay.Max = 90 BanDelay.Min = 30 BanDelay.Max = 90 IPBanDelay.Min = 30 IPBanDelay.Max = 90 BanWave.Day = 1 BanWave.Hour = 10 BanWave.Minute = 0 Movement.UseExtrapolation = 1 Movement.SpeedHack.Enable = 1 Movement.WallClimb.TickCount = 0 Movement.WallClimb.TickAction = 0 Movement.WallClimb.TotalCount = 0 Movement.WallClimb.TotalAction = 0 # High-confidence cheats — kick on first detect Movement.WaterWalk.TickCount = 1 Movement.WaterWalk.TickAction = 7 Movement.WaterWalk.TotalCount = 0 Movement.WaterWalk.TotalAction = 0 Movement.SlowFall.TickCount = 1 Movement.SlowFall.TickAction = 7 Movement.SlowFall.TotalCount = 0 Movement.SlowFall.TotalAction = 0 Movement.FlyHack.TickCount = 1 Movement.FlyHack.TickAction = 7 Movement.FlyHack.TotalCount = 0 Movement.FlyHack.TotalAction = 0 Movement.Forbidden.TickCount = 1 Movement.Forbidden.TickAction = 7 Movement.Forbidden.TotalCount = 0 Movement.Forbidden.TotalAction= 0 Movement.NullClientTime.TickCount = 1 Movement.NullClientTime.TickAction = 7 Movement.NullClientTime.TotalCount = 0 Movement.NullClientTime.TotalAction = 0 Movement.RootMove.TickCount = 1 Movement.RootMove.TickAction = 7 Movement.RootMove.TotalCount = 0 Movement.RootMove.TotalAction= 0 Movement.TimeBack.TickCount = 1 Movement.TimeBack.TickAction = 7 Movement.TimeBack.TotalCount = 0 Movement.TimeBack.TotalAction= 0 Movement.FakeTransport.TickCount = 1 Movement.FakeTransport.TickAction = 7 Movement.FakeTransport.TotalCount = 0 Movement.FakeTransport.TotalAction = 0 Movement.TeleToTransport.TickCount = 1 Movement.TeleToTransport.TickAction = 7 Movement.TeleToTransport.TotalCount = 0 Movement.TeleToTransport.TotalAction= 0 Movement.FixedZ.TickCount = 1 Movement.FixedZ.TickAction = 7 Movement.FixedZ.TotalCount = 0 Movement.FixedZ.TotalAction= 0 # Twitchy under lag — log+prompt, kick after 10 cumulative Movement.MultiJump.TickCount = 1 Movement.MultiJump.TickAction = 3 Movement.MultiJump.TotalCount = 10 Movement.MultiJump.TotalAction = 7 Movement.FastJump.TickCount = 1 Movement.FastJump.TickAction = 3 Movement.FastJump.TotalCount = 10 Movement.FastJump.TotalAction = 7 Movement.JumpSpeedChange.TickCount = 1 Movement.JumpSpeedChange.TickAction = 3 Movement.JumpSpeedChange.TotalCount = 10 Movement.JumpSpeedChange.TotalAction= 7 Movement.HeartbeatSkip.TickCount = 1 Movement.HeartbeatSkip.TickAction = 3 Movement.HeartbeatSkip.TotalCount = 10 Movement.HeartbeatSkip.TotalAction= 7 Movement.ClockDesync.TickCount = 1 Movement.ClockDesync.TickAction = 3 Movement.ClockDesync.TotalCount = 10 Movement.ClockDesync.TotalAction= 7 # Mid-confidence — kick after 3-5 cumulative Movement.OverspeedZ.TickCount = 1 Movement.OverspeedZ.TickAction = 3 Movement.OverspeedZ.TotalCount = 5 Movement.OverspeedZ.TotalAction = 7 Movement.BadOrderAck.TickCount = 1 Movement.BadOrderAck.TickAction = 3 Movement.BadOrderAck.TotalCount = 5 Movement.BadOrderAck.TotalAction= 7 # Teleport — instant kick on first detect. Position revert is # built into the anticheat: src/game/Anticheat/module/Movement/ # movement.cpp:1034 calls Player::SavePositionInDB with the # PREVIOUS (legitimate) position and returns false to reject # the movement opcode. So a hacker teleporting to GM island # gets kicked AND the DB stores their pre-cheat location, so # relog doesn't keep them there. # GM island has an extra CHEAT_TYPE_FORBIDDEN detector at # movement.cpp:1031. # No false-positive concern: engine-initiated teleports (mage # portal, hearthstone, instance entry, gryphon arrivals) are # excluded from this check — only client-injected movements # the server didn't request trip it. Movement.Teleport.TickCount = 1 Movement.Teleport.TickAction = 7 Movement.Teleport.TotalCount = 0 Movement.Teleport.TotalAction = 0 Movement.TeleportFar.TickCount = 1 Movement.TeleportFar.TickAction = 7 Movement.TeleportFar.TotalCount = 0 Movement.TeleportFar.TotalAction= 0 # Exploration — info only, no kick Movement.Explore.TickCount = 3 Movement.Explore.TickAction = 3 Movement.Explore.TotalCount = 0 Movement.Explore.TotalAction = 0 Movement.ExploreHigh.TickCount = 1 Movement.ExploreHigh.TickAction = 3 Movement.ExploreHigh.TotalCount = 0 Movement.ExploreHigh.TotalAction = 0 Movement.BadFallReset.Enable = 1 Movement.BadFallReset.Threshold = 1 Movement.BadFallReset.Penalty = 7 # Antispam — silence (reversible) Antispam.Enable = 1 Antispam.Silence = 1 Antispam.MaxLevel = 25 # Warden re-enable attempt. Previous crash was 'Failed to locate # Warden modules' — root cause hypothesis: relative path # "warden_modules" doesn't resolve at the moment WardenModuleMgr # lazy-initializes on first player auth (boost::fs::exists from # a CWD that isn't /opt/mangos/bin). Switching to absolute path # rules out CWD-resolution issues; data files at this path are # confirmed present + readable + size-valid + non-zero header. Warden.Enable = 1 Warden.ModuleDir = "/opt/mangos/bin/warden_modules" Warden.Timeout = 30 Warden.ScanFrequency = 15 Warden.ScanCount = 10 Warden.MinimumLevel = 1 Warden.MinimumAdvancedLevel = 1 Warden.SuspiciousEndSceneHookAction = 7 Warden.TickCount = 1 Warden.TickAction = 7 Warden.TotalCount = 0 Warden.TotalAction = 0 vip-config: data: # merge_confs in the runner entrypoint splits each line on '=' and # uses LHS as the key. Section headers ([VipConf]) and # comments # don't parse as key=value, so they end up appended as garbage # '[VipConf] = [VipConf]' lines in /opt/mangos/etc/vip.conf. # Keep this to plain key=value only, matching attunement.conf. # MasterSpellId 22888 = Rallying Cry of the Dragonslayer. # Vanilla 1.12.1 client has it in spell.dbc (renders in # spellbook with that name + icon 1548). Zero references from # creatures, items, or AI scripts in this server's DB, so # reusing the ID does not collide with any in-game content. # The vanilla effects (10% crit / 140 AP / 5% spell crit, 2h) # ride along with whatever bundled spells get added below. # Previous ID 91200 ("Wayfarer's Boon") is Cataclysm-range # and invisible to vanilla clients without a custom patch-X.MPQ. vip.conf: | Vip.Enable = 1 Vip.MasterSpellId = 18282 # Explicit list (rather than "" which the mangos config parser # returns as a literal 2-char string, not an empty string — # the module's empty-string fallback to built-in defaults # never triggered). # Bundle (15 spells): # 22888 Rallying Cry of the Dragonslayer 16609 Warchief's Blessing # 24425 Spirit of Zandalar 15366 Songflower Serenade # 22817 Fengus' Ferocity 22818 Mol'dar's Moxie 22820 Slip'kik's Savvy (DM Tribute trio) # 23735 Sayge's Strength 23736 Sayge's Agility 23737 Sayge's Stamina (Sayge Dark Fortunes) # 23768 Sayge's Damage 26393 Elune's Blessing (Lunar Festival) # 17626 Flask of the Titans 17627 Distilled Wisdom 17628 Supreme Power Vip.BundledSpellIds = 22888,24425,15366,16609,22817,22818,22820,23735,23736,23737,23768,26393,17626,17627,17628 autoscale-config: data: autoscale.conf: | Autoscale.Enable = 1 Autoscale.RescanIntervalSeconds = 10 Autoscale.HpExponent = 0.85 Autoscale.MinScale = 0.20 Autoscale.MaxScale = 1.0 # Baselines reflect each raid's designed group size. MC/BWL/ # AQ40/Onyxia were built for 40, ZG/AQ20 for 20. The # MinScale=0.20 floor catches small-group attempts (e.g. 5p # MC at the floor = 20% HP) — the "smallest party we'll # bother supporting" tier. Adding bodies scales mobs back up # toward 100% smoothly. Autoscale.Baseline.Dungeon = 5 Autoscale.Baseline.RaidDefault = 40 Autoscale.MapBaselines = "309:20,509:20" Autoscale.MapBlacklist = "" Autoscale.Announce = 1 transmog-config: data: transmog.conf: | Transmog.Enable = 1 # Per-transmog gold cost (copper). 0 = free. Transmog.CostFee = 0 # Multiplier on item-quality-based cost (1.0 = no extra cost). Transmog.CostMultiplier = 1.0 # Token-gated transmog (0 = disabled, no token required). Transmog.TokenRequired = 0 Transmog.TokenEntry = 0 Transmog.TokenAmount = 1 barber-config: data: barber.conf: | Barber.Enable = 1 dualspec-config: data: dualspec.conf: | Dualspec.Enable = 1 # Cost to unlock second spec, in copper (100000 = 10g). Dualspec.Cost = 100000 trainingdummies-config: data: trainingdummies.conf: | Trainingdummies.Enable = 1 achievements-config: data: achievements.conf: | Achievements.Enable = 1 # Chat broadcast when an achievement is earned (1 = on). Achievements.SendMessage = 1 # Send special packets for the client-side "Achiever" addon (1 = on). Achievements.SendAddon = 1 # Visual sparkle effect on the player when earning achievement (1 = on). Achievements.SendVisual = 1 # Spell ID for the visual effect. Achievements.EffectId = 146 # Award achievements to random bots (0 = off — bots clutter realm-first leaderboards). Achievements.RandomBots = 0 Achievements.RandomBotsRealmFirst = 0 # Sync earned achievements across all characters of an account (0 = per-character). Achievements.AccountAchievements = 0 ahbot-config: data: ahbot.conf: | AuctionHouseBot.Seller.Enabled = 1 AuctionHouseBot.Buyer.Enabled = 1 AuctionHouseBot.Chance.Sell = 80 AuctionHouseBot.Chance.Buy = 40 AuctionHouseBot.Alliance.Items.Amount.Ratio = 100 AuctionHouseBot.Horde.Items.Amount.Ratio = 100 AuctionHouseBot.Neutral.Items.Amount.Ratio = 80 AuctionHouseBot.Buy.Value = 90 AuctionHouseBot.Bid.Min = 60 AuctionHouseBot.Bid.Max = 95 AuctionHouseBot.Time.Min = 2 AuctionHouseBot.Time.Max = 48 AuctionHouseBot.Value.Variance = 15 AuctionHouseBot.Items.Profession = 90, 100, 0, 60 AuctionHouseBot.Loot.Creature.Normal = 40, 50, 8, 15 AuctionHouseBot.Loot.Creature.Elite = 35, 40, 2, 4 AuctionHouseBot.Loot.Creature.Rare = 5, 15, 1, 2 AuctionHouseBot.Loot.Disenchant = 15, 20, 1, 3 AuctionHouseBot.Loot.Fishing = 5, 10, 30, 50 AuctionHouseBot.Loot.Gameobject = 20, 25, 7, 15 AuctionHouseBot.Loot.Skinning = 5, 10, 50, 80 persistence: database: existingClaim: cmangos-database advancedMounts: database: app: - path: /var/lib/mysql data: existingClaim: cmangos-data advancedMounts: mangosd: app: - path: /var/lib/mangos readOnly: true cores: existingClaim: cmangos-cores advancedMounts: mangosd: app: # Mount as a sibling of /opt/mangos/etc so that mangosd's # default config lookups (../etc/X.conf for aiplayerbot, # ahbot, twinkmaster) keep resolving when we chdir here # for core-dump capture. - path: /opt/mangos/cores cores-pruner: - path: /opt/mangos/cores mangosd-config: type: configMap name: cmangos-mangosd-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/mangosd.conf subPath: mangosd.conf realmd-config: type: configMap name: cmangos-realmd-config advancedMounts: realmd: app: - path: /opt/mangos/conf/realmd.conf subPath: realmd.conf aiplayerbot-config: type: configMap name: cmangos-aiplayerbot-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/aiplayerbot.conf subPath: aiplayerbot.conf twinkmaster-config: type: configMap name: cmangos-twinkmaster-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/twinkmaster.conf subPath: twinkmaster.conf attunement-config: type: configMap name: cmangos-attunement-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/attunement.conf subPath: attunement.conf anticheat-config: type: configMap name: cmangos-anticheat-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/anticheat.conf subPath: anticheat.conf vip-config: type: configMap name: cmangos-vip-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/vip.conf subPath: vip.conf autoscale-config: type: configMap name: cmangos-autoscale-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/autoscale.conf subPath: autoscale.conf transmog-config: type: configMap name: cmangos-transmog-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/transmog.conf subPath: transmog.conf barber-config: type: configMap name: cmangos-barber-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/barber.conf subPath: barber.conf dualspec-config: type: configMap name: cmangos-dualspec-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/dualspec.conf subPath: dualspec.conf trainingdummies-config: type: configMap name: cmangos-trainingdummies-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/trainingdummies.conf subPath: trainingdummies.conf achievements-config: type: configMap name: cmangos-achievements-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/achievements.conf subPath: achievements.conf ahbot-config: type: configMap name: cmangos-ahbot-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/ahbot.conf subPath: ahbot.conf mangosd-logs: existingClaim: cmangos-mangosd-logs advancedMounts: mangosd: app: - path: /opt/mangos/logs gm-log-tail: - path: /opt/mangos/logs readOnly: true realmd-logs: type: emptyDir advancedMounts: realmd: app: - path: /opt/mangos/logs ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - externalsecret-database.yaml - pvc-database.yaml - pvc-data.yaml - pvc-cores.yaml - pvc-logs.yaml - tcproutes.yaml - dnsendpoint.yaml - replicationsource.yaml - volsync-externalsecret.yaml - prometheusrule.yaml - mangos-string-517-migration-job.yaml - lookup-gm-security-migration-job.yaml # Vendored module migrations (cmangos-classic@main src/modules/*). # Comment-out individual lines for a staged rollout — all 5 modules also # gated by their .conf Enable= key in helmrelease.yaml. - transmog-migration-job.yaml - barber-migration-job.yaml - dualspec-migration-job.yaml - trainingdummies-migration-job.yaml - achievements-migration-job.yaml ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/lookup-gm-security-migration-job.yaml ================================================ --- apiVersion: v1 kind: ConfigMap metadata: name: cmangos-lookup-gm-security-migration-sql namespace: game-servers data: # Stock CMaNGOS ships the read-only .lookup subcommands (item, creature, # quest, spell, object, itemset, faction, skill, taxinode) at security # level 3 (Administrator). That blocks GMs (level 2) from basic lookups # like ".lookup item Hearthstone" — needed to ID NPCs/items/spells when # answering player tickets. The commands are read-only (return IDs, no # world mutation), so granting them to GMs is safe. # # `.reload command` in the mangosd console picks the change up without # a worldserver restart. lookup-gm-security.sql: | UPDATE `command` SET `security` = 2 WHERE `name` IN ( 'lookup creature', 'lookup faction', 'lookup item', 'lookup itemset', 'lookup object', 'lookup quest', 'lookup skill', 'lookup spell', 'lookup taxinode' ); --- apiVersion: batch/v1 kind: Job metadata: name: cmangos-lookup-gm-security-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e echo "=== Lowering .lookup subcommands to GM (security=2) in classicmangos ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos < /sql/lookup-gm-security.sql # PTR shares the schema; apply there too so a fresh PTR rebuild # lands on the same policy. if mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" -e "USE ptrmangos" 2>/dev/null; then echo "=== Lowering .lookup subcommands in ptrmangos ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" ptrmangos < /sql/lookup-gm-security.sql fi echo "=== Verifying ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos \ -e "SELECT name, security FROM command WHERE name LIKE 'lookup%' ORDER BY name;" echo "=== Done. Run '.reload command' in the mangosd console (no restart needed) ===" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: cmangos-lookup-gm-security-migration-sql ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/mangos-string-517-migration-job.yaml ================================================ --- apiVersion: v1 kind: ConfigMap metadata: name: cmangos-mangos-string-517-migration-sql namespace: game-servers data: # mangos_string row 517 (LANG_GO_MIXED_LIST_CHAT) drifted away from # what the C++ call site at Level2.cpp expects. The drifted format # had an extra "%d" in the Hgameobject:%d:%d link and put SpawnGroup # outside the |h|r link tags, giving 11 placeholders against 10 # args. vsnprintf then walked past the supplied varargs and ran # strlen on uninitialised stack bits — repeatable SIGSEGV on any # .gobject near / delete / target from a GM near gameobjects. # # Three cores on 2026-05-18 (12:56, 12:58, 13:02) all had identical # stacks: __strlen_avx2 → vfprintf → PSendSysMessage. Root-cause # write-up: see patches/0003-go-mixed-list-hardcoded-format.patch. # # Canonical format matches upstream sql/base/mangos.sql:3865. Patch # 0003 also hardcodes the format at both call sites so this row no # longer matters to the worldserver — keep this migration anyway so # any future DB rebuild starts from a sane row. mangos-string-517.sql: | UPDATE `mangos_string` SET `content_default` = '%d%s, Entry %d - |cffffffff|Hgameobject:%d|h[%s X:%f Y:%f Z:%f MapId:%d]SpawnGroup:%u|h|r' WHERE `entry` = 517; --- apiVersion: batch/v1 kind: Job metadata: name: cmangos-mangos-string-517-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e echo "=== Repairing classicmangos.mangos_string row 517 ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos < /sql/mangos-string-517.sql # PTR shares the schema; if it exists, apply there too so a # fresh PTR rebuild also lands on a sane row. if mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" -e "USE ptrmangos" 2>/dev/null; then echo "=== Repairing ptrmangos.mangos_string row 517 ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" ptrmangos < /sql/mangos-string-517.sql fi echo "=== Verifying ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos \ -e "SELECT entry, content_default FROM mangos_string WHERE entry = 517 \G" echo "=== Done. Worldserver must be restarted to reload mangos_string ===" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: cmangos-mangos-string-517-migration-sql ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/prometheusrule.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/prometheusrule_v1.json apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: name: game-servers-rules namespace: game-servers spec: groups: # ─── Availability ─────────────────────────────────────────────────────── - name: game-servers.availability interval: 1m rules: - alert: GameServerDown expr: | kube_deployment_status_replicas_available{ namespace="game-servers", deployment=~"cmangos-mangosd|cmangos-realmd|cmangos-database|azerothcore-worldserver|azerothcore-authserver|azerothcore-database|emberstone-portal" } == 0 for: 2m labels: severity: critical team: game-servers annotations: summary: "{{ $labels.deployment }} is down (no ready replicas)" description: | Deployment `{{ $labels.deployment }}` in namespace `{{ $labels.namespace }}` has had zero ready replicas for at least 2 minutes. Players cannot connect. - alert: GameServerDegraded expr: | ( kube_deployment_status_replicas{ namespace="game-servers", deployment=~"cmangos-.*|azerothcore-.*|emberstone-portal" } - kube_deployment_status_replicas_available{ namespace="game-servers", deployment=~"cmangos-.*|azerothcore-.*|emberstone-portal" } ) > 0 for: 10m labels: severity: warning team: game-servers annotations: summary: "{{ $labels.deployment }} degraded ({{ $value }} replicas missing)" description: | Deployment `{{ $labels.deployment }}` has had fewer ready replicas than desired for 10+ minutes. Service may still be reachable but is in a degraded state. # ─── Crash-loop detection ─────────────────────────────────────────────── # Multiple thresholds to catch both fast loops (every 30s) and slow # loops (every few minutes). The slow-loop case is what slipped through # on 2026-05-02 when mangosd was segfaulting every ~6 min on a single # corrupt player record — too sparse for [15m]>5 to fire, too transient # for KubePodCrashLooping to settle. - name: game-servers.crashloop interval: 1m rules: - alert: GameServerCrashLooping expr: | increase(kube_pod_container_status_restarts_total{ namespace="game-servers" }[15m]) >= 3 for: 5m labels: severity: critical team: game-servers annotations: summary: "{{ $labels.pod }} restarted {{ $value }} times in the last 15 min" description: | Pod `{{ $labels.pod }}` in namespace `{{ $labels.namespace }}` is crash-looping ({{ $value }} restarts in 15 minutes). Likely application bug or unhealthy dependency; check `kubectl logs --previous` and `kubectl describe pod`. - alert: GameServerRecentRestarts # Slow but persistent restart pattern — catches anything restarting # >= 3 times per hour, which a 6-min crash cycle hits easily. expr: | increase(kube_pod_container_status_restarts_total{ namespace="game-servers" }[1h]) >= 3 for: 10m labels: severity: warning team: game-servers annotations: summary: "{{ $labels.pod }} has restarted {{ $value }} times in the last hour" description: | Pod `{{ $labels.pod }}` is restarting at a rate of >= 3/hour. Could be a slow crash loop (e.g., one specific event triggers a segfault that takes minutes to recur). Examine `kubectl logs --previous` for the exit cause. - alert: GameServerSegfault # Container exited via signal (exit code 137=SIGKILL, 139=SIGSEGV). # 139 specifically means the process crashed at the binary level. expr: | kube_pod_container_status_last_terminated_exitcode{ namespace="game-servers" } == 139 for: 1m labels: severity: critical team: game-servers annotations: summary: "{{ $labels.pod }} segfaulted (exit code 139)" description: | Pod `{{ $labels.pod }}` in `{{ $labels.namespace }}` exited via SIGSEGV. Likely indicates a binary-level bug or corrupt input data. Check `kubectl logs --previous` for the stack trace and any preceding errors. # ─── Storage health (the class of bug that took us down today) ────────── - name: game-servers.storage interval: 1m rules: - alert: GameServerVolumeReadOnly expr: | node_filesystem_readonly{ mountpoint=~"/var/lib/kubelet/pods/.*", fstype!~"tmpfs|overlay|nsfs" } == 1 for: 1m labels: severity: critical team: game-servers annotations: summary: "A pod volume on {{ $labels.instance }} is mounted read-only" description: | Filesystem `{{ $labels.mountpoint }}` on `{{ $labels.instance }}` is read-only. Usually triggered by `errors=remount-ro` after underlying I/O errors (Ceph RBD session loss, disk failure). Pods using this volume will be unable to write — **force-recreate the pod** to remap the volume after underlying storage recovers. - alert: GameServerPVCNearFull expr: | ( kubelet_volume_stats_available_bytes{namespace="game-servers"} / kubelet_volume_stats_capacity_bytes{namespace="game-servers"} ) < 0.10 for: 15m labels: severity: warning team: game-servers annotations: summary: "PVC {{ $labels.persistentvolumeclaim }} is {{ $value | humanizePercentage }} free" description: | Game-server PVC is below 10% free space. Expand the PVC or clean up data before writes start failing. ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/pvc-cores.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: cmangos-cores namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 40Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/pvc-data.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: cmangos-data namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/pvc-database.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: cmangos-database namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/pvc-logs.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: cmangos-mangosd-logs namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/realm-address-migration-job.yaml ================================================ --- apiVersion: v1 kind: ConfigMap metadata: name: cmangos-realm-address-migration-sql namespace: game-servers data: realmd.sql: | UPDATE realmlist SET address = '${EXTERNAL_IP}' WHERE id = 1; SELECT id, name, address, port FROM realmlist WHERE id = 1; --- apiVersion: batch/v1 kind: Job metadata: name: cmangos-realm-address-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e echo "=== Updating realm address to external gateway IP ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicrealmd < /sql/realmd.sql echo "=== Realm address migration complete ===" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: cmangos-realm-address-migration-sql ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/realm-pvp-migration-job.yaml ================================================ --- apiVersion: v1 kind: ConfigMap metadata: name: cmangos-realm-pvp-migration-sql namespace: game-servers data: realm-pvp.sql: | -- Flip the realm to PvP type. -- realmlist.icon: 0=Normal, 1=PvP, 4=Normal, 6=RP, 8=RPPvP. Must match -- mangosd.conf GameType for the lobby badge + in-game enforcement to -- agree. Single-realm setup — no WHERE filter. Idempotent. -- -- Canonical copy: etc/emberstone/sql/realmd/realm-pvp.sql in -- xunholy/cmangos-classic. UPDATE `realmlist` SET `icon` = 1; pvp-state-reset.sql: | -- Clean stale per-character PvP / BG state at the realm-type flip. -- character_battleground_data tracks active BG slot + queue. After a -- realm-type change, lingering rows can reference BGs that no longer -- exist — same crash class as the 0002-WorldportAck patch. Honor / -- kill totals are NOT touched; those are durable progression stats. -- playerFlags PvP bits are derived per-tick by mangosd, no migration -- needed there. -- -- Canonical copy: etc/emberstone/sql/characters/pvp-state-reset.sql in -- xunholy/cmangos-classic. TRUNCATE TABLE `character_battleground_data`; --- apiVersion: batch/v1 kind: Job metadata: name: cmangos-realm-pvp-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e echo "=== Setting realmlist.icon=1 on classicrealmd ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicrealmd < /sql/realm-pvp.sql echo "=== Wiping stale BG state on classiccharacters ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters < /sql/pvp-state-reset.sql echo "=== Verifying realm icon ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicrealmd -e "SELECT id, name, icon FROM realmlist;" echo "=== Verifying BG state cleared ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters -e "SELECT COUNT(*) AS remaining_bg_rows FROM character_battleground_data;" echo "=== Done. Restart mangosd+realmd to pick up the new realm type ===" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: cmangos-realm-pvp-migration-sql ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: cmangos-database spec: sourcePVC: cmangos-database trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: cmangos-database-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/tcproutes.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/tcproute_v1alpha2.json apiVersion: gateway.networking.k8s.io/v1alpha2 kind: TCPRoute metadata: name: cmangos-auth spec: parentRefs: - name: envoy-external namespace: network-system sectionName: cmangos-auth rules: - backendRefs: - name: cmangos-auth port: 3724 --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/tcproute_v1alpha2.json apiVersion: gateway.networking.k8s.io/v1alpha2 kind: TCPRoute metadata: name: cmangos-world spec: parentRefs: - name: envoy-external namespace: network-system sectionName: cmangos-world rules: - backendRefs: - name: cmangos-world port: 8085 ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/trainingdummies-migration-job.yaml ================================================ --- # Trainingdummies module — spawns 3 dummy NPCs (Grandmaster/Advanced/Beginner) # at multiple training locations across Eastern Kingdoms + Kalimdor. World-only # (no characters-DB schema). Idempotent (DELETE-then-INSERT). apiVersion: v1 kind: ConfigMap metadata: name: cmangos-trainingdummies-migration-sql namespace: game-servers data: world.sql: | -- 3 dummy NPC templates. Faction 7 = Stormwind (player-attackable for melee -- training), CreatureTypeFlags 64 = "interactable target dummy" hint. DELETE FROM `creature_template` WHERE `entry` IN (190021, 190022, 190023); INSERT INTO `creature_template` (Entry, Name, SubName, MinLevel, MaxLevel, DisplayId1, DisplayIdProbability1, Faction, Scale, Family, CreatureType, InhabitType, RegenerateStats, RacialLeader, NpcFlags, UnitFlags, DynamicFlags, ExtraFlags, CreatureTypeFlags, SpeedWalk, SpeedRun, Detection, CallForHelp, Pursuit, Leash, Timeout, UnitClass, `Rank`, HealthMultiplier, PowerMultiplier, DamageMultiplier, DamageVariance, ArmorMultiplier, ExperienceMultiplier, MinLevelHealth, MaxLevelHealth, MinLevelMana, MaxLevelMana, MinMeleeDmg, MaxMeleeDmg, MinRangedDmg, MaxRangedDmg, Armor, MeleeAttackPower, RangedAttackPower, MeleeBaseAttackTime, RangedBaseAttackTime, DamageSchool, MinLootGold, MaxLootGold, LootId, PickpocketLootId, SkinningLootId, KillCredit1, KillCredit2, MechanicImmuneMask, SchoolImmuneMask, ResistanceHoly, ResistanceFire, ResistanceNature, ResistanceFrost, ResistanceShadow, ResistanceArcane, PetSpellDataId, MovementType, TrainerType, TrainerSpell, TrainerClass, TrainerRace, TrainerTemplateId, VendorTemplateId, EquipmentTemplateId, GossipMenuId, AIName, ScriptName) VALUES (190021, 'Grandmaster''s Training Dummy', '', 63, 63, 16074, 100, 7, 2.2, 0, 9, 3, 0, 0, 0, 32768, 0, 64, 4, 1, 1.14286, 20, 0, 0, 0, 0, 1, 3, 1000, 1, 1, 1, 1, 1, 7888000, 7888000, 0, 0, 0, 0, 0, 0, 4700, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8585235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', ''), (190022, 'Advanced Training Dummy', '', 61, 61, 3019, 100, 7, 1.8, 0, 9, 3, 3, 0, 0, 0, 0, 64, 0, 1, 1.14286, 20, 0, 0, 0, 0, 1, 1, 200, 1, 1, 1, 1, 1, 1397200, 1397200, 0, 0, 2, 2, 0, 0, 3700, 0, 0, 2000, 2000, 0, 0, 0, 0, 0, 0, 0, 0, 8585235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', ''), (190023, 'Beginner Training Dummy', '', 60, 60, 3019, 100, 7, 1.2, 0, 9, 3, 3, 0, 0, 0, 0, 64, 0, 1, 1.14286, 20, 0, 0, 0, 0, 1, 0, 200, 1, 1, 1, 1, 1, 1397200, 1397200, 0, 0, 2, 2, 0, 0, 3000, 0, 0, 2000, 2000, 0, 0, 0, 0, 0, 0, 0, 0, 8585235, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', ''); -- Spanish localisations DELETE FROM `locales_creature` WHERE `entry` IN (190021, 190022, 190023); INSERT INTO `locales_creature` (`entry`, `name_loc6`, `subname_loc6`) VALUES (190021, 'Muñeco de entrenamiento mayor', ''), (190022, 'Muñeco de entrenamiento avanzado', ''), (190023, 'Muñeco de entrenamiento basico', ''); -- Spawns: 6 locations × 3 dummies = 18 rows. Locations are the major -- city / class-trainer areas in Classic. Some coords (10000+, 2258+) -- are TBC-only and inert on Classic but kept for upstream fidelity. DELETE FROM `creature` WHERE `id` IN (190021, 190022, 190023); INSERT INTO `creature` (`id`, `map`, `spawnMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecsmin`, `spawntimesecsmax`, `spawndist`, `MovementType`) VALUES -- Grandmaster (190021) (190021, 1, 1, -1416.73, -76.4812, 158.526, 1.04029, 25, 25, 0, 0), (190021, 0, 1, 1768.18, 352.747, -62.2883, 4.4141, 25, 25, 0, 0), (190021, 1, 1, 2151.77, -4632.69, 50.4428, 3.59001, 25, 25, 0, 0), (190021, 1, 1, 10000.5, 2258.5, 1329.8, 3.99055, 25, 25, 0, 0), (190021, 0, 1, -4910.96, -1151.19, 501.449, 3.09082, 25, 25, 0, 0), (190021, 0, 1, -8795.57, 363.195, 101.021, 5.41645, 25, 25, 0, 0), -- Advanced (190022) (190022, 1, 1, -1422.05, -72.171, 157.476, 0.693121, 25, 25, 0, 0), (190022, 0, 1, 1780.49, 333.857, -62.2898, 2.37992, 25, 25, 0, 0), (190022, 1, 1, 2152.63, -4639.71, 50.3799, 3.22873, 25, 25, 0, 0), (190022, 1, 1, 10006.2, 2252.62, 1329.75, 3.99449, 25, 25, 0, 0), (190022, 0, 1, -4936.94, -1138.88, 501.46, 6.12402, 25, 25, 0, 0), (190022, 0, 1, -8789.85, 367.182, 101.021, 5.33006, 25, 25, 0, 0), -- Beginner (190023) (190023, 1, 1, -1410.51, -78.656, 158.935, 1.37014, 25, 25, 0, 0), (190023, 0, 1, 1783.91, 341.82, -62.3358, 2.8865, 25, 25, 0, 0), (190023, 1, 1, 2148.06, -4627.23, 50.9305, 3.88454, 25, 25, 0, 0), (190023, 1, 1, 9993.03, 2260.47, 1330.81, 4.48136, 25, 25, 0, 0), (190023, 0, 1, -4938.02, -1148.3, 501.497, 6.14209, 25, 25, 0, 0), (190023, 0, 1, -8800.62, 358.618, 101.021, 5.44787, 25, 25, 0, 0); --- apiVersion: batch/v1 kind: Job metadata: name: cmangos-trainingdummies-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e echo "=== Applying Trainingdummies NPCs + locales + spawns to classicmangos ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos < /sql/world.sql echo "=== Verifying NPC templates (expect 3 rows: 190021/22/23) ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT entry, name FROM creature_template WHERE entry IN (190021, 190022, 190023);" echo "=== Verifying spawns (expect 18 rows: 6 locations × 3 dummies) ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT id, COUNT(*) AS spawn_count FROM creature WHERE id IN (190021, 190022, 190023) GROUP BY id;" echo "=== Trainingdummies migration complete ===" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: cmangos-trainingdummies-migration-sql ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/transmog-migration-job.yaml ================================================ --- # Transmog module — applies schema for the appearance system and spawns the # Magister Stellaria NPC (entry 190010). Idempotent (CREATE TABLE IF NOT # EXISTS, DELETE-then-INSERT) so Flux can recreate the Job after ttl expires # without damage. Pattern matches attunement-migration-job.yaml. apiVersion: v1 kind: ConfigMap metadata: name: cmangos-transmog-migration-sql namespace: game-servers data: characters.sql: | CREATE TABLE IF NOT EXISTS `custom_transmog_active` ( `item_guid` int(11) unsigned NOT NULL, `transmog_entry` int(11) unsigned NOT NULL, `player` int(11) unsigned NOT NULL, PRIMARY KEY (`item_guid`), KEY `player` (`player`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `custom_transmog_discovered` ( `player` int(11) unsigned NOT NULL, `item_entry` int(11) unsigned NOT NULL, PRIMARY KEY (`player`, `item_entry`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; world.sql: | -- Transmog NPC: Magister Stellaria (entry 190010) -- Spawn coords avoid overlap with attunement's Attuner of Paths (190014) -- and dualspec's NPC (190024). See cmangos-classic 39b23109f. SET @Entry := 190010; DELETE FROM `creature_template` WHERE `entry` = @Entry; INSERT INTO `creature_template` (`entry`, `DisplayId1`, `DisplayIdProbability1`, `name`, `subname`, `GossipMenuId`, `minlevel`, `maxlevel`, `faction`, `NpcFlags`, `scale`, `rank`, `DamageSchool`, `MeleeBaseAttackTime`, `RangedBaseAttackTime`, `unitClass`, `unitFlags`, `CreatureType`, `CreatureTypeFlags`, `lootid`, `PickpocketLootId`, `SkinningLootId`, `AIName`, `MovementType`, `RacialLeader`, `RegenerateStats`, `MechanicImmuneMask`, `ExtraFlags`) VALUES (@Entry, 2240, 100, 'Magister Stellaria', 'Transmogrifier', 0, 60, 60, 35, 1, 1, 0, 0, 2000, 0, 1, 0, 7, 138936390, 0, 0, 0, '', 0, 0, 1, 0, 0); DELETE FROM `creature` WHERE `id` = @Entry; INSERT INTO `creature` (`id`, `map`, `spawnMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecsmin`, `spawntimesecsmax`, `spawndist`, `MovementType`) VALUES (@Entry, 0, 1, -8930.96, 770.06, 100.21, 4.70, 25, 25, 0, 0), -- Stormwind Trade District tailor area (@Entry, 1, 1, 1623.00, -4419.00, 22.00, 4.00, 25, 25, 0, 0); -- Orgrimmar Drag's tailor district --- apiVersion: batch/v1 kind: Job metadata: name: cmangos-transmog-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e echo "=== Applying Transmog schema to classiccharacters ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters < /sql/characters.sql echo "=== Applying Transmog NPC + spawns to classicmangos ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos < /sql/world.sql echo "=== Verifying characters tables ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters -e "SHOW TABLES LIKE 'custom_transmog%';" echo "=== Verifying NPC template ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT entry, name, subname FROM creature_template WHERE entry = 190010;" echo "=== Verifying spawns (expect 2 rows: Stormwind + Orgrimmar) ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT id, map, position_x, position_y FROM creature WHERE id = 190010;" echo "=== Transmog migration complete ===" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: cmangos-transmog-migration-sql ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/twink-vendor-migration-job.yaml ================================================ --- apiVersion: v1 kind: ConfigMap metadata: name: cmangos-twink-vendor-migration-sql namespace: game-servers data: characters.sql: | CREATE TABLE IF NOT EXISTS `custom_twinkmaster_player_config` ( `guid` int(11) unsigned NOT NULL COMMENT 'Character GUID', `xp_locked` boolean DEFAULT FALSE COMMENT 'Whether XP gain is blocked', `level_set` boolean DEFAULT FALSE COMMENT 'Whether level was set by Twink Master', `created_at` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`guid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Twink Master player configuration'; world.sql: | -- ============================================================ -- Twink Master NPC - Level 19 Multi-Vendor -- Alliance: 190012 | Horde: 190013 -- Categories: 1=BiS Gear, 2=Consumables, 3=Honor Gear, 4=Insane -- ============================================================ SET @AllianceEntry := 190012; SET @HordeEntry := 190013; -- NPC Templates: Alliance (Stormwind faction) + Horde (Orgrimmar faction) DELETE FROM `creature_template` WHERE `entry` IN (@AllianceEntry, @HordeEntry); INSERT INTO `creature_template` (`entry`, `DisplayId1`, `DisplayIdProbability1`, `name`, `subname`, `GossipMenuId`, `minlevel`, `maxlevel`, `faction`, `NpcFlags`, `scale`, `rank`, `DamageSchool`, `MeleeBaseAttackTime`, `RangedBaseAttackTime`, `unitClass`, `unitFlags`, `CreatureType`, `CreatureTypeFlags`, `ScriptName`, `lootid`, `PickpocketLootId`, `SkinningLootId`, `AIName`, `MovementType`, `RacialLeader`, `RegenerateStats`, `MechanicImmuneMask`, `ExtraFlags`) VALUES (@AllianceEntry, 3455, 100, 'Twink Master', 'Level 19 Specialist', 0, 19, 19, 12, 5, 1, 0, 0, 2000, 0, 1, 0, 7, 138936390, 'npc_twinkmaster', 0, 0, 0, '', 0, 0, 1, 0, 0), (@HordeEntry, 1374, 100, 'Twink Master', 'Level 19 Specialist', 0, 19, 19, 85, 5, 1, 0, 0, 2000, 0, 1, 0, 7, 138936390, 'npc_twinkmaster', 0, 0, 0, '', 0, 0, 1, 0, 0); -- Spawns: Stormwind Trade District (Alliance) + Orgrimmar WSG area (Horde) DELETE FROM `creature` WHERE `id` IN (@AllianceEntry, @HordeEntry); INSERT INTO `creature` (`id`, `map`, `spawnMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecsmin`, `spawntimesecsmax`, `spawndist`, `MovementType`) VALUES (@AllianceEntry, 0, 1, -8830.0, 665.0, 97.9, 0.65, 25, 25, 0, 0), (@HordeEntry, 1, 1, 1986.0, -4785.0, 55.82, 4.26, 25, 25, 0, 0); -- NPC Text SET @TEXT_ID := 50920; DELETE FROM `npc_text` WHERE `ID` BETWEEN @TEXT_ID AND @TEXT_ID+2; INSERT INTO `npc_text` (`ID`, `text0_0`) VALUES (@TEXT_ID, 'Welcome, $N! Looking to gear up for the battleground? I have everything a level 19 champion needs. Browse my wares - everything is on the house!'), (@TEXT_ID+1, 'Ready to lock in at level 19? I can set your level and lock your experience so you stay in peak form for Warsong Gulch.'), (@TEXT_ID+2, 'Only the finest equipment for aspiring twinks. May your battles be glorious, $N!'); -- ============================================================ -- Vendor Category Table (read by C++ module) -- Discrete values: 1=BiS Gear, 2=Consumables, 3=Honor Gear, 4=Insane -- ============================================================ DROP TABLE IF EXISTS `custom_twinkmaster_vendor_categories`; CREATE TABLE `custom_twinkmaster_vendor_categories` ( `item` int(11) unsigned NOT NULL, `categories` tinyint(3) unsigned NOT NULL DEFAULT 1, PRIMARY KEY (`item`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Twink Master vendor item categories'; INSERT INTO `custom_twinkmaster_vendor_categories` (`item`, `categories`) VALUES -- ============================================= -- BiS Gear (cat=1) - Equipment only -- ============================================= -- Weapons (melee) (1482, 1), -- Shadowfang (5191, 1), -- Cruel Barb (1935, 1), -- Assassin's Blade (6448, 1), -- Tail Spike (1483, 1), -- Face Smasher (6472, 1), -- Stinging Viper (6504, 1), -- Wingblade (7230, 1), -- Smite's Mighty Hammer (5815, 1), -- Glacial Stone (890, 1), -- Twisted Chanter's Staff (6505, 1), -- Crescent Staff (1484, 1), -- Witching Stave (5201, 1), -- Emberstone Staff (2271, 1), -- Staff of the Blessed Seer (1318, 1), -- Night Reaver (2H Axe, shadow proc) (2256, 1), -- Skeletal Club (1H Mace, shadow proc) (5196, 1), -- Smite's Reaver (1H axe) (2567, 1), -- Evocator's Blade (caster dagger) (935, 1), -- Night Watch Shortsword (caster sword) (790, 1), -- Forester's Axe (1H axe, Paladin) -- Weapons (ranged/wand) (6469, 1), -- Venomstrike (13136, 1), -- Lil Timmy's Peashooter (7001, 1), -- Gravestone Scepter -- Head (19972, 1), -- Lucky Fishing Hat (4385, 1), -- Green Tinted Goggles -- Shoulders (5404, 1), -- Serpent's Shoulders (10657, 1), -- Talbar Mantle (6579, 1), -- Defender Spaulders (random enchant) -- Back (2059, 1), -- Sentry Cloak (6449, 1), -- Glowing Lizardscale Cloak (6667, 1), -- Engineer's Cloak -- Chest (10399, 1), -- Blackened Defias Armor (2041, 1), -- Tunic of Westfall (1486, 1), -- Tree Bark Jacket (6473, 1), -- Armor of the Fang -- Wrist (1974, 1), -- Mindthrust Bracers (4534, 1), -- Steel-clasped Bracers (15331, 1), -- Wrangler's Wristbands (random enchant) (7003, 1), -- Beetle Clasps (mail) (3202, 1), -- Forest Leather Bracers (14160, 1), -- Pagan Bands (cloth, random enchant) -- Hands (6467, 1), -- Deviate Scale Gloves (10413, 1), -- Gloves of the Fang (12977, 1), -- Magefist Gloves (892, 1), -- Gnoll Casting Gloves (6586, 1), -- Scouting Gloves (random enchant) (12994, 1), -- Thorbia's Gauntlets (mail) (6577, 1), -- Defender Gauntlets (mail, random enchant) -- Waist (6468, 1), -- Deviate Scale Belt (10412, 1), -- Belt of the Fang (6460, 1), -- Cobrahn's Grasp (9814, 1), -- Fortified Belt (mail, random enchant) (2911, 1), -- Keller's Girdle (cloth) (16987, 1), -- Screecher Belt (leather) -- Legs (6087, 1), -- Chausses of Westfall (10410, 1), -- Leggings of the Fang (12987, 1), -- Darkweave Breeches (15511, 1), -- Grunt's Legguards (mail, random enchant) (6587, 1), -- Scouting Trousers (leather, random enchant) (4800, 1), -- Mighty Chain Pants (mail) (10043, 1), -- Pious Legwraps (cloth, Alliance quest) -- Feet (1121, 1), -- Feet of the Lynx (19969, 1), -- Nat Pagle's Extreme Anglin' Boots (12982, 1), -- Silver-linked Footguards (10411, 1), -- Footpads of the Fang -- Rings (2933, 1), -- Seal of Wrynn (6414, 1), -- Seal of Sylvanas (4998, 1), -- Blood Ring (12054, 1), -- Demon Band (1156, 1), -- Lavishly Jeweled Ring (12996, 1), -- Band of Purification (12006, 1), -- Meadow Ring (random enchant) -- Trinkets (19024, 1), -- Arena Grand Master (4381, 1), -- Minor Recombobulator -- Shields (5443, 1), -- Gold-plated Buckler (12997, 1), -- Redbeard Crest (7002, 1), -- Arctic Buckler (3761, 1), -- Deadskull Shield -- Off-hand (2879, 1), -- Antipodean Rod (5183, 1), -- Pulsating Hydra Heart (16768, 1), -- Furbolg Medicine Pouch -- ============================================= -- Consumables (cat=2) -- ============================================= -- Potions / Elixirs (2459, 2), -- Swiftness Potion (3388, 2), -- Strong Troll's Blood Potion (2454, 2), -- Elixir of Lion's Strength (2455, 2), -- Minor Mana Potion (929, 2), -- Healing Potion (3390, 2), -- Elixir of Lesser Agility (3389, 2), -- Elixir of Defense (6373, 2), -- Elixir of Firepower (3384, 2), -- Minor Magic Resistance Potion (6372, 2), -- Swim Speed Potion (WSG essential) (5631, 2), -- Rage Potion (+20-40 Rage, Warriors only) (6051, 2), -- Holy Protection Potion (absorb holy) (2458, 2), -- Elixir of Minor Fortitude (+27 HP, Guardian) (3383, 2), -- Elixir of Wisdom (+6 Int, Battle) -- Scrolls (1478, 2), -- Scroll of Protection II (3012, 2), -- Scroll of Agility (+5 Agi) (1180, 2), -- Scroll of Stamina (+5 Stam) (954, 2), -- Scroll of Strength (+5 Str) (2290, 2), -- Scroll of Intellect II -- Head/Leg Enchants (Lesser Arcanums - BRD) (11642, 2), -- Lesser Arcanum of Constitution (+100 HP) (11622, 2), -- Lesser Arcanum of Rumination (+150 Mana) (11643, 2), -- Lesser Arcanum of Tenacity (+125 Armor) (11644, 2), -- Lesser Arcanum of Resilience (+20 Fire Resist) (11645, 2), -- Lesser Arcanum of Voracity (+8 Str) (11646, 2), -- Lesser Arcanum of Voracity (+8 Agi) (11647, 2), -- Lesser Arcanum of Voracity (+8 Stam) (11648, 2), -- Lesser Arcanum of Voracity (+8 Int) (11649, 2), -- Lesser Arcanum of Voracity (+8 Spi) -- Head/Leg Enchants (Arcanums - Dire Maul) (18329, 2), -- Arcanum of Rapidity (+1% Haste) (18330, 2), -- Arcanum of Focus (+8 Spell Power) (18331, 2), -- Arcanum of Protection (+1% Dodge) -- Drinks (stamina buffs) (21151, 2), -- Rumsey Rum Black Label (+15 Stam) (18269, 2), -- Gordok Green Grog (+10 Stam) -- Transformation / Fun (6657, 2), -- Savory Deviate Delight (pirate/ninja) (6662, 2), -- Elixir of Giant Growth (size increase) (6522, 2), -- Deviate Fish (random effects) -- Engineering gadgets (4388, 2), -- Discombobulator Ray (transform + slow) (4380, 2), -- Big Bronze Bomb (AoE stun) (4378, 2), -- Heavy Dynamite (AoE damage) (4384, 2), -- Explosive Sheep (mobile AoE) (4376, 2), -- Flame Deflector (absorb fire) (4366, 2), -- Target Dummy (attracts mobs, no Eng req) (6714, 2), -- EZ-Thro Dynamite (AoE, no Eng req) -- PvP utility (2091, 2), -- Magic Dust (sleep target) (4984, 2), -- Skull of Impending Doom (speed boost) (13180, 2), -- Stratholme Holy Water (AoE vs undead) (7676, 2), -- Thistle Tea (instant 100 energy) -- Food buffs (3665, 2), -- Curiously Tasty Omelet (6890, 2), -- Smoked Bear Meat -- Weapon buffs (4406, 2), -- Standard Scope (+2 damage) (10548, 2), -- Sniper Scope (+7 damage) (2871, 2), -- Heavy Sharpening Stone (+4 weapon damage) (2863, 2), -- Coarse Sharpening Stone (+3 weapon damage) (20744, 2), -- Minor Wizard Oil (+8 Spell Damage) (1322, 2), -- Fishliver Oil (+8 melee AP) -- Ammo (3464, 2), -- Feathered Arrow (3465, 2), -- Exploding Shot -- Bandages (6451, 2), -- Heavy Silk Bandage (First Aid 125) (8544, 2), -- Mageweave Bandage (First Aid 150) -- Utility (6048, 2), -- Shadow Protection Potion (level 17) (3241, 2), -- Heavy Weightstone (+4 blunt weapon dmg) (1712, 2), -- Scroll of Spirit II -- ============================================= -- Honor Gear (cat=3) - PvP / WSG reputation items -- ============================================= -- PvP accessories (rings, trinkets, medallions) (20444, 3), -- Sentinel's Medallion (20442, 3), -- Scout's Medallion (20439, 3), -- Protector's Band (20429, 3), -- Legionnaire's Band (20431, 3), -- Lorekeeper's Ring (20426, 3), -- Advisor's Ring (18854, 3), -- Insignia of the Alliance (18834, 3), -- Insignia of the Horde -- Class-specific insignias (Alliance) (18856, 3), -- Insignia of the Alliance (Hunter) (18857, 3), -- Insignia of the Alliance (Rogue) (18858, 3), -- Insignia of the Alliance (Warlock) (18859, 3), -- Insignia of the Alliance (Mage) (18862, 3), -- Insignia of the Alliance (Priest) (18863, 3), -- Insignia of the Alliance (Druid) (18864, 3), -- Insignia of the Alliance (Paladin) -- Class-specific insignias (Horde) (18845, 3), -- Insignia of the Horde (Shaman) (18846, 3), -- Insignia of the Horde (Hunter) (18849, 3), -- Insignia of the Horde (Rogue) (18850, 3), -- Insignia of the Horde (Mage) (18851, 3), -- Insignia of the Horde (Priest) (18852, 3), -- Insignia of the Horde (Warlock) (18853, 3), -- Insignia of the Horde (Druid) -- Battle Standards (18606, 3), -- Alliance Battle Standard (18607, 3), -- Horde Battle Standard -- Tabards (15196, 3), -- Private's Tabard (Alliance) (15197, 3), -- Scout's Tabard (Horde) (19506, 3), -- Silverwing Battle Tabard (Alliance WSG) (19505, 3), -- Warsong Battle Tabard (Horde WSG) -- WSG reputation weapons and cloaks (20425, 3), -- Advisor's Gnarled Staff (20427, 3), -- Battle Healer's Cloak (20428, 3), -- Caretaker's Cape (20430, 3), -- Legionnaire's Sword (20434, 3), -- Lorekeeper's Staff (20437, 3), -- Outrider's Bow (20438, 3), -- Outrunner's Bow (20440, 3), -- Protector's Sword (20441, 3), -- Scout's Blade (20443, 3), -- Sentinel's Blade -- ============================================= -- Insane (cat=4) - Raid/endgame items with no level req -- ============================================= -- Trinkets (23206, 4), -- Mark of the Champion (melee) (23207, 4), -- Mark of the Champion (caster) (18406, 4), -- Onyxia Blood Talisman (19948, 4), -- Zandalarian Hero Badge (19949, 4), -- Zandalarian Hero Medallion (19950, 4), -- Zandalarian Hero Charm (21180, 4), -- Earthstrike (21326, 4), -- Defender of the Timbermaw (22678, 4), -- Talisman of Ascendance (17904, 4), -- Stormpike Insignia Rank 6 (17909, 4), -- Frostwolf Insignia Rank 6 -- Rings (18403, 4), -- Dragonslayer's Signet (22707, 4), -- Ramaladni's Icy Grasp (21189, 4), -- Might of Cenarius (21190, 4), -- Wrath of Cenarius -- Necklaces (18404, 4), -- Onyxia Tooth Pendant (22657, 4), -- Amulet of the Dawn (22659, 4), -- Medallion of the Dawn (19577, 4), -- Rage of Mugamba (19588, 4), -- Hero's Brand (19594, 4), -- The All-Seeing Eye of Zuldazar (19601, 4), -- Jewel of Kajaro (19605, 4), -- Kezan's Unstoppable Taint (19609, 4), -- Unmarred Vision of Voodress (19613, 4), -- Pristine Enchanted South Seas Kelp (19617, 4), -- Zandalarian Shadow Mastery Talisman (19621, 4), -- Maelstrom's Wrath -- Cloth armor (no level req, raid) (22968, 4), -- Glacial Mantle (22700, 4), -- Glacial Leggings (12752, 4), -- Cap of the Scarlet Savant -- Off-hand (21185, 4), -- Earthcalm Orb -- Weapon (22656, 4), -- The Purifier -- Shoulder Enchants (ZG, no level req) (20077, 4), -- Zandalar Signet of Might (+30 AP) (20076, 4), -- Zandalar Signet of Mojo (+18 SP) (20078, 4), -- Zandalar Signet of Serenity (+33 Healing) -- Shoulder Enchants (Naxx, level req removed below) (23545, 4), -- Power of the Scourge (+15 SP, +1% Spell Crit) (23547, 4), -- Resilience of the Scourge (+31 Healing, +5 MP5) (23548, 4), -- Might of the Scourge (+26 AP, +1% Crit) (23549, 4), -- Fortitude of the Scourge (+16 Stam, +100 Armor) -- Bags (17966, 4); -- Onyxia Hide Backpack (18 slot) -- ============================================================ -- Remove level requirements from Naxx shoulder enchants -- so they are usable at level 19 (Insane category) -- ============================================================ UPDATE `item_template` SET `RequiredLevel` = 0 WHERE `entry` IN (23545, 23547, 23548, 23549); -- ============================================================ -- Restore original prices if previously zeroed, then drop backup -- ============================================================ SET @tbl_exists = (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'custom_twinkmaster_original_prices'); SET @restore_sql = IF(@tbl_exists > 0, 'UPDATE `item_template` it JOIN `custom_twinkmaster_original_prices` op ON it.`entry` = op.`entry` SET it.`BuyPrice` = op.`original_buy_price`, it.`SellPrice` = op.`original_sell_price` WHERE it.`BuyPrice` = 0 AND op.`original_buy_price` > 0', 'SELECT 1'); PREPARE stmt FROM @restore_sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; DROP TABLE IF EXISTS `custom_twinkmaster_original_prices`; -- ============================================================ -- NPC Vendor Inventory (for standard vendor fallback only; -- category vendor uses custom SMSG_LIST_INVENTORY with price=0) -- ============================================================ DELETE FROM `npc_vendor` WHERE `entry` IN (@AllianceEntry, @HordeEntry); INSERT INTO `npc_vendor` (`entry`, `item`, `maxcount`, `incrtime`) SELECT @AllianceEntry, `item`, 0, 0 FROM `custom_twinkmaster_vendor_categories` UNION ALL SELECT @HordeEntry, `item`, 0, 0 FROM `custom_twinkmaster_vendor_categories`; --- apiVersion: batch/v1 kind: Job metadata: name: cmangos-twink-vendor-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e echo "=== Applying Twink Master schema to classiccharacters ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters < /sql/characters.sql echo "=== Characters schema applied successfully ===" echo "=== Applying Twink Master data to classicmangos ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos < /sql/world.sql echo "=== World data applied successfully ===" echo "=== Verifying characters table ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters -e "SHOW TABLES LIKE 'custom_twinkmaster%';" echo "=== Verifying Twink Master NPCs ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT entry, name, subname, faction, NpcFlags FROM creature_template WHERE entry IN (190012, 190013);" echo "=== Verifying creature spawns ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT id, map, position_x, position_y, position_z FROM creature WHERE id IN (190012, 190013);" echo "=== Verifying vendor items per entry ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT entry, COUNT(*) AS vendor_item_count FROM npc_vendor WHERE entry IN (190012, 190013) GROUP BY entry;" echo "=== Verifying vendor categories ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e " SELECT CASE categories WHEN 1 THEN 'BiS Gear' WHEN 2 THEN 'Consumables' WHEN 3 THEN 'Honor Gear' WHEN 4 THEN 'Insane' END AS category, COUNT(*) AS item_count FROM custom_twinkmaster_vendor_categories GROUP BY categories ORDER BY categories; " echo "=== Validating all vendor item IDs exist in item_template ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e " SELECT nv.entry, nv.item AS missing_item_id FROM npc_vendor nv LEFT JOIN item_template it ON nv.item = it.entry WHERE nv.entry IN (190012, 190013) AND it.entry IS NULL; " echo "=== Twink Master vendor migration complete ===" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: cmangos-twink-vendor-migration-sql ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/vip-master-spell-migration-job.yaml ================================================ --- apiVersion: v1 kind: ConfigMap metadata: name: cmangos-vip-master-spell-migration-sql namespace: game-servers data: vip-master-spell.sql: | -- VIP master spell migration: cleanup + existing-VIP swap. -- -- We use vanilla spell 18282 'Dummy Spell' as the master (already -- Effect1=SPELL_EFFECT_DUMMY in vanilla spell_template, exists in -- the client's Spell.dbc, zero references in item/trainer/chain -- tables). VipModule::OnCast hooks the cast and fires the cascade. -- No INSERT/UPDATE on spell_template needed. -- -- This script: -- 1) DELETEs the obsolete custom spell row 91200 we tried first -- (vanilla 1.12 clients couldn't display it). -- 2) UPDATEs character_spell to swap 22888 (the v2 hot-fix master) -- with 18282 for any existing VIPs. Rallying Cry of the -- Dragonslayer is not legitimately learnable in vanilla — anyone -- with it as a known spell got it from `.vip grant`, so the -- swap is safe. -- -- Canonical SQL: etc/emberstone/sql/world/vip-master-spell.sql in -- xunholy/cmangos-classic. Keep in sync. -- -- Idempotent on both statements. DELETE FROM `classicmangos`.`spell_template` WHERE `Id` = 91200; UPDATE `classiccharacters`.`character_spell` SET `spell` = 18282 WHERE `spell` = 22888; --- apiVersion: batch/v1 kind: Job metadata: name: cmangos-vip-master-spell-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e echo "=== Cleanup obsolete spell 91200 + swap existing VIPs 22888 → 18282 ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" < /sql/vip-master-spell.sql echo "=== Verify cleanup ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicmangos -e "SELECT COUNT(*) AS spell_91200_rows FROM spell_template WHERE Id = 91200;" echo "=== Verify VIP migration ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classiccharacters -e "SELECT spell, COUNT(*) AS chars FROM character_spell WHERE spell IN (22888, 18282) GROUP BY spell;" echo "=== Done. Restart mangosd so the new Vip.MasterSpellId from the ConfigMap takes effect ===" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: cmangos-vip-master-spell-migration-sql ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: cmangos-database-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: cmangos-database-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/game-servers/cmangos/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: cmangos namespace: game-servers labels: gitops.owncloud.ai/defaults: disabled spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 10m path: "./apps/base/game-servers/cmangos/app" prune: true wait: true sourceRef: kind: ExternalArtifact name: cmangos namespace: flux-system dependsOn: - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: game-servers ================================================ FILE: kubernetes/apps/base/game-servers/cmangos-ptr/app/db-init-job.yaml ================================================ --- # Seeds the PTR databases on the shared MariaDB. World DB is a full clone # of live so PTR has every NPC/quest/item/script the GMs would actually # want to test against. Characters + logs are schema-only so PTR # characters stay separate from live (the realm is GM-only via realmlist # allowedSecurityLevel=3 anyway). # # Idempotent: if ptrmangos already has a non-trivial table count, the # job exits 0 without touching anything. To force a fresh clone, drop # the ptr* databases and let Flux re-run the job. apiVersion: batch/v1 kind: Job metadata: name: cmangos-ptr-db-init namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: init image: mariadb:12.2 # CREATE DATABASE + GRANT must be run as root (the app user lacks # global CREATE). Dumps + restores then run as root too, since # we already have a root session here. App-user grants are what # the runtime PTR mangosd actually needs — username from secret. envFrom: - secretRef: name: cmangos-database-creds env: - name: ROOT_PWD value: password command: - /bin/bash - -c - | set -euo pipefail MARIADB="mariadb -h cmangos-database -P 3306 -u root -p$${ROOT_PWD}" DUMP="mariadb-dump -h cmangos-database -P 3306 -u root -p$${ROOT_PWD} --single-transaction --routines --triggers" already_seeded() { local db=$1 local count count=$($${MARIADB} -N -B -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='$${db}';") [ "$${count}" -gt 0 ] } echo "=== Ensuring PTR databases exist ===" $${MARIADB} -e "CREATE DATABASE IF NOT EXISTS ptrmangos CHARACTER SET utf8 COLLATE utf8_general_ci;" $${MARIADB} -e "CREATE DATABASE IF NOT EXISTS ptrcharacters CHARACTER SET utf8 COLLATE utf8_general_ci;" $${MARIADB} -e "CREATE DATABASE IF NOT EXISTS ptrlogs CHARACTER SET utf8 COLLATE utf8_general_ci;" echo "=== Granting $${MANGOS_DBUSER}@% access to PTR databases ===" $${MARIADB} -e "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE ROUTINE, ALTER ROUTINE ON \`ptrmangos\`.* TO '$${MANGOS_DBUSER}'@'%';" $${MARIADB} -e "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON \`ptrcharacters\`.* TO '$${MANGOS_DBUSER}'@'%';" $${MARIADB} -e "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON \`ptrlogs\`.* TO '$${MANGOS_DBUSER}'@'%';" $${MARIADB} -e "FLUSH PRIVILEGES;" if already_seeded ptrmangos; then echo "=== ptrmangos already populated, skipping world clone ===" else echo "=== Cloning classicmangos -> ptrmangos (full data) ===" $${DUMP} classicmangos | $${MARIADB} ptrmangos fi if already_seeded ptrcharacters; then echo "=== ptrcharacters already populated, skipping characters clone ===" else echo "=== Cloning classiccharacters -> ptrcharacters (schema + version row) ===" $${DUMP} --no-data classiccharacters | $${MARIADB} ptrcharacters # mangosd refuses to boot without a row in *_db_version # (compatibility check). Copy the live row so PTR runs # against whatever schema rev live is on. $${MARIADB} -e "INSERT INTO ptrcharacters.character_db_version SELECT * FROM classiccharacters.character_db_version;" fi if already_seeded ptrlogs; then echo "=== ptrlogs already populated, skipping logs clone ===" else echo "=== Cloning classiclogs -> ptrlogs (schema + version row) ===" $${DUMP} --no-data classiclogs | $${MARIADB} ptrlogs $${MARIADB} -e "INSERT INTO ptrlogs.logs_db_version SELECT * FROM classiclogs.logs_db_version;" fi echo "=== Done. Table counts: ===" for db in ptrmangos ptrcharacters ptrlogs; do c=$($${MARIADB} -N -B -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='$${db}';") echo " $${db}: $${c} tables" done ================================================ FILE: kubernetes/apps/base/game-servers/cmangos-ptr/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json # # Emberstone PTR — mangosd-only worldserver. # # Auth and the MariaDB live in the cmangos HelmRelease and are shared # with the live realm. PTR has its own world/characters/logs databases # (ptrmangos/ptrcharacters/ptrlogs) on the same MariaDB instance, and # is gated to GM (security >= 3) accounts via realmlist.allowedSecurityLevel. # Realm id is 2 (live is 1). # # Compute is sized for "a handful of GMs poking at content," not live # load — half the live mangosd footprint. apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: cmangos-ptr namespace: game-servers spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: mangosd: pod: terminationGracePeriodSeconds: 180 initContainers: wait-db: image: repository: busybox tag: latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do sleep 2; done'] containers: app: image: repository: ghcr.io/xunholy/cmangos-classic tag: 2473619f4ff3431fe68bacec5b05fa52fa0e0fba args: ["mangosd"] tty: true stdin: true env: TZ: ${CLUSTER_TIMEZONE} MANGOS_DBHOST: cmangos-database MANGOS_DBPORT: "3306" # Auth DB is shared with live so accounts/GM flags carry over. MANGOS_REALMD_DBNAME: classicrealmd # Game state isolated from live. MANGOS_WORLD_DBNAME: ptrmangos MANGOS_CHARACTERS_DBNAME: ptrcharacters MANGOS_LOGS_DBNAME: ptrlogs envFrom: # MANGOS_DBUSER + MANGOS_DBPASS from 1Password via ESO — # shared with live (same MariaDB instance, cmangos_app has # grants on ptrmangos / ptrcharacters / ptrlogs and the # shared classicrealmd). Hardcoded mangos:mangos was left # over from before the rotation; the old PTR pod survived # only because it held a pre-rotation DB connection. - secretRef: name: cmangos-database-creds # Matches live's graceful-shutdown pattern, tightened for PTR: # 120s in-game countdown + 140s drain, SIGTERM at ~160s, SIGKILL # at 180s. PTR will rarely have anyone logged in so a shorter # window keeps rollouts snappy. lifecycle: preStop: exec: command: - /bin/sh - -c - | echo "server restart 120" > /tmp/mangosd-stdin sleep 140 probes: liveness: enabled: true custom: true spec: tcpSocket: port: 8086 periodSeconds: 30 timeoutSeconds: 3 failureThreshold: 3 readiness: enabled: true custom: true spec: tcpSocket: port: 8086 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 startup: enabled: true custom: true spec: tcpSocket: port: 8086 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 180 resources: requests: cpu: "1" memory: 2Gi limits: memory: 6Gi # Tail GM audit log to stdout — same pattern as live so GM # actions on PTR are visible in kubectl logs and any future # log collector. gm-log-tail: image: repository: busybox tag: latest command: - /bin/sh - -c - | while [ ! -f /opt/mangos/logs/gm.log ]; do sleep 5; done exec tail -F /opt/mangos/logs/gm.log resources: requests: cpu: 5m memory: 8Mi limits: memory: 32Mi securityContext: runAsUser: 1001 runAsGroup: 1001 runAsNonRoot: true readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: ["ALL"] # Cores-pruner — same UID + cap reasoning as live. Keeps the # 20Gi PTR cores PVC from wedging if PTR ever enters a crash loop. cores-pruner: image: repository: busybox tag: latest command: - /bin/sh - -c - | while true; do if cd /opt/mangos/cores 2>/dev/null; then find . -maxdepth 1 -name 'core.*' -size 0 -delete 2>/dev/null # shellcheck disable=SC2012 ls -1t core.* 2>/dev/null | tail -n +3 | xargs -r rm -f -- fi sleep 600 done resources: requests: cpu: 5m memory: 8Mi limits: memory: 32Mi securityContext: runAsUser: 1001 runAsGroup: 1001 runAsNonRoot: true readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: ["ALL"] service: world: controller: mangosd ports: world: port: 8086 soap: controller: mangosd ports: soap: # Different cluster-internal port than live so the two SOAP # endpoints don't collide if anything ever cross-references. port: 7879 configMaps: mangosd-config: data: mangosd.conf: | RealmID = 2 GameType = 1 RealmZone = 8 WorldServerPort = 8086 BindIP = "0.0.0.0" # Tight cap — PTR is for GM smoke tests, not live load. PlayerLimit = 50 MapUpdate.Threads = 1 Motd = "Welcome to Emberstone PTR — GM-only test realm" LogLevel = 3 LogFile = "/opt/mangos/logs/Server.log" LogFileLevel = 3 LogTimestamp = 1 GmLogFile = "/opt/mangos/logs/gm.log" GmLogTimestamp = 1 GmLogPerAccount = 0 LogGMTrade = 1 LogFilter_GMChat = 0 SOAP.Enabled = 1 SOAP.IP = 0.0.0.0 SOAP.Port = 7879 Rate.XP.Kill = 1 Rate.XP.Quest = 1 Rate.XP.Explore = 1 Rate.Drop.Item.Poor = 3 Rate.Drop.Item.Normal = 3 Rate.Drop.Item.Uncommon = 3 Rate.Drop.Item.Rare = 2 Rate.Drop.Item.Epic = 1 Rate.Drop.Money = 3 Rate.Reputation.Gain = 3 AllowTwoSide.Interaction.Group = 1 AllowTwoSide.Interaction.Guild = 1 AllowTwoSide.Interaction.Chat = 1 AllowTwoSide.Interaction.Channel = 1 MailDeliveryDelay = 0 StartPlayerMoney = 100000 SkillGain.Crafting = 3 SkillGain.Gathering = 3 SkillGain.Defense = 3 SkillGain.Weapon = 3 Rate.Drop.Item.Quest = 3 Death.Ghost.RunSpeed.World = 1.5 PlayerSaveInterval = 60000 Rate.Health = 3 Rate.Mana = 3 # All side-modules kept enabled so GMs can test the same feature # surface as live. PlayerBots is the only module disabled — no # aiplayerbot.conf is mounted, the module no-ops without config. hardcore-config: data: hardcore.conf: | Hardcore.Enable = 1 Hardcore.PlayerConfig = 1 Hardcore.BroadcastDeathGuild = 1 Hardcore.BroadcastDeathWorld = 1 Hardcore.SpawnGrave = 1 Hardcore.GraveGameObjectID = 61 Hardcore.GraveMessage = "PTR death. " Hardcore.RemoveGravesOnCharacterDeleted = 1 Hardcore.DropGear = 0 Hardcore.DropItems = 0 Hardcore.DropMoney = 0 Hardcore.BotDropGear = 0 Hardcore.BotDropItems = 0 Hardcore.BotDropMoney = 0 Hardcore.RemoveLootOnCharacterDeleted = 1 Hardcore.LootGameObjectID = 2850 Hardcore.ReviveDisabled = 1 Hardcore.ReviveOnGraveyard = 0 Hardcore.LevelDown = 0 Hardcore.MaxPlayerLoot = 99 Hardcore.DropOnDungeons = 1 Hardcore.DropOnRaids = 1 Hardcore.LevelDownOnDungeons = 1 Hardcore.LevelDownOnRaids = 1 Hardcore.LevelDownMinLevel = 1 Hardcore.DropMinLevel = 1 Hardcore.DisablePVP = 0 Hardcore.SelfFound = 0 Hardcore.CustomXPRates = 0 twinkmaster-config: data: twinkmaster.conf: | Twinkmaster.Enable = 1 Twinkmaster.TargetLevel = 19 attunement-config: data: attunement.conf: | Attunement.Enable = 1 Attunement.DefaultRate = 1.0 Attunement.MinRate = 0.1 Attunement.MaxRate = 100 Attunement.Aura.Tier1.SpellId = 0 Attunement.Aura.Tier2.SpellId = 0 Attunement.Aura.Tier3.SpellId = 0 Attunement.Aura.Tier4.SpellId = 0 Attunement.Aura.Tier5.SpellId = 0 anticheat-config: data: anticheat.conf: | [AnticheatConf] ConfVersion=2017102301 Enable = 1 FingerprintHistory = 30 FingerprintLevel = 6 KickDelay.Min = 30 KickDelay.Max = 90 BanDelay.Min = 30 BanDelay.Max = 90 IPBanDelay.Min = 30 IPBanDelay.Max = 90 BanWave.Day = 1 BanWave.Hour = 10 BanWave.Minute = 0 Movement.UseExtrapolation = 1 Movement.SpeedHack.Enable = 1 Movement.WallClimb.TickCount = 0 Movement.WallClimb.TickAction = 0 Movement.WallClimb.TotalCount = 0 Movement.WallClimb.TotalAction = 0 Movement.WaterWalk.TickCount = 1 Movement.WaterWalk.TickAction = 7 Movement.WaterWalk.TotalCount = 0 Movement.WaterWalk.TotalAction = 0 Movement.SlowFall.TickCount = 1 Movement.SlowFall.TickAction = 7 Movement.SlowFall.TotalCount = 0 Movement.SlowFall.TotalAction = 0 Movement.FlyHack.TickCount = 1 Movement.FlyHack.TickAction = 7 Movement.FlyHack.TotalCount = 0 Movement.FlyHack.TotalAction = 0 Movement.Forbidden.TickCount = 1 Movement.Forbidden.TickAction = 7 Movement.Forbidden.TotalCount = 0 Movement.Forbidden.TotalAction= 0 Movement.NullClientTime.TickCount = 1 Movement.NullClientTime.TickAction = 7 Movement.NullClientTime.TotalCount = 0 Movement.NullClientTime.TotalAction = 0 Movement.RootMove.TickCount = 1 Movement.RootMove.TickAction = 7 Movement.RootMove.TotalCount = 0 Movement.RootMove.TotalAction= 0 Movement.TimeBack.TickCount = 1 Movement.TimeBack.TickAction = 7 Movement.TimeBack.TotalCount = 0 Movement.TimeBack.TotalAction= 0 Movement.FakeTransport.TickCount = 1 Movement.FakeTransport.TickAction = 7 Movement.FakeTransport.TotalCount = 0 Movement.FakeTransport.TotalAction = 0 Movement.TeleToTransport.TickCount = 1 Movement.TeleToTransport.TickAction = 7 Movement.TeleToTransport.TotalCount = 0 Movement.TeleToTransport.TotalAction= 0 Movement.FixedZ.TickCount = 1 Movement.FixedZ.TickAction = 7 Movement.FixedZ.TotalCount = 0 Movement.FixedZ.TotalAction= 0 Movement.MultiJump.TickCount = 1 Movement.MultiJump.TickAction = 3 Movement.MultiJump.TotalCount = 10 Movement.MultiJump.TotalAction = 7 Movement.FastJump.TickCount = 1 Movement.FastJump.TickAction = 3 Movement.FastJump.TotalCount = 10 Movement.FastJump.TotalAction = 7 Movement.JumpSpeedChange.TickCount = 1 Movement.JumpSpeedChange.TickAction = 3 Movement.JumpSpeedChange.TotalCount = 10 Movement.JumpSpeedChange.TotalAction= 7 Movement.HeartbeatSkip.TickCount = 1 Movement.HeartbeatSkip.TickAction = 3 Movement.HeartbeatSkip.TotalCount = 10 Movement.HeartbeatSkip.TotalAction= 7 Movement.ClockDesync.TickCount = 1 Movement.ClockDesync.TickAction = 3 Movement.ClockDesync.TotalCount = 10 Movement.ClockDesync.TotalAction= 7 Movement.OverspeedZ.TickCount = 1 Movement.OverspeedZ.TickAction = 3 Movement.OverspeedZ.TotalCount = 5 Movement.OverspeedZ.TotalAction = 7 Movement.BadOrderAck.TickCount = 1 Movement.BadOrderAck.TickAction = 3 Movement.BadOrderAck.TotalCount = 5 Movement.BadOrderAck.TotalAction= 7 Movement.Teleport.TickCount = 1 Movement.Teleport.TickAction = 7 Movement.Teleport.TotalCount = 0 Movement.Teleport.TotalAction = 0 Movement.TeleportFar.TickCount = 1 Movement.TeleportFar.TickAction = 7 Movement.TeleportFar.TotalCount = 0 Movement.TeleportFar.TotalAction= 0 Movement.Explore.TickCount = 3 Movement.Explore.TickAction = 3 Movement.Explore.TotalCount = 0 Movement.Explore.TotalAction = 0 Movement.ExploreHigh.TickCount = 1 Movement.ExploreHigh.TickAction = 3 Movement.ExploreHigh.TotalCount = 0 Movement.ExploreHigh.TotalAction = 0 Movement.BadFallReset.Enable = 1 Movement.BadFallReset.Threshold = 1 Movement.BadFallReset.Penalty = 7 Antispam.Enable = 1 Antispam.Silence = 1 Antispam.MaxLevel = 25 Warden.Enable = 1 Warden.ModuleDir = "/opt/mangos/bin/warden_modules" Warden.Timeout = 30 Warden.ScanFrequency = 15 Warden.ScanCount = 10 Warden.MinimumLevel = 1 Warden.MinimumAdvancedLevel = 1 Warden.SuspiciousEndSceneHookAction = 7 Warden.TickCount = 1 Warden.TickAction = 7 Warden.TotalCount = 0 Warden.TotalAction = 0 vip-config: data: vip.conf: | Vip.Enable = 1 Vip.MasterSpellId = 22888 Vip.BundledSpellIds = "" autoscale-config: data: autoscale.conf: | Autoscale.Enable = 1 Autoscale.RescanIntervalSeconds = 10 Autoscale.HpExponent = 0.85 Autoscale.MinScale = 0.20 Autoscale.MaxScale = 1.0 Autoscale.Baseline.Dungeon = 5 Autoscale.Baseline.RaidDefault = 40 Autoscale.MapBaselines = "309:20,509:20" Autoscale.MapBlacklist = "" Autoscale.Announce = 1 ahbot-config: data: ahbot.conf: | AuctionHouseBot.Seller.Enabled = 1 AuctionHouseBot.Buyer.Enabled = 1 AuctionHouseBot.Chance.Sell = 80 AuctionHouseBot.Chance.Buy = 40 AuctionHouseBot.Alliance.Items.Amount.Ratio = 100 AuctionHouseBot.Horde.Items.Amount.Ratio = 100 AuctionHouseBot.Neutral.Items.Amount.Ratio = 80 AuctionHouseBot.Buy.Value = 90 AuctionHouseBot.Bid.Min = 60 AuctionHouseBot.Bid.Max = 95 AuctionHouseBot.Time.Min = 2 AuctionHouseBot.Time.Max = 48 AuctionHouseBot.Value.Variance = 15 AuctionHouseBot.Items.Profession = 90, 100, 0, 60 AuctionHouseBot.Loot.Creature.Normal = 40, 50, 8, 15 AuctionHouseBot.Loot.Creature.Elite = 35, 40, 2, 4 AuctionHouseBot.Loot.Creature.Rare = 5, 15, 1, 2 AuctionHouseBot.Loot.Disenchant = 15, 20, 1, 3 AuctionHouseBot.Loot.Fishing = 5, 10, 30, 50 AuctionHouseBot.Loot.Gameobject = 20, 25, 7, 15 AuctionHouseBot.Loot.Skinning = 5, 10, 50, 80 persistence: data: existingClaim: cmangos-ptr-data advancedMounts: mangosd: app: - path: /var/lib/mangos readOnly: true cores: existingClaim: cmangos-ptr-cores advancedMounts: mangosd: app: - path: /opt/mangos/cores cores-pruner: - path: /opt/mangos/cores mangosd-config: type: configMap name: cmangos-ptr-mangosd-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/mangosd.conf subPath: mangosd.conf hardcore-config: type: configMap name: cmangos-ptr-hardcore-config advancedMounts: mangosd: app: - path: /opt/mangos/etc/hardcore.conf subPath: hardcore.conf twinkmaster-config: type: configMap name: cmangos-ptr-twinkmaster-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/twinkmaster.conf subPath: twinkmaster.conf attunement-config: type: configMap name: cmangos-ptr-attunement-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/attunement.conf subPath: attunement.conf anticheat-config: type: configMap name: cmangos-ptr-anticheat-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/anticheat.conf subPath: anticheat.conf vip-config: type: configMap name: cmangos-ptr-vip-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/vip.conf subPath: vip.conf autoscale-config: type: configMap name: cmangos-ptr-autoscale-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/autoscale.conf subPath: autoscale.conf ahbot-config: type: configMap name: cmangos-ptr-ahbot-config advancedMounts: mangosd: app: - path: /opt/mangos/conf/ahbot.conf subPath: ahbot.conf mangosd-logs: existingClaim: cmangos-ptr-mangosd-logs advancedMounts: mangosd: app: - path: /opt/mangos/logs gm-log-tail: - path: /opt/mangos/logs readOnly: true ================================================ FILE: kubernetes/apps/base/game-servers/cmangos-ptr/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - pvc-cores.yaml - pvc-data.yaml - pvc-logs.yaml - tcproute.yaml - db-init-job.yaml - realm-row-migration-job.yaml ================================================ FILE: kubernetes/apps/base/game-servers/cmangos-ptr/app/pvc-cores.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: cmangos-ptr-cores namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 20Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/game-servers/cmangos-ptr/app/pvc-data.yaml ================================================ --- # CoW clone of the live cmangos-data PVC at PVC-creation time so PTR # gets its own copy of /var/lib/mangos (DBC + maps + vmaps + mmaps) # without competing for the live volume's ReadWriteOnce lock. Clone is # point-in-time; refreshing PTR data later means deleting and recreating # this PVC (Flux will reclone from current live state). apiVersion: v1 kind: PersistentVolumeClaim metadata: name: cmangos-ptr-data namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: ceph-block dataSource: kind: PersistentVolumeClaim name: cmangos-data ================================================ FILE: kubernetes/apps/base/game-servers/cmangos-ptr/app/pvc-logs.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: cmangos-ptr-mangosd-logs namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/game-servers/cmangos-ptr/app/realm-row-migration-job.yaml ================================================ --- apiVersion: v1 kind: ConfigMap metadata: name: cmangos-ptr-realm-row-sql namespace: game-servers data: # realmlist.allowedSecurityLevel=2 = Game Master tier and above (GM + # Admin). Regular players + Moderator-tier accounts see the realm # greyed out in the launcher and the auth server rejects their connect # attempt with "Server is for higher level account." cmangos security # tiers: 0=Player, 1=Moderator, 2=GM, 3=Admin. # icon=1 (PvP) matches the live realm so the lobby badge agrees with # mangosd.conf GameType=1. realmbuilds matches live ("5875 6005 6141 ") # so the same set of client builds are accepted. Same EXTERNAL_IP as # live — clients route by port (8086 vs 8085). realm-ptr.sql: | INSERT INTO `realmlist` (id, name, address, port, icon, realmflags, timezone, allowedSecurityLevel, population, realmbuilds) VALUES (2, 'Emberstone PTR', '${EXTERNAL_IP}', 8086, 1, 0, 8, 2, 0, '5875 6005 6141 ') ON DUPLICATE KEY UPDATE name = VALUES(name), address = VALUES(address), port = VALUES(port), icon = VALUES(icon), realmflags = VALUES(realmflags), timezone = VALUES(timezone), allowedSecurityLevel = VALUES(allowedSecurityLevel), population = VALUES(population), realmbuilds = VALUES(realmbuilds); --- apiVersion: batch/v1 kind: Job metadata: name: cmangos-ptr-realm-row-migration namespace: game-servers spec: ttlSecondsAfterFinished: 86400 backoffLimit: 3 template: spec: restartPolicy: Never initContainers: - name: wait-db image: busybox:latest command: ['sh', '-c', 'until nc -z cmangos-database 3306; do echo "Waiting for database..."; sleep 2; done'] containers: - name: migrate image: mariadb:12.2 envFrom: - secretRef: name: cmangos-database-creds command: - /bin/bash - -c - | set -e echo "=== Upserting Emberstone PTR realmlist row (id=2) ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicrealmd < /sql/realm-ptr.sql echo "=== Verifying ===" mariadb -h cmangos-database -P 3306 -u "$MANGOS_DBUSER" -p"$MANGOS_DBPASS" classicrealmd \ -e "SELECT id, name, address, port, allowedSecurityLevel FROM realmlist ORDER BY id;" volumeMounts: - name: sql-scripts mountPath: /sql volumes: - name: sql-scripts configMap: name: cmangos-ptr-realm-row-sql ================================================ FILE: kubernetes/apps/base/game-servers/cmangos-ptr/app/tcproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/tcproute_v1alpha2.json apiVersion: gateway.networking.k8s.io/v1alpha2 kind: TCPRoute metadata: name: cmangos-ptr-world spec: parentRefs: - name: envoy-external namespace: network-system sectionName: cmangos-world-ptr rules: - backendRefs: - name: cmangos-ptr-world port: 8086 ================================================ FILE: kubernetes/apps/base/game-servers/cmangos-ptr/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: cmangos-ptr namespace: game-servers labels: gitops.owncloud.ai/defaults: disabled spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 10m path: "./apps/base/game-servers/cmangos-ptr/app" prune: true wait: true sourceRef: kind: ExternalArtifact name: cmangos-ptr namespace: flux-system dependsOn: - name: cmangos namespace: game-servers targetNamespace: game-servers ================================================ FILE: kubernetes/apps/base/game-servers/emberstone-portal/app/externalsecret-soap.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: cmangos-soap-creds namespace: game-servers spec: refreshInterval: 1h secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: cmangos-soap-creds template: data: SOAP_USER: "{{ .SOAP_USER }}" SOAP_PASSWORD: "{{ .SOAP_PASSWORD }}" dataFrom: - extract: key: cmangos ================================================ FILE: kubernetes/apps/base/game-servers/emberstone-portal/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: emberstone-portal-captcha namespace: game-servers spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: emberstone-portal-captcha template: data: CAPTCHA_KEY: "{{ .SITE_KEY }}" CAPTCHA_SECRET: "{{ .SECRET_KEY }}" dataFrom: - extract: key: emberstone ================================================ FILE: kubernetes/apps/base/game-servers/emberstone-portal/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: emberstone-portal namespace: game-servers spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: app: containers: app: image: repository: ghcr.io/xunholy/cmangos-registration tag: da24e639b3b8e8366f792423399cb8ef0ca2f4b7 env: TZ: ${CLUSTER_TIMEZONE} envFrom: - secretRef: name: emberstone-portal-captcha # SOAP creds (cmangos GM service account) from 1Password # via ESO. Replaces hardcoded soapadmin:soapadmin that # used to live in config.php. - secretRef: name: cmangos-soap-creds # cmangos DB creds (MANGOS_DBUSER / MANGOS_DBPASS) from # 1Password via ESO. Replaces hardcoded mangos:mangos in # config.php — that user was deleted in 2534bce98 and the # portal's server-status / registration / change-password # flows all 500'd until config.php picked these up. - secretRef: name: cmangos-database-creds probes: liveness: enabled: true custom: true spec: httpGet: path: / port: 80 periodSeconds: 30 timeoutSeconds: 3 failureThreshold: 3 readiness: enabled: true custom: true spec: httpGet: path: / port: 80 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 startup: enabled: true custom: true spec: httpGet: path: / port: 80 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 30 resources: requests: cpu: 10m memory: 64Mi limits: memory: 256Mi defaultPodOptions: securityContext: fsGroup: 33 fsGroupChangePolicy: OnRootMismatch service: app: controller: app ports: http: port: 80 persistence: config: type: configMap name: emberstone-portal-config advancedMounts: app: app: - path: /var/www/html/application/config/config.php subPath: config.php - path: /var/www/html/template/kaelthas/tpl/header.php subPath: header.php - path: /var/www/html/template/kaelthas/tpl/footer.php subPath: footer.php - path: /var/www/html/template/kaelthas/tpl/main.php subPath: main.php - path: /var/www/html/template/kaelthas/tpl/posts.php subPath: posts.php - path: /var/www/html/template/kaelthas/tpl/howtoconnect.php subPath: howtoconnect.php - path: /var/www/html/template/kaelthas/tpl/bot_filter.php subPath: bot_filter.php ================================================ FILE: kubernetes/apps/base/game-servers/emberstone-portal/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: emberstone-portal annotations: external-dns.alpha.kubernetes.io/external: 'true' spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https hostnames: - 'emberstone.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: emberstone-portal port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/game-servers/emberstone-portal/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml - externalsecret.yaml - externalsecret-soap.yaml configMapGenerator: - name: emberstone-portal-config namespace: game-servers files: - config.php=./resources/config.php - header.php=./resources/header.php - footer.php=./resources/footer.php - main.php=./resources/main.php - posts.php=./resources/posts.php - howtoconnect.php=./resources/howtoconnect.php - bot_filter.php=./resources/bot_filter.php generatorOptions: annotations: kustomize.toolkit.fluxcd.io/substitute: disabled configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/game-servers/emberstone-portal/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/values/persistence/config/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/game-servers/emberstone-portal/app/resources/bot_filter.php ================================================ )` clause. Bot account ids are * looked up once per request from the auth DB (RandomBotAccountPrefix * defaults to "rndbot") and cached in a static variable. * * These names deliberately differ from the upstream (`portal_*` vs * `user::`/`status::`) so that a future upstream bump cannot silently * revert the filter — main.php has to be updated to opt in. */ /** * Account ids of AI Playerbot accounts. Cached per request. * @return int[] */ function portal_bot_account_ids() { static $ids = null; if ($ids === null) { // LIKE 'RNDBOT%' with UPPER() to survive collation quirks. Matches the // default AiPlayerbot.RandomBotAccountPrefix; if the admin changes // that prefix, this filter stops working and bots reappear in the // lists — make that the failure mode, not silent matching of the // wrong accounts. $ids = database::$auth->fetchFirstColumn( "SELECT id FROM account WHERE UPPER(username) LIKE 'RNDBOT%'" ); } return $ids; } /** * Attach the bot-exclusion clause to a QueryBuilder that selects from * characters. No-op when there are no bot accounts. */ function portal_apply_bot_filter($qb) { $bots = portal_bot_account_ids(); if (!empty($bots)) { $qb->andWhere('account NOT IN (:portalBotIds)') ->setParameter('portalBotIds', $bots, \Doctrine\DBAL\ArrayParameterType::INTEGER); } return $qb; } function portal_online_count($realm) { $qb = database::$chars[$realm['realmid']]->createQueryBuilder() ->select('COUNT(*)') ->from('characters') ->where('online = 1'); portal_apply_bot_filter($qb); return (int) $qb->executeQuery()->fetchOne(); } function portal_online_players($realm) { $qb = database::$chars[$realm['realmid']]->createQueryBuilder() ->select('name, race, class, gender, level') ->from('characters') ->where('online = 1') ->orderBy('level', 'DESC') ->setMaxResults(49); portal_apply_bot_filter($qb); $rows = $qb->executeQuery()->fetchAllAssociative(); return empty($rows[0]['name']) ? false : $rows; } /** * Real characters active in the past 30 days (online now or logged out * within the window), online-first and then most-recently-seen. Returns * raw `online` flag and `logout_time` so the view can render a * "Last seen" label. */ function portal_recent_activity($realm, $windowSeconds = 2592000) { $qb = database::$chars[$realm['realmid']]->createQueryBuilder() ->select('name, race, class, gender, level, online, logout_time') ->from('characters') ->where('online = 1 OR logout_time >= :cutoff') ->setParameter('cutoff', time() - $windowSeconds) ->orderBy('online', 'DESC') ->addOrderBy('logout_time', 'DESC') ->setMaxResults(49); portal_apply_bot_filter($qb); $rows = $qb->executeQuery()->fetchAllAssociative(); return empty($rows[0]['name']) ? false : $rows; } /** * Highest-level real character on the realm (all-time, not restricted to * the recent-activity window — the point is bragging rights). Returns a * single row or false. */ function portal_highest_level_char($realm) { $qb = database::$chars[$realm['realmid']]->createQueryBuilder() ->select('name, race, class, gender, level') ->from('characters') ->orderBy('level', 'DESC') ->addOrderBy('totaltime', 'DESC') ->setMaxResults(1); portal_apply_bot_filter($qb); $rows = $qb->executeQuery()->fetchAllAssociative(); return empty($rows[0]['name']) ? false : $rows[0]; } /** * Render a short "Last seen" label for a character row with `online` * and `logout_time` fields. Pure formatter — no DB access. */ function portal_format_last_seen($row) { if (!empty($row['online'])) { return 'Online now'; } $ago = max(0, time() - (int) ($row['logout_time'] ?? 0)); if ($ago < 60) { return 'just now'; } if ($ago < 3600) { return floor($ago / 60) . 'm ago'; } if ($ago < 86400) { return floor($ago / 3600) . 'h ago'; } return floor($ago / 86400) . 'd ago'; } function portal_top_playtime($realm) { $qb = database::$chars[$realm['realmid']]->createQueryBuilder() ->select('name, race, class, gender, level, totaltime') ->from('characters') ->orderBy('totaltime', 'DESC') ->setMaxResults(10); portal_apply_bot_filter($qb); $rows = $qb->executeQuery()->fetchAllAssociative(); return empty($rows[0]['totaltime']) ? false : $rows; } function portal_top_killers($realm) { $conn = database::$chars[$realm['realmid']]; // AzerothCore-style schema (totalKills column). try { $qb = $conn->createQueryBuilder() ->select('name, race, class, gender, level, totalKills') ->from('characters') ->orderBy('totalKills', 'DESC') ->setMaxResults(10); portal_apply_bot_filter($qb); $rows = $qb->executeQuery()->fetchAllAssociative(); // Query succeeded — schema is AzerothCore. Don't fall through to // the CMaNGOS-only column even if no real player has any kills, // otherwise stored_honorable_kills will throw on AzerothCore. return empty($rows[0]['totalKills']) ? false : $rows; } catch (\Exception $e) { // CMaNGOS Classic: totalKills column doesn't exist; fall through. } // CMaNGOS Classic schema (stored_honorable_kills column). try { $qb = $conn->createQueryBuilder() ->select('name, race, class, gender, level, stored_honorable_kills as totalKills') ->from('characters') ->orderBy('stored_honorable_kills', 'DESC') ->setMaxResults(10); portal_apply_bot_filter($qb); $rows = $qb->executeQuery()->fetchAllAssociative(); return empty($rows[0]['totalKills']) ? false : $rows; } catch (\Exception $e) { return false; } } function portal_top_honorpoints($realm) { $conn = database::$chars[$realm['realmid']]; // AzerothCore / Classic-Era schema (totalHonorPoints / honorLevel+honor). try { $qb = $conn->createQueryBuilder(); if (get_config('expansion') >= 6) { $qb->select('name, race, class, gender, level, honorLevel, honor') ->from('characters') ->orderBy('honorLevel', 'DESC') ->addOrderBy('honor', 'DESC') ->setMaxResults(10); } else { $qb->select('name, race, class, gender, level, totalHonorPoints') ->from('characters') ->orderBy('totalHonorPoints', 'DESC') ->setMaxResults(10); } portal_apply_bot_filter($qb); $rows = $qb->executeQuery()->fetchAllAssociative(); // Query succeeded — schema fits. Don't fall through to the // CMaNGOS-only column even if no real player has honor; otherwise // stored_honor_rating will throw on AzerothCore. return empty($rows[0]['level']) ? false : $rows; } catch (\Exception $e) { // CMaNGOS Classic: totalHonorPoints column doesn't exist; fall through. } // CMaNGOS Classic schema (stored_honor_rating column). try { $qb = $conn->createQueryBuilder() ->select('name, race, class, gender, level, stored_honor_rating as totalHonorPoints') ->from('characters') ->orderBy('stored_honor_rating', 'DESC') ->setMaxResults(10); portal_apply_bot_filter($qb); $rows = $qb->executeQuery()->fetchAllAssociative(); return empty($rows[0]['level']) ? false : $rows; } catch (\Exception $e) { return false; } } function portal_top_arenapoints($realm) { try { $qb = database::$chars[$realm['realmid']]->createQueryBuilder() ->select('name, race, class, gender, level, arenaPoints') ->from('characters') ->orderBy('arenaPoints', 'DESC') ->setMaxResults(10); portal_apply_bot_filter($qb); $rows = $qb->executeQuery()->fetchAllAssociative(); return empty($rows[0]['arenaPoints']) ? false : $rows; } catch (\Exception $e) { return false; } } /** * Arena teams don't store account directly; filter by captain character. * Fetch a wider slice (20 teams) so the post-filter has a decent chance * of still returning 10 real entries when bot captains dominate the top. */ function portal_top_arenateams($realm) { try { $qb = database::$chars[$realm['realmid']]->createQueryBuilder() ->select('arenaTeamId, name, captainGuid, rating') ->from('arena_team') ->orderBy('rating', 'DESC') ->setMaxResults(20); $teams = $qb->executeQuery()->fetchAllAssociative(); } catch (\Exception $e) { return false; } if (empty($teams)) { return false; } $bots = portal_bot_account_ids(); if (empty($bots)) { return array_slice($teams, 0, 10); } $captainGuids = array_values(array_filter(array_column($teams, 'captainGuid'))); if (empty($captainGuids)) { return array_slice($teams, 0, 10); } $guidQb = database::$chars[$realm['realmid']]->createQueryBuilder() ->select('guid') ->from('characters') ->where('guid IN (:guids)') ->andWhere('account NOT IN (:bots)') ->setParameter('guids', $captainGuids, \Doctrine\DBAL\ArrayParameterType::INTEGER) ->setParameter('bots', $bots, \Doctrine\DBAL\ArrayParameterType::INTEGER); $realCaptainGuids = array_flip($guidQb->executeQuery()->fetchFirstColumn()); $filtered = array_values(array_filter( $teams, fn($t) => isset($realCaptainGuids[$t['captainGuid']]) )); return empty($filtered) ? false : array_slice($filtered, 0, 10); } ================================================ FILE: kubernetes/apps/base/game-servers/emberstone-portal/app/resources/config.php ================================================ [ 'label' => 'Classic (1.12.1)', 'page_title' => 'Emberstone', 'game_version' => '1.12.1', 'expansion' => '0', 'server_core' => 5, // CMaNGOS: s/v fields, reversed salt in SRP6 'realmlist' => 'wow.owncloud.ai', 'soap_host' => 'cmangos-soap', 'soap_port' => '7878', 'soap_uri' => 'urn:MaNGOS', 'db_auth_host' => 'cmangos-database', 'db_auth_port' => '3306', // DB creds from 1Password via cmangos-database-creds ESO (envFrom // in helmrelease). The previous hardcoded mangos:mangos user was // deleted in commit 2534bce98; empty fallback so a missing env // fails loudly (Access denied) rather than silently retrying the // dead user. 'db_auth_user' => getenv('MANGOS_DBUSER') ?: '', 'db_auth_pass' => getenv('MANGOS_DBPASS') ?: '', 'db_auth_dbname' => 'classicrealmd', 'realmlists' => [ '1' => [ 'realmid' => 1, 'realmname' => 'Emberstone', 'db_host' => 'cmangos-database', 'db_port' => '3306', 'db_user' => getenv('MANGOS_DBUSER') ?: '', 'db_pass' => getenv('MANGOS_DBPASS') ?: '', 'db_name' => 'classiccharacters', ], ], 'theme' => [ 'gold' => '#C9A84C', 'gold_bright' => '#E8D48B', 'gold_dark' => '#8B6B1A', 'gold_muted' => '#A08A4E', 'gold_glow' => 'rgba(201, 168, 76, 0.5)', 'gold_dim' => 'rgba(201, 168, 76, 0.07)', 'border' => 'rgba(201, 168, 76, 0.08)', 'border_hover' => 'rgba(201, 168, 76, 0.20)', 'border_active' => 'rgba(201, 168, 76, 0.40)', 'particle_rgb' => '201, 168, 76', ], 'hero_logo' => 'wow-classic-logo.png', 'hero_badge' => 'Classic', 'hero_sub' => 'Return to the world as it was meant to be. A Classic World of Warcraft realm with faithful 1.12.1 mechanics, authentic content progression, and a dedicated community.', 'bg_glow_css' => '', 'hero_filter' => '', ], 'wotlk' => [ 'label' => 'Wrath of the Lich King (3.3.5a)', 'page_title' => 'Emberstone', 'game_version' => '3.3.5a', 'expansion' => '2', 'server_core' => 1, // AzerothCore: salt/verifier fields 'realmlist' => 'wow.owncloud.ai:3725', 'soap_host' => 'azerothcore-soap', 'soap_port' => '7878', 'soap_uri' => 'urn:AC', 'db_auth_host' => 'azerothcore-database', 'db_auth_port' => '3306', 'db_auth_user' => 'root', 'db_auth_pass' => 'password', 'db_auth_dbname' => 'acore_auth', 'realmlists' => [ '1' => [ 'realmid' => 1, 'realmname' => 'Emberstone', 'db_host' => 'azerothcore-database', 'db_port' => '3306', 'db_user' => 'root', 'db_pass' => 'password', 'db_name' => 'acore_characters', ], ], 'theme' => [ 'gold' => '#7CB9E8', 'gold_bright' => '#B3D9F7', 'gold_dark' => '#1B5E8A', 'gold_muted' => '#5A9DC4', 'gold_glow' => 'rgba(124, 185, 232, 0.5)', 'gold_dim' => 'rgba(124, 185, 232, 0.07)', 'border' => 'rgba(124, 185, 232, 0.08)', 'border_hover' => 'rgba(124, 185, 232, 0.20)', 'border_active' => 'rgba(124, 185, 232, 0.40)', 'particle_rgb' => '124, 185, 232', ], 'hero_logo' => 'wow-logo.png', 'hero_badge' => 'Wrath of the Lich King', 'hero_sub' => 'The Lich King awaits. A Wrath of the Lich King realm with 5x rates, AI companions, solo dungeons, and every quality-of-life feature to make your adventure legendary.', 'bg_glow_css' => 'radial-gradient(ellipse 800px 600px at 25% 20%, rgba(56, 140, 204, 0.06) 0%, transparent 70%), radial-gradient(ellipse 600px 800px at 75% 80%, rgba(100, 60, 180, 0.05) 0%, transparent 70%), radial-gradient(ellipse 1200px 400px at 50% 50%, rgba(124, 185, 232, 0.03) 0%, transparent 60%)', 'hero_filter' => 'hue-rotate(190deg) saturate(1.4) brightness(0.85)', ], ]; // ── Expansion Selection (GET > POST > cookie > default) ───────────────────── $default_expansion = 'vanilla'; $selected_expansion = $default_expansion; if (!empty($_GET['expansion']) && isset($expansions[$_GET['expansion']])) { $selected_expansion = $_GET['expansion']; } elseif (!empty($_POST['expansion']) && isset($expansions[$_POST['expansion']])) { $selected_expansion = $_POST['expansion']; } elseif (!empty($_COOKIE['selected_expansion']) && isset($expansions[$_COOKIE['selected_expansion']])) { $selected_expansion = $_COOKIE['selected_expansion']; } setcookie('selected_expansion', $selected_expansion, time() + 86400 * 30, '/'); // ── Shared Config (same across all expansions) ──────────────────────��─────── $config['baseurl'] = 'https://emberstone.owncloud.ai'; $config['language'] = 'english'; $config['supported_langs'] = ['english' => 'English']; $config['debug_mode'] = false; $config['patch_location'] = ''; $config['battlenet_support'] = false; $config['srp6_support'] = true; $config['srp6_version'] = 0; $config['template'] = 'kaelthas'; $config['captcha_type'] = 3; $config['captcha_key'] = getenv('CAPTCHA_KEY') ?: ''; $config['captcha_secret'] = getenv('CAPTCHA_SECRET') ?: ''; $config['captcha_language'] = 'en'; $config['soap_for_register'] = false; $config['soap_style'] = 'SOAP_RPC'; // SOAP creds come from ExternalSecret cmangos-soap-creds, mounted via // envFrom on the portal container. See externalsecret-soap.yaml. $config['soap_username'] = getenv('SOAP_USER') ?: ''; $config['soap_password'] = getenv('SOAP_PASSWORD') ?: ''; $config['soap_ca_command'] = 'account create {USERNAME} {PASSWORD}'; $config['smtp_host'] = ''; $config['smtp_port'] = 587; $config['smtp_auth'] = false; $config['smtp_user'] = ''; $config['smtp_pass'] = ''; $config['smtp_secure'] = 'tls'; $config['smtp_mail'] = ''; $config['vote_system'] = false; $config['vote_sites'] = []; $config['2fa_support'] = false; $config['soap_2d_command'] = 'account set 2fa {USERNAME} off'; $config['soap_2e_command'] = 'account set 2fa {USERNAME} {SECRET}'; $config['disable_changepassword'] = true; $config['disable_top_players'] = false; $config['disable_online_players'] = false; $config['multiple_email_use'] = true; $config['script_version'] = '2.0.4'; // ── Override config with selected expansion ─��─────────────────────────────── $exp = $expansions[$selected_expansion]; $override_keys = [ 'page_title', 'game_version', 'expansion', 'server_core', 'realmlist', 'soap_host', 'soap_port', 'soap_uri', 'db_auth_host', 'db_auth_port', 'db_auth_user', 'db_auth_pass', 'db_auth_dbname', 'realmlists', ]; foreach ($override_keys as $key) { $config[$key] = $exp[$key]; } // Expose expansion metadata for templates $config['_expansions'] = $expansions; $config['_selected'] = $selected_expansion; $config['_expansion_theme'] = $exp['theme']; $config['_expansion_meta'] = $exp; // ── Unified registration helper ───────────────────────────────────────────── // Computes SRP6 salt+verifier for a specific core type and returns values // ready for DB insertion (hex strings for CMaNGOS, binary for AzerothCore). function portal_compute_srp6($username, $password, $server_core) { $g = gmp_init(7); $N = gmp_init('894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7', 16); $salt = random_bytes(32); $h1 = sha1(strtoupper($username . ':' . $password), true); if ($server_core == 5) { $h2 = sha1(strrev($salt) . $h1, true); } else { $h2 = sha1($salt . $h1, true); } $h2 = gmp_import($h2, 1, GMP_LSW_FIRST); $verifier = gmp_powm($g, $h2, $N); $verifier = str_pad(gmp_export($verifier, 1, GMP_LSW_FIRST), 32, chr(0), STR_PAD_RIGHT); if ($server_core == 5) { return ['salt' => strtoupper(bin2hex($salt)), 'verifier' => strtoupper(bin2hex($verifier)), 'salt_field' => 's', 'verifier_field' => 'v']; } return ['salt' => $salt, 'verifier' => $verifier, 'salt_field' => 'salt', 'verifier_field' => 'verifier']; } // Creates account in a specific expansion's auth DB. Returns true on success. function portal_create_mirror_account($exp_config, $username, $password, $email) { $conn = \Doctrine\DBAL\DriverManager::getConnection([ 'dbname' => $exp_config['db_auth_dbname'], 'user' => $exp_config['db_auth_user'], 'password' => $exp_config['db_auth_pass'], 'host' => $exp_config['db_auth_host'], 'port' => $exp_config['db_auth_port'], 'driver' => 'pdo_mysql', 'charset' => 'utf8', ], new \Doctrine\DBAL\Configuration()); // Skip if account already exists $existing = $conn->createQueryBuilder() ->select('id')->from('account') ->where('username = :u')->setParameter('u', strtoupper($username)) ->executeQuery()->fetchOne(); if ($existing) { $conn->close(); return false; } $srp = portal_compute_srp6($username, $password, $exp_config['server_core']); $conn->insert('account', [ 'username' => strtoupper($username), $srp['salt_field'] => $srp['salt'], $srp['verifier_field'] => $srp['verifier'], 'email' => strtoupper($email), 'expansion' => $exp_config['expansion'], ]); $conn->close(); return true; } ================================================ FILE: kubernetes/apps/base/game-servers/emberstone-portal/app/resources/footer.php ================================================
================================================ FILE: kubernetes/apps/base/game-servers/emberstone-portal/app/resources/header.php ================================================ "> <?php echo $antiXss->xss_clean(get_config("page_title")); ?> /favicon.ico" type="image/x-icon"> /template/xss_clean(get_config("template")); ?>/css/bootstrap.min.css"> /template/xss_clean(get_config("template")); ?>/css/bootsnav.css"> /template/xss_clean(get_config("template")); ?>/css/animate.css"> /template/xss_clean(get_config("template")); ?>/css/style.css"> ' . lang('custom_css') . '' : ''); ?>
/template/xss_clean(get_config("template")); ?>/images/" alt="World of Warcraft">
· Patch xss_clean(get_config("game_version")); ?>

xss_clean(get_config("page_title")); ?>

:
================================================ FILE: kubernetes/apps/base/game-servers/emberstone-portal/app/resources/howtoconnect.php ================================================

How to Connect


1.

2. Download and install the World of Warcraft 3.3.5a client (build 12340).

MEGA limits free downloads to ~5 GB/day. The client is ~6.3 GB so you may need to resume across two days. The torrent links have no limits but require a torrent client such as qBittorrent.

3.

4.

set realmlist set realmname xss_clean(get_config('page_title')); ?>

5. Launch Wow.exe directly. Do not use the Launcher or it will try to update the client. Log in with your username, not your email.

How to Connect


1.

2.

3.

4.

set realmlist set realmname xss_clean(get_config('page_title')); ?>

5. Launch WoW.exe directly. Do not use the Launcher or it will try to update the client. Log in with your username, not your email.

================================================ FILE: kubernetes/apps/base/game-servers/emberstone-portal/app/resources/main.php ================================================ $exp_cfg) { if ($key === $current) continue; portal_create_mirror_account($exp_cfg, $_POST['username'], $_POST['password'], $_POST['email']); } } require_once 'header.php'; // Real-player wrappers for server-status + top-players. Filters out // AI Playerbot ("rndbot*") accounts that the upstream queries include // by default. See bot_filter.php for the query details. require_once 'bot_filter.php'; ?>
================================================ FILE: kubernetes/apps/base/game-servers/emberstone-portal/app/resources/posts.php ================================================

Welcome to Emberstone


Emberstone is a Wrath of the Lich King realm running patch 3.3.5a with enhanced rates and quality-of-life features designed for fun. Whether you are a returning veteran or experiencing Northrend for the first time, Emberstone offers a polished WotLK experience with AI companions, solo-friendly dungeons, and a living world.

Server Rates & Features


5x XP on kills, quests, exploration, and battlegrounds. 5x loot for common and uncommon drops, 3x for rare, 2x for epic. 5x gold, 5x reputation, and 5x honor gains. 5x profession skill-ups for crafting and gathering. All flight paths unlocked with instant travel. 10g starting gold (50g for Death Knights). Mail delivered instantly. Max level 80.

Modules & Extras


PlayerBots — AI-controlled players that quest, group, and PvP alongside you. AutoBalance — Dungeons and raids scale to your party size, solo or with friends. Transmogrification — Change the look of your gear at the Transmog NPC. Auction House Bot — The AH is always stocked with items. AoE Loot — Loot all nearby corpses at once. Auto-Learn Spells — New abilities learned automatically on level up. Solo Dungeon Finder — Queue for dungeons solo or with any group size. Cross-Faction BGs — Battlegrounds pop regardless of faction balance.

Getting Started


Create your account to begin your adventure. Once registered, download a WoW 3.3.5a client, update your realmlist.wtf file, and log in to explore Northrend, storm Icecrown Citadel, battle in Wintergrasp, and conquer Ulduar. Check the "How to Connect" page for setup instructions.

Join Our Discord


Hop into the Emberstone Discord to chat with the community, get help, find groups, and stay on top of server announcements.

Vote for Emberstone


Enjoying the server? Help us grow by voting! Every vote helps new players discover Emberstone.

Welcome to Emberstone


Emberstone is a Classic World of Warcraft realm running the original 1.12.1 patch with faithful game mechanics, class balance, and progressive content unlocks. Whether you are a returning veteran or stepping into Azeroth for the first time, Emberstone offers a stable, blizzlike experience with an active community and dedicated staff.

Server Rates & Features


3x XP on kills, quests, and exploration. 3x loot for common and uncommon drops, 2x for rare, and 1x (blizzlike) for epic items. 3x gold and 3x reputation gains across the board. Mail is delivered instantly with no delay. Max level is 60 with up to 10 characters per account.

Getting Started


Create your account to begin your adventure. Once registered, update your realmlist.wtf file and log in to explore the Eastern Kingdoms and Kalimdor, run dungeons with friends, raid Molten Core and Onyxia, and fight for honor in Alterac Valley. Check the "How to Connect" page for setup instructions.

Join Our Discord


Hop into the Emberstone Discord to chat with the community, get help, find groups, and stay on top of server announcements.

Vote for Emberstone


Enjoying the server? Help us grow by voting! Every vote helps new players discover Emberstone.

================================================ FILE: kubernetes/apps/base/game-servers/emberstone-portal/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: emberstone-portal namespace: game-servers labels: gitops.owncloud.ai/defaults: disabled spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 10m path: "./apps/base/game-servers/emberstone-portal/app" prune: true wait: true sourceRef: kind: ExternalArtifact name: emberstone-portal namespace: flux-system dependsOn: - name: cmangos namespace: game-servers - name: azerothcore namespace: game-servers targetNamespace: game-servers ================================================ FILE: kubernetes/apps/base/game-servers/enemy-territory/app/configmap.yaml ================================================ --- apiVersion: v1 kind: ConfigMap metadata: name: enemy-territory-config namespace: game-servers data: server.cfg: | // Headshot Gaming server configuration // Loads the custom HS config (encrypted secret), then applies // overrides that ensure correct behavior regardless of // auto-saved etconfig_server.cfg values. // Load Headshot Gaming config exec hs_etpub.cfg // MASTER SERVERS - add ET Legacy and etmaster.net masters // (original only had etmaster.idsoftware.com) set sv_master1 "etmaster.idsoftware.com" set sv_master2 "master.etlegacy.com" set sv_master3 "master0.etmaster.net" // SECURITY - ET Legacy specific overrides set g_guidCheck "0" set sv_wh_active "1" set sv_wh_bbox_horz "60" set sv_wh_bbox_vert "100" // OVERRIDES - values that differ from the original hs_etpub.cfg set sv_maxclients "32" // Disable built-in config preset (defaultpublic.config resets // respawn times, speed, and other values AFTER hs_etpub.cfg loads) set g_customConfig "" campaigncycle.cfg: | set d1 "campaign cmpgn_northafrica ; set nextcampaign vstr d2" set d2 "campaign cmpgn_centraleurope ; set nextcampaign vstr d1" // server doesn't recognise the campaign command when the gamecode isn't running yet. set d_initial "set g_gametype 4 ; map oasis ; set nextcampaign vstr d2" vstr d_initial lmscycle.cfg: | set d1 "set g_gametype 5 ; map oasis ; set nextmap vstr d2" set d2 "set g_gametype 5 ; map battery ; set nextmap vstr d3" set d3 "set g_gametype 5 ; map goldrush ; set nextmap vstr d4" set d4 "set g_gametype 5 ; map radar ; set nextmap vstr d5" set d5 "set g_gametype 5 ; map railgun ; set nextmap vstr d6" set d6 "set g_gametype 5 ; map fueldump ; set nextmap vstr d1" vstr d1 objectivecycle.cfg: | set d1 "set g_gametype 2 ; map oasis ; set nextmap vstr d2" set d2 "set g_gametype 2 ; map battery ; set nextmap vstr d3" set d3 "set g_gametype 2 ; map goldrush ; set nextmap vstr d4" set d4 "set g_gametype 2 ; map radar ; set nextmap vstr d5" set d5 "set g_gametype 2 ; map railgun ; set nextmap vstr d6" set d6 "set g_gametype 2 ; map fueldump ; set nextmap vstr d1" vstr d1 mapvotecycle.cfg: | // Each map in this map order is executed whenever there are no votes for a map, // otherwise, the map that gets the most votes for is played set d1 "set g_gametype 6 ; map oasis ; set nextmap vstr d2" set d2 "set g_gametype 6 ; map battery ; set nextmap vstr d3" set d3 "set g_gametype 6 ; map goldrush ; set nextmap vstr d4" set d4 "set g_gametype 6 ; map radar ; set nextmap vstr d5" set d5 "set g_gametype 6 ; map railgun ; set nextmap vstr d6" set d6 "set g_gametype 6 ; map fueldump ; set nextmap vstr d1" vstr d1 mapvoteplayerscount.cfg: | // Map Vote Player Count // config file used for listing maps depending of players number in map vote mod // if the config file doesn't exist, all the map are listed // if the map doesn't exist in the config file, the map will appear in the map vote list // if the minimum / maximum values is < 0, one or both condition is not take into account // there is no limit for minimum / maximum values // // map min max "oasis" -1 -1 "battery" -1 -1 "goldrush" -1 -1 "radar" -1 -1 "railgun" -1 -1 "fueldump" -1 -1 omni-bot.cfg: | [Log] LogInfo = true LogWarnings = true LogErrors = true LogCriticalErrors = true [Script] LiveUpdate = false [ServerManager] MinBots = -1 MaxBots = 16 BalanceTeams = 1 SaveConfigChanges = 0 CountSpectators = 0 SleepBots = 0 InitialDelayTime = 2.1 [Versus] BotTeam = -1 HumanTeam = -1 BotsPerHuman = 3 [CombatMovement] moveskill = 3 [Difficulty] CurrentDifficulty = 4 AdjustAim = 1 [FireTeam] enabled = 0 [XP] Reset = -1 Max = 10000 [HeavyWeapons] MinPlayersForMortar = -1 MinPlayersForMobileMG = -1 ================================================ FILE: kubernetes/apps/base/game-servers/enemy-territory/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: enemy-territory namespace: game-servers spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: enemy-territory: containers: app: image: repository: xunholy/enemy-territory tag: sha-33fad6a env: FS_HOMEPATH: /config args: - "+set" - dedicated - "2" - "+set" - net_port - "27960" - "+set" - sv_advert - "3" - "+set" - vm_game - "0" - "+set" - fs_basepath - /etlegacy - "+set" - fs_homepath - /config - "+set" - fs_game - legacy - "+set" - sv_maxclients - "32" - "+set" - sv_punkbuster - "0" - "+exec" - server.cfg securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: false capabilities: { drop: ["ALL"] } resources: requests: cpu: 100m memory: 512Mi defaultPodOptions: hostNetwork: true dnsPolicy: ClusterFirstWithHostNet securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch supplementalGroups: [44] seccompProfile: { type: RuntimeDefault } service: app: controller: enemy-territory ports: udp: port: 27960 protocol: UDP persistence: server-data: existingClaim: enemy-territory globalMounts: - path: /config config: type: configMap name: enemy-territory-config globalMounts: - path: /config/legacy/server.cfg subPath: server.cfg - path: /config/legacy/campaigncycle.cfg subPath: campaigncycle.cfg - path: /config/legacy/lmscycle.cfg subPath: lmscycle.cfg - path: /config/legacy/objectivecycle.cfg subPath: objectivecycle.cfg - path: /config/legacy/mapvotecycle.cfg subPath: mapvotecycle.cfg - path: /config/legacy/mapvoteplayerscount.cfg subPath: mapvoteplayerscount.cfg - path: /etlegacy/legacy/omni-bot/et/user/omni-bot.cfg subPath: omni-bot.cfg secret-config: type: secret name: enemy-territory-server-config globalMounts: - path: /config/legacy/hs_etpub.cfg subPath: hs_etpub.cfg ================================================ FILE: kubernetes/apps/base/game-servers/enemy-territory/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - configmap.yaml - secret.enc.age.yaml - pvc.yaml - udproute.yaml ================================================ FILE: kubernetes/apps/base/game-servers/enemy-territory/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: enemy-territory namespace: game-servers spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 10Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/game-servers/enemy-territory/app/secret.enc.age.yaml ================================================ apiVersion: v1 kind: Secret metadata: name: enemy-territory-server-config namespace: game-servers type: Opaque stringData: hs_etpub.cfg: ENC[AES256_GCM,data:cLUD9B2X1rIVs5MpWeLf4ljv3qfzxlWMRHR6Tgs0wxAZyfbf3CgSDJWrmN8Yb9kBGYXOboS+HR71m3/Qxn23SCDfgEZyA5FqEAUZ9BOJ5Z/XlFy2Ayp6oplspq07ao68etHx6Zp4Ls1B3o4SStFB+u9vNt3CNKaXkeQgpAcFJFcGWzoAbkIWoeUJB5amJ3BOLqm/306+7Vcre3LIJwN0Egz5S0U0FZc9ObDFiGQsAMpSlyqROhCtTRfMWF7cFJpE9SqsGjVoFw0aeY2wGGM7wTW+iNqzwtGXXNi13/GTlowuXA8yJVdkUJPToo37vEBWwWWA6aBYktm+/2YCa3vebdsk/+JJtt/HMU27F8GkjLOKSHDMg909YABmXiF/rpTKaSSmoSILuK3g5POmWEkXI8kljQmBTOxGMGNRU1stcR1yvAJwUFgxptZ4Gn6MP6yEuxce51/MwHnXzacuzBDD/qW3dkb1Q3jVMfa9Zg1FrXcXv3sogqWb1h0Z1M6wMCY+G+BknMkQ5lynw7ehjLHnnCLN/9axZM37RAQmqJbpfdaGQekp5k/W1uoWNc8Xln16gzZaohfjOhEmsKrrohfknXfHAvOoQfVTKTOGRz1K3EA82hESG5NR2FEIraelhd9P+IkwYaFjFY6nnG6zJDotVpXxiXirbsRWAzVKcp610zFuws4j0C8dnAqXdlfnw2w4hoo9zv2EXkaRAfe2s4mKtcOhzaQ9iOVzympN50WiTvShaMF1oE6f0tppu8nErvB1MWEeIBFdD3SK10J8Vbau65c1XR3032nybDQw+4ffTm2fC/YV1GkbnSU0mMjjwtNcnQn8ly+u708vdNk6oFOkfLOMDFWS4NpSHlWltgrAQ3rn0bKJPM0cETIPsftH438ALHg2DJ7LhWWZIT8opt1ar+wC8z+y8J9nd6CI5/5xQ5twJe6+XA/46uvv6x5fVJuS8niEj1Ww2Fl/nhJxg5+rGcDvoHQEe3mP0MuehiC3UofJ/Ugwmt2AAk6HQHy7EFL4M27IxJGv+wQabs+Cl4VkZEbp/+7iCi4dhI8WYzosN4t0XnUSuno1HnW8nK5rWCKDvS7r20CVv28SL9Mi8R5vkXw/0quzBYLpVP9tzPV/3S+Zb5jakvWZVP452vik/XBPAua/99pZugvW7fKirdOhhrz4Ewy8xSlQfn78Mj58pHJ1ScMnQW8cwrO5c3XbZwaqa5Lu6XejHsSsP+Qv6dqjAsh5hn0cRlJnMJSaX845W0+XN21DHzsO+Z4VlTH5ytbXrgk1JpEjAypzSk9YvQgzV8p1XHO3qPrXXGokRH2XeeixGncqqctM0axJqLg5Ed/mD1XcjUlfi5pSfM+qYgVix56GIh5VLyah5MalwVs7WQc6f79R88Kjt0kCPgJKPpm5Bgp7Xhso8CzXbIwM79EuTkQBuQMkRbsRBzDnsuQNUMlyiAWB/tmY90NFKqo+hM4L0ruHiXmMJ2cjqpWrGw7UPzyWqHS/P0j5piQSebalk+3SWRCqV5lbkxgY/EweZfvylFd1KxCCgW2q0j16dfEfNHFY9xOqL8y3WH3OcM5ATnhfBr7nzPpht2YNBeZmSIsUD+A/FBjooakl4uT0Ko4MJGfeGD7wZWTMlmIEeJOmpaf947qcFQooey/atOJu46vjhsmhyiXSI29cfjZhb5bBR09eQL0K/tXFpRi6OJuKrSg8ruTGINdZhyYBH9LnD7cXBDVxcXTJAIRPU1qn4tcGiKqeYkFm5qmNeSRoMzMi+SnJzfnmee6svfLwTn190UdxYt7lnHFgAQH/sbcejzsKHl9aORZdkOUL+lr+UwUIiZjJ9ectwqT70LmymDNno32ZmrnYspOpVCJZSMaodXGNNuVyhopH9F7kN/3tGFBs12Y9Nt3FK1Jgs6VAfnXXt3uiE3WlrVExq/359GR30B+G7bDHNcc2eMZNDrnEGrk+KBKod1OjpvQnliPxXzCg9lLWm7tyTQJyhPYY5YAzs5XKRr5oQVhbufdObiQfm1FmOpJ9YlNbaDoDsZEUQ3vg0WjN7dTK36fFcO5mqjstAcvbIMIGeiZ823r/HRMvMFrVY3N/r+O/VUZXGNetfAJ3Emdu2MISiKGWXq5I/F1j8niUxfEGPNtj9JqkRoBHeb1fKHTWIf2QaWItcIxL/NZsAkTLu9STadAZ/N5j+hkwnGMOl/QTKzvTvuOYx6+Tyw2IzfHSJsE05WMXstn+XD+P3Z3TDNCtIhqhXEUZ8gMiYvu9btCenJEzmxbHrMAlQyDlJqi5g5kIG2G6DYS2ow+dr348ZOcy/ydi9dfEiv0wZ+T2JPSXq8tPW+jXQXT1YDJh1WZJDMPGC8SjjvtHmbkJWR7SZ+JVUAbfNT7GUUlYGu08pTk9t1iLmd+qjxr2qNWYIB6SNTgez3zE6YlvbwRdsM4IKeo/LrnebdL/+EKEmYDa5jx5jFkDjrUluqK96yMFLRAa8EeJMy3eJWin833K4GOnDi/Uhq8rBT2URLUTEHphkRdSZ6uKCzyEK5gjRUDdL5xkbgOeshqxzWdlLpyn0AbtBGpgp/lOheNVDFLFtn47suv7LNzmjTnxtktZL3aSZQXfNusEU/dAAG35L9ko7WJJSHh7PpLfB6GODTLEzNTui1NAzdjChsXA/qeOFw18R76LNAjwrjVVyqvlbemqUo/ndL1b2pr0TCC/dQZBXf3WTumcr9hYaA+HQPaXerb+Jkwdly7T3D6hMa1LbzyCrJy8QFL5cGoky0CxY8yh/v1rZl3Al5wt13lVjujI7+k5nXNdJ3S08vFS+YZmM8fISV2Paxd5adAPgQ6QJCy8XvvB4/pibtiKWxRy7Uw+idz3QwNwCn+P5m1z/mYeKHC40G1XK+YhV9X4QdkZmxprwIwXDzcX/HYsfnbOS/1XgXkMG8iPy4XtB+LnKCQuBD0D7u5bQMAVDs3A6LF5Up7th6IuZam6iKEUTBOLXbFQhw6b28y8AdAWd2Az47oVC0bOhqbseTyfrx6StbQZjPeJJWZX5JP8FJLW3b1e/ZFu62XK4eHD4Yaio+5QRLZlJqmScn8Eh6LsWNlgkTDWm3AZdkwSoPAKKAGKjVE1HTtVHCJXmnw5qScrF8S+y1miNdqCmQorvOU+mGHcd4b6pkhH9SQc5NYgryUiUDbZxBhoES10dTW7TrTcgHcF68+EnP5nGJv8wTho90eUbS+K7bHc3p93WlWnGit8HPXt41X7nmG8A/ak3KKm+7J2EPkmyj0H8Of8BM1Ktnl6yk9r52x6eg5V0EHJea4gdnlGfJ5S6Qa4nh5UnQ1JGxtHfzf/jLEDqUPn6fhzpSFWTYjFgpSCHlINHZSApqPIXxGRnHVJq4lEtiDRK3IWM5FkzNoZrT8b4qT5H1qOsP3pD5i6GzlY3hY5vU90OQXKqglVMTQqB9gxwch6ZxyOkilrD8JFkr6pDNb2+LCjWB23IoMn2raAF+bwKAUfTvdaFHxssxu0EaycB5s4X21ym2RRN/9NM1B+ZrIIQRNmSpnC5sc5lLGLb1YVuqtWkVEWzqd7ElMYY2R9gOIFtePa7Eb8P/YL77ffQ7wTaDYBLdV86HyZClZVLQ3x9hzdHA2dwXTkvbnOZcF7IhQ+c/ZnMh4X7/0RfA9HG6qZn8GdZqapQCUSMzWIbBzDnOR9X5FqwLhSuZqFBoxGxPNXR6B7diojuXuW1CgL+nYUHHUOHQ/yulewYxQjf0LS937q+3QN5YkZUPPtnzcrJRCwjCUW13ZUHCY2//8keHM695LWkzhw2ALqnseaq15tj0/3kOx4dMUFv9nccZzvwnRc4Yn6M2RwG9e3IZj19C/q8tOeep/yDXjD+/kgh4o1sc/eX1YrDvv/DTVTvfjXjJXl2NnoIvC8qdTSaLAxg2nZBHhKUy7UxnPD7wW9/g7Q9/jDWBcvBtgqVHWCEn9/oJs8DtFxNUCVa87QX+Pf8F4t58xCDNuSsee31vfSSYW47evbumta2lg3QVAFUfVWYB0Xd0XIXUZrhdP7ebAlAPQdt6TcgIK5rbClirWy/Dnyfhrm0tKacM/b53NYjMMIjiccATZtRPLGzuKIY2ZU+LoSAshsFHe5Cdys2ZadI6fz00FRx+Cht+l2i7RcnBU8aLyM9TDc2zJS7azpwYPFi9nONNv167dNffg00ZVY0sLIK3yuUtDBBZmtYO12BsDh6E+4Say8YcFCT7xKIlFIFPqUGHpIvHV8QW98bf02OqnWZbgdgb+McVyNcORHQW1HKwgJfzV7ueXZhzCYOgFFJsEy7g0i57FlO6AFMMqM7zjLH7hoUFbPh2mlJfQQXfwSavYKGLtQMAIbbaoHWGY8LDK2qLODdpySA4j0B+vw8OgKJdOAHoMKoYV59bX2DfLZwlWj420dGyVBZcp1ObGpiYJtPO3AJfayZXeiDHgy91qg8D5pHTWPWjNvL9DvAUb5bJZYSSm8qlyAC+eaG+RbnDzHMZbjIAPcbyJXEvuAZnzfcLmDmZTWLeTuAOQhUzZgJoSQ3c04dW77OE62pdH6URiuEWjAajvxnH4UcLtTikfZE7SxWpYxInvnqvDUEhfbVY/SNmW6b9YyoJKCw7bq+QpFwFBnrWa5sJumENmGqvMnGpYc+B0KrmkDzur0gJzW5RbqPsU1RMHKBH6O5pq3Z5O7MY+sX5emW5LG9pOYFiaCnrtvmjTW+kBOBT4JT/4ocCrapbdijcEJqSLx9hQVcovLLC+IMtizb8bosipW4+tXL2giKYILcW/PdG0J5MfGGIJ7LcTx1cgmH1UmI4A1EDFj7Vuq4oQm04NnYayGH4jJ1YE681VRaKmIf1/GCcbmRBOE7bbPUCNonQRx6hvZIpcl24b2pDwPkociNYCNHfn9zw+F3NUqu02r1RK4re3fSyQn/dOENgsltr8nj/6uv5d1HynJidUYZNb1/jOH4bXGOLqIp2Xr3Dhmpe267tvttgyBAMhYW06tmchumahSMqLCCI7Bq4b2oAwrxX+QjKD9UO2zI00sbYkhViokAHQW5V7OxYQIUMQ5+XzTxUaw06BxH3zzvfOA5WPRRj7euHurEoy4fdndr0NdHRwdNalpBn6jM8LBYAV0x5YrAVypCNE9iP45bPK4BLPolf8lGk1mGtK6BVMrp/yKKhQE3Kf6UYD+nRHJtxzyONYdvDmr2UKKg2A45rIl2gv/jaf5hVMTTLYwxnsmlQeK90Tni5Q7yoZ5/X3jUM03XTxZNnZO1tm2mnxtI3VksIX1xd9lIalYG+XYkUV6t0FxGhm2oq1e1uuTsrz5GfkbH+kqG/e8yQp91kSX49RCw7Jh5A8AnvMOSnybhvpYWVRQF5BEprG8e8Hj15A9Tkkl2AeW82OWfzA3OW43UToY4N199e/CkLtI0eLr302CMq8RR9c4AXSfN8ycWwbIer4yLPFhjenAPx65zOJChJPdr8NJ5/cdqp1WMmf9SFDP0Pk/S7DHXjAwn9M9t34wFG8rSZWTeasietNubrRdsczXqYFbkjrSkTa87Kmarbv2ycGyPEmd7mb0kuXmUETX/Zw0c12b68POmPPGYeV9G5bWy77Ila1xu78ZOGG8HfjTywEvpSogZC6zxV1lIcR58Exr7ZQ7j4ysN4fdB52p4CwcSMkT0i1/evdZlaBr0EnJ5JNX1Avhuy6HX67e2HuBitvadWP5Zyy6qkXtb/AmIc35wDjr1Ri5+8foRdBwOSUTkgoLZdpYIiTebTAjCudNDyEVqqnsQt5be0OOixpts6RZSkIUhvR6GypYecT6iVtsEq/o4eY5S0NmhOqiCl2fKTToWvY1OG04I84rRto0jIR90MvuJrHmcPocURBQeoQ8t5H6838lpNcx8zaVvatuk82xdqiEYrF/wC2CkL0vw5ACezI30D3KEFUMufdVFQsQ8AUy3Z2WqtCvB/ntPJm9rcF2IS1rMn5KEc/G+fc3MAUkKp3r10bsGFfI9qbmfZcUpOoTKd9h4P+npgVpu20LK6j6ApCimbrZYe1mXfD54dzONNcwBoiw0/yKtgWYAkpAua09o8V7le50z0XCqNgkX4sOxz2ecsGr1OpXhGryEoImB+A8zYzALlgSPUVbjyk82GuhXuCDbYpeUumOe3Ajs8XS6xtmtSF2IxopARvPXTv49Wk3yQYU6sACfJqqmOkELN/RksP64v/mHbtSr/5WtICZrzk5+aURrBqyqe/zFx5uQpeZby7cTHU4IYpziYuNmBoTqzPg71zKsm/6BO8hjqQ9JwQbiJpXIduJuc1+Ul2Q+YzX6y9s1lSDyhG0CTxj4kZi+5GHR9Dyntdkh8jVNb6kez6xa7XqEH2ijcu1DNJ2sWWtihyeOhu9oKlC6tOl2aMJc4bOnhoPHwcFjsPn0eEPTv1dc4gEB+xXFc8uJLjofvY5b9OF9px9JvcB3HoogL/aZ3Wi77M5TbKSR3/d+IbGgLPgXg7nrNvCNnZmW0sWJF26XxIoqTEA41Skk4F5czIiGPXtUMnrbYIAY6kGrRvpEac6/asYCPA1FZ24hyBtSXv0cqfzjz7H0yhxpBsN+Fh9si+Z/WAiW5NlTQdu2+pFw9rGvNHmFNUyNmjJVg5FXwJiVBx4Hfh8pdC6Srp/QGRFoU43OOFh6K6iLDlFz1RbFQ/4up32Rzti0jM6LphhWzK7XHhbriMH5Tt76h0AkQ+zYFseXJ6WspGwrqODqRSnYt4fLiEpIp3Rxm4IeYvsj9JEwhXgJtr5CmplX40T+B7Sq9IffY7ezCNQNvsQn7Yh+hVbvvg7QcLyOAT8TgGmSxL5OQ9pFmWNeImgI6Wu0S0YcXm1SMYJxn5TsMN6LKrzSpQPfMg0czZCTxdqnn7+xbzU8zomrIXNdkmh6tPRSNbmAbQEVYiUfoFzsh6oyuXnLZWtraEy2CKCcq6V9JGSKJTAIeHns5opPft2H61Sk6dKA+hHZeOkhnrr2vCGIMgk6CpJDBq9tJHfkbnw0KY00v5dWWkrG+Tb1ju9lFppwsyWXHOC0SrmcqOdALQytb0UR+8Mm24ZxVbmJdLK6nSLCOc3t5sZa0QTRmmWc7d+1gDphsTLJ5KLYQwVp6rMHpTNsWDl/Pwzw0p9kibtZSKx7U7URbXwqZqJPjTJsiuiinj8VfZkjNtJvqskCRXAbGDnRYZSbVYcWjOcNUgEHi+WgkpB9Ra4krjfghQDCEwSRnqrVQ8wcHGoA/vNyebm4AKyTp49anvuhbw+wMmUJVI7CVb6YPw0N8VCKV6jbpjE/uo7vmdSVkNu1LlAhY1hK+dhCUx2U8bDAjeKpXAqBvJu83B51kLK3n62OA4juBUJU1axF7YXk1DYYkO15gJQ+At+oCWR4dY9tBNfStffe1xwiiGFfMQQLKgJCQyscIe9k+rAqpuT87QH8zBLdnM4A+n4vbQhPKzBeylasI7YL7GMXQ22/qDR38J570J715B+lPED66z8yIEJQXzZEBh3z7EuN19cI77yC0fjPUQ1iu7+/7F239BA0zNYlFw5vW5FWLIMpK5hAnbYk75SfsW3NNaZeult6w1/YCCtV0I1iwFzbORLyGOOQDA2gDkRTFcThniD683mjFDDQkkA3LQyKKrbPFV84gT0tA2FtV1cm0HklQbR9JfDjYwBocmb09syFWX+BOvlnqF2id4L7RalBeRZ1j8k18OpKnWJb4F637xI/uc9CjNcPjMYTHuwcqLXuHyGlUnAULPwIKetIYRMnnzpNALn1cAACCghdN/M7mVOee55jRcs0GykrDqmjnKLVskCpBS9+/i3GH+5f4TxXLH+RschaVJuP7DnovWAyVtnBk3vhTxgiT1oEZ5hMNAwd4vajLh5SSWFpenzV/rcCWeAG51OZgZ49galLqLHSeR85ZkRqgkxit3uXAxIYRUl5cg9Lo6kepkrc1gOrv/DRWmDkcxqJCnqNsTUsw8MtfNMjdPG3n1KItGjjVSgGMAuXjq4WOSjXS8WxH3mQwSugNeYDpFMdEvTekmHljUXuBV/KisKq29UftzzOShJHAnCH1fVYJG1BT7JUiftICfhYRbHD00sNRqI/7wVwdgBo+HnF2eeUHtakVmp12PkrGDnMl3fCLoNO/IemSV/+SjJ0UU9QomTPWEzU0MTFyHknda/5jQ8jCfGBm2J0bdA53XwkWwMI3SEDFvu1OpMO33FX4hGATdaUfQ3W5Ubizgo1A0/T+00ss7JaDTkgG7u2luFAohWCVEG/MS4G9JvEicOFrqQn6ivwHQJ3ONmLvfDBjw7xUI/AnzM4zG3uJWhpyOIQ4Ad/hnBpW/EB98AQ+oheK4dSbH/a/XNU9rVAyxlZ4pf/ZD+a/OOtqImfUVtBUL3oFYtamgWaSUreJUU727BN7NMTj4aTB/3g66iI5ixp3sj2aCnSOoNy8yusMmKva+jd3ozxUXMjyTfQvyRHCoJke5Mrj273sDmwQzmEl5ztJqLUfaBVMII1IzrElabxCGlrAgdHTuTvl6iKp65L13ajdeH8ETRKTU1V7YX/mqZoDDiIdOcFcsbpB11qOckeEp3aKJ6AKkmvm+r18hNMcAGdlkfGhqoehA3n6T0qR5R2R6MjRrSE4Z0wp31d7lVWngXZgLlSe3g7YKHNq2XOVjm+3IERrhpiEUbgWi+CpTScEOSnMVmr/x8dbPILUP9yBCCV/c+/CS+DqnEjZXSxgdFlcxYoAmofdDoHi583OKl0RzQhPyRapA5RvqQZduiZP20JkKsqf6UZuUGW1dC6qXXFusz6zEtUCVK44ZhU8UtugevL/UuKdcdVLIfqzp0iqKnlRHgv/EVr2tX85Daol3oXnZCI6Hnp6Ij4fyVZgeiWWUBIaEKdlRv3uoy6f1zZq78s9mV+HN+/wsnUbxFN4ghqb543A6cHTolMZxHTZcA6sC3+2zY0p8dbKezRfNDfJjjQaCxMT5ZV/4uDLlkjxJcIQtE3CZcz+++tAOMoknCdUwRKtmTvqP2DMayzH2H8Ad2o1c1uUdOF/4d2g9LsEyYp3IfpG5fzvfzLBK8KqRZyaDu3BdjGYnhfdh4niJiDXgO7e7oggG2+vK9tV0jZsfTU6Jcoci8ODZPm/+oXeyb1EL9SX2DGOMaBRzPoagkZg3mDY18+t0atYhComOd92gEZjTX3NACSGRAUeJns35hYvIIeIjTN/Xl9lfTTR44VliKb2rD4aDuFbAx1v3bMd6HyDjcDhM1rJqYhjjOHGnKtkmhrAhw05WFHmTCHBSVDNoSAz5AiHsHPVXaHYLkkl/PUJjbpfwyF66uVk8x0xHuhVd8t33cshOQLbYYpCSlUYkINPSOv4p2fjblw8vCox2PmWGYML/ktzO1peqnIqb5zKAP1yXHFN/IupaxHNIx0kOIXku2elEJfSHylm6SDbU6VE5cmakFX+dgFVtrgjmzQWkeeN4mT2ng0YKw63ahYqtZjGvixeqOs0ASX56U3r78LXNA18iicBc5cR+Fxzbs3UJrF5XFEW3zhEU84znCVH9Z2+S1reH/FkWfg+rx7R5TUgIG2s43pc3JVAfhVlnX3c6W/b7ByU/3ZfMFCVMbjbeeJKX7P6tJ8ofQJJmPj4P9e3suayfsQm8m6bKysRChgnAXb0VMd6KDE/kE7ai6OVCHZGInvyds2mVdhZU+zZliqLCCCZRlRMkwH/f854OhZNnV5EyqBH7TtHuSUQBFXZmC/bVtT6qRvaxtO3Wap+v+XMZX9Zyn/oxcaLzP7XVc/5n9X3cMQha7guWWEUAOVPFBKxXHMH2LxmIuHJkWJWMb/zEeGF8UbzpfntF2hCv3pqBZt9thZsqtxt5cxkONfjBa+Fpa5zabqvMlsl1fMTWia61IyjKH2onIZh78WVwaBC+HYf1bKSC2HQCI4U44XFKb/ovjWyW9JWeLVvWrlTR1PuIblCUw72sRzkvRohKQtBqTXDqeZNoM+5aYRZ6x43s+YS7tKrNQ5UIc23vf8Kkl8YEKtlYsjuMyIkGWKV5JkOze4hHt51D0U74HWjk21D8DWADxIoNOEBynlrpwRIT8xOIG7XV2qTKoo8cfiYxvxGoJtHRsOOVdIsBsKsGENUOqiDVGr+4WhZ0kpYsaY29tcQF9/HAFBcyTdlHwGmUKoixHb56Id4tfa+hV/2Gk10lk5UesfEV/I4pZv7CxuJoTuMVHgnkiIbZGRs97HQKcLLgqymgVaZVeufcm+mbK782uq9+cqGCvYECbbE+YIeJqp7TXNvhebY68veIy1mMhFBk9vH9F3JlxO0GyfMKd5k1HQukuYUNV5qigNQ5Q/iRmwZrmQMUIxHmy1SsWSKqCDQDi/sU3UAvIZNM/cDARPgcPeXhspOCccorub7YFnq8M24o1EaO6Uo+jey6r2boQKHN0DYgOaHhJYJcqjD8lhcCpQbNIqcY/LjbA50ENutckKE4ZJkzv3UQ99gJ5C1PM4yZ0FN+nJny9uGjpHkkbvNulapfMT3b+o2JTuUtK7NTni/2qItoouqcXtP+9n+ZYW1hR1BuZhfKTX0eMnsZsHY/Dc/auKHE9jSSnVrQ2XeRahvGjrdyPFd7GihPseju1+PeZA02mn3H2k/GHExrKm8SOR48hq1hUWLel5ogdcsyZB6IkYOX7BI6ZBzyma15meh8Qa5HbD8IhYeqgFdyILBEHYJ6iUpoWlyX3+n79f8WgDSWrZxwU2uuThSzRG6HnOMEA459dnwkohZmeoeAHMWc8i7i3nCQ5hvcBvl2faoaVIrdvvqL+PRIjXcBmEBOFA2F45tZ/23wktIXo+oD6dGYQRr1ipZf8VAXg5bzynWZtfUYuE+6cwoVtb8K4etuhmUt4N3OdoZaBvKvYm9Y1wz+xYCPAksLspPhSsY9k1bmnbNqa3hylUjtzxdAlQFtQjJwywQGIPQedzWIu742Y5qs3IaxincZt2Zm44Rk9c//BBY6gnSAmTPN16iauAj2STS8YFrTNYm0k7gSJY2Ws1vLwLnDVlD29aW90GBFUz2O7Oidp+yKraAg09tSV2AbVqeI8cJjMr0QRnKjCvk51GjD+dmg+hUyI61GD/+JuakOlAa5oaA8/drUvvp3NLsp4YUKoSDPQiU0Guom+JasT0wLADkHwjNTSolBvY6JbenPA08w0AIXwhnVgqx59kv7I4l2bjSQKKYN1B2TMEzYl3IJiv38rDeTfrHx2p7so9gvyBxyCTVxOLmQyDGSslzjUtmNReLbu6aAWlyajY9GyuWBCL4QAMZc8KElmy6j95ao7AKW3y1nP+IlIvRa9mc+/G1LkiszwpUXhgTLLu3t+YCpwblhvfSi2/dokeuAlWUl9sYXwmNoxFmwgp5kfTu+sDeXkwJeu52h4JtTanfESCP2YAbTtdhmxt/Ddag3kmJZsP018+qDpO5+usyhI9ZxagtJl5Mc/6ku0vZucvAIrmEAXiZWjZUqNWwtWSqLZT7fcxJ4TgNf5D+8xCd2+b3uJSlv0nTO/AOWeQ6dBIkBkuXOy94ygNt4Go0BE+A3mU/i5WlmEooY5+ONnJXikM4FPSeF/gP0/9mTfwj65C9oI3Hs+FuyGadpWFgxULJqe8J9AtQbzPWpf0H2GmxescMwln1Rx0x7RULWHxAjBE5a7U2oN6nFfyso+HA//6SJs5Alu0H3wZwZdqo1u+GeDHWp/KKrddDQOY1SfY8JTn8fl/k9mX56i56RY17ndQOL9DLYBpu/hlLTjxHDfs3nuExTdetamanseJ2cUvdfuu3hLUZyvjE5ImhWKwz25pEQ/k+c+sPZEPc0Il5EqxVCmphWJsYftNJQQxwWjUVpChAbwJLxEfvyUyS+U3c+weTbmDzwVcygRdx1z5vqBo1552/MY0WkbQdmvIiJVIyJq7CTnozr5CKC1v57prpxdFyjdccsmb/23MChdWMD0KiVAbx2VwZ+yme6gxI36sj7WlSZH0+RvDDH5uK5xRYp0k5n+UI3d6x/rBOiQQibByuzVX+B2uy/BeUMlGa8JsU+LJ97KgVy67Zq7VdEcbwcMbhUg4x3onnr5Jpbk0d8mLXhiWu8ouTGMfiLSh8goPQynKejuSDR/uttsSkeovzYTd+dy7Lh1EM9lpQp9R4DQmN5p0ljTJj1i42+aP4jnJO3u/HD7TODo3/ZM7Pcm3sUzLPEveGCj/09Smj8qMWkARgl4h4yBDReb5qtNFPcWuIYCf3Hum6tHHeTehlPFHFqfB7HxjjRVwYAjRejumi5BXF/+xgn9K4tkmP5IFzzWQu3zwPqWdXbWw0crrQ+0JUW1iIOgYpMVtck/Q26lxJXpkQx2cV/ph0gop6RFDAfG0EsFpqoiMuMF+PmdE6eUOC9lVMLtjv6y54e8YMbWUI0Jo0BQLfLf7QBqWcwNHxy3vkWU6mSfDAh3LnLjREAmnMgAYzRT/pWUdJHWn5ndaPKC1IX0VMfZ0eb2Sm+lnDJta6YNFnZaEVTmQVV5oJArqrJ2GHNSzPLjNCQQ0m62pGCEH/8oeJXxoltGjnTHlNR8zHX4uwpsoKoAzxblHvy5s0N57h0yksF/Tl4q1mJr3L047tWW1R4B1sxAO7lEB1l+xDq//C/D46MI64i6jwYOfh1CIIAh5pTV+k9TVOuH3xcJWn2Lf+wfiO0rlTHxRr7DKd1cT0dPuvf5P48K0VkH+qPXvIAsniA2FastwvbaCuAICi0m/JWo2wewbchbARMaVYQqB+mHGU2d3VoW8svX6wmWClWoSo1WfngB3BR6/imyGf/u6cnf9YKbacl6+adOetJY5QdkmF1kQIXgeOyleI6L6710dNLCixqHtidG8aL2K7rHHLCcHczBXM8IMu+MCWXPyfUmRc0nEdmabNOI3CYwYzOydDC57XETQt63CYMEyRZTMSaxXBj9qV8vQqAjU1oCVBe2QwSZVw6/pYkmQzNdlRVtpsi5mAtRi6LGOjxe3Nh5+Hh5E76SbkaYq3b5B4/s8s47D6yyzYdIIq3h5rtca/dg9SRGE17YJoiJvUlvRoJkILDuNt6QEZ4Mvx/WmOJnTJ2fjjevGjcg8jTb6uIc/tsZfqoKqs8kubtJLkIuo49P10xSD5cghAky1quRCarm8Cg3Y2emyvAo0vZi6HGQ1q0NwIfyaxTutgoR+7bH/b17skfV3UMDFwjvZ4yYT5CDpW+YPmE4Ia4kpTBNU3GD2Vmijdu/mh/0VUYHUGbBHiE1JvjzfGxT1jnamOES2oOlXIIv+PnyomlKZspl9HhG6zG6Rk4QqtQ8JgR+xgzvxdEejYCjWmhUHFSlGurWP9ZPYdyw7AGAaLjqhjkon5yKLgIz/8SZh83aC/u2C11/CkzVRIjdfRU9tFxdk/QLxZys8Y06luaLMjKHQp6jDEPl2GYWmI1YNAlQRsGjHSQQQWZNHF9hd8Xp0H5q8OA4ZJ/ghLsoRYCbsR/O5l7GjASW6tugSnhATY1C0g0I/V98P957lW1zuRI5fbraNonq7lHkEI9MLwyFAWtyL002UIhCLcYfxiebyD0+GC8gEHETEmZzZkGP5Ii3wRhPVePkuisfHyXO8XMz/HvEGqdmbUqOMpHUdLruRUrXBKiRhYPFQRFVAkVs1jUtHRQCukK52fzGnbXJXoVBdhegpmnpKr7zv3nndKfOqKKAMGIMHhjMhJy2pcCaF51CZEn4lDPm6MEk9D/YaxBdw+nFiKm2AJyjYvceOVjDYI2rG8Jj3ft0CWAcNhP66pzpNLT487CVkpgpPnFW+NVNFBSsZ2/ah5Sf4mo0MP4+zH2LMfESB3QHwFaaplSb0EyHhBDOZR3JotZdHhUv8El05AyAv0SonxEqOaUGq5vZ/Zs5EG+px5yr9qj8oox1yoEMZ17Z5zpf6XyuWDDeaxzUqK3u5Qu500H7uwt93PJ9HuIJ+1+TdRzf85nootKISRPqZd2ozWPNl4Gbzya04F3uWC7zPAGLnqIQQJuTEw+dCfGy+Ro3So2pIpX1J0GlQTEAPmLhfR4zeyE2sOl7ZKhUOQhTEDpFSmZDXDKfS+o56e87LsCTymINUUCSw6co7ysKYmRFQtHpNGy69lXRlQOxryrFK6l1EE+YOnN7TB89gMfSiaFlUDVpWrWx4W4891xcOm1a5B3vjTlQnEJQ3lPPYYX+7nGIZP6/lpjh/AyvuU+DrQxmsGpWDF4pdvUG0mbObfazd6M1DsA1l2PsxL4LP2z3ws5mdNzcBbbQboPYsLvRSSm5HX0zn7tv6w8+CtNU8hu4fxE47d4lEcOMO6x6j6OiMOhhpggJl1ay8e6KX33MNC982XLBD+U3GFBK9YpmFj1ZOwUt/UxrN3yyYcPdEYhY7n3fosKz/mtLB67uYkjqThgQbeiiONPdGiimpqhY1Pd0Z3tu/pHSErgYXRzQNo+bUUIr+EEYfHjsRMWQ9evA2ewi5yQW+Zw52X3cRXTXG6zaGDPCP+hGPNpVXK+FcRh0DS4g9ECVP4457Fyz/xh58WAJnqiOUnfosJPmXQbTxCvl31Kxpe6/PN3236GX/dDQNq02TmzIWd0aeR57tI6WHEBG30w25rHP7iA9ENA/h/ZdAYa9x5pQGQv1RaEexk+fQNDUrG/Uu7YKvHf11Q2m0D8qowzS+g5M/4i6gD4bCUQAsEx5JZkfPJl1lTAP2CoVXCAzqZf2yLwiu7sVrto2AAvoWKBUKRcnznHxnc/dc+nfEXRVXfCGa0g2fqCY382Fv9l9tfvFJrk2qXwh98uVSeo3eLIV1fry/yvOp65dFln5QMCfPw+k+EgiWzdY7PGFHXhTmB75G4mkY8k526ur6rZLuLZzgbPMtzOHYR1cfV+ink/lUazPX801k6ogaqOcuoYYohmNnzZrJi/QMHwm+U8Xwz6SWnyDWsGf7wJGdp3/HDZhFVEWwweMcMN4ZW492RsVxedJ86MLT+wivDcLhRfoH6T23Bu7BX/ZvdsAIfRi/Xeuk95rzqDPJ/Vmq/Py2U+N84RpLm0LnH25H4z1MCY797mKFi8gzLi96CaWg1rJa25TGX590stONDqWQD0CMgwOCQpYlk/QqTlDp12mAOyke04kEV/NKls7grhf369K1XJri1S25qywuaCv5tY0J/sezwmJBoQcSYnoFbutr0cppa91jAtpphbwVkslsIPOqAWcCWCKak8Jc45G2866GD1L5gIKk9kawraDtRqy+Lq51DI7F1s/JAu7l4Ioz/WmUYRmNi8NTIZ3w/7A+VT8r64sJI7+phhz9lFk5NyTyZN1lKFKKT/EA/QhapSN/hKRFoS2c8Pd07weUdM3OWb+kkeFaVycvO10uJFwF+wWiqoIwD3W9bTuRUzxactA7rE4OiIoCrvjdz9dkw+GM4hk7hEVWl2Qps4u0UlPVPA/JODR61lSGWdCSRO0diBtFFEtnU3o7LVIh/mVuco8CaqEfatu2HEEI9OeaBLVtl0/W425pHNQrNMYUpQ1149xMk4LR6miz75xFOJH4/sN+u9eFaGqLR7y5dcx/5UT/V1pg9j34cmZHVgE5zMeRLt2AsntkKsJUdBvcajv7fW5KZdvqJivbGlKlvuipTyruLQVEFGiyHrBaYcjl5xak5wx6ur+xj2jjZTEPh5+ZQaqVcw6RzQAFYvdd/rehE3VE/Uvj0PsLfMjuojp33N2/IWxBQWcw+IAom4UWlF45Psxr3TJ/NXda68VmuzOvUFSWmDeN5hm0Qr1ayCup2M+iLWyWwGzNEpDCpktEg0Bm8wE1rp+1paBHU/YC2UKGEYaNpl4u8jr++ilxziqztZT0c6ChTabzN4feBD/xTl6Wu9S3lHyGDBuyRXww8EwCklySVlb6cjFmOJyplY9GEKYJxkRC7GTd6TpAX7jOE85Nxkzit/E7i8g5AaKo1/qV1rp7a+3k8gPX5TvontAF2tGoo248l4Hjtk+n28twweTyeDgK7NhPnxdVaKIsVY5WYxlecrjODN/rusRO0Irdqldkg5wuKg61oZZlc0e6VbWTA4wNWjctaXzv5WpBTzKugGQdqEIYwUHDFQakWOz9v1PZ9nGoO569ZsbOQWHvXYNRVS6ardQ9QF5kIHCWj2O7RDSZCaMnWopbNGPL7CJuklPglJVD+veZOPkTGk2jgB4ol0VQr/9rPKgHNrFfQHZa/kPIJjyAwI3KqVpgqyoreE19hYxC/N9QWfRa5wyQfvPSWMReRfdNGmUjPn+PaFKYx7KMrDaBImKTL9faWxF11LoZDJ4BV281v+lizcJbgcQOjvVSEfp0UbgHx+Kw3OKqwBPb78z1E2643V+6gXUmb3xYOWE5MDYBpZaj3TlpSqonJj7Id7SgEKF8CEviRnN9ziWiiSSxZOHrQJ1PgoLTXyoQJv9NvSHwzALIEC4qqgxsqj7GJQfeldnzUuv9oNFuqHUmG+WKDfZTt0hik/2vnOKDmglfTKA0NGUpm606gtwclnrBwug02PZbnKTMahxlaNVlIKPHz9rJCVNyfCqwJBgeqjHzkBCA/EHG8Wg/uqfxHgyBOZftD+EBW/iY6CvkhPDs1VPoURMRPzyXgfo+YF53pvTsQE6T/HVAl0f8ciLR0yBMhRoWSCUsduwoO0X2Oq3QKMSuUcY0mm8bQpGuIH9ksFxIG+E32hn/mVIN/eSenPff4A4ZDthNinz0IwAU26OvK4BimwGRH+wuuLuSlYzlw2dLmOp4h70hDUmwiBNJCU0Wtcgp0CEi8uCrgDaP43PlQOVvtYP+rzxmkzJ8WvytTdIbFUq/MpeU/2WJEr7rau6afxI6dRnn/mZVna/ylr2lXzn8g1oTCxbiB4vVmOJt4Y6DW3gIDhkkVo9dDLBBQRJ5olczopsdmAXxlpgfhwSMVkeJHUs2JFX10fS6bDD14wgOrohZYTgIWkI4LDIG8BZNZYabAeaijMlKszqwR/t1ZeKjcZB9azBZ9a1oBb8Wgt9w6UHXrcKtbglYXZysn2IlGXheBRG42WgegLPWvpwEqm+h7gUCbFFQ8L8QAze5J+yG0UGyANXw8Xa9SqcCE85hWvKWC3FSJ2S5582rW9pdhFVegYFlnHRxR+tviLJSeB9aBPsckLCnL0w2iF3ZTFkps1Y1n2f0v/nFaIZfkGrs+BLfiOQSTptb65WZWyKY5SfPJs3FLDPU33ecYaMiRpKcFUa8MyBX9QJpCInTYdeB6TG/xTEe57zWFeLwBlukZ8do1hDLk0330lbo2dFhzrNwN5Ky7pAy1Aru8c6B++YlvjOIahY8Aq3OqxyO8Y23NwSooUqRIc4/ss0u1d5fUVZpwzyz5oMByM5pY/glJyRsVP6pUrCJNASwZoNk3m7Kxrla71C3ZIoMDFPjPwEfnG/RLFTbsjdBNOnGVEH0N1B8/WsO29bdU0EcUhby1taN/um+LIcj5Fn87CWBjly43qtHk5tIYs+QrhUKFv0+5wmvwKRPZVUApM2nTAncQ6/QBj25g3TsQL9wl5GwHSTRuo6LBnqzig29dSZtsgjGpjoxePpoc/MuDIDFte7bO5JGgGx+lL/kF+0q/98IYeBtZefSQaCfPq/p3pXQDiKtFe5Fo5qdSx0bQk3P2W1tWKCljH+3YJwZy7jMjTnukCNbkfdbr4ZvsldGqKu/x8Y+4ePTJCcf5/zIYLZb8wNMd44oGj5m8pfCwF7xQ686+XmJLH5r8M7AH+4fTLtMXNRpWzCnwmm2sDK3LO7CVhHGqRz5RuKte/l0qikW4C9Xz9X7/XRjvVlZbbY7NK/Y3xxmYXv4loRVrla304j0+XHklXCZegLP9KVlg9Ge5dqUZUti0O0Jxr2Balah0c3hv4SAWRX18HY7M64zjTzQkWNk/4DIwztFsxaP+rNhFFx17ra9r0ZEvjQyRl/K7LyZ0G1AeQICTf5DLh+RrnqTybQOUhrfK/M4MERQaoyNQresPk9q7cTdjIEw/24Urp7BHusiAiSxEKrlDHMrpbXuouRGdOoqB6Jv6OpVzyS68N9ZvInIx5KPXlEFPH0RAYhBU2oSY93E3VJqwaOttjrS4H9mxDEhxOKCo8FrdVIV+9MJiShYjj44Prs8UBA4apB77nCu0rJE/ntEiDvYPMscGzA6/BvJhwcJvLlpfTM+WQJKcfqfb27CPYJu1gQC6HEmwBAXHTQm6br3Xv8XlvMDagaKREkWpSZTEx7NzBr8vOkbUeEis+kUz4W45iuUw88Qo9QyEHP/TUp6r7VtpI19//PEKPYhyxb4bc1v04pJ3g1uWfM+HMjXUOrjHypkPaJA1eRVIYgYhrfJOM7BM9oPNa7C0X/8rJyX0bawTOUnNhGyYfArSDLvqcxASSbT44jJu/p4cA1izJs1g+4y/pb/TFpmGXz6f7jRix2Ehd5uxO72z0vcjIs4TMymsuiY0f5uuzmxN4+/oKzNV7PZqv5ExLVgWlO4p9216kZWHm/cNXiaRzGkzu17R1IZrEiu9mFbAQACKpJSJsf4BtoqKLTnxZtTJuix6d/HTAa0kwKyMYDuLQOnpV+Z+YDiswCLEtIfVgFur301Rcj2JRTrlcNKoGU+cuWCnXQCzkHdw3QGT6MotNwTWF/qyKYJmMSXPoSSn2Hyb5yg2HUTTvggD65bQzqYGrkDC/mw1wtLTnuZgUq/uufy9mvhtcIH1trygEEdpKoIawJA0LrzrYXRyUTu+EwHgYwpLMjqBY2RTIP5wZQ8IVxfsOzYPbtMCohTrtx+XsWlvHJUFfYbXJb0EI1Qg73sZmZuPYmMbM0jhkYWcC6TdauWwYAFx4CxmaVoL+9bOHZcVAZypVW4U5Bx9SyFrksWl1BhXUa22k2SljRzuCtEBX/FPqG4nv5IQhoPmyxnj542LqoTfWfqNwHI8NCtpxiIa5W2COFvmo9EixsHxcq+I7jjM+puN+ObmOFKwX1b9f1INKx12+vzKXthwS0l9Z1L4F1Mbc4BNoIwmLKnzhQ7MnQmKds/yUfs2dLG9HdWL9p413jLQenhRlfhg0b1M+kcjbOD4oC5hgvlS9Hr/5+FumKtpgaq2v0WwisIkIfiff3i1OL0hZRWreG+GnFnmKqVQ9GHWUtuKHmSq4/2mQOzwkfKasvsqGHd4UIjMc6lf1dgVEBrQMiSIIw4BFQ3d1BM9Pm/DDZdJOL/Htt2gTAxZfXkYYh+jmHAC+giAz8KUx8XpwcONppihHglOAgh4maqR4+gWISh8mpf1RcQxKuM4BbPfrJeeMbDKjjnqzJOB5fEA==,iv:7ObL15TI4fzVmnXi/cwFs4HLDJ0NH5IIeZnYwdhY8mo=,tag:vKju4lziBmciCyNgTUB6Mw==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4b0xPVTIxajhEa3QrczhM OTFHNG16ZEwrUWVZUVAyR0JxU0tGVVRvNVQ4Cms1dkZjb3l5ZXFRTGhYT1NnaG5w M2dWQi9lTzBGT0F6Q0ptd0dtalZUeGsKLS0tIGk2dDkzYTBXSmdTLzZNSzY5U0o2 cW9EdGFyMGpjQUlZeVlEdVRGM2FxamMKeDR1M86D3WoAVwWkjXVi5V/vTOZpQsZv wfadn8FhNqneQKUshQFw8rR4Jpr+NEBtRBBq2Z3JyASoEMzXql5qpw== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-02-28T11:58:11Z" mac: ENC[AES256_GCM,data:/kMPexoeMlEc2I9mL0MqrogoVfFRmmo1kmxGEfipXENzILsnc33bRpYZYgwB5GqeCkMy82ZUlC1X355G/y8gLAGZTT76Yzi0UFv1/3wDCKWsF0OGKzj5tkGOI/UDdMt4fzgXWKt6pKaFEMZDpplAG1lmg6pacswkDQn6fuS+lBs=,iv:KPzK1F9bImkA5eG2Ff21Senk3Dc3HULaNjaR+71+hvc=,tag:l17JN3ejB2e0+u3cdof0KQ==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.12.1 ================================================ FILE: kubernetes/apps/base/game-servers/enemy-territory/app/udproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/udproute_v1alpha2.json apiVersion: gateway.networking.k8s.io/v1alpha2 kind: UDPRoute metadata: name: enemy-territory spec: parentRefs: - name: envoy-external namespace: network-system sectionName: enemy-territory rules: - backendRefs: - name: enemy-territory port: 27960 ================================================ FILE: kubernetes/apps/base/game-servers/enemy-territory/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: enemy-territory namespace: game-servers spec: path: "./apps/base/game-servers/enemy-territory/app" wait: true dependsOn: - name: rook-ceph-cluster namespace: rook-ceph targetNamespace: game-servers sourceRef: kind: ExternalArtifact name: enemy-territory namespace: flux-system ================================================ FILE: kubernetes/apps/base/game-servers/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: game-servers components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/game-servers/minecraft/app/config/geysermc.yaml ================================================ # -------------------------------- # Geyser Configuration File # # A bridge between Minecraft: Bedrock Edition and Minecraft: Java Edition. # # GitHub: https://github.com/GeyserMC/Geyser # Discord: https://discord.gg/geysermc # Wiki: https://wiki.geysermc.org/ # # NOTICE: See https://wiki.geysermc.org/geyser/setup/ for the setup guide. Many video tutorials are outdated. # In most cases, especially with server hosting providers, further hosting-specific configuration is required. # -------------------------------- bedrock: # The IP address that will listen for connections. # Generally, you should only uncomment and change this if you want to limit what IPs can connect to your server. #address: 0.0.0.0 # The port that will listen for connections port: 19132 # Some hosting services change your Java port everytime you start the server and require the same port to be used for Bedrock. # This option makes the Bedrock port the same as the Java port every time you start the server. # This option is for the plugin version only. clone-remote-port: false # The MOTD that will be broadcasted to Minecraft: Bedrock Edition clients. This is irrelevant if "passthrough-motd" is set to true # If either of these are empty, the respective string will default to "Geyser" motd1: "Geyser" motd2: "Welcome to Minecraft on Kubernetes!" # The Server Name that will be sent to Minecraft: Bedrock Edition clients. This is visible in both the pause menu and the settings menu. server-name: "world" # How much to compress network traffic to the Bedrock client. The higher the number, the more CPU usage used, but # the smaller the bandwidth used. Does not have any effect below -1 or above 9. Set to -1 to disable. compression-level: 6 # The port to broadcast to Bedrock clients with the MOTD that they should use to connect to the server. # DO NOT uncomment and change this unless Geyser runs on a different internal port than the one that is used to connect. # broadcast-port: 19132 # Whether to enable PROXY protocol or not for clients. You DO NOT WANT this feature unless you run UDP reverse proxy # in front of your Geyser instance. enable-proxy-protocol: false # A list of allowed PROXY protocol speaking proxy IP addresses/subnets. Only effective when "enable-proxy-protocol" is enabled, and # should really only be used when you are not able to use a proper firewall (usually true with shared hosting providers etc.). # Keeping this list empty means there is no IP address whitelist. # IP addresses, subnets, and links to plain text files are supported. #proxy-protocol-whitelisted-ips: [ "127.0.0.1", "172.18.0.0/16", "https://example.com/whitelist.txt" ] remote: # The IP address of the remote (Java Edition) server # If it is "auto", for standalone version the remote address will be set to 127.0.0.1, # for plugin versions, it is recommended to keep this as "auto" so Geyser will automatically configure address, port, and auth-type. # Leave as "auto" if floodgate is installed. address: auto # The port of the remote (Java Edition) server # For plugin versions, if address has been set to "auto", the port will also follow the server's listening port. port: 25565 # Authentication type. Can be offline, online, or floodgate (see https://github.com/GeyserMC/Geyser/wiki/Floodgate). # For plugin versions, it's recommended to keep the `address` field to "auto" so Floodgate support is automatically configured. # If Floodgate is installed and `address:` is set to "auto", then "auth-type: floodgate" will automatically be used. auth-type: online # Whether to enable PROXY protocol or not while connecting to the server. # This is useful only when: # 1) Your server supports PROXY protocol (it probably doesn't) # 2) You run Velocity or BungeeCord with the option enabled in the proxy's main config. # IF YOU DON'T KNOW WHAT THIS IS, DON'T TOUCH IT! use-proxy-protocol: false # Forward the hostname that the Bedrock client used to connect over to the Java server # This is designed to be used for forced hosts on proxies forward-hostname: false # Floodgate uses encryption to ensure use from authorised sources. # This should point to the public key generated by Floodgate (BungeeCord, Spigot or Velocity) # You can ignore this when not using Floodgate. # If you're using a plugin version of Floodgate on the same server, the key will automatically be picked up from Floodgate. floodgate-key-file: key.pem # For online mode authentication type only. # Stores a list of Bedrock players that should have their Java Edition account saved after login. # This saves a token that can be reused to authenticate the player later. This does not save emails or passwords, # but you should still be cautious when adding to this list and giving others access to this Geyser instance's files. # Removing a name from this list will delete its cached login information on the next Geyser startup. # The file that tokens will be saved in is in the same folder as this config, named "saved-refresh-tokens.json". saved-user-logins: - ThisExampleUsernameShouldBeLongEnoughToNeverBeAnXboxUsername - ThisOtherExampleUsernameShouldAlsoBeLongEnough # Specify how many seconds to wait while user authorizes Geyser to access their Microsoft account. # User is allowed to disconnect from the server during this period. pending-authentication-timeout: 120 # Bedrock clients can freeze when opening up the command prompt for the first time if given a lot of commands. # Disabling this will prevent command suggestions from being sent and solve freezing for Bedrock clients. command-suggestions: true # The following three options enable "ping passthrough" - the MOTD, player count and/or protocol name gets retrieved from the Java server. # Relay the MOTD from the remote server to Bedrock players. passthrough-motd: true # Relay the player count and max players from the remote server to Bedrock players. passthrough-player-counts: true # Enable LEGACY ping passthrough. There is no need to enable this unless your MOTD or player count does not appear properly. # This option does nothing on standalone. legacy-ping-passthrough: false # How often to ping the remote server, in seconds. Only relevant for standalone or legacy ping passthrough. # Increase if you are getting BrokenPipe errors. ping-passthrough-interval: 3 # Whether to forward player ping to the server. While enabling this will allow Bedrock players to have more accurate # ping, it may also cause players to time out more easily. forward-player-ping: false # Maximum amount of players that can connect. This is only visual at this time and does not actually limit player count. max-players: 100 # If debug messages should be sent through console debug-mode: false # Allow a fake cooldown indicator to be sent. Bedrock players otherwise do not see a cooldown as they still use 1.8 combat. # Please note: if the cooldown is enabled, some users may see a black box during the cooldown sequence, like below: # https://cdn.discordapp.com/attachments/613170125696270357/957075682230419466/Screenshot_from_2022-03-25_20-35-08.png # This can be disabled by going into Bedrock settings under the accessibility tab and setting "Text Background Opacity" to 0 # This setting can be set to "title", "actionbar" or "false" show-cooldown: title # Controls if coordinates are shown to players. show-coordinates: true # Whether Bedrock players are blocked from performing their scaffolding-style bridging. disable-bedrock-scaffolding: false # If set, when a Bedrock player performs any emote, it will swap the offhand and mainhand items, just like the Java Edition keybind # There are three options this can be set to: # disabled - the default/fallback, which doesn't apply this workaround # no-emotes - emotes will NOT be sent to other Bedrock clients and offhand will be swapped. This effectively disables all emotes from being seen. # emotes-and-offhand - emotes will be sent to Bedrock clients and offhand will be swapped emote-offhand-workaround: "disabled" # The default locale if we dont have the one the client requested. Uncomment to not use the default system language. # default-locale: en_us # Specify how many days images will be cached to disk to save downloading them from the internet. # A value of 0 is disabled. (Default: 0) cache-images: 0 # Allows custom skulls to be displayed. Keeping them enabled may cause a performance decrease on older/weaker devices. allow-custom-skulls: true # The maximum number of custom skulls to be displayed per player. Increasing this may decrease performance on weaker devices. # Setting this to -1 will cause all custom skulls to be displayed regardless of distance or number. max-visible-custom-skulls: 128 # The radius in blocks around the player in which custom skulls are displayed. custom-skull-render-distance: 32 # Whether to add any items and blocks which normally does not exist in Bedrock Edition. # This should only need to be disabled if using a proxy that does not use the "transfer packet" style of server switching. # If this is disabled, furnace minecart items will be mapped to hopper minecart items. # Geyser's block, item, and skull mappings systems will also be disabled. # This option requires a restart of Geyser in order to change its setting. add-non-bedrock-items: true # Bedrock prevents building and displaying blocks above Y127 in the Nether. # This config option works around that by changing the Nether dimension ID to the End ID. # The main downside to this is that the entire Nether will have the same red fog rather than having different fog for each biome. above-bedrock-nether-building: false # Force clients to load all resource packs if there are any. # If set to false, it allows the user to connect to the server even if they don't # want to download the resource packs. force-resource-packs: true # Allows Xbox achievements to be unlocked. xbox-achievements-enabled: false # Whether player IP addresses will be logged by the server. log-player-ip-addresses: true # Whether to alert the console and operators that a new Geyser version is available that supports a Bedrock version # that this Geyser version does not support. It's recommended to keep this option enabled, as many Bedrock platforms # auto-update. notify-on-new-bedrock-update: true # Which item to use to mark unavailable slots in a Bedrock player inventory. Examples of this are the 2x2 crafting grid while in creative, # or custom inventory menus with sizes different from the usual 3x9. A barrier block is the default item. unusable-space-block: minecraft:barrier # bStats is a stat tracker that is entirely anonymous and tracks only basic information # about Geyser, such as how many people are online, how many servers are using Geyser, # what OS is being used, etc. You can learn more about bStats here: https://bstats.org/. # https://bstats.org/plugin/server-implementation/GeyserMC metrics: # If metrics should be enabled enabled: true # UUID of server, don't change! uuid: 9df3bf45-81e3-47d4-a334-539311a55da7 # ADVANCED OPTIONS - DO NOT TOUCH UNLESS YOU KNOW WHAT YOU ARE DOING! # Geyser updates the Scoreboard after every Scoreboard packet, but when Geyser tries to handle # a lot of scoreboard packets per second can cause serious lag. # This option allows you to specify after how many Scoreboard packets per seconds # the Scoreboard updates will be limited to four updates per second. scoreboard-packet-threshold: 20 # Allow connections from ProxyPass and Waterdog. # See https://www.spigotmc.org/wiki/firewall-guide/ for assistance - use UDP instead of TCP. enable-proxy-connections: false # The internet supports a maximum MTU of 1492 but could cause issues with packet fragmentation. # 1400 is the default. mtu: 1400 # Whether to connect directly into the Java server without creating a TCP connection. # This should only be disabled if a plugin that interfaces with packets or the network does not work correctly with Geyser. # If enabled on plugin versions, the remote address and port sections are ignored # If disabled on plugin versions, expect performance decrease and latency increase use-direct-connection: true # Whether Geyser should attempt to disable compression for Bedrock players. This should be a benefit as there is no need to compress data # when Java packets aren't being handled over the network. # This requires use-direct-connection to be true. disable-compression: true config-version: 4 ================================================ FILE: kubernetes/apps/base/game-servers/minecraft/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app minecraft namespace: game-servers spec: interval: 5m chart: spec: chart: minecraft version: 5.1.3 sourceRef: kind: HelmRepository name: minecraft-server-charts namespace: flux-system interval: 5m values: fullnameOverride: *app serviceAnnotations: lbipam.cilium.io/ips: ${CLUSTER_LB_MINECRAFT} extraVolumes: - volumeMounts: - name: geyser-config-volume mountPath: /data/plugins/Geyser-Spigot/config.yml subPath: config.yml volumes: - name: geyser-config-volume configMap: name: geysermc-config valuesFrom: - kind: ConfigMap name: minecraft-values - kind: Secret name: minecraft-secret-values ================================================ FILE: kubernetes/apps/base/game-servers/minecraft/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: minecraft-map namespace: game-servers annotations: external-dns.alpha.kubernetes.io/external: 'true' spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'map.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: minecraft port: 8100 weight: 100 ================================================ FILE: kubernetes/apps/base/game-servers/minecraft/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml - tcproute.yaml - pvc.yaml - pvc-ceph.yaml - replicationsource.yaml - volsync-externalsecret.yaml - secret.enc.age.yaml configMapGenerator: - name: minecraft-values namespace: game-servers files: - values.yaml=./values.yaml - name: geysermc-config namespace: game-servers files: - config.yml=./config/geysermc.yaml secretGenerator: - name: minecraft-secret-values namespace: game-servers files: - values.yaml=values.enc.age.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/game-servers/minecraft/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease - kind: ConfigMap version: v1 fieldSpecs: - path: spec/values/extraVolumes/volumes/configMap/name kind: HelmRelease - kind: Secret version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/game-servers/minecraft/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: minecraft-ceph namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: ceph-block --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: geyser-data-ceph namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/game-servers/minecraft/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: minecraft namespace: game-servers spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 5Gi storageClassName: truenas-iscsi-csi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: geyser-data namespace: game-servers spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 1Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/game-servers/minecraft/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: minecraft spec: sourcePVC: minecraft-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: minecraft-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/game-servers/minecraft/app/secret.enc.age.yaml ================================================ apiVersion: v1 kind: Secret metadata: name: minecraft-rcon namespace: game-servers type: Opaque stringData: rcon-password: ENC[AES256_GCM,data:gAYP5VK/26E=,iv:iWNuUfWkT4yKDXzaEanSQMKmr8vv3D2ubhuvfzCeM7k=,tag:ogs1Mzvgh15s3pIzF2RaDQ==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6ZVFOVUcrYkgyTU04QUpx ODVIa3RodFhLdHM2aVVHQWRLWVJjY1d4cjNRCnlLampjSVNiQm9hWXJoY2JVNHN6 UlVEbVAraXN3Yi9ZZVlXWFR6dHVXbFEKLS0tIDlGdThUejVIeS9pZG84bDJUZnpi L21jSjZYQTNPcUxULzRhN0g2NXFWemcKcrv10p3PQrvN4tEH1/gz5M0myy0eDLSj 2Ch+miySQRbW/IYe+bTQVybCsv0CdlCEtNzUc5VzVtcZnWn9tl9Mxw== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-03-04T21:37:14Z" mac: ENC[AES256_GCM,data:rsRoA82BiXT1kgxcFxh+pkklLGj60BdXY1ps3YViOZfsih5QCnQuJ2fsh+xDwtaJQs7x1jzUIXR/GW5TIjyyBI+wdd4eA2sp41nCTMyDd4D+PONvdM4GxVVFim09cDa+43QXwZYwH4h5RvPCipLSLPGY43cl1k187ugbN83dZNc=,iv:34f35VFTSHOucueZW0bZJFQ9ZhDh0rBMnPGTSy8c6Do=,tag:mDDH4GPCGcB1rllhZ3Tkug==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.12.1 ================================================ FILE: kubernetes/apps/base/game-servers/minecraft/app/tcproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/tcproute_v1alpha2.json apiVersion: gateway.networking.k8s.io/v1alpha2 kind: TCPRoute metadata: name: minecraft-java annotations: external-dns.alpha.kubernetes.io/external: 'true' spec: parentRefs: - name: envoy-external namespace: network-system sectionName: minecraft-java rules: - backendRefs: - name: minecraft port: 25565 weight: 100 ================================================ FILE: kubernetes/apps/base/game-servers/minecraft/app/values.enc.age.yaml ================================================ minecraftServer: ops: .Unholy050,Unholy050, sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBDV24xaTJ5UEFFQ2FyeW1V V1dWVnA0bjhjYmFaTE1mTXRnSkhob2JWR0dBCjJPandVYWZJTkQ5UEU4WWJSSTR6 M1hFQW1LWHVKRmw1dFhVWXZOOUNmcnMKLS0tIGQ1akZheUlDQlhkbFF6Y0J4ZVRV aWZBd2hKZC9PTmJTMzdyUmZ6VUVwZ0kKS9hdfLUz5SeCop8Ij1TwsBZRGUflMuBe +cZPabbwZGGeEVKj6mzgH54DFovJJQns5xU6hmZTxzUszEDQtimHzA== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-03-05T02:58:26Z" mac: ENC[AES256_GCM,data:uvVfuCVRWvUEN778j4i+lTE0d9RH9jsLVqsr3gqt7C8NoH32P2ZR0KrPRWrXUihR1bfeKg90rMn2Yb7cG2i4vyBhgOvAdhE/6MxVLfpsC2e5hfZaLR4DKmSvu6+RAj2QwzKoYfPJCFUbiUmf2ulmMWqhLzDh/o7Bs+xSpRljjUc=,iv:JcO90Cf9fGaTnFAa49xDltLLBwNSqfBuBep+JJCcp5g=,tag:Vlzw7Pjr+iztO/D9oY25iw==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.12.1 ================================================ FILE: kubernetes/apps/base/game-servers/minecraft/app/values.yaml ================================================ extraEnv: TZ: "${CLUSTER_TIMEZONE}" # Force IPv4 stack to fix RCON connectivity issues JVM_OPTS: "-Djava.net.preferIPv4Stack=true" minecraftServer: serverName: Wildfire Minecraft Server eula: "TRUE" type: PAPER version: LATEST # REQUIRED: Must use for spigot plugins that are listed as available via external sites pluginUrls: - https://download.geysermc.org/v2/projects/geyser/versions/latest/builds/latest/downloads/spigot - https://download.geysermc.org/v2/projects/floodgate/versions/latest/builds/latest/downloads/spigot spigetResources: - 34315 # Vault modrinth: projects: - multiverse-core - essentialsx - worldguard - worldedit - bluemap - viaversion - viarewind - viabackwards - luckperms downloadDependencies: required allowedVersionType: beta resourcePackUrl: https://download.geysermc.org/v2/projects/geyseroptionalpack/versions/latest/builds/latest/downloads/geyseroptionalpack maxPlayers: 10 maxTickTime: -1 gameMode: survival hardcore: false pvp: false worldSaveName: world onlineMode: true rcon: enabled: true existingSecret: minecraft-rcon secretKey: rcon-password motd: "Welcome to Minecraft on Kubernetes!" playerIdleTimeout: 10 memory: 8192M cheats: true enableLanVisibility: true defaultPermission: operator enableSSH: true serviceType: LoadBalancer extraPorts: - name: geysermc containerPort: 19132 protocol: UDP service: enabled: true embedded: true port: 19132 - name: bluemap containerPort: 8100 protocol: TCP service: enabled: true embedded: true port: 8100 overrideServerProperties: true removeOldMods: true tolerations: - key: "node-role.kubernetes.io/control-plane" operator: "Exists" effect: "NoSchedule" affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: "node-role.kubernetes.io/control-plane" operator: "Exists" resources: requests: memory: 8Gi cpu: 4 persistence: dataDir: enabled: true existingClaim: minecraft-ceph podSecurityContext: runAsUser: 1000 runAsGroup: 1000 runAsNonRoot: true fsGroup: 1000 seccompProfile: type: RuntimeDefault ================================================ FILE: kubernetes/apps/base/game-servers/minecraft/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: minecraft-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: minecraft-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/game-servers/minecraft/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: minecraft namespace: game-servers spec: dependsOn: - name: democratic-csi namespace: democratic-csi - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system path: "./apps/base/game-servers/minecraft/app" wait: true targetNamespace: game-servers sourceRef: kind: ExternalArtifact name: minecraft namespace: flux-system ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app minecraft-bedrock namespace: game-servers spec: interval: 5m chart: spec: chart: minecraft-bedrock version: 2.9.0 sourceRef: kind: HelmRepository name: minecraft-server-charts namespace: flux-system interval: 5m values: fullnameOverride: *app valuesFrom: - kind: ConfigMap name: mincraft-bedrock-values - kind: Secret name: mincraft-bedrock-secret-values postRenderers: # IMPORTANT: Does not work with multus when using hostNetwork: true - kustomize: patches: - target: version: v1 kind: Deployment name: minecraft-bedrock-minecraft-bedrock patch: | - op: add path: /spec/template/spec/hostNetwork value: true ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - pvc.yaml - pvc-ceph.yaml - udproute.yaml - replicationsource.yaml - volsync-externalsecret.yaml configMapGenerator: - name: mincraft-bedrock-values namespace: game-servers files: - values.yaml=./values.yaml secretGenerator: - name: mincraft-bedrock-secret-values namespace: game-servers files: - values.yaml=values.enc.age.yaml generatorOptions: annotations: kustomize.toolkit.fluxcd.io/substitute: disabled configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease - kind: Secret version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: minecraft-bedrock-ceph namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: minecraft-bedrock namespace: game-servers spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 10Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: minecraft-bedrock spec: sourcePVC: minecraft-bedrock-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 2000 fsGroup: 2000 parallelism: 2 repository: minecraft-bedrock-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock/app/udproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/udproute_1alpha2.json apiVersion: gateway.networking.k8s.io/v1alpha2 kind: UDPRoute metadata: name: minecraft-bedrock annotations: external-dns.alpha.kubernetes.io/external: 'true' spec: parentRefs: - name: envoy-external namespace: network-system sectionName: minecraft-bedrock rules: - backendRefs: - name: minecraft port: 19132 weight: 100 ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock/app/values.enc.age.yaml ================================================ minecraftServer: passwordSSH: password enableSSH: true sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQYmVaRDNFY2lNY3N4eGIv dGttVGxaUWVJdk40cnl6NkRucWF6UFl5STFVCjdZUDdjWG5nM3F3Z1ZqVTRtbUN0 N1BCd2Y5WERVa0JnNUc3ekczQVVLTHcKLS0tIHNIUnBZZHVmaW04TitkL2tEVjZE RVQybDREdjZFYjZMR0FjZXEvN3hCR1EKwN+/60aLJRJ1zS4iMOIOIc8rZhgqDVIZ DdmYa9uXhJd8Ejqvh8jgMxaohzQHPV1gnThKRpHFRD8a8yN5IkBDtA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:21:04Z" mac: ENC[AES256_GCM,data:aGJYrzWNfkzXAGabdvN3nHcx6X/7+C9p+hJA0cZoHeDffO3LUneIJmHODAwkGeG3BJkt7g16u8cM/gRIO2Rc5mME7xwokVdz19s4RIIK2fOO7v5dkPTFBNC8EpmRhAQtdMNSMJb8vQoSZujYwutOsWGFv9TdO5aM+Mr2Wb2zluI=,iv:sCxGx8AzReG3EQlQZgOaG03No2tb83YhAuuCJ3lv72o=,tag:CYvm53Hliew+ue04urcFNA==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock/app/values.yaml ================================================ image: repository: itzg/minecraft-bedrock-server tag: latest minecraftServer: serverName: Bedrock Minecraft Server levelName: Wildfire serverPort: 19131 eula: "TRUE" version: LATEST difficulty: peaceful maxPlayers: 10 gameMode: survival playerIdleTimeout: 10 cheats: true enableLanVisibility: true defaultPermission: operator serviceType: LoadBalancer # TODO: Consider disabling if Microsoft login failure occurs; # Check accounts against Minecraft account service. onlineMode: false podAnnotations: k8s.v1.cni.cncf.io/networks: network-system/wifi-network persistence: dataDir: enabled: true existingClaim: minecraft-bedrock-ceph ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: minecraft-bedrock-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: minecraft-bedrock-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: minecraft-bedrock namespace: game-servers spec: dependsOn: - name: democratic-csi namespace: democratic-csi - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system path: "./apps/base/game-servers/minecraft-bedrock/app" wait: true targetNamespace: game-servers sourceRef: kind: ExternalArtifact name: minecraft-bedrock namespace: flux-system ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock-broadcaster/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app minecraft-bedrock-broadcaster namespace: game-servers spec: interval: 5m chart: spec: chart: minecraft-bedrock version: 2.9.0 sourceRef: kind: HelmRepository name: minecraft-server-charts namespace: flux-system interval: 5m values: fullnameOverride: *app valuesFrom: - kind: ConfigMap name: minecraft-bedrock-broadcaster-values - kind: Secret name: minecraft-bedrock-broadcaster-secret-values postRenderers: # IMPORTANT: Does not work with multus when using hostNetwork: true - kustomize: patches: - target: version: v1 kind: Deployment name: minecraft-bedrock-broadcaster-minecraft-bedrock patch: | - op: add path: /spec/template/spec/hostNetwork value: true ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock-broadcaster/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - pvc.yaml - pvc-ceph.yaml - udproute.yaml - replicationsource.yaml - volsync-externalsecret.yaml configMapGenerator: - name: minecraft-bedrock-broadcaster-values namespace: game-servers files: - values.yaml=./values.yaml secretGenerator: - name: minecraft-bedrock-broadcaster-secret-values namespace: game-servers files: - values.yaml=values.enc.age.yaml generatorOptions: annotations: kustomize.toolkit.fluxcd.io/substitute: disabled configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock-broadcaster/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease - kind: Secret version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock-broadcaster/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: minecraft-bedrock-broadcaster-ceph namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock-broadcaster/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: minecraft-bedrock-broadcaster namespace: game-servers spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 10Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock-broadcaster/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: minecraft-bedrock-broadcaster spec: sourcePVC: minecraft-bedrock-broadcaster-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 2000 fsGroup: 2000 parallelism: 2 repository: minecraft-bedrock-broadcaster-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock-broadcaster/app/udproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/udproute_1alpha2.json apiVersion: gateway.networking.k8s.io/v1alpha2 kind: UDPRoute metadata: name: minecraft-bedrock-broadcaster annotations: external-dns.alpha.kubernetes.io/external: 'true' external-dns.alpha.kubernetes.io/hostname: play.bedrockbroadcaster.com spec: parentRefs: - name: envoy-external namespace: network-system sectionName: minecraft-bedrock-broadcaster rules: - backendRefs: - name: minecraft-bedrock-broadcaster port: 19132 weight: 100 ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock-broadcaster/app/values.enc.age.yaml ================================================ minecraftServer: passwordSSH: password enableSSH: true sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQYmVaRDNFY2lNY3N4eGIv dGttVGxaUWVJdk40cnl6NkRucWF6UFl5STFVCjdZUDdjWG5nM3F3Z1ZqVTRtbUN0 N1BCd2Y5WERVa0JnNUc3ekczQVVLTHcKLS0tIHNIUnBZZHVmaW04TitkL2tEVjZE RVQybDREdjZFYjZMR0FjZXEvN3hCR1EKwN+/60aLJRJ1zS4iMOIOIc8rZhgqDVIZ DdmYa9uXhJd8Ejqvh8jgMxaohzQHPV1gnThKRpHFRD8a8yN5IkBDtA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:21:04Z" mac: ENC[AES256_GCM,data:aGJYrzWNfkzXAGabdvN3nHcx6X/7+C9p+hJA0cZoHeDffO3LUneIJmHODAwkGeG3BJkt7g16u8cM/gRIO2Rc5mME7xwokVdz19s4RIIK2fOO7v5dkPTFBNC8EpmRhAQtdMNSMJb8vQoSZujYwutOsWGFv9TdO5aM+Mr2Wb2zluI=,iv:sCxGx8AzReG3EQlQZgOaG03No2tb83YhAuuCJ3lv72o=,tag:CYvm53Hliew+ue04urcFNA==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock-broadcaster/app/values.yaml ================================================ image: repository: itzg/minecraft-bedrock-server tag: latest minecraftServer: serverName: Bedrock Broadcaster Server levelName: Broadcaster serverPort: 19135 eula: "TRUE" version: LATEST difficulty: peaceful maxPlayers: 10 gameMode: survival playerIdleTimeout: 10 cheats: true enableLanVisibility: true defaultPermission: operator serviceType: LoadBalancer # TODO: Consider disabling if Microsoft login failure occurs; # Check accounts against Minecraft account service. onlineMode: false texturepackRequired: true podAnnotations: k8s.v1.cni.cncf.io/networks: network-system/wifi-network persistence: dataDir: enabled: true existingClaim: minecraft-bedrock-broadcaster-ceph ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock-broadcaster/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: minecraft-bedrock-broadcaster-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: minecraft-bedrock-broadcaster-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-bedrock-broadcaster/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: minecraft-bedrock-broadcaster namespace: game-servers spec: dependsOn: - name: democratic-csi namespace: democratic-csi - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system path: "./apps/base/game-servers/minecraft-bedrock-broadcaster/app" wait: true targetNamespace: game-servers sourceRef: kind: ExternalArtifact name: minecraft-bedrock-broadcaster namespace: flux-system ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-pixelmon/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app minecraft-pixelmon namespace: game-servers spec: interval: 5m chart: spec: chart: minecraft-bedrock version: 2.9.0 sourceRef: kind: HelmRepository name: minecraft-server-charts namespace: flux-system interval: 5m values: fullnameOverride: *app valuesFrom: - kind: ConfigMap name: minecraft-pixelmon-values postRenderers: - kustomize: patches: - target: version: v1 kind: Deployment name: minecraft-pixelmon-minecraft-bedrock patch: | - op: add path: /spec/template/spec/hostNetwork value: true ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-pixelmon/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - pvc-ceph.yaml configMapGenerator: - name: minecraft-pixelmon-values namespace: game-servers files: - values.yaml=./values.yaml generatorOptions: annotations: kustomize.toolkit.fluxcd.io/substitute: disabled configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-pixelmon/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-pixelmon/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: minecraft-pixelmon-ceph namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-pixelmon/app/values.yaml ================================================ image: repository: itzg/minecraft-bedrock-server tag: latest minecraftServer: serverName: Wildfire Pixelmon Server levelName: Pixelmon serverPort: 19138 eula: "TRUE" version: LATEST difficulty: normal maxPlayers: 10 gameMode: survival playerIdleTimeout: 10 cheats: true enableLanVisibility: true defaultPermission: operator serviceType: LoadBalancer onlineMode: false texturepackRequired: true extraEnv: SERVER_PORT_V6: "19139" initContainers: - name: install-pokedrock image: alpine:latest securityContext: runAsUser: 0 runAsNonRoot: false command: - /bin/sh - -c - | set -e apk add --no-cache curl unzip jq ADDON_URL="https://edge.forgecdn.net/files/7358/835/SERPpokedrock.mcaddon" DATA_DIR="/data" LEVEL_NAME="Pixelmon" # Skip if already installed if [ -f "$DATA_DIR/.serp-pokedrock-v1.29.1" ]; then echo "SERP Pokedrock v1.29.1 already installed, skipping..." exit 0 fi # Download the addon echo "Downloading SERP Pokedrock addon..." curl -L -o /tmp/addon.mcaddon "$ADDON_URL" # Extract (mcaddon is a renamed zip) echo "Extracting addon..." mkdir -p /tmp/addon unzip -o /tmp/addon.mcaddon -d /tmp/addon # Extract any nested zip/mcpack files within the addon find /tmp/addon -name "*.zip" -o -name "*.mcpack" | while IFS= read -r nested; do echo "Extracting nested archive: $(basename "$nested")" NESTED_DIR="/tmp/addon/$(basename "$nested" | sed 's/\.[^.]*$//')" mkdir -p "$NESTED_DIR" unzip -o "$nested" -d "$NESTED_DIR" rm "$nested" done # Initialize pack activation files echo "[]" > /tmp/bp.json echo "[]" > /tmp/rp.json # Process each manifest.json to find behavior and resource packs find /tmp/addon -name "manifest.json" -type f | while IFS= read -r manifest; do PACK_DIR="$(dirname "$manifest")" PACK_TYPE="$(jq -r '.modules[0].type' "$manifest")" PACK_UUID="$(jq -r '.header.uuid' "$manifest")" PACK_VERSION="$(jq -c '.header.version' "$manifest")" PACK_NAME="$(basename "$PACK_DIR")" echo "Found pack: $PACK_NAME (type: $PACK_TYPE, uuid: $PACK_UUID)" if [ "$PACK_TYPE" = "data" ] || [ "$PACK_TYPE" = "script" ]; then echo "Installing behavior pack: $PACK_NAME" mkdir -p "$DATA_DIR/behavior_packs" cp -r "$PACK_DIR" "$DATA_DIR/behavior_packs/$PACK_NAME" jq --arg uuid "$PACK_UUID" --argjson ver "$PACK_VERSION" \ '. + [{"pack_id": $uuid, "version": $ver}]' /tmp/bp.json > /tmp/bp_new.json mv /tmp/bp_new.json /tmp/bp.json elif [ "$PACK_TYPE" = "resources" ]; then echo "Installing resource pack: $PACK_NAME" mkdir -p "$DATA_DIR/resource_packs" cp -r "$PACK_DIR" "$DATA_DIR/resource_packs/$PACK_NAME" jq --arg uuid "$PACK_UUID" --argjson ver "$PACK_VERSION" \ '. + [{"pack_id": $uuid, "version": $ver}]' /tmp/rp.json > /tmp/rp_new.json mv /tmp/rp_new.json /tmp/rp.json fi done # Activate packs for the world mkdir -p "$DATA_DIR/worlds/$LEVEL_NAME" cp /tmp/bp.json "$DATA_DIR/worlds/$LEVEL_NAME/world_behavior_packs.json" cp /tmp/rp.json "$DATA_DIR/worlds/$LEVEL_NAME/world_resource_packs.json" echo "=== Installed behavior packs ===" cat "$DATA_DIR/worlds/$LEVEL_NAME/world_behavior_packs.json" echo "=== Installed resource packs ===" cat "$DATA_DIR/worlds/$LEVEL_NAME/world_resource_packs.json" # Mark as installed touch "$DATA_DIR/.serp-pokedrock-v1.29.1" echo "SERP Pokedrock addon installation complete!" volumeMounts: - name: datadir mountPath: /data startupProbe: enabled: true failureThreshold: 60 periodSeconds: 10 livenessProbe: initialDelaySeconds: 60 readinessProbe: initialDelaySeconds: 60 persistence: dataDir: enabled: true existingClaim: minecraft-pixelmon-ceph ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-pixelmon/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: minecraft-pixelmon namespace: game-servers spec: dependsOn: - name: democratic-csi namespace: democratic-csi - name: rook-ceph-cluster namespace: rook-ceph path: "./apps/base/game-servers/minecraft-pixelmon/app" wait: true targetNamespace: game-servers sourceRef: kind: ExternalArtifact name: minecraft-pixelmon namespace: flux-system ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-proxy/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app minecraft-proxy namespace: game-servers spec: interval: 5m chart: spec: chart: minecraft-proxy version: 3.10.0 sourceRef: kind: HelmRepository name: minecraft-server-charts namespace: flux-system interval: 5m values: fullnameOverride: *app valuesFrom: - kind: ConfigMap name: mincraft-proxy-values ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-proxy/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: game-servers resources: - helmrelease.yaml configMapGenerator: - name: mincraft-proxy-values namespace: game-servers files: - values.yaml=./values.yaml generatorOptions: annotations: kustomize.toolkit.fluxcd.io/substitute: disabled configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-proxy/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-proxy/app/values.yaml ================================================ minecraftProxy: type: BUNGEECORD onlineMode: true rcon: enabled: true ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-proxy/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: minecraft-proxy namespace: game-servers spec: path: "./apps/base/game-servers/minecraft-proxy/app" wait: true targetNamespace: game-servers sourceRef: kind: ExternalArtifact name: minecraft-proxy namespace: flux-system ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-rcon-web/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app minecraft-rcon-web namespace: game-servers spec: interval: 5m chart: spec: chart: rcon-web-admin version: 1.2.1 sourceRef: kind: HelmRepository name: minecraft-server-charts namespace: flux-system interval: 5m values: fullnameOverride: *app valuesFrom: - kind: ConfigMap name: minecraft-rcon-web-values ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-rcon-web/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: minecraft-rcon namespace: game-servers spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'rcon.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: minecraft-rcon-web port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-rcon-web/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: game-servers resources: - helmrelease.yaml - httproute.yaml configMapGenerator: - name: minecraft-rcon-web-values namespace: game-servers files: - values.yaml=./values.yaml generatorOptions: annotations: kustomize.toolkit.fluxcd.io/substitute: disabled configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-rcon-web/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-rcon-web/app/secret.enc.age.yaml ================================================ apiVersion: v1 kind: Secret metadata: name: minecraft-rcon namespace: game-servers type: Opaque stringData: rcon-password: ENC[AES256_GCM,data:gAYP5VK/26E=,iv:iWNuUfWkT4yKDXzaEanSQMKmr8vv3D2ubhuvfzCeM7k=,tag:ogs1Mzvgh15s3pIzF2RaDQ==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6ZVFOVUcrYkgyTU04QUpx ODVIa3RodFhLdHM2aVVHQWRLWVJjY1d4cjNRCnlLampjSVNiQm9hWXJoY2JVNHN6 UlVEbVAraXN3Yi9ZZVlXWFR6dHVXbFEKLS0tIDlGdThUejVIeS9pZG84bDJUZnpi L21jSjZYQTNPcUxULzRhN0g2NXFWemcKcrv10p3PQrvN4tEH1/gz5M0myy0eDLSj 2Ch+miySQRbW/IYe+bTQVybCsv0CdlCEtNzUc5VzVtcZnWn9tl9Mxw== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-03-04T21:37:14Z" mac: ENC[AES256_GCM,data:rsRoA82BiXT1kgxcFxh+pkklLGj60BdXY1ps3YViOZfsih5QCnQuJ2fsh+xDwtaJQs7x1jzUIXR/GW5TIjyyBI+wdd4eA2sp41nCTMyDd4D+PONvdM4GxVVFim09cDa+43QXwZYwH4h5RvPCipLSLPGY43cl1k187ugbN83dZNc=,iv:34f35VFTSHOucueZW0bZJFQ9ZhDh0rBMnPGTSy8c6Do=,tag:mDDH4GPCGcB1rllhZ3Tkug==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.12.1 ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-rcon-web/app/values.yaml ================================================ # Required: When not using ingress.enabled=true then must use Loadbalancer for deployment spec to render. service: type: LoadBalancer # Required: Hack to avoid the startup scripts from determining the WS IP:PORT. ingress: enabled: true rconWeb: isAdmin: true game: minecraft passwordExistingSecret: minecraft-rcon passwordKey: rcon-password rconHost: minecraft-rcon.game-servers.svc.cluster.local rconPort: 25575 rconPasswordExistingSecret: minecraft-rcon rconPasswordKey: "rcon-password" serverName: "Wildfire Minecraft Server" extraEnv: TZ: ${CLUSTER_TIMEZONE} # Required: Cannot install jq as part of startup script. # securityContext: {} # readOnlyRootFilesystem: false # allowPrivilegeEscalation: true # podSecurityContext: {} # runAsUser: 1000 # runAsGroup: 1000 # runAsNonRoot: true # fsGroup: 1000 # seccompProfile: # type: RuntimeDefault ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-rcon-web/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: minecraft-rcon-web namespace: game-servers spec: dependsOn: - name: minecraft namespace: game-servers path: "./apps/base/game-servers/minecraft-rcon-web/app" wait: true targetNamespace: game-servers sourceRef: kind: ExternalArtifact name: minecraft-rcon-web namespace: flux-system ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-router/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app minecraft-router namespace: game-servers spec: interval: 5m chart: spec: chart: mc-router version: 1.5.0 sourceRef: kind: HelmRepository name: minecraft-server-charts namespace: flux-system interval: 5m values: fullnameOverride: *app valuesFrom: - kind: ConfigMap name: mincraft-router-values ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-router/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: game-servers resources: - helmrelease.yaml configMapGenerator: - name: mincraft-router-values namespace: game-servers files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-router/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-router/app/values.yaml ================================================ services: # Service for Minecraft client connections minecraft: type: LoadBalancer port: 19132 annotations: lbipam.cilium.io/ips: ${CLUSTER_LB_MINECRAFT_ROUTER} minecraftRouter: debug: enabled: true # Default Minecraft server to use when mapping not found defaultServer: host: "minecraft.game-servers.svc.cluster.local" port: 19132 mappings: - externalHostname: "bedrock.${CLUSTER_DOMAIN}" host: "minecraft.game-servers.svc.cluster.local" port: 19132 - externalHostname: "java.${CLUSTER_DOMAIN}" host: "minecraft.game-servers.svc.cluster.local" port: 25565 ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-router/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: minecraft-router namespace: game-servers spec: path: "./apps/base/game-servers/minecraft-router/app" wait: true targetNamespace: game-servers sourceRef: kind: ExternalArtifact name: minecraft-router namespace: flux-system ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-witherstorm/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app minecraft-witherstorm namespace: game-servers spec: interval: 5m chart: spec: chart: minecraft-bedrock version: 2.9.0 sourceRef: kind: HelmRepository name: minecraft-server-charts namespace: flux-system interval: 5m values: fullnameOverride: *app valuesFrom: - kind: ConfigMap name: minecraft-witherstorm-values postRenderers: - kustomize: patches: - target: version: v1 kind: Deployment name: minecraft-witherstorm-minecraft-bedrock patch: | - op: add path: /spec/template/spec/hostNetwork value: true ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-witherstorm/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - pvc-ceph.yaml configMapGenerator: - name: minecraft-witherstorm-values namespace: game-servers files: - values.yaml=./values.yaml generatorOptions: annotations: kustomize.toolkit.fluxcd.io/substitute: disabled configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-witherstorm/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-witherstorm/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: minecraft-witherstorm-data namespace: game-servers spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-witherstorm/app/values.yaml ================================================ image: repository: itzg/minecraft-bedrock-server tag: latest minecraftServer: serverName: Wither Storm Bedrock Server levelName: WitherStorm serverPort: 19136 eula: "TRUE" version: LATEST difficulty: normal maxPlayers: 10 gameMode: survival playerIdleTimeout: 10 cheats: true enableLanVisibility: true defaultPermission: operator serviceType: LoadBalancer onlineMode: false texturepackRequired: true extraEnv: SERVER_PORT_V6: "19137" initContainers: - name: install-wither-storm image: alpine:latest securityContext: runAsUser: 0 runAsNonRoot: false command: - /bin/sh - -c - | set -e apk add --no-cache curl unzip jq ADDON_URL="https://edge.forgecdn.net/files/6413/077/CWSP%20Bedrock%200.4.8.4.mcaddon" DATA_DIR="/data" LEVEL_NAME="WitherStorm" # Skip if already installed if [ -f "$DATA_DIR/.wither-storm-addon-v0.4.8.4" ]; then echo "Wither Storm addon v0.4.8.4 already installed, skipping..." exit 0 fi # Download the addon echo "Downloading Cracker's Wither Storm Bedrock Port addon..." curl -L -o /tmp/addon.mcaddon "$ADDON_URL" # Extract (mcaddon is a renamed zip) echo "Extracting addon..." mkdir -p /tmp/addon unzip -o /tmp/addon.mcaddon -d /tmp/addon # Initialize pack activation files echo "[]" > /tmp/bp.json echo "[]" > /tmp/rp.json # Process each manifest.json to find behavior and resource packs find /tmp/addon -name "manifest.json" -type f | while IFS= read -r manifest; do PACK_DIR="$(dirname "$manifest")" PACK_TYPE="$(jq -r '.modules[0].type' "$manifest")" PACK_UUID="$(jq -r '.header.uuid' "$manifest")" PACK_VERSION="$(jq -c '.header.version' "$manifest")" PACK_NAME="$(basename "$PACK_DIR")" echo "Found pack: $PACK_NAME (type: $PACK_TYPE, uuid: $PACK_UUID)" if [ "$PACK_TYPE" = "data" ] || [ "$PACK_TYPE" = "script" ]; then echo "Installing behavior pack: $PACK_NAME" mkdir -p "$DATA_DIR/behavior_packs" cp -r "$PACK_DIR" "$DATA_DIR/behavior_packs/$PACK_NAME" jq --arg uuid "$PACK_UUID" --argjson ver "$PACK_VERSION" \ '. + [{"pack_id": $uuid, "version": $ver}]' /tmp/bp.json > /tmp/bp_new.json mv /tmp/bp_new.json /tmp/bp.json elif [ "$PACK_TYPE" = "resources" ]; then echo "Installing resource pack: $PACK_NAME" mkdir -p "$DATA_DIR/resource_packs" cp -r "$PACK_DIR" "$DATA_DIR/resource_packs/$PACK_NAME" jq --arg uuid "$PACK_UUID" --argjson ver "$PACK_VERSION" \ '. + [{"pack_id": $uuid, "version": $ver}]' /tmp/rp.json > /tmp/rp_new.json mv /tmp/rp_new.json /tmp/rp.json fi done # Activate packs for the world mkdir -p "$DATA_DIR/worlds/$LEVEL_NAME" cp /tmp/bp.json "$DATA_DIR/worlds/$LEVEL_NAME/world_behavior_packs.json" cp /tmp/rp.json "$DATA_DIR/worlds/$LEVEL_NAME/world_resource_packs.json" echo "=== Installed behavior packs ===" cat "$DATA_DIR/worlds/$LEVEL_NAME/world_behavior_packs.json" echo "=== Installed resource packs ===" cat "$DATA_DIR/worlds/$LEVEL_NAME/world_resource_packs.json" # Mark as installed touch "$DATA_DIR/.wither-storm-addon-v0.4.8.4" echo "Wither Storm addon installation complete!" volumeMounts: - name: datadir mountPath: /data startupProbe: enabled: true failureThreshold: 60 periodSeconds: 10 livenessProbe: initialDelaySeconds: 60 readinessProbe: initialDelaySeconds: 60 persistence: dataDir: enabled: true existingClaim: minecraft-witherstorm-data ================================================ FILE: kubernetes/apps/base/game-servers/minecraft-witherstorm/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: minecraft-witherstorm namespace: game-servers spec: dependsOn: - name: democratic-csi namespace: democratic-csi path: "./apps/base/game-servers/minecraft-witherstorm/app" wait: true targetNamespace: game-servers sourceRef: kind: ExternalArtifact name: minecraft-witherstorm namespace: flux-system ================================================ FILE: kubernetes/apps/base/game-servers/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: game-servers labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/harbor/harbor/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: harbor spec: interval: 1h chart: spec: chart: harbor version: 1.19.0 sourceRef: kind: HelmRepository name: harbor-charts namespace: flux-system interval: 10m values: expose: type: clusterIP tls: enabled: false externalURL: https://harbor.${CLUSTER_DOMAIN} persistence: enabled: true persistentVolumeClaim: registry: storageClass: ceph-block size: 50Gi database: storageClass: ceph-block size: 5Gi redis: storageClass: ceph-block size: 1Gi trivy: storageClass: ceph-block size: 5Gi trivy: enabled: true metrics: enabled: true serviceMonitor: enabled: true ================================================ FILE: kubernetes/apps/base/harbor/harbor/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: harbor namespace: harbor spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'harbor.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: harbor-core port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/harbor/harbor/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml - replicationsource.yaml - volsync-externalsecret.yaml ================================================ FILE: kubernetes/apps/base/harbor/harbor/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: harbor-registry spec: sourcePVC: harbor-registry trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: harbor-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: harbor-database spec: sourcePVC: database-data-harbor-database-0 trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 2Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: harbor-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/harbor/harbor/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: harbor-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: harbor-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/harbor/harbor/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: harbor namespace: harbor spec: path: "./apps/base/harbor/harbor/app" wait: true dependsOn: - name: cert-manager namespace: network-system - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: harbor sourceRef: kind: ExternalArtifact name: harbor namespace: flux-system ================================================ FILE: kubernetes/apps/base/harbor/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: harbor components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/harbor/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: harbor labels: kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/home-system/autobrr/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: autobrr spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: autobrr-secret template: data: AUTOBRR__SESSION_SECRET: "{{ .AUTOBRR_SESSION_SECRET }}" dataFrom: - extract: key: autobrr ================================================ FILE: kubernetes/apps/base/home-system/autobrr/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app autobrr spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system dependsOn: - name: qbittorrent namespace: home-system values: controllers: *app : containers: app: image: repository: ghcr.io/autobrr/autobrr tag: v1.79.0@sha256:5b8c29a86598907496af01ec75ef21f9c0e4e28ce9d6ae6496ef91c71543ec20 env: AUTOBRR__HOST: 0.0.0.0 AUTOBRR__PORT: &port 80 AUTOBRR__METRICS_ENABLED: true AUTOBRR__METRICS_HOST: 0.0.0.0 AUTOBRR__METRICS_PORT: &metricsPort 9094 AUTOBRR__CHECK_FOR_UPDATES: false AUTOBRR__LOG_LEVEL: INFO envFrom: - secretRef: name: autobrr-secret probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /api/healthz/liveness port: *port initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes startup: enabled: true spec: failureThreshold: 30 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 10m memory: 256Mi limits: memory: 512Mi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: controller: *app ports: http: port: *port metrics: port: *metricsPort serviceMonitor: app: serviceName: autobrr endpoints: - port: metrics persistence: config: existingClaim: autobrr-ceph config-log: type: emptyDir globalMounts: - path: /config/log tmp: type: emptyDir ================================================ FILE: kubernetes/apps/base/home-system/autobrr/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: autobrr namespace: home-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'autobrr.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: autobrr port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/home-system/autobrr/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml - httproute.yaml - pvc.yaml - pvc-ceph.yaml - replicationsource.yaml - volsync-externalsecret.yaml ================================================ FILE: kubernetes/apps/base/home-system/autobrr/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: autobrr-ceph namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/home-system/autobrr/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: autobrr spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 5Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/home-system/autobrr/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: autobrr spec: sourcePVC: autobrr-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: autobrr-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/home-system/autobrr/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: autobrr-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: autobrr-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/home-system/autobrr/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: &app autobrr namespace: home-system spec: path: "./apps/base/home-system/autobrr/app" wait: false dependsOn: - name: democratic-csi namespace: democratic-csi - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: home-system sourceRef: kind: ExternalArtifact name: autobrr namespace: flux-system ================================================ FILE: kubernetes/apps/base/home-system/bazarr/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: bazarr spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: bazarr-secret template: data: BAZARR__AUTH__APIKEY: "{{ .BAZARR_API_KEY }}" dataFrom: - extract: key: bazarr ================================================ FILE: kubernetes/apps/base/home-system/bazarr/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: bazarr spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: bazarr: annotations: reloader.stakater.com/auto: "true" containers: app: image: repository: ghcr.io/home-operations/bazarr tag: 1.5.6@sha256:79fc37491f55c7e24427bcd669bce3df2d7415ca432a47ce9d53cc5988af8411 env: TZ: ${CLUSTER_TIMEZONE} envFrom: - secretRef: name: bazarr-secret probes: liveness: enabled: true spec: periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 5 readiness: enabled: true custom: true spec: httpGet: path: /api/system/ping port: &port 6767 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 5 startup: enabled: true spec: failureThreshold: 30 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 100m memory: 256Mi limits: memory: 2Gi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: controller: bazarr ports: http: port: *port persistence: config: existingClaim: bazarr-ceph tmp: type: emptyDir media: type: nfs server: ${CLUSTER_NFS_SERVER} path: ${CLUSTER_NFS_PATH} globalMounts: - path: /media ================================================ FILE: kubernetes/apps/base/home-system/bazarr/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: bazarr namespace: home-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'bazarr.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: bazarr port: 6767 weight: 100 ================================================ FILE: kubernetes/apps/base/home-system/bazarr/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml - httproute.yaml - pvc-ceph.yaml - replicationsource.yaml - volsync-externalsecret.yaml ================================================ FILE: kubernetes/apps/base/home-system/bazarr/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: bazarr-ceph namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/home-system/bazarr/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: bazarr spec: sourcePVC: bazarr-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: bazarr-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/home-system/bazarr/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: bazarr-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: bazarr-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/home-system/bazarr/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: bazarr namespace: home-system spec: path: "./apps/base/home-system/bazarr/app" wait: false dependsOn: - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: home-system sourceRef: kind: ExternalArtifact name: bazarr namespace: flux-system ================================================ FILE: kubernetes/apps/base/home-system/home-assistant/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app home-assistant namespace: home-system spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: *app : containers: app: image: repository: ghcr.io/home-operations/home-assistant tag: 2026.5.1@sha256:516ae5c85089b3f2960cf2a21dc3c105356969499964fabf0b0358e5f3a7e0a2 env: TZ: ${CLUSTER_TIMEZONE} HASS_HTTP_TRUSTED_PROXY_1: 192.168.50.0/24 HASS_HTTP_TRUSTED_PROXY_2: 192.168.86.0/24 HASS_HTTP_TRUSTED_PROXY_3: 10.0.0.0/8 # TODO: Setup local secrets # envFrom: # - secretRef: # name: home-assistant-secret probes: liveness: &probes enabled: true custom: true spec: tcpSocket: port: 8123 initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes startup: enabled: true custom: true spec: tcpSocket: port: 8123 failureThreshold: 30 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 10m memory: 512Mi limits: memory: 2Gi code-server: image: repository: ghcr.io/coder/code-server tag: 4.118.0@sha256:4aff9947c113487113201da811564fade1af5f23038b4d683998d024eebbac92 args: ["--auth", "none", "--user-data-dir", "/config/.vscode", "--extensions-dir", "/config/.vscode", "--port", "12321", "/config"] resources: requests: cpu: 10m limits: memory: 512Mi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: controller: home-assistant ports: http: port: 8123 code-server: port: 12321 persistence: config: existingClaim: home-assistant-ceph globalMounts: - path: /config logs: type: emptyDir globalMounts: - path: /config/logs tts: type: emptyDir globalMounts: - path: /config/tts tmp: type: emptyDir globalMounts: - path: /tmp venv: type: emptyDir globalMounts: - path: /config/.venv ================================================ FILE: kubernetes/apps/base/home-system/home-assistant/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: home-assistant namespace: home-system annotations: external-dns.alpha.kubernetes.io/external: 'true' spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'hass.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: home-assistant port: 8123 weight: 100 --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: home-assistant-code namespace: home-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'hass-code.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: home-assistant port: 12321 weight: 100 ================================================ FILE: kubernetes/apps/base/home-system/home-assistant/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml - pvc.yaml - pvc-ceph.yaml - replicationsource.yaml - volsync-externalsecret.yaml ================================================ FILE: kubernetes/apps/base/home-system/home-assistant/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: home-assistant-ceph namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/home-system/home-assistant/app/pvc.yaml ================================================ apiVersion: v1 kind: PersistentVolumeClaim metadata: name: home-assistant namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/home-system/home-assistant/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: home-assistant spec: sourcePVC: home-assistant-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: home-assistant-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/home-system/home-assistant/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: home-assistant-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: home-assistant-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/home-system/home-assistant/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: home-assistant namespace: home-system spec: path: "./apps/base/home-system/home-assistant/app" wait: false dependsOn: - name: democratic-csi namespace: democratic-csi - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: home-system sourceRef: kind: ExternalArtifact name: home-assistant namespace: flux-system ================================================ FILE: kubernetes/apps/base/home-system/jellyseerr/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: jellyseerr spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: jellyseerr-secret template: data: API_KEY: "{{ .JELLYSEERR_API_KEY }}" dataFrom: - extract: key: jellyseerr ================================================ FILE: kubernetes/apps/base/home-system/jellyseerr/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app jellyseerr spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: *app : containers: app: image: repository: docker.io/fallenbagel/jellyseerr tag: 2.7.3@sha256:4538137bc5af902dece165f2bf73776d9cf4eafb6dd714670724af8f3eb77764 env: TZ: ${CLUSTER_TIMEZONE} LOG_LEVEL: "info" PORT: &port 80 envFrom: - secretRef: name: jellyseerr-secret probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /api/v1/status port: *port initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 readiness: *probes securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 10m memory: 512Mi limits: memory: 2Gi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: controller: *app ports: http: port: *port persistence: config: existingClaim: jellyseerr-ceph globalMounts: - path: /app/config cache: existingClaim: jellyseerr-cache-ceph globalMounts: - path: /app/config/cache logs: type: emptyDir globalMounts: - path: /app/config/logs tmp: type: emptyDir ================================================ FILE: kubernetes/apps/base/home-system/jellyseerr/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: jellyseerr namespace: home-system annotations: external-dns.alpha.kubernetes.io/external: 'true' spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'requests.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: jellyseerr port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/home-system/jellyseerr/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml - httproute.yaml - pvc.yaml - pvc-ceph.yaml - replicationsource.yaml - volsync-externalsecret.yaml ================================================ FILE: kubernetes/apps/base/home-system/jellyseerr/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: jellyseerr-ceph namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: ceph-block --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: jellyseerr-cache-ceph namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/home-system/jellyseerr/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: jellyseerr spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 5Gi storageClassName: truenas-iscsi-csi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: jellyseerr-cache spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 10Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/home-system/jellyseerr/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: jellyseerr spec: sourcePVC: jellyseerr-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: jellyseerr-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/home-system/jellyseerr/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: jellyseerr-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: jellyseerr-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/home-system/jellyseerr/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: jellyseerr namespace: home-system spec: path: "./apps/base/home-system/jellyseerr/app" wait: false dependsOn: - name: democratic-csi namespace: democratic-csi - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: home-system sourceRef: kind: ExternalArtifact name: jellyseerr namespace: flux-system ================================================ FILE: kubernetes/apps/base/home-system/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: home-system components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/home-system/mosquitto/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app mosquitto namespace: home-system spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: *app : containers: app: image: repository: public.ecr.aws/docker/library/eclipse-mosquitto tag: 2.0.22 env: TZ: ${CLUSTER_TIMEZONE} securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 10m limits: memory: 100Mi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: controller: *app type: LoadBalancer annotations: lbipam.cilium.io/ips: '${CLUSTER_LB_MOSQUITTO}' ports: http: port: 1883 configMaps: config: data: mosquitto.conf: | allow_anonymous true autosave_interval 60 connection_messages false listener 1883 per_listener_settings false persistence true persistence_location /data persistence: data: existingClaim: mosquitto-cache-ceph config-file: type: configMap name: mosquitto advancedMounts: mosquitto: app: - path: /mosquitto/config/mosquitto.conf subPath: mosquitto.conf ================================================ FILE: kubernetes/apps/base/home-system/mosquitto/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - pvc.yaml - pvc-ceph.yaml - replicationsource.yaml - volsync-externalsecret.yaml ================================================ FILE: kubernetes/apps/base/home-system/mosquitto/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mosquitto-cache-ceph namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/home-system/mosquitto/app/pvc.yaml ================================================ apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mosquitto-cache namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/home-system/mosquitto/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: mosquitto spec: sourcePVC: mosquitto-cache-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: mosquitto-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/home-system/mosquitto/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: mosquitto-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: mosquitto-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/home-system/mosquitto/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: mosquitto namespace: home-system spec: path: "./apps/base/home-system/mosquitto/app" wait: false dependsOn: - name: democratic-csi namespace: democratic-csi - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: home-system sourceRef: kind: ExternalArtifact name: mosquitto namespace: flux-system ================================================ FILE: kubernetes/apps/base/home-system/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: home-system labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/home-system/prowlarr/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: prowlarr spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: prowlarr-secret template: data: PROWLARR__AUTH__APIKEY: "{{ .PROWLARR_API_KEY }}" dataFrom: - extract: key: prowlarr ================================================ FILE: kubernetes/apps/base/home-system/prowlarr/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app prowlarr spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: *app : containers: app: image: repository: ghcr.io/home-operations/prowlarr tag: 2.3.7.5365@sha256:b9557d772c974901aed9285189d904b613f1f07750fca930eecfe78544bd3d48 env: PROWLARR__APP__INSTANCENAME: Prowlarr PROWLARR__APP__THEME: dark PROWLARR__AUTH__METHOD: External PROWLARR__AUTH__REQUIRED: DisabledForLocalAddresses PROWLARR__LOG__DBENABLED: "False" PROWLARR__LOG__LEVEL: info PROWLARR__SERVER__PORT: &port 80 PROWLARR__UPDATE__BRANCH: develop TZ: ${CLUSTER_TIMEZONE} envFrom: - secretRef: name: prowlarr-secret probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /ping port: *port initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes startup: enabled: true spec: failureThreshold: 30 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 100m memory: 512Mi limits: memory: 1Gi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: controller: *app ports: http: port: *port persistence: config: existingClaim: prowlarr-ceph tmp: type: emptyDir ================================================ FILE: kubernetes/apps/base/home-system/prowlarr/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: prowlarr namespace: home-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'prowlarr.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: prowlarr port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/home-system/prowlarr/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml - httproute.yaml - pvc.yaml - pvc-ceph.yaml - replicationsource.yaml - volsync-externalsecret.yaml ================================================ FILE: kubernetes/apps/base/home-system/prowlarr/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: prowlarr-ceph namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/home-system/prowlarr/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: prowlarr spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 5Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/home-system/prowlarr/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: prowlarr spec: sourcePVC: prowlarr-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: prowlarr-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/home-system/prowlarr/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: prowlarr-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: prowlarr-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/home-system/prowlarr/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: prowlarr namespace: home-system spec: path: "./apps/base/home-system/prowlarr/app" wait: false dependsOn: - name: democratic-csi namespace: democratic-csi - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: home-system sourceRef: kind: ExternalArtifact name: prowlarr namespace: flux-system ================================================ FILE: kubernetes/apps/base/home-system/qbittorrent/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app qbittorrent spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: *app : containers: app: image: repository: ghcr.io/home-operations/qbittorrent tag: 5.2.0@sha256:788796013c3da75f2dba568c5319975a5c41f555586dfd13987be4631181e00e env: TZ: ${CLUSTER_TIMEZONE} QBT_WEBUI_PORT: &port 80 QBT_TORRENTING_PORT: &torrentPort 50413 probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /api/v2/app/version port: *port initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes startup: enabled: true spec: failureThreshold: 30 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 100m memory: 512Mi limits: memory: 4Gi defaultPodOptions: terminationGracePeriodSeconds: 300 securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: controller: *app type: LoadBalancer annotations: lbipam.cilium.io/ips: ${CLUSTER_LB_QB} ports: http: port: *port bittorrent: enabled: true port: *torrentPort protocol: TCP persistence: config: existingClaim: qbittorrent-ceph tmp: type: emptyDir media: type: nfs server: ${CLUSTER_NFS_SERVER} path: ${CLUSTER_NFS_PATH} globalMounts: - path: /media/Downloads/qbittorrent subPath: Downloads/qbittorrent ================================================ FILE: kubernetes/apps/base/home-system/qbittorrent/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: qbittorrent namespace: home-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'qb.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: qbittorrent port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/home-system/qbittorrent/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: home-system resources: - helmrelease.yaml - httproute.yaml - pvc.yaml - pvc-ceph.yaml - replicationsource.yaml - volsync-externalsecret.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/home-system/qbittorrent/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/values/persistence/scripts/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/home-system/qbittorrent/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: qbittorrent-ceph namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/home-system/qbittorrent/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: qbittorrent namespace: home-system spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 5Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/home-system/qbittorrent/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: qbittorrent spec: sourcePVC: qbittorrent-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: qbittorrent-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/home-system/qbittorrent/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: qbittorrent-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: qbittorrent-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/home-system/qbittorrent/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: qbittorrent namespace: home-system spec: path: "./apps/base/home-system/qbittorrent/app" wait: false dependsOn: - name: democratic-csi namespace: democratic-csi - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: home-system sourceRef: kind: ExternalArtifact name: qbittorrent namespace: flux-system ================================================ FILE: kubernetes/apps/base/home-system/qui/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: qui spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: qui-secret template: data: QUI__SESSION_SECRET: "{{ .QUI_SESSION_SECRET }}" dataFrom: - extract: key: qui ================================================ FILE: kubernetes/apps/base/home-system/qui/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app qui spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: *app : containers: app: image: repository: ghcr.io/autobrr/qui tag: v1.18.0 env: TZ: ${CLUSTER_TIMEZONE} QUI__HOST: 0.0.0.0 QUI__PORT: &port 80 envFrom: - secretRef: name: "{{ .Release.Name }}-secret" probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /health port: *port initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 10m limits: memory: 512Mi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: ports: http: port: *port persistence: config: existingClaim: "{{ .Release.Name }}" media: type: nfs server: ${CLUSTER_NFS_SERVER} path: ${CLUSTER_NFS_PATH} globalMounts: - path: /media ================================================ FILE: kubernetes/apps/base/home-system/qui/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: qui namespace: home-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'qui.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: qui port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/home-system/qui/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: home-system resources: - externalsecret.yaml - helmrelease.yaml - httproute.yaml - pvc.yaml - replicationsource.yaml - volsync-externalsecret.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/home-system/qui/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/values/persistence/scripts/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/home-system/qui/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: qui namespace: home-system spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 2Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/home-system/qui/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: qui spec: sourcePVC: qui trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: qui-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/home-system/qui/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: qui-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: qui-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/home-system/qui/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: qui namespace: home-system spec: path: "./apps/base/home-system/qui/app" wait: false dependsOn: - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: home-system sourceRef: kind: ExternalArtifact name: qui namespace: flux-system ================================================ FILE: kubernetes/apps/base/home-system/radarr/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: radarr spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: radarr-secret template: data: RADARR__AUTH__APIKEY: "{{ .RADARR_API_KEY }}" dataFrom: - extract: key: radarr ================================================ FILE: kubernetes/apps/base/home-system/radarr/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: radarr spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: radarr: annotations: reloader.stakater.com/auto: "true" containers: app: image: repository: ghcr.io/home-operations/radarr tag: 6.2.0.10390@sha256:be596a2f896fdf15077af027f44500f73e1f6fb7b450a6494b37dd25b7cc5927 env: RADARR__APP__INSTANCENAME: Radarr RADARR__APP__THEME: dark RADARR__AUTH__METHOD: External RADARR__AUTH__REQUIRED: DisabledForLocalAddresses RADARR__LOG__DBENABLED: "False" RADARR__LOG__LEVEL: info RADARR__SERVER__PORT: &port 80 RADARR__UPDATE__BRANCH: develop TZ: ${CLUSTER_TIMEZONE} envFrom: - secretRef: name: radarr-secret probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /ping port: *port initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes startup: enabled: true spec: failureThreshold: 30 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 100m memory: 512Mi limits: memory: 4Gi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: controller: radarr ports: http: port: *port persistence: config: existingClaim: radarr-ceph tmp: type: emptyDir media: type: nfs server: ${CLUSTER_NFS_SERVER} path: ${CLUSTER_NFS_PATH} globalMounts: - path: /media ================================================ FILE: kubernetes/apps/base/home-system/radarr/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: radarr namespace: home-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'radarr.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: radarr port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/home-system/radarr/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml - httproute.yaml - pvc.yaml - pvc-ceph.yaml - replicationsource.yaml - volsync-externalsecret.yaml ================================================ FILE: kubernetes/apps/base/home-system/radarr/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: radarr-ceph namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/home-system/radarr/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: radarr namespace: home-system spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 5Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/home-system/radarr/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: radarr spec: sourcePVC: radarr-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: radarr-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/home-system/radarr/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: radarr-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: radarr-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/home-system/radarr/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: radarr namespace: home-system spec: path: "./apps/base/home-system/radarr/app" wait: false dependsOn: - name: democratic-csi namespace: democratic-csi - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: home-system sourceRef: kind: ExternalArtifact name: radarr namespace: flux-system ================================================ FILE: kubernetes/apps/base/home-system/recyclarr/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: recyclarr spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: recyclarr-secret template: data: RADARR_API_KEY: "{{ .RADARR_API_KEY }}" SONARR_API_KEY: "{{ .SONARR_API_KEY }}" dataFrom: - extract: key: radarr - extract: key: sonarr ================================================ FILE: kubernetes/apps/base/home-system/recyclarr/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app recyclarr spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: *app : type: cronjob cronjob: schedule: 0 0 * * * backoffLimit: 0 concurrencyPolicy: Forbid successfulJobsHistory: 1 failedJobsHistory: 1 ttlSecondsAfterFinished: 86400 containers: app: image: repository: ghcr.io/recyclarr/recyclarr tag: 8.6.0@sha256:3c38ceeb54438dd8327e4e65c9b48ba601a6d20fff833342d93c9b0bc4b1930b env: RECYCLARR_DATA_DIR: /tmp envFrom: - secretRef: name: recyclarr-secret args: ["sync"] securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 10m limits: memory: 128Mi pod: restartPolicy: Never defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } persistence: config: existingClaim: recyclarr-ceph config-file: type: configMap name: recyclarr-configmap globalMounts: - path: /config/recyclarr.yml subPath: recyclarr.yml readOnly: true tmpfs: type: emptyDir advancedMounts: recyclarr: app: - path: /config/logs subPath: logs - path: /config/repositories subPath: repositories - path: /tmp subPath: tmp ================================================ FILE: kubernetes/apps/base/home-system/recyclarr/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml - pvc.yaml - pvc-ceph.yaml - replicationsource.yaml - volsync-externalsecret.yaml configMapGenerator: - name: recyclarr-configmap files: - recyclarr.yml=./resources/recyclarr.yml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/home-system/recyclarr/app/kustomizeconfig.yaml ================================================ nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/values/persistence/config-file/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/home-system/recyclarr/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: recyclarr-ceph namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/home-system/recyclarr/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: recyclarr spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 5Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/home-system/recyclarr/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: recyclarr spec: sourcePVC: recyclarr-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: recyclarr-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/home-system/recyclarr/app/resources/recyclarr.yml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/recyclarr/recyclarr/refs/tags/v8.0.0/schemas/config-schema.json sonarr: series: base_url: http://sonarr.home-system.svc.cluster.local api_key: !env_var SONARR_API_KEY delete_old_custom_formats: true media_management: propers_and_repacks: do_not_prefer quality_definition: type: series quality_profiles: - trash_id: 72dae194fc92bf828f32cde7744e51a1 # WEB-1080p reset_unmatched_scores: enabled: true custom_formats: - trash_ids: - 32b367365729d530ca1c124a0b180c64 # Bad Dual Groups - 82d40da2bc6923f41e14394075dd4b03 # No-RlsGroup - e1a997ddb54e3ecbfe06341ad323c458 # Obfuscated - 06d66ab109d4d2eddb2794d21526d140 # Retags - 1b3994c551cbb92a2c781af061f4ab44 # Scene assign_scores_to: - name: WEB-1080p radarr: movies: base_url: http://radarr.home-system.svc.cluster.local api_key: !env_var RADARR_API_KEY delete_old_custom_formats: true media_management: propers_and_repacks: do_not_prefer quality_definition: type: movie quality_profiles: - trash_id: d1d67249d3890e49bc12e275d989a7e9 # HD Bluray + WEB reset_unmatched_scores: enabled: true custom_formats: - trash_ids: - b6832f586342ef70d9c128d40c07b872 # Bad Dual Groups - ae9b7c9ebde1f3bd336a8cbd1ec4c5e5 # No-RlsGroup - 7357cf5161efbf8c4d5d0c30b4815ee2 # Obfuscated - 5c44f52a8714fdd79bb4d98e2673be1f # Retags - f537cf427b64c38c8e36298f657e4828 # Scene assign_scores_to: - name: HD Bluray + WEB ================================================ FILE: kubernetes/apps/base/home-system/recyclarr/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: recyclarr-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: recyclarr-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/home-system/recyclarr/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: recyclarr namespace: home-system spec: path: "./apps/base/home-system/recyclarr/app" wait: false dependsOn: - name: democratic-csi namespace: democratic-csi - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: home-system sourceRef: kind: ExternalArtifact name: recyclarr namespace: flux-system ================================================ FILE: kubernetes/apps/base/home-system/sabnzbd/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: sabnzbd spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: sabnzbd-secret template: data: CROSS_SEED_API_KEY: "{{ .CROSS_SEED_API_KEY }}" SABNZBD__API_KEY: "{{ .SABNZBD_API_KEY }}" SABNZBD__NZB_KEY: "{{ .SABNZBD_NZB_KEY }}" dataFrom: - extract: key: sabnzbd - extract: key: cross-seed ================================================ FILE: kubernetes/apps/base/home-system/sabnzbd/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app sabnzbd spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: *app : containers: app: image: repository: ghcr.io/home-operations/sabnzbd tag: 5.0.3@sha256:53064020792b2e21305c892c11aaa1eb32af2141cbd59119b52df226d664cd05 env: TZ: ${CLUSTER_TIMEZONE} SABNZBD__PORT: &port 80 SABNZBD__HOST_WHITELIST_ENTRIES: >- sabnzbd, sabnzbd.home-system, sabnzbd.home-system.svc, sabnzbd.home-system.svc.cluster, sabnzbd.home-system.svc.cluster.local, sab.${CLUSTER_DOMAIN} XSEED_HOST: cross-seed.home-system.svc.cluster.local XSEED_PORT: 80 XSEED_APIKEY: valueFrom: secretKeyRef: name: sabnzbd-secret key: CROSS_SEED_API_KEY envFrom: - secretRef: name: sabnzbd-secret probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /api?mode=version port: *port initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes startup: enabled: true spec: failureThreshold: 30 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 100m memory: 512Mi limits: memory: 4Gi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: controller: *app ports: http: port: *port persistence: config: existingClaim: sabnzbd-ceph advancedMounts: sabnzbd: app: - path: /config tmpfs: type: emptyDir advancedMounts: sabnzbd: app: - path: /config/logs subPath: logs - path: /tmp subPath: tmp scripts: type: configMap name: sabnzbd-scripts defaultMode: 0775 advancedMounts: sabnzbd: app: - path: /config/scripts media: type: nfs server: ${CLUSTER_NFS_SERVER} path: ${CLUSTER_NFS_PATH} globalMounts: - path: /media/Downloads/sabnzbd subPath: Downloads/sabnzbd ================================================ FILE: kubernetes/apps/base/home-system/sabnzbd/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: sabnzbd namespace: home-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'sab.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: sabnzbd port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/home-system/sabnzbd/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml - httproute.yaml - pvc.yaml - pvc-ceph.yaml - replicationsource.yaml - volsync-externalsecret.yaml configMapGenerator: - name: sabnzbd-scripts files: - resources/xseed.sh generatorOptions: annotations: kustomize.toolkit.fluxcd.io/substitute: disabled configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/home-system/sabnzbd/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/values/persistence/scripts/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/home-system/sabnzbd/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: sabnzbd-ceph namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/home-system/sabnzbd/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: sabnzbd spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 5Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/home-system/sabnzbd/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: sabnzbd spec: sourcePVC: sabnzbd-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: sabnzbd-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/home-system/sabnzbd/app/resources/xseed.sh ================================================ #!/usr/bin/env bash XSEED_HOST=${XSEED_HOST:-crossseed} XSEED_PORT=${XSEED_PORT:-8080} XSEED_APIKEY=${XSEED_APIKEY:-unset} XSEED_SLEEP_INTERVAL=${CROSS_SEED_SLEEP_INTERVAL:-30} SEARCH_PATH=$1 response=$(curl \ --silent \ --output /dev/null \ --write-out "%{http_code}" \ --request POST \ --data-urlencode "path=${SEARCH_PATH}" \ --header "X-Api-Key: ${XSEED_APIKEY}" \ "http://${XSEED_HOST}:${XSEED_PORT}/api/webhook" ) if [[ "${response}" != "204" ]]; then printf "Failed to search cross-seed for '%s'\n" "${SEARCH_PATH}" exit 1 fi printf "Successfully searched cross-seed for '%s'\n" "${SEARCH_PATH}" sleep "${XSEED_SLEEP_INTERVAL}" ================================================ FILE: kubernetes/apps/base/home-system/sabnzbd/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: sabnzbd-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: sabnzbd-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/home-system/sabnzbd/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: sabnzbd namespace: home-system spec: path: "./apps/base/home-system/sabnzbd/app" wait: false dependsOn: - name: democratic-csi namespace: democratic-csi - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: home-system sourceRef: kind: ExternalArtifact name: sabnzbd namespace: flux-system ================================================ FILE: kubernetes/apps/base/home-system/smtp-relay/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: smtp-relay spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: smtp-relay-secret template: data: SMTP_RELAY_HOSTNAME: "{{ .SMTP_RELAY_HOSTNAME }}" SMTP_RELAY_PASSWORD: "{{ .SMTP_RELAY_PASSWORD }}" SMTP_RELAY_SERVER: "{{ .SMTP_RELAY_SERVER }}" SMTP_RELAY_USERNAME: "{{ .SMTP_RELAY_USERNAME }}" dataFrom: - extract: key: smtp-relay ================================================ FILE: kubernetes/apps/base/home-system/smtp-relay/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: smtp-relay spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: smtp-relay: replicas: 2 strategy: RollingUpdate annotations: reloader.stakater.com/auto: "true" containers: app: image: repository: ghcr.io/foxcpp/maddy tag: 0.9.4@sha256:cf79fddee12228b3c47af5fbbfadceef115d46d4ae434429bef70f1d565a0abf env: SMTP_RELAY_SMTP_PORT: &port 25 envFrom: - secretRef: name: smtp-relay-secret probes: liveness: enabled: true readiness: enabled: true startup: enabled: true spec: failureThreshold: 30 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 10m memory: 32Mi limits: memory: 64Mi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: controller: smtp-relay ports: smtp: port: *port configMaps: config: data: maddy.conf: |- state_dir /cache/state runtime_dir /cache/run tls off hostname {env:SMTP_RELAY_HOSTNAME} smtp tcp://0.0.0.0:{env:SMTP_RELAY_SMTP_PORT} { default_source { deliver_to &remote_queue } } target.queue remote_queue { target &remote_smtp } target.smtp remote_smtp { starttls yes auth plain {env:SMTP_RELAY_USERNAME} {env:SMTP_RELAY_PASSWORD} targets tcp://{env:SMTP_RELAY_SERVER}:587 } persistence: cache: type: emptyDir config-file: type: configMap identifier: config globalMounts: - path: /data/maddy.conf subPath: maddy.conf ================================================ FILE: kubernetes/apps/base/home-system/smtp-relay/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml ================================================ FILE: kubernetes/apps/base/home-system/smtp-relay/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: smtp-relay namespace: home-system spec: path: "./apps/base/home-system/smtp-relay/app" wait: true dependsOn: - name: onepassword namespace: external-secrets targetNamespace: home-system sourceRef: kind: ExternalArtifact name: smtp-relay namespace: flux-system ================================================ FILE: kubernetes/apps/base/home-system/sonarr/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: sonarr spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: sonarr-secret template: data: SONARR__AUTH__APIKEY: "{{ .SONARR_API_KEY }}" dataFrom: - extract: key: sonarr ================================================ FILE: kubernetes/apps/base/home-system/sonarr/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: sonarr spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: sonarr: containers: app: image: repository: ghcr.io/home-operations/sonarr tag: 4.0.17.2967@sha256:4ff5667a371e08b098858fa2457a99a5fef5f6a32640eb8567efe979d13ac9fc env: SONARR__APP__INSTANCENAME: Sonarr SONARR__APP__THEME: dark SONARR__AUTH__METHOD: External SONARR__AUTH__REQUIRED: DisabledForLocalAddresses SONARR__LOG__DBENABLED: "False" SONARR__LOG__LEVEL: info SONARR__SERVER__PORT: &port 80 SONARR__UPDATE__BRANCH: develop TZ: ${CLUSTER_TIMEZONE} envFrom: - secretRef: name: sonarr-secret probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /ping port: *port initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes startup: enabled: true spec: failureThreshold: 30 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 100m memory: 512Mi limits: memory: 4Gi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: controller: sonarr ports: http: port: *port persistence: config: existingClaim: sonarr-ceph tmp: type: emptyDir media: type: nfs server: ${CLUSTER_NFS_SERVER} path: ${CLUSTER_NFS_PATH} globalMounts: - path: /media ================================================ FILE: kubernetes/apps/base/home-system/sonarr/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: sonarr namespace: home-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'sonarr.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: sonarr port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/home-system/sonarr/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml - httproute.yaml - pvc.yaml - pvc-ceph.yaml - replicationsource.yaml - volsync-externalsecret.yaml ================================================ FILE: kubernetes/apps/base/home-system/sonarr/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: sonarr-ceph namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/home-system/sonarr/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: sonarr spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 5Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/home-system/sonarr/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: sonarr spec: sourcePVC: sonarr-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: sonarr-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/home-system/sonarr/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: sonarr-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: sonarr-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/home-system/sonarr/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: sonarr namespace: home-system spec: path: "./apps/base/home-system/sonarr/app" wait: false dependsOn: - name: democratic-csi namespace: democratic-csi - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: home-system sourceRef: kind: ExternalArtifact name: sonarr namespace: flux-system ================================================ FILE: kubernetes/apps/base/home-system/tautulli/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: tautulli spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: tautulli-secret template: data: TAUTULLI_API_KEY: "{{ .TAUTULLI_API_KEY }}" dataFrom: - extract: key: tautulli ================================================ FILE: kubernetes/apps/base/home-system/tautulli/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app tautulli spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: *app : containers: app: image: repository: ghcr.io/home-operations/tautulli tag: 2.17.1@sha256:2183820d45a1413b4b8868fc18ad5eb9259630ea0151348cdc9cfb4017a0dd33 env: TZ: ${CLUSTER_TIMEZONE} TAUTULLI_HTTP_BASE_URL: https://tautulli.${CLUSTER_DOMAIN} TAUTULLI_HTTP_PORT: &port 80 envFrom: - secretRef: name: tautulli-secret probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /status port: *port initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes startup: enabled: true spec: failureThreshold: 30 periodSeconds: 10 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 10m limits: memory: 1Gi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch seccompProfile: { type: RuntimeDefault } service: app: controller: *app ports: http: port: *port persistence: config: existingClaim: tautulli-ceph tmpfs: type: emptyDir advancedMounts: tautulli: app: - path: /config/logs subPath: logs - path: /tmp subPath: tmp ================================================ FILE: kubernetes/apps/base/home-system/tautulli/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: tautulli namespace: home-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'tautulli.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: tautulli port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/home-system/tautulli/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml - httproute.yaml - pvc.yaml - pvc-ceph.yaml - replicationsource.yaml - volsync-externalsecret.yaml ================================================ FILE: kubernetes/apps/base/home-system/tautulli/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: tautulli-ceph namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/home-system/tautulli/app/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: tautulli spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 5Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/home-system/tautulli/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: tautulli spec: sourcePVC: tautulli-ceph trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: tautulli-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/home-system/tautulli/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: tautulli-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: tautulli-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/home-system/tautulli/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: tautulli namespace: home-system spec: path: "./apps/base/home-system/tautulli/app" wait: false dependsOn: - name: democratic-csi namespace: democratic-csi - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: home-system sourceRef: kind: ExternalArtifact name: tautulli namespace: flux-system ================================================ FILE: kubernetes/apps/base/home-system/zigbee2mqtt/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app zigbee2mqtt spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: *app : type: deployment replicas: 1 containers: main: image: repository: ghcr.io/koenkk/zigbee2mqtt tag: 2.10.0@sha256:e9279e580bb25c512cf6e54c36e215a5cbd2881d1f201cf2a8213a97b14be3d2 env: TZ: ${CLUSTER_TIMEZONE} ZIGBEE2MQTT_DATA: /data ZIGBEE2MQTT_CONFIG_EXPERIMENTAL_NEW_API: true # adapter ZIGBEE2MQTT_CONFIG_SERIAL_PORT: tcp://${EXT_ZIGBEE_CONTROLLER_IP}:6638 ZIGBEE2MQTT_CONFIG_SERIAL_ADAPTER: zstack ZIGBEE2MQTT_CONFIG_SERIAL_BAUDRATE: 115200 ZIGBEE2MQTT_CONFIG_ADVANCED_TRANSMIT_POWER: 20 ZIGBEE2MQTT_CONFIG_ADVANCED_DISABLE_LED: false # mqtt ZIGBEE2MQTT_CONFIG_MQTT_SERVER: "mqtt://mosquitto.home-system.svc.cluster.local:1883" ZIGBEE2MQTT_CONFIG_MQTT_BASE_TOPIC: zigbee2mqtt ZIGBEE2MQTT_CONFIG_MQTT_INCLUDE_DEVICE_INFORMATION: true ZIGBEE2MQTT_CONFIG_MQTT_USER: ${MQTT_USER_USERNAME} ZIGBEE2MQTT_CONFIG_MQTT_PASSWORD: ${MQTT_USER_PASSWORD} ZIGBEE2MQTT_CONFIG_MQTT_VERSION: 5 ZIGBEE2MQTT_CONFIG_ADVANCED_LAST_SEEN: ISO_8601 # zigbee network ZIGBEE2MQTT_CONFIG_ADVANCED_CHANNEL: 25 # frontend ZIGBEE2MQTT_CONFIG_FRONTEND_ENABLED: true ZIGBEE2MQTT_CONFIG_FRONTEND_PORT: &port 80 ZIGBEE2MQTT_CONFIG_FRONTEND_URL: https://zigbee2mqtt.${CLUSTER_DOMAIN} # devices and groups ZIGBEE2MQTT_CONFIG_DEVICES: devices.yaml ZIGBEE2MQTT_CONFIG_GROUPS: groups.yaml # logging ZIGBEE2MQTT_CONFIG_ADVANCED_LOG_LEVEL: info ZIGBEE2MQTT_CONFIG_ADVANCED_LOG_OUTPUT: '["console"]' # device-availability ZIGBEE2MQTT_CONFIG_AVAILABILITY_ENABLED: true ZIGBEE2MQTT_CONFIG_AVAILABILITY_ACTIVE_TIMEOUT: 60 ZIGBEE2MQTT_CONFIG_AVAILABILITY_PASSIVE_TIMEOUT: 2000 ZIGBEE2MQTT_CONFIG_DEVICE_OPTIONS_RETAIN: true # home-assistant ZIGBEE2MQTT_CONFIG_HOMEASSISTANT_ENABLED: true ZIGBEE2MQTT_CONFIG_HOMEASSISTANT_DISCOVERY_TOPIC: homeassistant ZIGBEE2MQTT_CONFIG_HOMEASSISTANT_STATUS_TOPIC: homeassistant/status # security ZIGBEE2MQTT_CONFIG_PERMIT_JOIN: true probes: liveness: enabled: true readiness: enabled: true startup: enabled: true spec: failureThreshold: 30 periodSeconds: 10 initialDelaySeconds: 10 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: ["ALL"] resources: requests: cpu: "10m" memory: "128Mi" limits: memory: "256Mi" service: zigbee2mqtt: controller: *app ports: http: port: *port protocol: HTTP appProtocol: http serviceMonitor: app: serviceName: *app endpoints: - port: http scheme: http path: /metrics interval: 1m scrapeTimeout: 10s persistence: data: existingClaim: zigbee2mqtt-cache defaultPodOptions: automountServiceAccountToken: false enableServiceLinks: false securityContext: runAsNonRoot: true runAsUser: &uid 1000 runAsGroup: *uid fsGroup: *uid fsGroupChangePolicy: Always seccompProfile: { type: "RuntimeDefault" } topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: app.kubernetes.io/name: *app ================================================ FILE: kubernetes/apps/base/home-system/zigbee2mqtt/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: zigbee2mqtt namespace: home-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'zigbee2mqtt.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: zigbee2mqtt port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/home-system/zigbee2mqtt/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml - pvc.yaml - pvc-ceph.yaml - replicationsource.yaml - volsync-externalsecret.yaml ================================================ FILE: kubernetes/apps/base/home-system/zigbee2mqtt/app/pvc-ceph.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: zigbee2mqtt-cache-ceph namespace: home-system spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/home-system/zigbee2mqtt/app/pvc.yaml ================================================ apiVersion: v1 kind: PersistentVolumeClaim metadata: name: zigbee2mqtt-cache spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: truenas-iscsi-csi ================================================ FILE: kubernetes/apps/base/home-system/zigbee2mqtt/app/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: zigbee2mqtt spec: sourcePVC: zigbee2mqtt-cache trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: zigbee2mqtt-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/home-system/zigbee2mqtt/app/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: zigbee2mqtt-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: zigbee2mqtt-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/home-system/zigbee2mqtt/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: zigbee2mqtt namespace: home-system spec: path: "./apps/base/home-system/zigbee2mqtt/app" wait: false dependsOn: - name: democratic-csi namespace: democratic-csi - name: mosquitto namespace: home-system - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: home-system sourceRef: kind: ExternalArtifact name: zigbee2mqtt namespace: flux-system ================================================ FILE: kubernetes/apps/base/kguardian/kguardian/app/auditnetworkpolicy-baseline.yaml ================================================ --- # Cluster-wide audit-only default-deny baseline. # # Tells the kguardian-evaluator to evaluate every pod-to-pod flow in # the cluster against a "deny everything ingress" rule, *without # enforcing it*. Result: the Audit panel in the frontend (and the # audit_verdicts table in the broker) populate with a per-flow row # tagged "WouldDeny", giving you a complete picture of what cluster # traffic looks like before you commit to enforcement. # # kguardian itself is excluded so the evaluator + broker + frontend # don't drown out the signal with their own internal traffic. # # Promote per-namespace by copying the spec under kind: NetworkPolicy # (or use Calico GlobalNetworkPolicy / k8s AdminNetworkPolicy if your # CNI supports cluster-wide enforcement). See the chart's # UPGRADING.md / docs/concepts/audit-network-policy.mdx. apiVersion: kguardian.dev/v1alpha1 kind: AuditClusterNetworkPolicy metadata: name: cluster-baseline-audit spec: # Empty namespaceSelector with an explicit not-in match excludes # kguardian's own namespace. Everywhere else gets evaluated. namespaceSelector: matchExpressions: - key: kubernetes.io/metadata.name operator: NotIn values: [kguardian, kube-system, flux-system] podSelector: {} policyTypes: [Ingress] # No ingress rules → default-deny in every matched namespace. ================================================ FILE: kubernetes/apps/base/kguardian/kguardian/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app kguardian spec: interval: 1h chartRef: kind: OCIRepository name: kguardian valuesFrom: - kind: ConfigMap name: kguardian-values ================================================ FILE: kubernetes/apps/base/kguardian/kguardian/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: kguardian namespace: kguardian spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'kguardian.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: kguardian-frontend port: 5173 weight: 100 ================================================ FILE: kubernetes/apps/base/kguardian/kguardian/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml - ocirepository.yaml - pvc-database.yaml - auditnetworkpolicy-baseline.yaml configMapGenerator: - name: kguardian-values namespace: kguardian files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/kguardian/kguardian/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/kguardian/kguardian/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: kguardian spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 1.11.1 url: oci://ghcr.io/kguardian-dev/charts/kguardian ================================================ FILE: kubernetes/apps/base/kguardian/kguardian/app/pvc-database.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: kguardian-db namespace: kguardian spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: ceph-block ================================================ FILE: kubernetes/apps/base/kguardian/kguardian/app/values.yaml ================================================ --- controller: image: # v1.8.2 — eBPF ring-buffer callbacks log first receiver-closed once # then drop subsequent events silently, instead of flooding stderr at # syscall frequency (kguardian-dev/kguardian#880). tag: "v1.8.2" sha: "sha256:bfb9a3b52bc6a146acf19ebec700343ae245431fb17555e8a55ed239caa37356" excludedNamespaces: - kguardian broker: image: # v1.9.1 — /health checks schema state so kubelet self-heals on DB wipe # (kguardian-dev/kguardian#876). Validated end-to-end against this cluster. tag: "v1.9.1" sha: "sha256:65261cdfa672c7ad61044e4fe58d945cc5b422dd64de6341aa23c46fd555570e" resources: limits: memory: 2Gi requests: cpu: 500m memory: 512Mi frontend: image: tag: "v1.9.0" sha: "sha256:32bb6300f51f0bdc3040d6bfa524c8ad56ecd27feb76fb28f9e46dcda7eede83" llmBridge: enabled: true image: tag: "v1.2.3" sha: "sha256:333aa8e252dcea145975d094408a7ab1e4abaedd5ac39e617bdf1cc5894a8437" secrets: openai: enabled: true name: "kguardian-secrets" # kguardian-evaluator — audit-mode policy preview (chart 1.11.0+). # Watches AuditNetworkPolicy / AuditClusterNetworkPolicy CRDs and reports # flows that *would* be denied (and that are explicitly allowed) without # blocking traffic. Surfaces in the frontend's "Audit" panel. evaluator: image: # v0.2.2 — empty results encode as `[]` not `null`, eliminating # broker decode warnings on flows with no matching policies # (kguardian-dev/kguardian#880). tag: "v0.2.2" sha: "sha256:a7c21bdb710402059df9a2709ec64b607be63de9337e47967b0bf97af3948fe4" database: # Pin postgres image — `latest` drifts and PG major-version bumps break the on-disk format image: tag: "18.1" sha: "sha256:1090bc3a8ccfb0b55f78a494d76f8d603434f7e4553543d6e807bc7bd6bbd17f" # Persistent storage so the DB survives pod restarts (chart default is emptyDir → wipes on every recreate) persistence: enabled: true existingClaim: kguardian-db # Sized to observed load: postgres uses 2.0–2.8 cores under autovacuum + ingest pressure resources: limits: memory: 1Gi requests: cpu: "2" memory: 512Mi mcpServer: enabled: false useKmcp: false image: tag: "v1.3.2" sha: "sha256:1ca186593b1948ec5a237f8f863047bea56880d73015b35576ec45a27b51a604" ================================================ FILE: kubernetes/apps/base/kguardian/kguardian/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kguardian namespace: kguardian spec: path: "./apps/base/kguardian/kguardian/app" wait: true targetNamespace: kguardian sourceRef: kind: ExternalArtifact name: kguardian namespace: flux-system ================================================ FILE: kubernetes/apps/base/kguardian/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: kguardian components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/kguardian/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: kguardian labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/kube-system/cilium/app/grafanadashboard.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: cilium spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS configMapRef: name: cilium-dashboard key: cilium-dashboard.json --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: cilium-operator spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS configMapRef: name: cilium-operator-dashboard key: cilium-operator-dashboard.json ================================================ FILE: kubernetes/apps/base/kube-system/cilium/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: cilium namespace: kube-system spec: interval: 5m timeout: 10m chartRef: kind: OCIRepository name: cilium valuesFrom: - kind: ConfigMap name: cilium-values ================================================ FILE: kubernetes/apps/base/kube-system/cilium/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: hubble-ui namespace: network-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'hubble.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: hubble-ui port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/kube-system/cilium/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: kube-system resources: - grafanadashboard.yaml - helmrelease.yaml - httproute.yaml - loadbalancer.yaml - ocirepository.yaml configMapGenerator: - name: cilium-values files: - values.yaml=./values.yaml generatorOptions: annotations: kustomize.toolkit.fluxcd.io/substitute: disabled configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/kube-system/cilium/app/kustomizeconfig.yaml ================================================ nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/kube-system/cilium/app/loadbalancer.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cilium.io/ciliuml2announcementpolicy_v2alpha1.json apiVersion: cilium.io/v2alpha1 kind: CiliumL2AnnouncementPolicy metadata: name: l2-policy spec: nodeSelector: matchLabels: kubernetes.io/os: linux externalIPs: true loadBalancerIPs: true --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cilium.io/ciliumloadbalancerippool_v2alpha1.json apiVersion: cilium.io/v2alpha1 kind: CiliumLoadBalancerIPPool metadata: name: l2-pool spec: allowFirstLastIPs: "Yes" blocks: - start: 192.168.50.180 stop: 192.168.50.199 ================================================ FILE: kubernetes/apps/base/kube-system/cilium/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: cilium namespace: kube-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 1.19.4 url: oci://quay.io/cilium/charts/cilium ================================================ FILE: kubernetes/apps/base/kube-system/cilium/app/values.yaml ================================================ --- annotateK8sNode: true autoDirectNodeRoutes: true bandwidthManager: bbr: true enabled: true bpf: datapathMode: netkit masquerade: true preallocateMaps: true bpfClockProbe: true bgpControlPlane: enabled: false cgroup: autoMount: enabled: false hostRoot: /sys/fs/cgroup cni: exclusive: false dashboards: enabled: true annotations: grafana_folder: kube-system enableIPv4BIGTCP: true endpointRoutes: enabled: true envoy: enabled: false hubble: enabled: true metrics: enabled: - dns:query;ignoreAAAA - drop - tcp - flow - icmp - http - port-distribution - policy-verdict:sourceContext=pod;destinationContext=pod;labelsContext=source_namespace,destination_namespace enableOpenMetrics: true serviceMonitor: enabled: true labels: prometheus: kube-prometheus ui: enabled: true PodDisruptionBudget: enabled: true minAvailable: 1 unhealthyPodEvictionPolicy: AlwaysAllow relay: enabled: true PodDisruptionBudget: enabled: true minAvailable: 1 unhealthyPodEvictionPolicy: AlwaysAllow ipam: mode: kubernetes ipv4NativeRoutingCIDR: 10.244.0.0/16 k8sServiceHost: 127.0.0.1 k8sServicePort: 7445 kubeProxyReplacement: true kubeProxyReplacementHealthzBindAddr: 0.0.0.0:10256 l2announcements: enabled: true loadBalancer: algorithm: maglev mode: hybrid serviceTopology: true localRedirectPolicies: enabled: true operator: priorityClassName: system-cluster-critical PodDisruptionBudget: enabled: true minAvailable: 1 unhealthyPodEvictionPolicy: AlwaysAllow dashboards: enabled: true annotations: grafana_folder: kube-system prometheus: enabled: true serviceMonitor: enabled: true trustCRDsExist: true replicas: 2 rollOutPods: true pmtuDiscovery: enabled: true prometheus: enabled: true serviceMonitor: enabled: true trustCRDsExist: true priorityClassName: system-node-critical rollOutCiliumPods: true routingMode: native securityContext: capabilities: ciliumAgent: - CHOWN - KILL - NET_ADMIN - NET_RAW - IPC_LOCK - SYS_ADMIN - SYS_RESOURCE - PERFMON - BPF - DAC_OVERRIDE - FOWNER - SETGID - SETUID cleanCiliumState: - NET_ADMIN - SYS_ADMIN - SYS_RESOURCE socketLB: enabled: true hostNamespaceOnly: true ================================================ FILE: kubernetes/apps/base/kube-system/cilium/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: cilium namespace: kube-system spec: path: "./apps/base/kube-system/cilium/app" wait: false targetNamespace: kube-system sourceRef: kind: ExternalArtifact name: cilium namespace: flux-system ================================================ FILE: kubernetes/apps/base/kube-system/descheduler/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: descheduler spec: interval: 1h chartRef: kind: OCIRepository name: descheduler valuesFrom: - kind: ConfigMap name: descheduler-values ================================================ FILE: kubernetes/apps/base/kube-system/descheduler/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml configMapGenerator: - name: descheduler-values namespace: kube-system files: - values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/kube-system/descheduler/app/kustomizeconfig.yaml ================================================ nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/kube-system/descheduler/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: descheduler spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 0.35.1 url: oci://ghcr.io/home-operations/charts-mirror/descheduler ================================================ FILE: kubernetes/apps/base/kube-system/descheduler/app/values.yaml ================================================ service: enabled: true serviceMonitor: enabled: true kind: Deployment leaderElection: enabled: true leaseDuration: 30s renewDeadline: 15s retryPeriod: 5s resourceLock: "leases" resourceName: "descheduler" resourceNamescape: "kube-system" ================================================ FILE: kubernetes/apps/base/kube-system/descheduler/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: descheduler namespace: kube-system spec: path: "./apps/base/kube-system/descheduler/app" wait: true targetNamespace: kube-system sourceRef: kind: ExternalArtifact name: descheduler namespace: flux-system ================================================ FILE: kubernetes/apps/base/kube-system/keda/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: keda spec: interval: 1h chartRef: kind: OCIRepository name: keda values: crds: install: true operator: replicaCount: 2 metricsServer: replicaCount: 2 prometheus: metricServer: enabled: true serviceMonitor: enabled: true operator: enabled: true serviceMonitor: enabled: true webhooks: enabled: true serviceMonitor: enabled: true ================================================ FILE: kubernetes/apps/base/kube-system/keda/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/kube-system/keda/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: keda spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 2.19.0 url: oci://ghcr.io/home-operations/charts-mirror/keda ================================================ FILE: kubernetes/apps/base/kube-system/keda/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: keda namespace: kube-system spec: path: "./apps/base/kube-system/keda/app" wait: true targetNamespace: kube-system sourceRef: kind: ExternalArtifact name: keda namespace: flux-system ================================================ FILE: kubernetes/apps/base/kube-system/kubelet-csr-approver/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kubelet-csr-approver namespace: kube-system spec: interval: 5m chartRef: kind: OCIRepository name: kubelet-csr-approver valuesFrom: - kind: ConfigMap name: kubelet-csr-approver-values ================================================ FILE: kubernetes/apps/base/kube-system/kubelet-csr-approver/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml configMapGenerator: - name: kubelet-csr-approver-values namespace: kube-system files: - values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/kube-system/kubelet-csr-approver/app/kustomizeconfig.yaml ================================================ nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/kube-system/kubelet-csr-approver/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: kubelet-csr-approver namespace: kube-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 1.2.13 url: oci://ghcr.io/postfinance/charts/kubelet-csr-approver ================================================ FILE: kubernetes/apps/base/kube-system/kubelet-csr-approver/app/values.yaml ================================================ metrics: enable: true serviceMonitor: enabled: true providerRegex: ^talos-\d$ ================================================ FILE: kubernetes/apps/base/kube-system/kubelet-csr-approver/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kubelet-csr-approver namespace: kube-system spec: path: "./apps/base/kube-system/kubelet-csr-approver/app" wait: true targetNamespace: kube-system sourceRef: kind: ExternalArtifact name: kubelet-csr-approver namespace: flux-system ================================================ FILE: kubernetes/apps/base/kube-system/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: kube-system components: - ../../../components/common resources: - namespace.yaml - priorityclass.yaml ================================================ FILE: kubernetes/apps/base/kube-system/metrics-server/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: metrics-server namespace: kube-system spec: interval: 1h chartRef: kind: OCIRepository name: metrics-server values: args: - --kubelet-insecure-tls - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname - --kubelet-use-node-status-port - --metric-resolution=15s metrics: enabled: true serviceMonitor: enabled: true ================================================ FILE: kubernetes/apps/base/kube-system/metrics-server/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/kube-system/metrics-server/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: metrics-server namespace: kube-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 3.13.0 url: oci://ghcr.io/home-operations/charts-mirror/metrics-server ================================================ FILE: kubernetes/apps/base/kube-system/metrics-server/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: metrics-server namespace: kube-system spec: path: "./apps/base/kube-system/metrics-server/app" wait: true targetNamespace: kube-system sourceRef: kind: ExternalArtifact name: metrics-server namespace: flux-system ================================================ FILE: kubernetes/apps/base/kube-system/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: kube-system labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/kube-system/priorityclass.yaml ================================================ --- apiVersion: scheduling.k8s.io/v1 description: Used for cluster critical pods that must not be moved from their current node. kind: PriorityClass metadata: name: platform-cluster-critical preemptionPolicy: PreemptLowerPriority value: 100000000 --- apiVersion: scheduling.k8s.io/v1 description: Used for cluster critical pods that must not be moved from their current node. kind: PriorityClass metadata: name: platform-node-critical preemptionPolicy: PreemptLowerPriority value: 100001000 ================================================ FILE: kubernetes/apps/base/kube-system/reflector/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app reflector namespace: kube-system spec: interval: 5m chartRef: kind: OCIRepository name: reflector ================================================ FILE: kubernetes/apps/base/kube-system/reflector/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/kube-system/reflector/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: reflector namespace: kube-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 10.0.43 url: oci://ghcr.io/emberstack/helm-charts/reflector ================================================ FILE: kubernetes/apps/base/kube-system/reflector/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: reflector namespace: kube-system spec: path: "./apps/base/kube-system/reflector/app" wait: true targetNamespace: kube-system sourceRef: kind: ExternalArtifact name: reflector namespace: flux-system ================================================ FILE: kubernetes/apps/base/kube-system/snapshot-controller/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: snapshot-controller namespace: kube-system spec: interval: 1h chartRef: kind: OCIRepository name: snapshot-controller values: controller: serviceMonitor: create: true ================================================ FILE: kubernetes/apps/base/kube-system/snapshot-controller/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/kube-system/snapshot-controller/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: snapshot-controller namespace: kube-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 5.0.4 url: oci://ghcr.io/piraeusdatastore/helm-charts/snapshot-controller ================================================ FILE: kubernetes/apps/base/kube-system/snapshot-controller/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: snapshot-controller namespace: kube-system spec: path: "./apps/base/kube-system/snapshot-controller/app" wait: true targetNamespace: kube-system sourceRef: kind: ExternalArtifact name: snapshot-controller namespace: flux-system ================================================ FILE: kubernetes/apps/base/kube-system/spegel/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app spegel spec: interval: 1h chartRef: kind: OCIRepository name: spegel valuesFrom: - kind: ConfigMap name: spegel-values ================================================ FILE: kubernetes/apps/base/kube-system/spegel/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml configMapGenerator: - name: spegel-values files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/kube-system/spegel/app/kustomizeconfig.yaml ================================================ nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/kube-system/spegel/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: spegel spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 0.7.0 url: oci://ghcr.io/spegel-org/helm-charts/spegel ================================================ FILE: kubernetes/apps/base/kube-system/spegel/app/values.yaml ================================================ grafanaDashboard: enabled: true service: registry: hostPort: 29999 serviceMonitor: enabled: true spegel: containerdSock: /run/containerd/containerd.sock containerdRegistryConfigPath: /etc/cri/conf.d/hosts ================================================ FILE: kubernetes/apps/base/kube-system/spegel/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: spegel namespace: kube-system spec: path: "./apps/base/kube-system/spegel/app" wait: true targetNamespace: kube-system sourceRef: kind: ExternalArtifact name: spegel namespace: flux-system ================================================ FILE: kubernetes/apps/base/kube-system/tetragon/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: tetragon spec: interval: 1h chartRef: kind: OCIRepository name: tetragon valuesFrom: - kind: ConfigMap name: tetragon-values ================================================ FILE: kubernetes/apps/base/kube-system/tetragon/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml configMapGenerator: - name: tetragon-values files: - values.yaml=values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/kube-system/tetragon/app/kustomizeconfig.yaml ================================================ nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/kube-system/tetragon/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: tetragon namespace: kube-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 1.6.0 url: oci://ghcr.io/cilium/charts/tetragon ================================================ FILE: kubernetes/apps/base/kube-system/tetragon/app/values.yaml ================================================ enabled: true imagePullPolicy: IfNotPresent imagePullSecrets: [] serviceAccount: create: true annotations: {} name: "" podAnnotations: {} podSecurityContext: {} nodeSelector: {} tolerations: - operator: Exists affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/arch operator: In values: - amd64 extraHostPathMounts: [] extraConfigmapMounts: [] daemonSetAnnotations: {} extraVolumes: [] updateStrategy: {} daemonSetLabelsOverride: {} selectorLabelsOverride: {} podLabelsOverride: {} serviceLabelsOverride: {} # Set DNS policy for tetragon pods. # # Recommended DNS policy for tetragon pod depends on whether the export container # needs to resolve external DNS names (e.g. an S3 URL) or internal ones (e.g. a Kubernetes # DNS name for elasticsearch service). # # - For external DNS names, use "Default" so that the export container continues to function # properly in case there is a connectivity issue between the export container and core-dns. # - For internal DNS names, use "ClusterFirstWithHostNet" so that the export container can # resolve them. # # https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy dnsPolicy: Default # exportDirectory specifies directory to put Hubble and FGS JSON export files. exportDirectory: "/var/run/cilium/tetragon" # exportFileRotationInterval specifies file creation interval for hubble-export-s3. exportFileCreationInterval: "120s" # # Configures whether Tetragon pods run on the host network. # # IMPORTANT: Tetragon must be on the host network for the process visibility to # function properly. # hostNetwork: true tetragon: enabled: true image: override: ~ repository: quay.io/cilium/tetragon resources: {} extraArgs: {} extraEnv: [] # extraEnv: # - name: foo # value: bar extraVolumeMounts: [] securityContext: privileged: true # Tetragon puts processes in an LRU cache. The cache is used to find ancestors for subsequently exec'ed # processes. processCacheSize: 65536 # JSON export filename. Set it to an empty string to disable JSON export altogether. exportFilename: tetragon.log # Size in megabytes at which to rotate JSON export files. exportFileMaxSizeMB: 10 # Number of rotated files to retain. exportFileMaxBackups: 5 # Compress rotated JSON export files. exportFileCompress: false # Rate-limit event export (events per minute), Set to -1 to export all events. exportRateLimit: -1 # Allowlist for JSON export. For example, to export only process_connect events from # the default namespace: # # exportAllowList: | # {"namespace":["default"],"event_set":["PROCESS_EXEC"]} exportAllowList: |- {"event_set":["PROCESS_EXEC", "PROCESS_EXIT", "PROCESS_KPROBE"]} # Denylist for JSON export. For example, to exclude exec events that look similar to # Kubernetes health checks and all the events from kube-system namespace and the host: # # exportDenyList: | # {"health_check":true} # {"namespace":["kube-system",""]} # exportDenyList: |- {"health_check":true} {"namespace":["", "cilium", "kube-system"]} # Filters to include or exclude fields from Tetragon events. Without any filters, all # fields are included by default. The presence of at least one inclusion filter implies # default-exclude (i.e. any fields that don't match an inclusion filter will be # excluded). Field paths are expressed using dot notation like "a.b.c" and multiple # field paths can be separated by commas like "a.b.c,d,e.f". An optional "event_set" may # be specified to apply the field filter to a specific set of events. # # For example, to exclude the "parent" field from all events and include the "process" # field in PROCESS_KPROBE events while excluding all others: # # fieldFilters: | # {"fields": "parent", "action": "EXCLUDE"} # {"event_set": ["PROCESS_KPROBE"], "fields": "process", "action": "INCLUDE"} # fieldFilters: |- {} # Access Kubernetes API to associate Tetragon events with Kubernetes pods. enableK8sAPI: true # Access Cilium API to associate Tetragon events with Cilium endpoints and DNS cache. enableCiliumAPI: true # enableProcessCred enables Capabilities visibility in exec and kprobe events. enableProcessCred: true # enableProcessNs enables Namespaces visibility in exec and kprobe events. enableProcessNs: true # Set --btf option to explicitly specify an absolute path to a btf file. For advanced users only. btf: "" # Override the command. For advanced users only. commandOverride: [] # Override the arguments. For advanced users only. argsOverride: [] prometheus: # -- Whether to enable exposing Tetragon metrics. enabled: true # -- The address at which to expose metrics. Set it to "" to expose on all available interfaces. address: "" # -- The port at which to expose metrics. port: 2112 serviceMonitor: # -- Whether to create a 'ServiceMonitor' resource targeting the 'tetragon' pods. enabled: true # -- The set of labels to place on the 'ServiceMonitor' resource. labelsOverride: {} grpc: # -- Whether to enable exposing Tetragon gRPC. enabled: true # -- The address at which to expose gRPC. Examples: localhost:54321, unix:///var/run/tetragon/tetragon.sock address: "localhost:54321" gops: # -- The address at which to expose gops. address: "localhost" # -- The port at which to expose gops. port: 8118 # Enable policy filter. This is required for K8s namespace filtering. # NB: this is currently a work-in-progress feature enablePolicyFilter: false tetragonOperator: # -- Enable the tetragon-operator component (required). enabled: true # -- tetragon-operator image. image: override: ~ repository: quay.io/cilium/tetragon-operator # tetragon-operator image-digest suffix: "" export: # "stdout". "" to disable. mode: "stdout" resources: {} extraArgs: {} extraEnv: [] # extraEnv: # - name: foo # value: bar extraVolumeMounts: [] securityContext: {} # Override the command. For advanced users only. commandOverride: [] # Override the arguments. For advanced users only. argsOverride: [] # filenames defines list of files for fluentd to tail and export. filenames: - tetragon.log # stdout specific exporter settings stdout: extraEnv: [] # extraEnv: # - name: foo # value: bar # * When enabledCommand=true and commandOverride is not set, the command inserted will be hubble-export-stdout. # This supports the default for the current deployment instructions to deploy stdout-export sidecar container. # * When enabledCommand=true and commandOverride override is set, the command inserted will be the value of commandOverride. # This is useful for inserting another sidecar container that requires a command override. # * When enabledCommand=false, no command will be specified in the manifest and container's default command will take over. enabledCommand: true # * When enabledArgs=true and argsOverride is not set, the args inserted will be the default ones for export-stdout. # * When enabledArgs=true and argsOverride override is set, the args value inserted will be the value of argsOverride. # This is useful for inserting another sidecar container that requires args override. # * When enabledArgs=false, no command will be specified in the manifest and container's default args value will take over. enabledArgs: true # specific manifest command to use commandOverride: [] # specific manifest args to use argsOverride: [] # Extra volume mounts to add to stdout export pod extraVolumeMounts: [] image: override: ~ repository: quay.io/cilium/hubble-export-stdout ================================================ FILE: kubernetes/apps/base/kube-system/tetragon/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: tetragon namespace: kube-system spec: path: "./apps/base/kube-system/tetragon/app" wait: true targetNamespace: kube-system sourceRef: kind: ExternalArtifact name: tetragon namespace: flux-system ================================================ FILE: kubernetes/apps/base/network-system/README.md ================================================ # Cloudflare DDNS https://github.com/hotio/docker-cloudflare-ddns Use the following command to generate the secret with the required fields for the deployment. ```bash kubectl create secret generic cloudflare-ddns \ --from-literal=api-token="" \ --from-literal=zones="owncloud.ai" \ --from-literal=hosts="owncloud.ai" \ --from-literal=record-types="A;A;AAAA" \ --namespace network-system --dry-run -o yaml > .secrets/k8s-secret-cloudflare-ddns.yaml ``` # Cert-Manager ```bash kubectl create secret generic cloudflare-cert-manager-token \ --from-literal=api-token="" \ --namespace network-system --dry-run -o yaml > .secrets/k8s-secret-cloudflare-cert-manager-token.yaml ``` # Oauth2-Proxy https://github.com/oauth2-proxy/oauth2-proxy/blob/master/docs/configuration/configuration.md Run the following command to generate a secure cookie secret: ```bash python -c 'import os,base64; print base64.b64encode(os.urandom(16))' ``` Then, create the Kubernetes secret, substituting the highlighted values for your cookie secret, your GitHub client ID, and your GitHub secret key: ```bash kubectl -n network-system create secret generic oauth2-proxy \ --from-literal=cookie-secret="" \ --from-literal=client-id="" \ --from-literal=client-secret="" --dry-run -o yaml > .secrets/k8s-secret-github-oauth2.yaml ``` ================================================ FILE: kubernetes/apps/base/network-system/cert-manager/app/clusterissuer-prod.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cert-manager.io/clusterissuer_v1.json apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: ${PRIVATE_EMAIL} privateKeySecretRef: name: letsencrypt-prod solvers: - dns01: cloudflare: email: ${PRIVATE_EMAIL} apiTokenSecretRef: name: cert-manager-cloudflare-token key: CERT_MANAGER_CLOUDFLARE_API_TOKEN ================================================ FILE: kubernetes/apps/base/network-system/cert-manager/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: cert-manager-cloudflare-token spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: cert-manager-cloudflare-token template: data: CERT_MANAGER_CLOUDFLARE_API_TOKEN: "{{ .CERT_MANAGER_CLOUDFLARE_API_TOKEN }}" dataFrom: - extract: key: cloudflare ================================================ FILE: kubernetes/apps/base/network-system/cert-manager/app/grafanadashboard.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: cert-manager spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/20842/revisions/3/download ================================================ FILE: kubernetes/apps/base/network-system/cert-manager/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app cert-manager namespace: network-system spec: interval: 1h chartRef: kind: OCIRepository name: cert-manager valuesFrom: - kind: ConfigMap name: cert-manager-values ================================================ FILE: kubernetes/apps/base/network-system/cert-manager/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - clusterissuer-prod.yaml - externalsecret.yaml - grafanadashboard.yaml - helmrelease.yaml - ocirepository.yaml - prometheusrule.yaml configMapGenerator: - name: cert-manager-values namespace: network-system files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/network-system/cert-manager/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/network-system/cert-manager/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: cert-manager namespace: network-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: v1.20.2 url: oci://quay.io/jetstack/charts/cert-manager ================================================ FILE: kubernetes/apps/base/network-system/cert-manager/app/prometheusrule.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/prometheusrule_v1.json apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: name: cert-manager-rules spec: groups: - name: cert-manager.rules rules: - alert: CertManagerAbsent expr: |- absent(up{job="cert-manager"}) for: 30m annotations: summary: >- Cert Manager has disappeared from Prometheus service discovery labels: severity: critical - name: certificates rules: - alert: CertManagerCertExpirySoon expr: |- avg by (exported_namespace, namespace, name) (certmanager_certificate_expiration_timestamp_seconds - time()) < (21 * 24 * 3600) for: 15m annotations: summary: >- The cert {{ $labels.name }} is {{ $value | humanizeDuration }} from expiry, it should have renewed over a week ago labels: severity: critical - alert: CertManagerCertNotReady expr: |- max by (name, exported_namespace, namespace, condition) (certmanager_certificate_ready_status{condition!="True"} == 1) for: 1h annotations: summary: >- The cert {{ $labels.name }} is not ready to serve traffic labels: severity: warning - alert: CertManagerHittingRateLimits expr: |- sum by (host) (rate(certmanager_http_acme_client_request_count{status="429"}[5m])) > 0 for: 15m annotations: summary: >- Cert manager hitting LetsEncrypt rate limits labels: severity: critical ================================================ FILE: kubernetes/apps/base/network-system/cert-manager/app/values.yaml ================================================ --- crds: enabled: true # webhook: # url: # host: cert-manager-webhook.network-system.svc global: # Set the verbosity of cert-manager. Range of 0 - 6 with 6 being the most verbose. logLevel: 2 priorityClassName: platform-cluster-critical leaderElection: # Override the namespace used to store the ConfigMap for leader election namespace: 'network-system' extraArgs: # Use this flag to set a namespace that cert-manager will use to store # supporting resources required for each ClusterIssuer (default is kube-system) - --cluster-resource-namespace=network-system # When this flag is enabled, secrets will be automatically removed when the certificate resource is deleted - --enable-certificate-owner-ref=true - --dns01-recursive-nameservers=https://1.1.1.1:443/dns-query,https://1.0.0.1:443/dns-query - --dns01-recursive-nameservers-only - --default-issuer-name=letsencrypt-prod - --default-issuer-kind=ClusterIssuer prometheus: servicemonitor: enabled: true podDisruptionBudget: enabled: true ================================================ FILE: kubernetes/apps/base/network-system/cert-manager/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: cert-manager namespace: network-system spec: healthChecks: - apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease name: cert-manager namespace: network-system - apiVersion: cert-manager.io/v1 kind: ClusterIssuer name: letsencrypt-prod healthCheckExprs: - apiVersion: cert-manager.io/v1 kind: ClusterIssuer failed: status.conditions.filter(e, e.type == 'Ready').all(e, e.status == 'False') current: status.conditions.filter(e, e.type == 'Ready').all(e, e.status == 'True') dependsOn: - name: onepassword namespace: external-secrets path: "./apps/base/network-system/cert-manager/app" wait: false targetNamespace: network-system sourceRef: kind: ExternalArtifact name: cert-manager namespace: flux-system ================================================ FILE: kubernetes/apps/base/network-system/cloudflare-tunnel/app/dnsendpoint.yaml ================================================ --- # This resource defines a DNSEndpoint for the ingress gateway with a CNAME record pointing to the Cloudflare Argo tunnel. apiVersion: externaldns.k8s.io/v1alpha1 kind: DNSEndpoint metadata: name: cloudflare-tunnel namespace: networking annotations: external-dns.alpha.kubernetes.io/target: "external.${CLUSTER_DOMAIN}" external-dns.alpha.kubernetes.io/external: 'true' spec: endpoints: - dnsName: "external.${CLUSTER_DOMAIN}" recordType: CNAME targets: - "${CLOUDFLARED_TUNNEL_ID}.cfargotunnel.com" --- # This resource defines a DNSEndpoint for the Kubernetes API server with a CNAME record pointing to the Cloudflare Argo tunnel. # It is used for exposing the kube-apiserver endpoint via Cloudflared. apiVersion: externaldns.k8s.io/v1alpha1 kind: DNSEndpoint metadata: name: cloudflared-api namespace: networking annotations: external-dns.alpha.kubernetes.io/target: "api.${CLUSTER_DOMAIN}" external-dns.alpha.kubernetes.io/external: 'true' spec: endpoints: - dnsName: "api.${CLUSTER_DOMAIN}" recordType: CNAME targets: - "external.${CLUSTER_DOMAIN}" ================================================ FILE: kubernetes/apps/base/network-system/cloudflare-tunnel/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: cloudflare-tunnel spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: cloudflare-tunnel-secret template: data: TUNNEL_TOKEN: |- {{ toJson (dict "a" .CLOUDFLARED_ACCOUNT_TAG "t" .CLOUDFLARED_TUNNEL_ID "s" .CLOUDFLARED_TUNNEL_SECRET) | b64enc }} dataFrom: - extract: key: cloudflare ================================================ FILE: kubernetes/apps/base/network-system/cloudflare-tunnel/app/grafanadashboard.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: cloudflare-tunnels spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/17457/revisions/6/download ================================================ FILE: kubernetes/apps/base/network-system/cloudflare-tunnel/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app cloudflare-tunnel namespace: network-system spec: interval: 30m chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: *app : replicas: 2 strategy: RollingUpdate annotations: reloader.stakater.com/auto: "true" containers: app: image: repository: docker.io/cloudflare/cloudflared tag: 2026.5.0@sha256:59bab8d3aceec09bf6bdb07d6beca0225ca5cd7ab79436a87ea97978fe1dc4f9 env: NO_AUTOUPDATE: true TUNNEL_METRICS: 0.0.0.0:8080 TUNNEL_TRANSPORT_PROTOCOL: quic TUNNEL_POST_QUANTUM: true envFrom: - secretRef: name: cloudflare-tunnel-secret args: - tunnel - run probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /ready port: &port 8080 initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 5m memory: 10Mi limits: memory: 256Mi defaultPodOptions: topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: app.kubernetes.io/name: cloudflare-tunnel securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 seccompProfile: { type: RuntimeDefault } service: app: controller: *app ports: http: port: *port serviceMonitor: app: serviceName: *app endpoints: - port: http scheme: http path: /metrics interval: 1m scrapeTimeout: 10s configMaps: config: data: config.yaml: |- ingress: - hostname: "api.${CLUSTER_DOMAIN}" service: tcp://kubernetes.default.svc.cluster.local:443 originRequest: proxyType: socks - hostname: "*.${CLUSTER_DOMAIN}" originRequest: http2Origin: true keepAliveTimeout: 3600s originServerName: external.${CLUSTER_DOMAIN} tcpKeepAlive: 7200s service: https://envoy-external.network-system.svc.cluster.local:443 - service: http_status:404 persistence: config-file: type: configMap identifier: config globalMounts: - path: /etc/cloudflared/config.yaml subPath: config.yaml readOnly: true ================================================ FILE: kubernetes/apps/base/network-system/cloudflare-tunnel/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - dnsendpoint.yaml - externalsecret.yaml - grafanadashboard.yaml - helmrelease.yaml ================================================ FILE: kubernetes/apps/base/network-system/cloudflare-tunnel/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: cloudflare-tunnel namespace: network-system spec: path: "./apps/base/network-system/cloudflare-tunnel/app" wait: true dependsOn: - name: external-dns namespace: network-system - name: onepassword namespace: external-secrets targetNamespace: network-system sourceRef: kind: ExternalArtifact name: cloudflare-tunnel namespace: flux-system ================================================ FILE: kubernetes/apps/base/network-system/dex/app/README.md ================================================ # Dex Enter valid secrets into the values.yaml and use the following command to generate the secret, then use sealed secrets to encrypt these values to be used within the helm release resource. ```bash kubectl create secret generic dex-helm-values --from-file=values.yaml=config/dex/values.yaml --dry-run=client -n network -o yaml > secret.yaml ``` ================================================ FILE: kubernetes/apps/base/network-system/dex/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app dex spec: interval: 5m chart: spec: chart: dex version: 0.24.0 sourceRef: kind: HelmRepository name: dex-chart namespace: flux-system interval: 10m valuesFrom: - kind: ConfigMap name: dex-values ================================================ FILE: kubernetes/apps/base/network-system/dex/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: dex annotations: external-dns.alpha.kubernetes.io/external: 'true' spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'dex.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: dex port: 5556 weight: 100 ================================================ FILE: kubernetes/apps/base/network-system/dex/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - httproute.yaml - helmrelease.yaml configMapGenerator: - name: dex-values namespace: network-system files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/network-system/dex/app/kustomizeconfig.yaml ================================================ nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/network-system/dex/app/values.yaml ================================================ image: repository: dexidp/dex tag: v2.45.1 env: KUBERNETES_POD_namespace: network-system config: issuer: 'https://dex.${CLUSTER_DOMAIN}' storage: type: kubernetes config: inCluster: true oauth2: alwaysShowLoginScreen: false responseTypes: ['code', 'token', 'id_token'] skipApprovalScreen: true web: http: 0.0.0.0:5556 frontend: theme: 'tectonic' issuer: 'Homelab SSO' issuerUrl: 'https://dex.${CLUSTER_DOMAIN}' logoUrl: https://raw.githubusercontent.com/raspbernetes/docs/master/website/static/img/logo.png expiry: signingKeys: '6h' idTokens: '24h' logger: level: debug format: json # Disable default email auth and only use oauth2 providers configured as connectors enablePasswordDB: false # Remember you can have multiple connectors of the same 'type' (with different 'id's) # If you need e.g. logins with groups for two different Microsoft 'tenants' connectors: # GitHub configure 'OAuth Apps' -> 'New OAuth App', add callback URL # https://github.com/settings/developers - type: github id: github name: GitHub config: clientID: '${DEX_GITHUB_CLIENT_ID}' clientSecret: '${DEX_GITHUB_CLIENT_SECRET}' redirectURI: 'https://dex.${CLUSTER_DOMAIN}/callback' # 'orgs' can be used to map groups from Github # https://github.com/coreos/dex/blob/master/Documentation/connectors/github.md orgs: - name: raspbernetes # The 'name' must match the k8s API server's 'oidc-client-id' staticClients: - id: oauth2-proxy name: 'oauth2-proxy' secret: '${DEX_OAUTH2_PROXY_SECRET}' redirectURIs: - 'https://alert-manager.${CLUSTER_DOMAIN}/oauth2/callback' - 'https://hass.${CLUSTER_DOMAIN}/oauth2/callback' - 'https://kiali.${CLUSTER_DOMAIN}/oauth2/callback' - 'https://prometheus.${CLUSTER_DOMAIN}/oauth2/callback' - 'https://sealed-secrets.${CLUSTER_DOMAIN}/oauth2/callback' - id: grafana name: 'grafana' secret: '${DEX_GRAFANA_SECRET}' redirectURIs: - 'https://grafana.${CLUSTER_DOMAIN}/login/generic_oauth' - id: dex-k8s-authenticator name: dex-k8s-authenticator secret: ${DEX_K8S_CLIENT_SECRET} redirectURIs: - https://login.${CLUSTER_DOMAIN}/callback - id: LitmusPortalAuthBackend name: 'LitmusPortalAuthBackend' secret: '${DEX_LITMUS_SECRET}' redirectURIs: - '/auth/dex/callback' - 'http://localhost:8080/auth/dex/callback' # Included for local testing purposes ================================================ FILE: kubernetes/apps/base/network-system/dex/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: dex namespace: network-system spec: path: "./apps/base/network-system/dex/app" wait: true dependsOn: - name: onepassword namespace: external-secrets - name: cert-manager namespace: network-system targetNamespace: network-system sourceRef: kind: ExternalArtifact name: dex namespace: flux-system ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/clusterrolebinding.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: k8s-admins-binding roleRef: kind: ClusterRole name: cluster-admin apiGroup: rbac.authorization.k8s.io subjects: - kind: Group name: raspbernetes:k8s-admins apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: k8s-guests-binding roleRef: kind: ClusterRole name: view apiGroup: rbac.authorization.k8s.io subjects: - kind: Group name: raspbernetes:k8s-guests apiGroup: rbac.authorization.k8s.io ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app dex-k8s-authenticator namespace: network-system spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: *app : replicas: 1 strategy: RollingUpdate containers: app: image: repository: ghcr.io/xunholy/dex-k8s-authenticator tag: 9e61a68b98fc980275a966137927b79e0d575103 probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /healthz port: &port 5555 initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 10m memory: 32Mi limits: memory: 128Mi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 seccompProfile: { type: RuntimeDefault } service: app: controller: *app ports: http: port: *port configMaps: config: data: config.yaml: |- listen: http://0.0.0.0:5555 web_path_prefix: / debug: true clusters: - name: kubernetes short_description: "Cluster 00" description: "Cluster Login" client_secret: "${DEX_K8S_CLIENT_SECRET}" issuer: "https://dex.${CLUSTER_DOMAIN}" k8s_master_uri: https://${CLUSTER_CONTROLPLANE_VIP}:6443 client_id: "${DEX_K8S_CLIENT_ID}" redirect_uri: https://login.${CLUSTER_DOMAIN}/callback k8s_ca_pem: | -----BEGIN CERTIFICATE----- MIIBijCCATCgAwIBAgIRAKe1fimhdjgMm+tAfHtovvowCgYIKoZIzj0EAwIwFTET MBEGA1UEChMKa3ViZXJuZXRlczAeFw0yNTEwMTEwMzEzMTdaFw0zNTEwMDkwMzEz MTdaMBUxEzARBgNVBAoTCmt1YmVybmV0ZXMwWTATBgcqhkjOPQIBBggqhkjOPQMB BwNCAATlqT+4DaHxabdX4JxwKstgqPkuR/1+H7RZgOmA1n/jjQP3jjKDxqMIzpbQ i6P/BFuYMY3L04kEz7iYqWMxa9byo2EwXzAOBgNVHQ8BAf8EBAMCAoQwHQYDVR0l BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O BBYEFAMIRFQ/gcCC4A7dGhyWciGP0c9yMAoGCCqGSM49BAMCA0gAMEUCIGj+4ye6 c2F26IJW75btkhtNGtonZxzgCahoguVKz9lPAiEApKt6F2obZ9axsIytkCtPph3R eL9OYSE6Q2PF5CvX5gI= -----END CERTIFICATE----- persistence: config: type: configMap identifier: config globalMounts: - path: /app/config.yaml subPath: config.yaml readOnly: true ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: dex-k8s-authenticator namespace: network-system annotations: external-dns.alpha.kubernetes.io/external: 'true' spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'login.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: dex-k8s-authenticator port: 5555 weight: 100 ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - httproute.yaml - clusterrolebinding.yaml - helmrelease.yaml ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/Dockerfile ================================================ FROM golang:1.25-alpine AS builder RUN apk add --no-cache ca-certificates WORKDIR /src COPY go.mod go.sum ./ RUN go mod download COPY *.go ./ RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /app/bin/dex-k8s-authenticator . FROM alpine:3.21 RUN apk add --no-cache ca-certificates tini \ && addgroup -g 1000 -S app \ && adduser -u 1000 -S app -G app WORKDIR /app COPY --from=builder /app/bin/dex-k8s-authenticator /app/bin/dex-k8s-authenticator COPY html/ /app/html/ COPY templates/ /app/templates/ COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh && mkdir -p /certs && chown -R app:app /app /certs USER 1000:1000 EXPOSE 5555 ENTRYPOINT ["/sbin/tini", "--", "/entrypoint.sh"] CMD ["--config", "/app/config.yaml"] ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/dex-auth.go ================================================ package main import ( "bytes" "encoding/json" "fmt" "log" "net/http" "path" "time" oidc "github.com/coreos/go-oidc/v3/oidc" "os" "github.com/spf13/cast" "golang.org/x/oauth2" ) const exampleAppState = "Vgn2lp5QnymFtLntKX5dM8k773PwcM87T4hQtiESC1q8wkUBgw5D3kH0r5qJ" func (cluster *Cluster) oauth2Config() *oauth2.Config { return &oauth2.Config{ ClientID: cluster.Client_ID, ClientSecret: cluster.Client_Secret, Endpoint: cluster.Provider.Endpoint(), Scopes: cluster.Scopes, RedirectURL: cluster.Redirect_URI, } } func (config *Config) handleIndex(w http.ResponseWriter, r *http.Request) { if len(config.Clusters) == 1 && r.URL.String() == config.Web_Path_Prefix { http.Redirect(w, r, path.Join(config.Web_Path_Prefix, "login", config.Clusters[0].Name), http.StatusSeeOther) } else { renderIndex(w, config) } } func (cluster *Cluster) handleLogin(w http.ResponseWriter, r *http.Request) { log.Printf("Handling login-uri for: %s", cluster.Name) authCodeURL := cluster.oauth2Config().AuthCodeURL(exampleAppState, oauth2.AccessTypeOffline) if cluster.Connector_ID != "" { log.Printf("Using dex connector with id %#q", cluster.Connector_ID) authCodeURL = fmt.Sprintf("%s&connector_id=%s", authCodeURL, cluster.Connector_ID) } log.Printf("Redirecting post-loginto: %s", authCodeURL) http.Redirect(w, r, authCodeURL, http.StatusSeeOther) } func (cluster *Cluster) handleCallback(w http.ResponseWriter, r *http.Request) { var ( err error token *oauth2.Token IdpCaPem string ) // An error message to that presented to the user userErrorMsg := "Invalid token request" log.Printf("Handling callback for: %s", cluster.Name) ctx := oidc.ClientContext(r.Context(), cluster.Client) oauth2Config := cluster.oauth2Config() switch r.Method { case "GET": // Authorization redirect callback from OAuth2 auth flow. if errMsg := r.FormValue("error"); errMsg != "" { cluster.renderHTMLError(w, userErrorMsg, http.StatusBadRequest) log.Printf("handleCallback: request error. error: %s, error_description: %s", errMsg, r.FormValue("error_description")) return } code := r.FormValue("code") if code == "" { cluster.renderHTMLError(w, userErrorMsg, http.StatusBadRequest) log.Printf("handleCallback: no code in request: %q", r.Form) return } if state := r.FormValue("state"); state != exampleAppState { cluster.renderHTMLError(w, userErrorMsg, http.StatusBadRequest) log.Printf("handleCallback: expected state %q got %q", exampleAppState, state) return } token, err = oauth2Config.Exchange(ctx, code) case "POST": // Form request from frontend to refresh a token. refresh := r.FormValue("refresh_token") if refresh == "" { cluster.renderHTMLError(w, userErrorMsg, http.StatusBadRequest) log.Printf("handleCallback: no refresh_token in request: %q", r.Form) return } t := &oauth2.Token{ RefreshToken: refresh, Expiry: time.Now().Add(-time.Hour), } token, err = oauth2Config.TokenSource(ctx, t).Token() default: // Return non-HTML error for non GET/POST requests which probably wasn't executed by browser http.Error(w, fmt.Sprintf("Method not implemented: %s", r.Method), http.StatusBadRequest) return } if err != nil { cluster.renderHTMLError(w, userErrorMsg, http.StatusBadRequest) log.Printf("handleCallback: failed to get token: %v", err) return } rawIDToken, ok := token.Extra("id_token").(string) if !ok { cluster.renderHTMLError(w, userErrorMsg, http.StatusBadRequest) log.Printf("handleCallback: no id_token in response: %q", token) return } idToken, err := cluster.Verifier.Verify(r.Context(), rawIDToken) if err != nil { cluster.renderHTMLError(w, userErrorMsg, http.StatusBadRequest) log.Printf("handleCallback: failed to verify ID token: %q, err: %v", rawIDToken, err) return } var claims json.RawMessage if err = idToken.Claims(&claims); err != nil { cluster.renderHTMLError(w, userErrorMsg, http.StatusBadRequest) log.Printf("handleCallback: failed to unmarshal json payload of ID token into claims: %v", err) return } buff := new(bytes.Buffer) if err = json.Indent(buff, []byte(claims), "", " "); err != nil { cluster.renderHTMLError(w, userErrorMsg, http.StatusBadRequest) log.Printf("handleCallback: failed to indent json: %v", err) return } if cluster.Config.IDP_Ca_Pem != "" { IdpCaPem = cluster.Config.IDP_Ca_Pem } else if cluster.Config.IDP_Ca_Pem_File != "" { content, err := os.ReadFile(cluster.Config.IDP_Ca_Pem_File) if err != nil { log.Fatalf("Failed to load CA from file %s, %s", cluster.Config.IDP_Ca_Pem_File, err) } IdpCaPem = cast.ToString(content) } cluster.renderToken(w, rawIDToken, token.RefreshToken, cluster.Config.IDP_Ca_URI, IdpCaPem, cluster.Config.Logo_Uri, cluster.Config.Web_Path_Prefix, cluster.Config.Kubectl_Version, buff.Bytes()) } ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/entrypoint.sh ================================================ #!/bin/sh if [ -n "$(ls -A /certs)" ]; then cp -L /certs/*.crt /usr/local/share/ca-certificates/ 2>/dev/null update-ca-certificates fi exec /app/bin/dex-k8s-authenticator "$@" ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/go.mod ================================================ module github.com/xunholy/dex-k8s-authenticator go 1.25.0 require ( github.com/coreos/go-oidc/v3 v3.18.0 github.com/spf13/cast v1.7.1 github.com/spf13/cobra v1.9.1 github.com/spf13/viper v1.20.1 golang.org/x/oauth2 v0.36.0 ) require ( github.com/fsnotify/fsnotify v1.8.0 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/sagikazarmark/locafero v0.7.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.12.0 // indirect github.com/spf13/pflag v1.0.6 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.38.0 // indirect golang.org/x/text v0.31.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/go.sum ================================================ github.com/coreos/go-oidc/v3 v3.18.0 h1:V9orjXynvu5wiC9SemFTWnG4F45v403aIcjWo0d41+A= github.com/coreos/go-oidc/v3 v3.18.0/go.mod h1:DYCf24+ncYi+XkIH97GY1+dqoRlbaSI26KVTCI9SrY4= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo= github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/html/static/main.css ================================================ * { box-sizing: border-box; } body { margin: 0; font-family: Arial; } h3 { font-size: 16px; } pre { background-color: #eff0f1; padding: 5px; white-space: pre-wrap; overflow-wrap: break-word; } .dex-container { color: #333; margin: 45px auto; max-width: 500px; min-width: 320px; text-align: center; } .dex-kubeconfig-container { color: #333; margin: 45px auto; max-width: 90%; min-width: 320px; text-align: left; } .dex-btn { border-radius: 4px; border: 0; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.25), 0 0 1px rgba(0, 0, 0, 0.25); cursor: pointer; font-size: 16px; padding: 0; } .dex-btn:focus { outline: none; } .dex-btn:active { box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); outline: none; } .dex-btn-icon { background-position: center; background-repeat: no-repeat; background-size: 24px; border-radius: 4px 0 0 4px; float: left; height: 36px; margin-right: 5px; width: 36px; } .dex-btn-icon--local { background-color: #84B6EF; background-image: url(./button.svg); } .dex-btn-text { font-weight: 600; line-height: 36px; padding: 6px 12px; text-align: center; } .dex-separator { color: #999; } .dex-error-box { background-color: #DD1327; color: #fff; font-size: 14px; font-weight: normal; max-width: 320px; padding: 4px 0; } .dex-error-box { margin: 20px auto; } div.groups { border: 1px solid #ccc; background-color: #f1f1f1; margin-bottom: 15px; } div.command { margin-top: 15px; } ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/html/static/snippets.js ================================================ var snippets=document.querySelectorAll('.snippet');[].forEach.call(snippets,function(snippet){snippet.firstChild.insertAdjacentHTML('beforebegin','');});var clipboardSnippets=new ClipboardJS('[data-clipboard-snippet]',{target:function(trigger){return trigger.nextElementSibling;}});clipboardSnippets.on('success',function(e){e.clearSelection();showTooltip(e.trigger,'Copied!');});clipboardSnippets.on('error',function(e){showTooltip(e.trigger,fallbackMessage(e.action));}); ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/html/static/styles.css ================================================ .theme-body { background-color: #efefef; color: #333; font-family: 'Source Sans Pro', Helvetica, sans-serif; } .theme-navbar { background-color: #fff; box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2); color: #333; font-size: 13px; font-weight: 100; height: 46px; overflow: hidden; padding: 0 10px; } .theme-navbar__logo-wrap { display: inline-block; height: 100%; overflow: hidden; padding: 10px 15px; width: 300px; } .theme-navbar__logo { height: 100%; max-height: 25px; } .theme-heading { font-size: 20px; font-weight: 500; margin-bottom: 10px; margin-top: 0; } .theme-panel { background-color: #fff; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); padding: 30px; } .theme-btn-provider { background-color: #fff; color: #333; min-width: 350px; } .theme-btn-provider:hover { color: #999; } .theme-btn--primary { background-color: #333; border: none; color: #fff; min-width: 200px; padding: 6px 12px; } .theme-btn--primary:hover { background-color: #666; color: #fff; } .theme-btn--success { background-color: #2FC98E; color: #fff; width: 350px; } .theme-btn--success:hover { background-color: #49E3A8; } .theme-form-row { display: block; margin: 20px auto; } .theme-form-input:focus, .theme-form-input:active { border-color: #66AFE9; outline: none; } .theme-form-label { font-size: 13px; font-weight: 600; margin: 4px auto; position: relative; text-align: left; width: 350px; } .theme-form-description { font-size: 13px; font-weight: 300; margin: 4px auto; position: relative; text-align: left; width: 350px; } ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/html/static/tabs.css ================================================ /* Style the tab */ .tab { overflow: hidden; border: 1px solid #ccc; background-color: #f1f1f1; } /* Style the buttons inside the tab */ .tab button { background-color: inherit; float: left; border: none; outline: none; cursor: pointer; padding: 14px 16px; transition: 0.3s; font-size: 17px; } /* Change background color of buttons on hover */ .tab button:hover { background-color: #ddd; } /* Create an active/current tablink class */ .tab button.active { background-color: #ccc; } /* Style the tab content */ .tabcontent { display: none; padding: 6px 12px; border: 1px solid #ccc; border-top: none; } ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/html/static/tooltips.js ================================================ var btns=document.querySelectorAll('.btn');for(var i=0;i 0 { for _, cert := range config.Trusted_Root_Ca { ok := certp.AppendCertsFromPEM([]byte(cert)) if !ok { log.Fatalf("Failed to parse a trusted cert, pem format expected") } } } // Load CA certs from file if config.Trusted_Root_Ca_File != "" { content, err := os.ReadFile(config.Trusted_Root_Ca_File) if err != nil { log.Fatalf("Failed to read file Trusted Root CA %s, %v", config.Trusted_Root_Ca_File, err) } ok := certp.AppendCertsFromPEM([]byte(content)) if !ok { log.Fatalf("Failed to parse a trusted cert from file %s, pem format expected", config.Trusted_Root_Ca_File) } } mTlsConfig := &tls.Config{ MinVersion: tls.VersionTLS12, // minimum TLS 1.2 // P curve order does not matter, as breaking one means all others can be brute-forced as well: // Golang developers prefer: CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256, tls.CurveP384, tls.CurveP521}, PreferServerCipherSuites: true, // Server chooses ciphersuite, order matters below: CipherSuites: []uint16{ tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, tls.TLS_CHACHA20_POLY1305_SHA256, // TLS 1.3 tls.TLS_AES_256_GCM_SHA384, // TLS 1.3 tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_AES_128_GCM_SHA256, // TLS 1.3 }, RootCAs: certp, } tr := &http.Transport{ TLSClientConfig: mTlsConfig, // Set proxy callback for proxy support in this transport Proxy: http.ProxyFromEnvironment, } // Ensure trailing slash on web-path-prefix web_path_prefix := config.Web_Path_Prefix if web_path_prefix != "/" { web_path_prefix = fmt.Sprintf("%s/", path.Clean(web_path_prefix)) config.Web_Path_Prefix = web_path_prefix } // Generate handlers for each cluster for i := range config.Clusters { cluster := config.Clusters[i] if debug { if cluster.Client == nil { cluster.Client = &http.Client{ Transport: debugTransport{tr}, } } else { cluster.Client.Transport = debugTransport{tr} } } else { cluster.Client = &http.Client{Transport: tr} } ctx := oidc.ClientContext(context.Background(), cluster.Client) log.Printf("Creating new provider %s", cluster.Issuer) provider, err := oidc.NewProvider(ctx, cluster.Issuer) if err != nil { log.Fatalf("Failed to query provider %q: %v\n", cluster.Issuer, err) } cluster.Provider = provider log.Printf("Verifying client %s", cluster.Client_ID) verifier := provider.Verifier(&oidc.Config{ClientID: cluster.Client_ID}) cluster.Verifier = verifier if err := provider.Claims(&s); err != nil { log.Fatalf("Failed to parse provider scopes_supported: %v", err) } if len(s.ScopesSupported) == 0 { // scopes_supported is a "RECOMMENDED" discovery claim, not a required // one. If missing, assume that the provider follows the spec and has // an "offline_access" scope. cluster.OfflineAsScope = true } else { // See if scopes_supported has the "offline_access" scope. cluster.OfflineAsScope = func() bool { for _, scope := range s.ScopesSupported { if scope == oidc.ScopeOfflineAccess { return true } } return false }() } if len(cluster.Scopes) == 0 { cluster.Scopes = []string{"openid", "profile", "email", "offline_access", "groups"} } if cluster.K8s_Ca_Pem_File != "" { content, err := os.ReadFile(cluster.K8s_Ca_Pem_File) if err != nil { log.Fatalf("Failed to load CA from file %s, %s", cluster.K8s_Ca_Pem_File, err) } cluster.K8s_Ca_Pem = cast.ToString(content) } if cluster.K8s_Ca_Pem == "" && cluster.K8s_Ca_Pem_Base64_Encoded != "" { p, err := base64.StdEncoding.DecodeString(cluster.K8s_Ca_Pem_Base64_Encoded) if err != nil { log.Fatalf("Failed to base64 decode ca pem: %s", err.Error()) } cluster.K8s_Ca_Pem = string(p) } cluster.Config = config base_redirect_uri, err := url.Parse(cluster.Redirect_URI) if err != nil { log.Fatalf("Parsing redirect_uri address: %v", err) } // Each cluster gets a different login and callback URL http.HandleFunc(base_redirect_uri.Path, cluster.handleCallback) log.Printf("Registered callback handler at: %s", base_redirect_uri.Path) login_uri := path.Join(config.Web_Path_Prefix, "login", cluster.Name) http.HandleFunc(login_uri, cluster.handleLogin) log.Printf("Registered login handler at: %s", login_uri) } // Index page http.HandleFunc(config.Web_Path_Prefix, config.handleIndex) // Serve static html assets fs := http.FileServer(http.Dir("html/static/")) static_uri := path.Join(config.Web_Path_Prefix, "static") + "/" log.Printf("Registered static assets handler at: %s", static_uri) http.Handle(static_uri, http.StripPrefix(static_uri, fs)) // Determine whether to use TLS or not switch listenURL.Scheme { case "http": log.Printf("Listening on %s", config.Listen) err := http.ListenAndServe(listenURL.Host, nil) log.Fatal(err) case "https": log.Printf("Listening on %s", config.Listen) err := http.ListenAndServeTLS(listenURL.Host, config.TLS_Cert, config.TLS_Key, nil) log.Fatal(err) default: log.Fatalf("Listen address %q is not using http or https", config.Listen) } } func substituteEnvVarsRecursive(copy, original reflect.Value) { switch original.Kind() { case reflect.Ptr: originalValue := original.Elem() if !originalValue.IsValid() { return } copy.Set(reflect.New(originalValue.Type())) substituteEnvVarsRecursive(copy.Elem(), originalValue) case reflect.Interface: originalValue := original.Elem() copyValue := reflect.New(originalValue.Type()).Elem() substituteEnvVarsRecursive(copyValue, originalValue) copy.Set(copyValue) case reflect.Struct: for i := 0; i < original.NumField(); i += 1 { substituteEnvVarsRecursive(copy.Field(i), original.Field(i)) } case reflect.Slice: copy.Set(reflect.MakeSlice(original.Type(), original.Len(), original.Cap())) for i := 0; i < original.Len(); i += 1 { substituteEnvVarsRecursive(copy.Index(i), original.Index(i)) } case reflect.Map: copy.Set(reflect.MakeMap(original.Type())) for _, key := range original.MapKeys() { originalValue := original.MapIndex(key) copyValue := reflect.New(originalValue.Type()).Elem() substituteEnvVarsRecursive(copyValue, originalValue) copy.SetMapIndex(key, copyValue) } case reflect.String: replacedString := substituteEnvVars(original.Interface().(string)) copy.SetString(replacedString) default: copy.Set(original) } } var RootCmd = &cobra.Command{ Use: "dex-k8s-authenticator", Short: "Dex Kubernetes Authenticator", Long: `Dex Kubernetes Authenticator provides a web-interface to generate a kubeconfig file based on a selected Kubernetes cluster. One or more clusters can be defined in the configuration file.`, Run: func(cmd *cobra.Command, args []string) { var config Config err := viper.Unmarshal(&config) if err != nil { log.Fatalf("Unable to decode configuration into struct, %v", err) } original := reflect.ValueOf(config) copy := reflect.New(original.Type()).Elem() substituteEnvVarsRecursive(copy, original) // Start the app start_app(copy.Interface().(Config)) // Fallback if no args specified cmd.HelpFunc()(cmd, args) }, } // Read in config file func initConfig() { if config_file != "" { //viper.SetConfigFile(config_file) // get the filepath abs, err := filepath.Abs(config_file) if err != nil { log.Fatalf("Error reading config file, %s", err) } // get the config name base := filepath.Base(abs) // get the path path := filepath.Dir(abs) viper.SetConfigName(strings.Split(base, ".")[0]) viper.AddConfigPath(path) viper.SetDefault("web_path_prefix", "/") config, err := os.ReadFile(config_file) if err != nil { log.Fatalf("Error reading config file, %s", err) } origConfigStr := bytes.NewBuffer(config).String() if err := viper.ReadConfig(bytes.NewBufferString(origConfigStr)); err != nil { log.Fatalf("viper.ReadConfig failed to read config, %s", err.Error()) } log.Printf("Using config file: %s", viper.ConfigFileUsed()) } } // Initialization func init() { cobra.OnInitialize(initConfig) if err := viper.BindPFlags(RootCmd.Flags()); err != nil { log.Fatal(err) } RootCmd.Flags().StringVar(&config_file, "config", "", "./config.yml") RootCmd.PersistentFlags().BoolVarP(&debug, "debug", "d", false, "Enable debug logging") } // Let's go! func main() { if err := RootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(-1) } } ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/templates/error.html ================================================ Error - {{ .Code }}
{{ if .Logo_Uri }}
{{ end }}

Error - {{ .Code }}

{{ if .Error_Description }}

An error has ocurred with the following details:

{{ .Error_Description }}

{{ end }}
================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/templates/id-token-tab.html ================================================ {{ define "id-token-content" }}

The ID Token signed by dex and returned as part of the OAuth2 response - represented as a Json Web Token (JWT).

{{ .IDToken }}
{{ end }} ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/templates/index.html ================================================ Generate Kubernetes Token
{{ if .Logo_Uri }}
{{ end }}

Generate Kubernetes Token

Select which cluster you require a token for:

{{ range $cluster := .Clusters }}

{{$cluster.Description}}

{{ end }}
================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/templates/kubeconfig.html ================================================ Kubernetes Configuration
{{ if .LogoURI }}
{{ end }}

Generated Kubernetes Token - {{ .ShortDescription }}

Please check that you have been assigned to the expected Groups, then follow the instructions based on your OS.

{{ .Claims }}
{{ template "linux-tab-content" . }}
{{ template "mac-tab-content" . }}
{{ template "windows-tab-content" . }}
{{ template "id-token-content" . }}
================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/templates/linux-mac-common.html ================================================ {{ define "linux-mac-common" }} {{ if .IDPCaURI }}

Copy IDP CA Certificate From URL

Copy this CA Certificate and download it to your .kube directory

curl --create-dirs -s {{ .IDPCaURI }} -o ${HOME}/.kube/certs/{{ .ClusterName }}/idp-ca.crt
{{ end }} {{ if .IDPCaPem }}

Copy IDP CA Certificate From PEM

Put the CA Certificate into your .kube directory

mkdir -p ${HOME}/.kube/certs/{{ .ClusterName }}/ && cat << EOF > ${HOME}/.kube/certs/{{ .ClusterName }}/idp-ca.crt
{{ .IDPCaPem }}
EOF
{{ end }} {{ if .K8sCaURI }}

Copy Kubernetes CA Certificate From URL

Copy this CA Certificate and download it to your .kube directory

curl --create-dirs -s {{ .K8sCaURI }} -o ${HOME}/.kube/certs/{{ .ClusterName }}/k8s-ca.crt
{{ end }} {{ if .K8sCaPem }}

Copy Kubernetes CA Certificate From PEM

Put the CA Certificate into your .kube directory

mkdir -p ${HOME}/.kube/certs/{{ .ClusterName }}/ && cat << EOF > ${HOME}/.kube/certs/{{ .ClusterName }}/k8s-ca.crt
{{ .K8sCaPem }}
EOF
{{ end }}

Run configuration commands

These commands will update ~/.kube/config

kubectl config set-cluster {{ .ClusterName }} \
  {{- if or .K8sCaPem .K8sCaURI }}
    --certificate-authority=${HOME}/.kube/certs/{{ .ClusterName}}/k8s-ca.crt \
  {{- end }}
    --server={{ .K8sMasterURI }}
kubectl config set-credentials {{ .Username }}-{{ .ClusterName }} \
    --auth-provider=oidc \
    --auth-provider-arg="idp-issuer-url={{ .Issuer }}" \
    --auth-provider-arg="client-id={{ .ClientID }}" \
    --auth-provider-arg="client-secret={{ .ClientSecret }}" \
    --auth-provider-arg="refresh-token={{ .RefreshToken }}" \
    --auth-provider-arg="id-token={{ .IDToken }}"
  {{- if or (.IDPCaURI) (.IDPCaPem) }} \
    --auth-provider-arg=idp-certificate-authority=${HOME}/.kube/certs/{{ .ClusterName }}/idp-ca.crt
  {{- end }}
kubectl config set-context {{ if not .StaticContextName }}{{ .Username }}-{{ end }}{{ .ClusterName }} \
    --cluster={{ .ClusterName }}{{ if .Namespace }} --namespace={{ .Namespace }}{{ end }} \
    --user={{ .Username}}-{{.ClusterName }}
kubectl config use-context {{ if not .StaticContextName }}{{ .Username }}-{{ end }}{{ .ClusterName}}
{{ end }} ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/templates/linux-tab.html ================================================ {{ define "linux-tab-content" }}

Install and Set Up kubectl

{{ template "linux-mac-common" . }} {{ end }} ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/templates/mac-tab.html ================================================ {{ define "mac-tab-content" }}

Install and Set Up kubectl

{{ template "linux-mac-common" . }} {{ end }} ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/templates/windows-tab.html ================================================ {{ define "windows-tab-content" }}

Install and Set Up kubectl

{{ if .IDPCaURI }}

Copy IDP CA Certificate From URL

Copy this CA Certificate and download it to your .kube directory

curl --create-dirs -s {{ .IDPCaURI }} -o ${HOME}/.kube/certs/{{ .ClusterName }}/idp-ca.crt
{{ end }} {{ if .IDPCaPem }}

Copy IDP CA From Pem

Put the CA Certificate into your .kube directory

mkdir -p ${HOME}/.kube/certs/{{ .ClusterName }}/ && cat << EOF > ${HOME}/.kube/certs/{{ .ClusterName }}/idp-ca.crt
{{ .IDPCaPem}}
EOF
{{ end }} {{ if .K8sCaURI }}

Copy Kubernetes CA Certificate From URL

Copy this CA Certificate and download it to your .kube directory

curl --create-dirs -s {{ .K8sCaURI }} -o ${HOME}/.kube/certs/{{ .ClusterName }}/k8s-ca.crt
{{ end }} {{ if .K8sCaPem }}

Copy Kubernetes CA Certificate From PEM

Put the CA Certificate into your .kube directory

mkdir -p ${HOME}/.kube/certs/{{ .ClusterName }}/ && cat << EOF > ${HOME}/.kube/certs/{{ .ClusterName }}/k8s-ca.crt
{{ .K8sCaPem }}
EOF
{{ end }}

Run configuration commands

These commands will update ~/.kube/config

kubectl config set-cluster {{ .ClusterName }}
    {{- if or .K8sCaPem .K8sCaURI }} --certificate-authority=${HOME}/.kube/certs/{{ .ClusterName}}/k8s-ca.crt
    {{- end }} --server={{ .K8sMasterURI }}
kubectl config set-credentials {{ .Username }}-{{ .ClusterName }} --auth-provider=oidc --auth-provider-arg=idp-issuer-url={{ .Issuer }} --auth-provider-arg=client-id={{ .ClientID }} --auth-provider-arg=client-secret={{ .ClientSecret }} --auth-provider-arg=refresh-token={{ .RefreshToken }} --auth-provider-arg=id-token={{ .IDToken }}
  {{- if or (.IDPCaURI) (.IDPCaPem) }} --auth-provider-arg=idp-certificate-authority=${HOME}/.kube/certs/{{ .ClusterName }}/idp-ca.crt
  {{- end }}
kubectl config set-context {{ if not .StaticContextName }}{{ .Username }}-{{ end }}{{ .ClusterName }} --cluster={{ .ClusterName }} --user={{ .Username}}-{{.ClusterName }}
kubectl config use-context {{ if not .StaticContextName }}{{ .Username }}-{{ end }}{{ .ClusterName}}
{{ end }} ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/app/resources/templates.go ================================================ // FIXME: Dislike this file a bit - what's the take on referencing // viper config values (treat it as a global, or pass values around?) package main import ( "encoding/json" "fmt" "html/template" "log" "net/http" "strings" ) // compile all templates and cache them var templates = template.Must(template.ParseGlob("./templates/*.html")) func renderIndex(w http.ResponseWriter, config *Config) { t, _ := template.ParseFiles("./templates/index.html") err := t.Execute(w, config) if err != nil { log.Println(err) http.Error(w, http.StatusText(500), 500) } } type templateData struct { IDToken string RefreshToken string RedirectURL string Claims string Username string Issuer string ClusterName string ShortDescription string ClientSecret string ClientID string K8sMasterURI string K8sCaURI string K8sCaPem string IDPCaURI string IDPCaPem string LogoURI string Web_Path_Prefix string StaticContextName bool KubectlVersion string Namespace string } func (cluster *Cluster) renderToken(w http.ResponseWriter, idToken, refreshToken string, idpCaURI string, idpCaPem string, logoURI string, webPathPrefix string, kubectlVersion string, claims []byte) { var data map[string]interface{} err := json.Unmarshal(claims, &data) if err != nil { panic(err) } unix_username := "user" if data["email"] != nil { email := data["email"].(string) unix_username = strings.Split(email, "@")[0] } token_data := templateData{ IDToken: idToken, RefreshToken: refreshToken, RedirectURL: cluster.Redirect_URI, Claims: string(claims), Username: unix_username, Issuer: data["iss"].(string), ClusterName: cluster.Name, ShortDescription: cluster.Short_Description, ClientSecret: cluster.Client_Secret, ClientID: cluster.Client_ID, K8sMasterURI: cluster.K8s_Master_URI, K8sCaURI: cluster.K8s_Ca_URI, K8sCaPem: cluster.K8s_Ca_Pem, IDPCaURI: idpCaURI, IDPCaPem: idpCaPem, LogoURI: logoURI, Web_Path_Prefix: webPathPrefix, StaticContextName: cluster.Static_Context_Name, Namespace: cluster.Namespace, KubectlVersion: kubectlVersion} if err := templates.ExecuteTemplate(w, "kubeconfig.html", token_data); err != nil { log.Println(err) http.Error(w, http.StatusText(500), 500) } } // renderHTMLError renders an HTML page that presents an HTTP error. func (cluster *Cluster) renderHTMLError(w http.ResponseWriter, errorMsg string, code int) { w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("X-Content-Type-Options", "nosniff") w.WriteHeader(code) if err := templates.ExecuteTemplate(w, "error.html", map[string]string{ "Logo_Uri": cluster.Config.Logo_Uri, "Web_Path_Prefix": cluster.Config.Web_Path_Prefix, "Code": fmt.Sprintf("%d", code), "Error_Description": errorMsg, }); err != nil { log.Println(err) http.Error(w, http.StatusText(500), 500) } } ================================================ FILE: kubernetes/apps/base/network-system/dex-k8s-authenticator/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: dex-k8s-authenticator namespace: network-system spec: path: "./apps/base/network-system/dex-k8s-authenticator/app" wait: true targetNamespace: network-system sourceRef: kind: ExternalArtifact name: dex-k8s-authenticator namespace: flux-system ================================================ FILE: kubernetes/apps/base/network-system/echo-server/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app echo-server namespace: network-system spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: echo-server: replicas: 1 strategy: RollingUpdate containers: app: image: repository: ghcr.io/mendhak/http-https-echo tag: 40 env: HTTP_PORT: &port 80 LOG_WITHOUT_NEWLINE: true LOG_IGNORE_PATH: /healthz PROMETHEUS_ENABLED: true probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /healthz port: *port initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } seccompProfile: type: RuntimeDefault resources: requests: cpu: 10m limits: memory: 128Mi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 seccompProfile: { type: RuntimeDefault } service: app: controller: *app ports: http: port: *port serviceMonitor: app: serviceName: *app endpoints: - port: http scheme: http path: /metrics interval: 1m scrapeTimeout: 10s ================================================ FILE: kubernetes/apps/base/network-system/echo-server/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: echo-server namespace: network-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'echo.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: echo-server port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/network-system/echo-server/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml ================================================ FILE: kubernetes/apps/base/network-system/echo-server/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: echo-server namespace: network-system spec: path: "./apps/base/network-system/echo-server/app" wait: true targetNamespace: network-system sourceRef: kind: ExternalArtifact name: echo-server namespace: flux-system ================================================ FILE: kubernetes/apps/base/network-system/envoy-gateway/app/certificates.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/cert-manager.io/certificate_v1.json apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: owncloud-ai-le spec: # The secret name where cert-manager should store the signed certificate secretName: owncloud-ai-le duration: 2160h0m0s # 90d renewBefore: 360h0m0s # 15d # cert-manager regenerates a new private key on each issuance # https://cert-manager.io/docs/usage/certificate/#rotation-private-key privateKey: rotationPolicy: Always algorithm: ECDSA encoding: PKCS8 size: 256 usages: - server auth - client auth issuerRef: name: letsencrypt-prod kind: ClusterIssuer commonName: ${CLUSTER_DOMAIN} dnsNames: - ${CLUSTER_DOMAIN} - '*.${CLUSTER_DOMAIN}' - '*.preview.${CLUSTER_DOMAIN}' ================================================ FILE: kubernetes/apps/base/network-system/envoy-gateway/app/envoy.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.envoyproxy.io/envoyproxy_v1alpha1.json apiVersion: gateway.envoyproxy.io/v1alpha1 kind: EnvoyProxy metadata: name: envoy spec: logging: level: default: info provider: type: Kubernetes kubernetes: envoyDeployment: replicas: 3 container: imageRepository: mirror.gcr.io/envoyproxy/envoy resources: requests: cpu: 200m memory: 512Mi limits: memory: 2Gi pod: topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: gateway.envoyproxy.io/owning-gateway-name: envoy-external envoyService: externalTrafficPolicy: Local shutdown: drainTimeout: 180s telemetry: accessLog: settings: - format: type: Text text: | [%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%" sinks: - type: File file: path: /dev/stdout metrics: prometheus: compression: type: Zstd ================================================ FILE: kubernetes/apps/base/network-system/envoy-gateway/app/gatewayclass.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/gatewayclass_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: envoy spec: controllerName: gateway.envoyproxy.io/gatewayclass-controller parametersRef: group: gateway.envoyproxy.io kind: EnvoyProxy name: envoy namespace: network-system ================================================ FILE: kubernetes/apps/base/network-system/envoy-gateway/app/gateways.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/gateway_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: envoy-external annotations: external-dns.alpha.kubernetes.io/target: &hostname "external.${CLUSTER_DOMAIN}" spec: gatewayClassName: envoy infrastructure: annotations: external-dns.alpha.kubernetes.io/hostname: *hostname lbipam.cilium.io/ips: ${CLUSTER_LB_ENVOY_EXT_GATEWAY_API} addresses: - type: IPAddress value: ${CLUSTER_LB_ENVOY_EXT_GATEWAY_API} listeners: - name: http protocol: HTTP port: 80 allowedRoutes: namespaces: from: Same - name: https protocol: HTTPS port: 443 allowedRoutes: namespaces: from: All tls: mode: Terminate certificateRefs: - kind: Secret name: owncloud-ai-le - name: minecraft-bedrock protocol: UDP port: 19131 allowedRoutes: namespaces: from: All - name: minecraft-bedrock-broadcaster protocol: UDP port: 19133 allowedRoutes: namespaces: from: All - name: minecraft-java protocol: TCP port: 25565 allowedRoutes: namespaces: from: All - name: enemy-territory protocol: UDP port: 27960 allowedRoutes: namespaces: from: All - name: cmangos-auth protocol: TCP port: 3724 allowedRoutes: namespaces: from: All - name: cmangos-world protocol: TCP port: 8085 allowedRoutes: namespaces: from: All - name: cmangos-world-ptr protocol: TCP port: 8086 allowedRoutes: namespaces: from: All - name: azerothcore-auth protocol: TCP port: 3725 allowedRoutes: namespaces: from: All - name: azerothcore-world protocol: TCP port: 3726 allowedRoutes: namespaces: from: All --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/gateway_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: envoy-internal annotations: external-dns.alpha.kubernetes.io/target: &hostname "internal.${CLUSTER_DOMAIN}" spec: gatewayClassName: envoy infrastructure: annotations: external-dns.alpha.kubernetes.io/hostname: *hostname lbipam.cilium.io/ips: ${CLUSTER_LB_ENVOY_INT_GATEWAY_API} addresses: - type: IPAddress value: ${CLUSTER_LB_ENVOY_INT_GATEWAY_API} listeners: - name: http protocol: HTTP port: 80 allowedRoutes: namespaces: from: Same - name: https protocol: HTTPS port: 443 allowedRoutes: namespaces: from: All tls: mode: Terminate certificateRefs: - kind: Secret name: owncloud-ai-le ================================================ FILE: kubernetes/apps/base/network-system/envoy-gateway/app/grafanadashboards.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: envoy-gateway spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://raw.githubusercontent.com/envoyproxy/gateway/refs/heads/main/charts/gateway-addons-helm/dashboards/envoy-gateway-global.json --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: envoy-proxy spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://raw.githubusercontent.com/envoyproxy/gateway/refs/heads/main/charts/gateway-addons-helm/dashboards/envoy-proxy-global.json --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: envoy-overview spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/24459/revisions/1/download --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: envoy-upstream spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/24457/revisions/1/download --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: envoy-downstream spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/24458/revisions/1/download ================================================ FILE: kubernetes/apps/base/network-system/envoy-gateway/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app envoy-gateway spec: interval: 5m chartRef: kind: OCIRepository name: envoy-gateway values: deployment: priorityClassName: platform-cluster-critical global: imageRegistry: mirror.gcr.io config: envoyGateway: provider: type: Kubernetes kubernetes: deploy: type: GatewayNamespace ================================================ FILE: kubernetes/apps/base/network-system/envoy-gateway/app/httproutes.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: https-redirect annotations: external-dns.alpha.kubernetes.io/controller: none spec: parentRefs: - name: envoy-external namespace: network-system sectionName: http - name: envoy-internal namespace: network-system sectionName: http rules: - filters: - type: RequestRedirect requestRedirect: scheme: https statusCode: 301 ================================================ FILE: kubernetes/apps/base/network-system/envoy-gateway/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - certificates.yaml - envoy.yaml - gatewayclass.yaml - gateways.yaml - grafanadashboards.yaml - helmrelease.yaml - httproutes.yaml - monitors.yaml - ocirepository.yaml - pdb.yaml - policies.yaml ================================================ FILE: kubernetes/apps/base/network-system/envoy-gateway/app/monitors.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/podmonitor_v1.json apiVersion: monitoring.coreos.com/v1 kind: PodMonitor metadata: name: envoy-proxy spec: jobLabel: envoy-proxy namespaceSelector: matchNames: - network-system podMetricsEndpoints: - port: metrics path: /stats/prometheus honorLabels: true selector: matchLabels: app.kubernetes.io/component: proxy app.kubernetes.io/name: envoy --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/servicemonitor_v1.json apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: envoy-gateway spec: endpoints: - port: metrics path: /metrics honorLabels: true jobLabel: envoy-gateway namespaceSelector: matchNames: - network-system selector: matchLabels: control-plane: envoy-gateway ================================================ FILE: kubernetes/apps/base/network-system/envoy-gateway/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: envoy-gateway spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 1.8.0 url: oci://mirror.gcr.io/envoyproxy/gateway-helm ================================================ FILE: kubernetes/apps/base/network-system/envoy-gateway/app/pdb.yaml ================================================ --- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: envoy-gateway spec: minAvailable: 1 selector: matchLabels: app.kubernetes.io/instance: envoy-gateway app.kubernetes.io/name: gateway-helm control-plane: envoy-gateway ================================================ FILE: kubernetes/apps/base/network-system/envoy-gateway/app/policies.yaml ================================================ --- apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy metadata: name: envoy-default spec: targetSelectors: - group: gateway.networking.k8s.io kind: Gateway compressor: - type: Zstd - type: Brotli - type: Gzip retry: numRetries: 2 retryOn: triggers: - reset tcpKeepalive: probes: 3 idleTime: 20m interval: 60s timeout: http: requestTimeout: "0s" --- apiVersion: gateway.envoyproxy.io/v1alpha1 kind: ClientTrafficPolicy metadata: name: envoy-default spec: targetSelectors: - group: gateway.networking.k8s.io kind: Gateway timeout: http: # Increase stream idle timeout from default 5m to prevent SSE/WebSocket disconnections streamIdleTimeout: "1h" clientIPDetection: xForwardedFor: numTrustedHops: 1 http2: onInvalidMessage: TerminateStream http3: {} tcpKeepalive: probes: 3 idleTime: 20m interval: 60s tls: minVersion: "1.2" alpnProtocols: - h2 - http/1.1 ================================================ FILE: kubernetes/apps/base/network-system/envoy-gateway/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: envoy-gateway namespace: network-system spec: path: "./apps/base/network-system/envoy-gateway/app" wait: true targetNamespace: network-system sourceRef: kind: ExternalArtifact name: envoy-gateway namespace: flux-system ================================================ FILE: kubernetes/apps/base/network-system/external-dns/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: external-dns-cloudflare spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: external-dns-cloudflare template: data: CLOUDFLARE_API_TOKEN: "{{ .CLOUDFLARE_API_TOKEN }}" dataFrom: - extract: key: cloudflare ================================================ FILE: kubernetes/apps/base/network-system/external-dns/app/grafanadashboard.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: cloudflare-tunnels spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/15038/revisions/3/download ================================================ FILE: kubernetes/apps/base/network-system/external-dns/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app external-dns namespace: network-system spec: interval: 1h chartRef: kind: OCIRepository name: external-dns valuesFrom: - kind: ConfigMap name: external-dns-values ================================================ FILE: kubernetes/apps/base/network-system/external-dns/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - grafanadashboard.yaml - helmrelease.yaml - ocirepository.yaml - pdb.yaml - prometheusrule.yaml configMapGenerator: - name: external-dns-values namespace: network-system files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/network-system/external-dns/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/network-system/external-dns/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: external-dns namespace: network-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 1.21.1 url: oci://ghcr.io/home-operations/charts-mirror/external-dns ================================================ FILE: kubernetes/apps/base/network-system/external-dns/app/pdb.yaml ================================================ --- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: external-dns spec: minAvailable: 1 selector: matchLabels: app.kubernetes.io/instance: external-dns app.kubernetes.io/name: external-dns ================================================ FILE: kubernetes/apps/base/network-system/external-dns/app/prometheusrule.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/prometheusrule_v1.json apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: name: external-dns-rules spec: groups: - name: external-dns.rules rules: - alert: ExternalDNSStale expr: |- time() - external_dns_controller_last_sync_timestamp_seconds > 900 for: 1h annotations: summary: >- ExternalDNS ({{ $labels.job }}) has not synced successfully in over 15 minutes labels: severity: warning ================================================ FILE: kubernetes/apps/base/network-system/external-dns/app/values.yaml ================================================ priorityClassName: platform-cluster-critical provider: name: cloudflare domainFilters: - "${CLUSTER_DOMAIN}" env: - name: CF_API_TOKEN valueFrom: secretKeyRef: key: CLOUDFLARE_API_TOKEN name: external-dns-cloudflare extraArgs: - --cloudflare-proxied - --crd-source-apiversion=externaldns.k8s.io/v1alpha1 - --crd-source-kind=DNSEndpoint - --annotation-filter=external-dns.alpha.kubernetes.io/external=true - --gateway-name=envoy-external policy: sync triggerLoopOnEvent: true txtPrefix: k8s. sources: - crd - gateway-httproute serviceMonitor: enabled: true ================================================ FILE: kubernetes/apps/base/network-system/external-dns/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: external-dns namespace: network-system spec: dependsOn: - name: onepassword namespace: external-secrets path: "./apps/base/network-system/external-dns/app" wait: true targetNamespace: network-system sourceRef: kind: ExternalArtifact name: external-dns namespace: flux-system ================================================ FILE: kubernetes/apps/base/network-system/external-dns-unifi/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: external-dns-unifi spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: external-dns-unifi template: data: UNIFI_API_KEY: "{{ .UNIFI_API_KEY }}" dataFrom: - extract: key: unifi ================================================ FILE: kubernetes/apps/base/network-system/external-dns-unifi/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app external-dns-unifi namespace: network-system spec: interval: 1h chartRef: kind: OCIRepository name: external-dns-unifi valuesFrom: - kind: ConfigMap name: external-dns-unifi-values ================================================ FILE: kubernetes/apps/base/network-system/external-dns-unifi/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml - ocirepository.yaml configMapGenerator: - name: external-dns-unifi-values namespace: network-system files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/network-system/external-dns-unifi/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/network-system/external-dns-unifi/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: external-dns-unifi namespace: network-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 1.21.1 url: oci://ghcr.io/home-operations/charts-mirror/external-dns ================================================ FILE: kubernetes/apps/base/network-system/external-dns-unifi/app/values.yaml ================================================ fullnameOverride: external-dns-unifi provider: name: webhook webhook: image: repository: ghcr.io/kashalls/external-dns-unifi-webhook tag: v0.8.2@sha256:7f0ddbbc83a36a2a9d762e25eef9cafcb3adf0493068a27d72ae71087eafe6f0 env: - name: UNIFI_HOST value: https://192.168.1.1 - name: UNIFI_API_KEY valueFrom: secretKeyRef: name: &secret external-dns-unifi key: UNIFI_API_KEY livenessProbe: httpGet: path: /healthz port: http-webhook initialDelaySeconds: 10 timeoutSeconds: 5 readinessProbe: httpGet: path: /readyz port: http-webhook initialDelaySeconds: 10 timeoutSeconds: 5 triggerLoopOnEvent: true policy: sync sources: - gateway-httproute extraArgs: - --gateway-name=envoy-internal txtOwnerId: unifi txtPrefix: k8s.unifi. domainFilters: - ${CLUSTER_DOMAIN} serviceMonitor: enabled: true ================================================ FILE: kubernetes/apps/base/network-system/external-dns-unifi/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: external-dns-unifi namespace: network-system spec: dependsOn: - name: external-dns namespace: network-system - name: onepassword namespace: external-secrets path: "./apps/base/network-system/external-dns-unifi/app" wait: true targetNamespace: network-system sourceRef: kind: ExternalArtifact name: external-dns-unifi namespace: flux-system ================================================ FILE: kubernetes/apps/base/network-system/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: network-system components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/network-system/multus/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app multus namespace: network-system spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system values: controllers: *app : type: daemonset pod: hostNetwork: true initContainers: cni-plugins: image: repository: ghcr.io/home-operations/cni-plugins tag: 1.9.1@sha256:56222d9cf686632f0951103a400adeeec8d982aaf8cbf4d21588da17a41dd228 containers: app: image: repository: ghcr.io/k8snetworkplumbingwg/multus-cni tag: latest@sha256:f4e21d437fe5407e23264ae4b66f0e52db9a07f77a37fc1d61cd3923405871a9 command: - /thin_entrypoint args: - --cleanup-config-on-exit securityContext: privileged: true resources: requests: cpu: 10m memory: 32Mi limits: memory: 256Mi serviceAccount: identifier: multus persistence: etc-cni-net-d: type: hostPath hostPath: /etc/cni/net.d globalMounts: - path: /host/etc/cni/net.d opt-cni-bin: type: hostPath hostPath: /opt/cni/bin globalMounts: - path: /host/opt/cni/bin serviceAccount: multus: {} defaultPodOptions: tolerations: - key: "node-role.kubernetes.io/control-plane" operator: "Exists" effect: "NoSchedule" ================================================ FILE: kubernetes/apps/base/network-system/multus/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - rbac.yaml ================================================ FILE: kubernetes/apps/base/network-system/multus/app/rbac.yaml ================================================ --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: multus rules: - apiGroups: ["k8s.cni.cncf.io"] resources: ["*"] verbs: ["*"] - apiGroups: [""] resources: ["pods", "pods/status"] verbs: ["get", "update"] - apiGroups: ["", "events.k8s.io"] resources: ["events"] verbs: ["create", "patch", "update"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: multus roleRef: kind: ClusterRole name: multus apiGroup: rbac.authorization.k8s.io subjects: - kind: ServiceAccount name: multus namespace: network-system ================================================ FILE: kubernetes/apps/base/network-system/multus/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: multus namespace: network-system spec: path: "./apps/base/network-system/multus/app" wait: true targetNamespace: network-system sourceRef: kind: ExternalArtifact name: multus namespace: flux-system --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: multus-networks namespace: network-system spec: path: "./apps/base/network-system/multus/networks" wait: true dependsOn: - name: multus namespace: network-system targetNamespace: network-system sourceRef: kind: ExternalArtifact name: multus-networks namespace: flux-system ================================================ FILE: kubernetes/apps/base/network-system/multus/networks/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - network.yaml ================================================ FILE: kubernetes/apps/base/network-system/multus/networks/network.yaml ================================================ --- apiVersion: k8s.cni.cncf.io/v1 kind: NetworkAttachmentDefinition metadata: name: wifi-network namespace: network-system spec: config: |- { "cniVersion": "0.3.1", "name": "wifi-network", "plugins": [ { "type": "macvlan", "master": "enp2s0", "mode": "bridge", "ipam": { "type": "host-local", "subnet": "192.168.86.0/24", "rangeStart": "192.168.86.100", "rangeEnd": "192.168.86.200", "routes": [ { "dst": "0.0.0.0/0", "gw": "192.168.86.1" } ] } } ] } --- apiVersion: k8s.cni.cncf.io/v1 kind: NetworkAttachmentDefinition metadata: name: lan-network namespace: network-system spec: config: |- { "cniVersion": "0.3.1", "name": "lan-network", "plugins": [ { "type": "macvlan", "master": "enp2s0", "mode": "bridge", "ipam": { "type": "host-local", "subnet": "192.168.50.0/24", "rangeStart": "192.168.50.100", "rangeEnd": "192.168.50.200", "routes": [ { "dst": "0.0.0.0/0", "gw": "192.168.50.1" } ] } } ] } ================================================ FILE: kubernetes/apps/base/network-system/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: network-system labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/network-system/oauth2-proxy/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: oauth2-proxy-dex spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: oauth2-proxy-dex template: data: client-id: "{{ .CLIENT_ID }}" client-secret: "{{ .CLIENT_SECRET }}" cookie-secret: "{{ .COOKIE_SECRET }}" dataFrom: - extract: key: dex ================================================ FILE: kubernetes/apps/base/network-system/oauth2-proxy/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app oauth2-proxy spec: interval: 1h chartRef: kind: OCIRepository name: oauth2-proxy dependsOn: - name: dex namespace: network-system - name: cert-manager namespace: network-system values: metrics: servicemonitor: enabled: true config: existingSecret: oauth2-proxy-dex configFile: | provider = "oidc" oidc_issuer_url = "https://dex.${CLUSTER_DOMAIN}" auth_logging = true cookie_domains = ".${CLUSTER_DOMAIN}" cookie_httponly = true cookie_name = "_owncloud_oauth" cookie_refresh = "1h" cookie_samesite = "lax" cookie_secure = true email_domains = [ "*" ] pass_access_token = true pass_authorization_header = true pass_basic_auth = false request_logging = true session_store_type = "cookie" silence_ping_logging = true set_authorization_header = true set_xauthrequest = true skip_jwt_bearer_tokens = true skip_provider_button = true ssl_insecure_skip_verify = false standard_logging = true upstreams = [ "static://200" ] whitelist_domains = ".${CLUSTER_DOMAIN}" ================================================ FILE: kubernetes/apps/base/network-system/oauth2-proxy/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: auth annotations: external-dns.alpha.kubernetes.io/external: 'true' spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'auth.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: oauth2-proxy port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/network-system/oauth2-proxy/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - helmrelease.yaml - ocirepository.yaml - httproute.yaml ================================================ FILE: kubernetes/apps/base/network-system/oauth2-proxy/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: oauth2-proxy namespace: network-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 10.4.3 url: oci://ghcr.io/oauth2-proxy/charts/oauth2-proxy ================================================ FILE: kubernetes/apps/base/network-system/oauth2-proxy/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: oauth2-proxy namespace: network-system spec: dependsOn: - name: onepassword namespace: external-secrets path: "./apps/base/network-system/oauth2-proxy/app" wait: true targetNamespace: network-system sourceRef: kind: ExternalArtifact name: oauth2-proxy namespace: flux-system ================================================ FILE: kubernetes/apps/base/nginx-ingress/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: nginx-ingress components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/nginx-ingress/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: nginx-ingress labels: kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/nginx-ingress/nginx-ingress/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app nginx-ingress namespace: nginx-ingress spec: interval: 1h releaseName: ingress-nginx chart: spec: chart: ingress-nginx version: 4.15.1 sourceRef: kind: HelmRepository name: ingress-nginx-chart namespace: flux-system interval: 10m values: tcp: '25565': "game-servers/minecraft:25565" udp: '19131': "game-servers/minecraft-bedrock-minecraft-bedrock:19131" '19132': "game-servers/minecraft:19132" controller: service: enableHttp: true enableHttps: true annotations: lbipam.cilium.io/ips: ${CLUSTER_LB_NGINX_INGRESS_GATEWAY} metrics: enabled: true serviceMonitor: enabled: true namespace: nginx-ingress namespaceSelector: any: true config: # https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#proxy-stream-responses proxy-stream-responses: '999999' enable-real-ip: "true" use-forwarded-headers: "true" enable-ocsp: "true" force-ssl-redirect: "true" log-format-escape-json: "true" ssl-protocols: TLSv1.3 hsts-max-age: 31449600 keep-alive: 120 keep-alive-requests: 10000 proxy-connect-timeout: 120 proxy-read-timeout: 120 proxy-send-timeout: 120 extraArgs: default-ssl-certificate: 'network-system/owncloud-ai-le' replicaCount: 2 resources: limits: memory: 512Mi requests: cpu: 25m memory: 256Mi podDisruptionBudget: enabled: true minAvailable: 1 ================================================ FILE: kubernetes/apps/base/nginx-ingress/nginx-ingress/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: kubernetes/apps/base/nginx-ingress/nginx-ingress/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: nginx-ingress namespace: nginx-ingress spec: path: "./apps/base/nginx-ingress/nginx-ingress/app" wait: true targetNamespace: nginx-ingress sourceRef: kind: ExternalArtifact name: nginx-ingress namespace: flux-system ================================================ FILE: kubernetes/apps/base/observability/blackbox-exporter/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: blackbox-exporter spec: interval: 1h chartRef: kind: OCIRepository name: blackbox-exporter valuesFrom: - kind: ConfigMap name: blackbox-exporter-values ================================================ FILE: kubernetes/apps/base/observability/blackbox-exporter/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml - probes.yaml configMapGenerator: - name: blackbox-exporter-values namespace: observability files: - values.yaml=./values.yaml generatorOptions: annotations: kustomize.toolkit.fluxcd.io/substitute: disabled configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/observability/blackbox-exporter/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/observability/blackbox-exporter/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: blackbox-exporter spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 11.10.0 url: oci://ghcr.io/prometheus-community/charts/prometheus-blackbox-exporter ================================================ FILE: kubernetes/apps/base/observability/blackbox-exporter/app/probes.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/probe_v1.json apiVersion: monitoring.coreos.com/v1 kind: Probe metadata: name: icmp spec: module: icmp prober: url: blackbox-exporter.observability.svc.cluster.local:9115 targets: staticConfig: static: - expanse.internal # - jetkvm-01.internal # - jetkvm-02.internal # - jetkvm-03.internal metricRelabelings: - targetLabel: service replacement: blackbox-exporter action: replace --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/probe_v1.json apiVersion: monitoring.coreos.com/v1 kind: Probe metadata: name: tcp spec: module: tcp_connect prober: url: blackbox-exporter.observability.svc.cluster.local:9115 targets: staticConfig: static: - expanse.internal:2049 metricRelabelings: - targetLabel: service replacement: blackbox-exporter action: replace ================================================ FILE: kubernetes/apps/base/observability/blackbox-exporter/app/values.yaml ================================================ fullnameOverride: blackbox-exporter securityContext: readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: { add: ["NET_RAW"] } config: modules: http_2xx: prober: http timeout: 5s http: valid_http_versions: - HTTP/1.1 - HTTP/2.0 follow_redirects: true preferred_ip_protocol: ip4 icmp: prober: icmp timeout: 5s icmp: preferred_ip_protocol: ip4 tcp_connect: prober: tcp timeout: 5s tcp: preferred_ip_protocol: ip4 serviceMonitor: enabled: true selfMonitor: enabled: true prometheusRule: enabled: true rules: - alert: LanProbeFailed expr: |- probe_success{ service="blackbox-exporter" } == 0 for: 1h labels: severity: warning annotations: summary: |- The probe targeting {{ $labels.instance }} is currently having connectivity issues ================================================ FILE: kubernetes/apps/base/observability/blackbox-exporter/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: blackbox-exporter namespace: observability spec: path: "./apps/base/observability/blackbox-exporter/app" wait: true targetNamespace: observability sourceRef: kind: ExternalArtifact name: blackbox-exporter namespace: flux-system ================================================ FILE: kubernetes/apps/base/observability/grafana/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: grafana namespace: observability spec: interval: 1h chartRef: kind: OCIRepository name: grafana-operator values: dashboard: enabled: true serviceMonitor: enabled: true ================================================ FILE: kubernetes/apps/base/observability/grafana/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/observability/grafana/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: grafana-operator namespace: observability spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 5.22.2 url: oci://ghcr.io/grafana/helm-charts/grafana-operator ================================================ FILE: kubernetes/apps/base/observability/grafana/instance/grafana.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafana_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: Grafana metadata: name: grafana labels: grafana.internal/instance: grafana spec: config: analytics: check_for_updates: "false" check_for_plugin_updates: "false" feedback_links_enabled: "false" reporting_enabled: "false" auth: disable_login_form: "true" auth.generic_oauth: auto_login: "true" # For variables see https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#env-provider enabled: "true" name: "GitHub SSO" allow_sign_up: "true" client_id: ${GRAFANA_AUTH_GENERIC_CLIENT_ID} client_secret: ${GRAFANA_AUTH_GENERIC_CLIENT_SECRET} scopes: "openid profile email groups" email_attribute_path: email login_attribute_path: username name_attribute_path: full_name groups_attribute_path: groups auth_url: "https://dex.${CLUSTER_DOMAIN}/auth" token_url: "https://dex.${CLUSTER_DOMAIN}/token" api_url: "https://dex.${CLUSTER_DOMAIN}/userinfo" role_attribute_path: "contains(groups[*], 'raspbernetes:k8s-admins') && 'Admin' || contains(groups[*], 'people') && 'Viewer'" log: mode: console metrics: enabled: "true" news: news_feed_enabled: "false" plugins: plugin_admin_enabled: "false" security: angular_support_enabled: "true" server: enable_gzip: "true" root_url: https://grafana.${CLUSTER_DOMAIN} smtp: enabled: "true" host: "smtp-relay.home-system.svc.cluster.local:25" from_address: "noreply@owncloud.ai" from_name: "Grafana" skip_verify: "true" deployment: spec: strategy: type: Recreate template: spec: containers: - name: grafana env: - name: GF_SECURITY_ADMIN_PASSWORD valueFrom: secretKeyRef: name: grafana-admin-credentials key: GF_SECURITY_ADMIN_PASSWORD securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch volumes: - name: grafana-data persistentVolumeClaim: claimName: grafana-pvc persistentVolumeClaim: spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: ceph-block disableDefaultSecurityContext: All ================================================ FILE: kubernetes/apps/base/observability/grafana/instance/grafanadatasource.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadatasource_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDatasource metadata: name: prometheus spec: instanceSelector: matchLabels: grafana.internal/instance: grafana datasource: type: prometheus name: prometheus access: proxy isDefault: true url: http://prometheus-operated.observability.svc.cluster.local:9090 --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadatasource_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDatasource metadata: name: alertmanager spec: instanceSelector: matchLabels: grafana.internal/instance: grafana datasource: type: alertmanager name: alertmanager access: proxy jsonData: implementation: prometheus url: http://alertmanager-operated.observability.svc.cluster.local:9093 ================================================ FILE: kubernetes/apps/base/observability/grafana/instance/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: grafana namespace: observability annotations: external-dns.alpha.kubernetes.io/external: 'true' spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'grafana.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: grafana-service port: 3000 weight: 100 ================================================ FILE: kubernetes/apps/base/observability/grafana/instance/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - grafana.yaml - grafanadatasource.yaml - httproute.yaml - replicationsource.yaml - servicemonitor.yaml - volsync-externalsecret.yaml ================================================ FILE: kubernetes/apps/base/observability/grafana/instance/replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: grafana spec: sourcePVC: grafana-pvc trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 parallelism: 2 repository: grafana-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/observability/grafana/instance/servicemonitor.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/servicemonitor_v1.json apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: grafana spec: endpoints: - port: grafana path: /metrics honorLabels: true jobLabel: grafana namespaceSelector: matchNames: - observability selector: matchLabels: grafana.internal/instance: grafana ================================================ FILE: kubernetes/apps/base/observability/grafana/instance/volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: grafana-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: grafana-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/observability/grafana/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: grafana namespace: observability spec: path: "./apps/base/observability/grafana/app" wait: true dependsOn: - name: cert-manager namespace: network-system targetNamespace: observability sourceRef: kind: ExternalArtifact name: grafana namespace: flux-system --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: grafana-instance namespace: observability spec: path: "./apps/base/observability/grafana/instance" wait: true dependsOn: - name: grafana namespace: observability - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: observability sourceRef: kind: ExternalArtifact name: grafana-instance namespace: flux-system ================================================ FILE: kubernetes/apps/base/observability/kromgo/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kromgo spec: interval: 1h chartRef: kind: OCIRepository name: app-template namespace: flux-system dependsOn: - name: kube-prometheus-stack namespace: observability values: controllers: kromgo: replicas: 1 strategy: RollingUpdate containers: app: image: repository: ghcr.io/kashalls/kromgo tag: v0.10.0@sha256:965ecc92d68dc1a4a969397855367bbc70da03227a941ea607b73bb7e0b78fd6 env: PROMETHEUS_URL: http://kube-prometheus-stack-prometheus.observability.svc.cluster.local:9090/ SERVER_PORT: &serverPort 80 HEALTH_PORT: &healthPort 8080 probes: liveness: &probes enabled: true custom: true spec: httpGet: path: /readyz port: *healthPort initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 10m limits: memory: 64Mi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 seccompProfile: { type: RuntimeDefault } service: app: controller: kromgo ports: http: primary: true port: *serverPort health: port: *healthPort persistence: config-file: type: configMap name: kromgo-config globalMounts: - path: /kromgo/config.yaml subPath: config.yaml readOnly: true ================================================ FILE: kubernetes/apps/base/observability/kromgo/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: kromgo namespace: observability annotations: external-dns.alpha.kubernetes.io/external: 'true' spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'kromgo.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: kromgo port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/observability/kromgo/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml configMapGenerator: - name: kromgo-config files: - config.yaml=./resources/config.yaml generatorOptions: annotations: kustomize.toolkit.fluxcd.io/substitute: disabled configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/observability/kromgo/app/kustomizeconfig.yaml ================================================ nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/values/persistence/config-file/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/observability/kromgo/app/resources/config.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/kashalls/kromgo/main/config.schema.json badge: font: Verdana.ttf size: 12 metrics: - name: talos_version query: label_replace(node_os_info{name="Talos"}, "version_id", "$1", "version_id", "v(.+)") label: version_id title: Talos - name: kubernetes_version query: label_replace(kubernetes_build_info{service="kubernetes"}, "git_version", "$1", "git_version", "v(.+)") label: git_version title: Kubernetes - name: flux_version query: label_replace(flux_instance_info, "revision", "$1", "revision", "v(.+)@sha256:.+") label: revision title: Flux - name: cluster_node_count query: count(count by (node) (kube_node_status_condition{condition="Ready"})) colors: - { color: "green", min: 0, max: 9999 } title: Nodes - name: cluster_pod_count query: sum(kube_pod_status_phase{phase="Running"}) colors: - { color: "green", min: 0, max: 9999 } title: Pods - name: cluster_cpu_usage query: round(avg(instance:node_cpu_utilisation:rate5m{pod!=""}) * 100, 0.1) suffix: "%" colors: - { color: "green", min: 0, max: 35 } - { color: "orange", min: 36, max: 75 } - { color: "red", min: 76, max: 9999 } title: CPU - name: cluster_memory_usage query: round(sum(node_memory_MemTotal_bytes{pod!=""} - node_memory_MemAvailable_bytes{pod!=""}) / sum(node_memory_MemTotal_bytes{pod!=""}) * 100, 0.1) suffix: "%" colors: - { color: "green", min: 0, max: 35 } - { color: "orange", min: 36, max: 75 } - { color: "red", min: 76, max: 9999 } title: Memory - name: cluster_power_usage query: round(upsHighPrecOutputLoad, 0.1) suffix: "w" colors: - { color: "green", min: 0, max: 400 } - { color: "orange", min: 401, max: 750 } - { color: "red", min: 751, max: 9999 } title: Power - name: cluster_age_days query: round((time() - min(kube_node_created) ) / 86400) suffix: "d" colors: - { color: "green", min: 0, max: 180 } - { color: "orange", min: 181, max: 360 } - { color: "red", min: 361, max: 9999 } title: Age - name: cluster_uptime_days query: round(avg(node_time_seconds{pod!=""} - node_boot_time_seconds{pod!=""}) / 86400) suffix: "d" colors: - { color: "green", min: 0, max: 180 } - { color: "orange", min: 181, max: 360 } - { color: "red", min: 361, max: 9999 } title: Uptime ================================================ FILE: kubernetes/apps/base/observability/kromgo/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kromgo namespace: observability spec: path: "./apps/base/observability/kromgo/app" wait: true targetNamespace: observability sourceRef: kind: ExternalArtifact name: kromgo namespace: flux-system ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/README.md ================================================ # kube-prometheus-stack ## NAS Deployments ### node-exporter ```yaml services: node-exporter: command: - '--path.rootfs=/host/root' - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' - '--path.udev.data=/host/root/run/udev/data' - '--web.listen-address=0.0.0.0:9100' - >- --collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/) image: quay.io/prometheus/node-exporter:v1.9.0 network_mode: host ports: - '9100:9100' restart: always volumes: - /:/host/root:ro - /proc:/host/proc:ro - /sys:/host/sys:ro ``` ### smartctl-exporter ```yaml services: smartctl-exporter: command: - '--smartctl.device-exclude=nvme0' image: quay.io/prometheuscommunity/smartctl-exporter:v0.13.0 ports: - '9633:9633' privileged: True restart: always user: root ``` ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/app/alertmanager-replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: alertmanager spec: sourcePVC: alertmanager-kube-prometheus-stack-db-alertmanager-kube-prometheus-stack-0 trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 2000 fsGroup: 2000 parallelism: 2 repository: alertmanager-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/app/alertmanager-volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: alertmanager-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: alertmanager-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/app/alertmanagerconfig.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/alertmanagerconfig_v1alpha1.json apiVersion: monitoring.coreos.com/v1alpha1 kind: AlertmanagerConfig metadata: name: alertmanager spec: route: receiver: email groupBy: - namespace - alertname - job groupWait: 24h groupInterval: 1h repeatInterval: 24h routes: # Drop Watchdog and InfoInhibitor — these are internal signals - receiver: "null" matchers: - name: alertname matchType: "=~" value: "InfoInhibitor|Watchdog" continue: false # Drop maintenance-signal alerts — their only purpose is to be the # source side of inhibit rules. Never email these. - receiver: "null" matchers: - name: alertname matchType: "=~" value: "NodeUnderMaintenance|FluxReconciliationInProgress" continue: false # Drop etcd alerts that are noisy on Talos single-node etcd restarts - receiver: "null" matchers: - name: alertname matchType: "=~" value: "etcdHighNumberOfLeaderChanges|etcdMembersDown|etcdInsufficientMembers|etcdHighNumberOfFailedGRPCRequests|etcdHighCommitDurations" - name: severity matchType: "!=" value: critical continue: false # Drop Ceph PG alerts that are already muted/acknowledged in Ceph itself - receiver: "null" matchers: - name: alertname matchType: "=~" value: "CephPGsDamaged|CephOSDScrubErrors" continue: false # Game-servers (WoW) — fast path. First email within 30s of any new # alert in the namespace; subsequent alerts in the same group batched # 5min apart; reminders only every 12h while still firing (and one # final RESOLVED email when it clears, via sendResolved). # Grouping by namespace + severity bundles related alerts into one # email — e.g. all `critical game-servers` alerts arrive together # rather than one email per alertname. - receiver: email matchers: - name: namespace matchType: "=" value: game-servers - name: severity matchType: "=~" value: critical|warning groupBy: - namespace - severity groupWait: 30s groupInterval: 5m repeatInterval: 12h continue: false # Critical alerts — only notify if sustained beyond 24h - receiver: email matchers: - name: severity matchType: "=" value: critical groupWait: 24h repeatInterval: 24h continue: false # Warning alerts — only notify if sustained beyond 24h - receiver: email matchers: - name: severity matchType: "=" value: warning groupWait: 24h repeatInterval: 24h continue: false receivers: - name: "null" - name: email emailConfigs: - to: "${PRIVATE_EMAIL}" from: "noreply@${CLUSTER_DOMAIN}" smarthost: "smtp-relay.home-system.svc.cluster.local:25" requireTLS: false sendResolved: true headers: - key: From value: "Alert Manager " - key: Subject value: '[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }}' inhibitRules: # Critical silences warning/info for the same alert - sourceMatch: - name: severity matchType: "=" value: critical targetMatch: - name: severity matchType: "=~" value: warning|info equal: - namespace - alertname # InfoInhibitor silences info - sourceMatch: - name: alertname matchType: "=" value: InfoInhibitor targetMatch: - name: severity matchType: "=" value: info equal: - namespace # KubePodCrashLooping inhibits KubePodNotReady for the same pod - sourceMatch: - name: alertname matchType: "=" value: KubePodCrashLooping targetMatch: - name: alertname matchType: "=" value: KubePodNotReady equal: - namespace - pod # GameServerSegfault is the root cause — silence the downstream # restart-pattern alerts for the same pod so we only get one email # for one underlying problem. - sourceMatch: - name: alertname matchType: "=" value: GameServerSegfault targetMatch: - name: alertname matchType: "=~" value: "GameServerCrashLooping|GameServerRecentRestarts|KubePodCrashLooping" equal: - namespace - pod # GameServerCrashLooping inhibits the slower GameServerRecentRestarts # for the same pod (same signal, different windows) - sourceMatch: - name: alertname matchType: "=" value: GameServerCrashLooping targetMatch: - name: alertname matchType: "=" value: GameServerRecentRestarts equal: - namespace - pod # GameServerDown inhibits GameServerDegraded for the same deployment - sourceMatch: - name: alertname matchType: "=" value: GameServerDown targetMatch: - name: alertname matchType: "=" value: GameServerDegraded equal: - namespace - deployment # Node-level alerts inhibit pod-level alerts on the same node - sourceMatch: - name: alertname matchType: "=~" value: "KubeNodeNotReady|KubeNodeUnreachable" targetMatch: - name: severity matchType: "=~" value: warning|info equal: - node # Planned maintenance: a cordoned/draining node suppresses # warning/info alerts about pods and targets on that node. # Critical alerts still fire — outages during a drain are real. - sourceMatch: - name: alertname matchType: "=" value: NodeUnderMaintenance targetMatch: - name: severity matchType: "=~" value: warning|info equal: - node # In-flight Flux HelmRelease/Kustomization reconciles suppress # warning/info alerts in the same workload namespace # (KubePodNotReady, KubeDeploymentReplicasMismatch, TargetDown, # etc.). Critical alerts still fire. - sourceMatch: - name: alertname matchType: "=" value: FluxReconciliationInProgress targetMatch: - name: severity matchType: "=~" value: warning|info equal: - namespace ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/app/grafanadashboard.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: kubernetes-api-server spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/15761/revisions/21/download --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: kubernetes-coredns spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/15762/revisions/22/download --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: kubernetes-global spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/15757/revisions/43/download --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: kubernetes-namespaces spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/15758/revisions/46/download --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: kubernetes-nodes spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/15759/revisions/40/download --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: kubernetes-pods spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/15760/revisions/39/download --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: kubernetes-volumes spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/11454/revisions/14/download --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: node-exporter-full spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/1860/revisions/45/download --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: prometheus spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/19105/revisions/9/download ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kube-prometheus-stack namespace: observability labels: gitops.owncloud.ai/defaults: disabled spec: interval: 1h chartRef: kind: OCIRepository name: kube-prometheus-stack valuesFrom: - kind: ConfigMap name: flux-metrics-configmap valuesKey: flux-metrics.yaml install: timeout: 1h replace: true crds: CreateReplace createNamespace: true upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace force: true test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 dependsOn: - name: grafana namespace: observability timeout: 30m values: cleanPrometheusOperatorObjectNames: true # Disable alerts that produce false positives in Talos/homelab environments defaultRules: disabled: # False positives from short-lived SA tokens on K8s 1.24+ KubeClientCertificateExpiration: true # Extremely noisy — fires on any container with CPU limits under throttle; not actionable in homelab CPUThrottlingHigh: true # Expected in resource-constrained homelab; not actionable without adding hardware KubeMemoryOvercommit: true KubeCPUOvercommit: true # Replaced with custom rule at 3x threshold (default 1.5x is too sensitive # with auto-compaction; fragmentation between defrag cycles is normal) etcdDatabaseHighFragmentationRatio: true # Extend "for:" durations on upgrade-sensitive alerts to avoid transient noise rules: kubeProxy: false customRules: KubePodNotReady: for: 30m KubePodCrashLooping: for: 30m KubeContainerWaiting: for: 1h KubeDeploymentReplicasMismatch: for: 30m KubeStatefulSetReplicasMismatch: for: 30m KubeDeploymentRolloutStuck: for: 30m KubeDaemonSetRolloutStuck: for: 30m KubeStatefulSetUpdateNotRolledOut: for: 30m KubeJobFailed: for: 1h TargetDown: for: 15m # 15m default fires on transient memory spikes (Kopia backups on TrueNAS, # ZFS scrubs, batch I/O). Real pressure outlasts 30m; backups don't. NodeMemoryHighUtilization: for: 30m alertmanager: alertmanagerSpec: alertmanagerConfiguration: name: alertmanager externalUrl: https://alertmanager.${CLUSTER_DOMAIN} storage: volumeClaimTemplate: spec: storageClassName: ceph-block resources: requests: storage: 1Gi grafana: enabled: false forceDeployDashboards: true operator: dashboardsConfigMapRefEnabled: true folder: observability matchLabels: grafana.internal/instance: grafana prometheus: # thanosService: # enabled: true # thanosServiceMonitor: # enabled: true ## Settings affecting prometheusSpec ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#prometheusspec prometheusSpec: priorityClassName: platform-cluster-critical # REQUIRED: Cilium Hubble metrics are exposed via OpenMetrics. Prometheus Operator requires the `exemplar-storage` feature to be enabled to scrape OpenMetrics. # https://docs.cilium.io/en/stable/observability/metrics/#openmetrics # https://prometheus.io/docs/prometheus/latest/feature_flags/#exemplars-storage enableFeatures: - exemplar-storage - memory-snapshot-on-shutdown scrapeInterval: 1m externalUrl: https://prometheus.${CLUSTER_DOMAIN} podAntiAffinity: hard ruleSelectorNilUsesHelmValues: false serviceMonitorSelectorNilUsesHelmValues: false podMonitorSelectorNilUsesHelmValues: false probeSelectorNilUsesHelmValues: false scrapeConfigSelectorNilUsesHelmValues: false retention: 14d retentionSize: 50GB storageSpec: volumeClaimTemplate: spec: storageClassName: ceph-block resources: requests: storage: 50Gi enableAdminAPI: true walCompression: true resources: requests: cpu: 100m limits: memory: 2000Mi additionalPrometheusRulesMap: etcd-fragmentation: groups: - name: etcd-fragmentation rules: - alert: etcdDatabaseHighFragmentationRatio annotations: summary: >- etcd {{ $labels.instance }} DB fragmentation is {{ $value | humanizePercentage }}, indicating auto-compaction may not be working or defragmentation is overdue expr: |- (last_over_time(etcd_mvcc_db_total_size_in_bytes[5m]) / last_over_time(etcd_mvcc_db_total_size_in_use_in_bytes[5m])) > 3 for: 30m labels: severity: warning oom-rules: groups: - name: oom rules: - alert: OomKilled annotations: summary: >- Container {{ $labels.container }} in pod {{ $labels.namespace }}/{{ $labels.pod }} has been OOMKilled {{ $value }} times in the last 10 minutes expr: |- (kube_pod_container_status_restarts_total - kube_pod_container_status_restarts_total offset 10m >= 1) and ignoring (reason) min_over_time(kube_pod_container_status_last_terminated_reason{reason="OOMKilled"}[10m]) == 1 labels: severity: critical # Maintenance signals — emit a low-severity alert when a node is # cordoned/draining or when a Flux HelmRelease/Kustomization is # mid-reconcile. These never email (routed to "null" in the # AlertmanagerConfig) — their only job is to be the SOURCE side of # inhibit rules so warning/info alerts sharing the same node or # namespace are suppressed during planned changes. Critical alerts # are intentionally NOT inhibited. maintenance-signals: groups: - name: maintenance-signals rules: - alert: NodeUnderMaintenance annotations: summary: >- Node {{ $labels.node }} is cordoned/unschedulable — pod and target alerts on this node are inhibited expr: kube_node_spec_unschedulable == 1 for: 1m labels: severity: info # label_replace rewrites `namespace` (which is flux-system, where # flux-operator runs) to the actual workload namespace, so the # inhibit rule can equal on `namespace`. - alert: FluxReconciliationInProgress annotations: summary: >- Flux {{ $labels.kind }} {{ $labels.exported_namespace }}/{{ $labels.name }} is reconciling ({{ $labels.reason }}) — child alerts in this namespace are inhibited expr: |- label_replace( flux_resource_info{kind=~"HelmRelease|Kustomization", ready="Unknown", suspended="False"} == 1, "namespace", "$1", "exported_namespace", "(.+)" ) for: 1m labels: severity: info prometheus-node-exporter: fullnameOverride: node-exporter kube-state-metrics: fullnameOverride: kube-state-metrics verticalPodAutoscaler: enabled: true metricLabelsAllowlist: - pods=[*] - deployments=[*] - persistentvolumeclaims=[*] # Talos binds scheduler and controller-manager to 0.0.0.0; # use kube-apiserver selector since Talos labels differ from upstream kubeScheduler: service: selector: component: kube-apiserver kubeControllerManager: service: selector: component: kube-apiserver # Disable kubeProxy whilst using Cilium as it's not deployed kubeProxy: enabled: false # etcd metrics exposed on http://0.0.0.0:2381 via Talos extraArgs kubeEtcd: service: selector: component: kube-apiserver port: 2381 targetPort: 2381 serviceMonitor: scheme: http caFile: "" certFile: "" keyFile: "" ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: alertmanager namespace: observability spec: parentRefs: - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'alertmanager.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: alertmanager-operated port: 9093 weight: 100 --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: prometheus namespace: observability spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'prometheus.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: kube-prometheus-stack-prometheus port: 9090 weight: 100 ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - alertmanager-replicationsource.yaml - alertmanager-volsync-externalsecret.yaml - alertmanagerconfig.yaml - grafanadashboard.yaml - helmrelease.yaml - httproute.yaml - ocirepository.yaml - prometheus-replicationsource.yaml - prometheus-volsync-externalsecret.yaml - scrapeconfig.yaml - silence-watchdog.yaml configMapGenerator: - name: flux-metrics-configmap files: - flux-metrics.yaml=./resources/flux-metrics.yaml generatorOptions: disableNameSuffixHash: true annotations: kustomize.toolkit.fluxcd.io/substitute: disabled ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: kube-prometheus-stack namespace: observability spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 85.2.0 url: oci://ghcr.io/prometheus-community/charts/kube-prometheus-stack ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/app/prometheus-replicationsource.yaml ================================================ --- apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: prometheus spec: sourcePVC: prometheus-kube-prometheus-stack-db-prometheus-kube-prometheus-stack-0 trigger: schedule: "0 * * * *" kopia: accessModes: - ReadWriteOnce cacheAccessModes: - ReadWriteOnce cacheCapacity: 5Gi cacheStorageClassName: ceph-block compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: 1000 runAsGroup: 2000 fsGroup: 2000 parallelism: 2 repository: prometheus-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ceph-block volumeSnapshotClassName: csi-ceph-blockpool ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/app/prometheus-volsync-externalsecret.yaml ================================================ --- apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: prometheus-volsync spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: prometheus-volsync-secret template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/app/resources/flux-metrics.yaml ================================================ --- kube-state-metrics: rbac: extraRules: - apiGroups: - source.toolkit.fluxcd.io - kustomize.toolkit.fluxcd.io - helm.toolkit.fluxcd.io - notification.toolkit.fluxcd.io resources: - gitrepositories - buckets - helmrepositories - helmcharts - ocirepositories - kustomizations - helmreleases - alerts - providers - receivers verbs: - list - watch customResourceState: enabled: true config: spec: resources: - groupVersionKind: group: kustomize.toolkit.fluxcd.io version: v1 kind: Kustomization metricNamePrefix: gotk metrics: - name: resource_info help: The current state of a Flux Kustomization resource. each: type: Info info: labelsFromPath: name: - metadata - name labelsFromPath: exported_namespace: - metadata - namespace ready: - status - conditions - "[type=Ready]" - status suspended: - spec - suspend revision: - status - lastAppliedRevision source_name: - spec - sourceRef - name - groupVersionKind: group: helm.toolkit.fluxcd.io version: v2 kind: HelmRelease metricNamePrefix: gotk metrics: - name: resource_info help: The current state of a Flux HelmRelease resource. each: type: Info info: labelsFromPath: name: - metadata - name labelsFromPath: exported_namespace: - metadata - namespace ready: - status - conditions - "[type=Ready]" - status suspended: - spec - suspend revision: - status - history - "0" - chartVersion chart_name: - status - history - "0" - chartName chart_app_version: - status - history - "0" - appVersion chart_ref_name: - spec - chartRef - name chart_source_name: - spec - chart - spec - sourceRef - name - groupVersionKind: group: source.toolkit.fluxcd.io version: v1 kind: GitRepository metricNamePrefix: gotk metrics: - name: resource_info help: The current state of a Flux GitRepository resource. each: type: Info info: labelsFromPath: name: - metadata - name labelsFromPath: exported_namespace: - metadata - namespace ready: - status - conditions - "[type=Ready]" - status suspended: - spec - suspend revision: - status - artifact - revision url: - spec - url - groupVersionKind: group: source.toolkit.fluxcd.io version: v1 kind: HelmRepository metricNamePrefix: gotk metrics: - name: resource_info help: The current state of a Flux HelmRepository resource. each: type: Info info: labelsFromPath: name: - metadata - name labelsFromPath: exported_namespace: - metadata - namespace ready: - status - conditions - "[type=Ready]" - status suspended: - spec - suspend revision: - status - artifact - revision url: - spec - url - groupVersionKind: group: source.toolkit.fluxcd.io version: v1 kind: HelmChart metricNamePrefix: gotk metrics: - name: resource_info help: The current state of a Flux HelmChart resource. each: type: Info info: labelsFromPath: name: - metadata - name labelsFromPath: exported_namespace: - metadata - namespace ready: - status - conditions - "[type=Ready]" - status suspended: - spec - suspend revision: - status - artifact - revision chart_name: - spec - chart chart_version: - spec - version - groupVersionKind: group: source.toolkit.fluxcd.io version: v1 kind: OCIRepository metricNamePrefix: gotk metrics: - name: resource_info help: The current state of a Flux OCIRepository resource. each: type: Info info: labelsFromPath: name: - metadata - name labelsFromPath: exported_namespace: - metadata - namespace ready: - status - conditions - "[type=Ready]" - status suspended: - spec - suspend revision: - status - artifact - revision url: - spec - url - groupVersionKind: group: notification.toolkit.fluxcd.io version: v1beta3 kind: Alert metricNamePrefix: gotk metrics: - name: resource_info help: The current state of a Flux Alert resource. each: type: Info info: labelsFromPath: name: - metadata - name labelsFromPath: exported_namespace: - metadata - namespace suspended: - spec - suspend - groupVersionKind: group: notification.toolkit.fluxcd.io version: v1beta3 kind: Provider metricNamePrefix: gotk metrics: - name: resource_info help: The current state of a Flux Provider resource. each: type: Info info: labelsFromPath: name: - metadata - name labelsFromPath: exported_namespace: - metadata - namespace suspended: - spec - suspend - groupVersionKind: group: notification.toolkit.fluxcd.io version: v1 kind: Receiver metricNamePrefix: gotk metrics: - name: resource_info help: The current state of a Flux Receiver resource. each: type: Info info: labelsFromPath: name: - metadata - name labelsFromPath: exported_namespace: - metadata - namespace ready: - status - conditions - "[type=Ready]" - status suspended: - spec - suspend webhook_path: - status - webhookPath ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/app/scrapeconfig.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/scrapeconfig_v1alpha1.json apiVersion: monitoring.coreos.com/v1alpha1 kind: ScrapeConfig metadata: name: node-exporter spec: staticConfigs: - targets: - expanse.internal:9100 metricsPath: /metrics relabelings: - action: replace targetLabel: job replacement: node-exporter --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/scrapeconfig_v1alpha1.json apiVersion: monitoring.coreos.com/v1alpha1 kind: ScrapeConfig metadata: name: smartctl-exporter spec: staticConfigs: - targets: - expanse.internal:9633 metricsPath: /metrics relabelings: - action: replace targetLabel: job replacement: smartctl-exporter --- # # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/scrapeconfig_v1alpha1.json apiVersion: monitoring.coreos.com/v1alpha1 kind: ScrapeConfig metadata: name: jetkvm spec: staticConfigs: - targets: - jetkvm-01.internal - jetkvm-02.internal - jetkvm-03.internal metricsPath: /metrics relabelings: - action: replace targetLabel: job replacement: jetkvm ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/app/silence-watchdog.yaml ================================================ --- apiVersion: observability.giantswarm.io/v1alpha2 kind: Silence metadata: name: watchdog namespace: observability spec: matchers: - name: alertname value: Watchdog matchType: "=" ================================================ FILE: kubernetes/apps/base/observability/kube-prometheus-stack/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kube-prometheus-stack namespace: observability spec: path: "./apps/base/observability/kube-prometheus-stack/app" wait: true dependsOn: - name: onepassword namespace: external-secrets - name: rook-ceph-cluster namespace: rook-ceph - name: volsync namespace: volsync-system targetNamespace: observability sourceRef: kind: ExternalArtifact name: kube-prometheus-stack namespace: flux-system ================================================ FILE: kubernetes/apps/base/observability/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: observability components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/observability/loki/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app loki namespace: observability spec: interval: 1h chartRef: kind: OCIRepository name: loki values: singleBinary: replicas: 1 nodeSelector: openebs.io/storage: "true" kubernetes.io/arch: arm64 loki: storage: type: filesystem auth_enabled: false commonConfig: replication_factor: 1 limits_config: retention_period: 14d enforce_metric_name: false reject_old_samples: true reject_old_samples_max_age: 168h max_cache_freshness_per_query: 10m split_queries_by_interval: 15m ingestion_rate_mb: 8 ingestion_burst_size_mb: 16 shard_streams: enabled: true compactor: working_directory: /var/loki/boltdb-shipper-compactor shared_store: filesystem compaction_interval: 10m retention_enabled: true retention_delete_delay: 2h retention_delete_worker_count: 150 ingester: max_chunk_age: 1h analytics: reporting_enabled: false test: enabled: false read: replicas: 1 # persistence: # storageClass: cstor-replica-raspberry-pi-pool write: replicas: 1 # persistence: # storageClass: cstor-replica-raspberry-pi-pool backend: replicas: 1 # persistence: # storageClass: cstor-replica-raspberry-pi-pool monitoring: dashboards: annotations: grafana_folder: Loki selfMonitoring: enabled: false grafanaAgent: installOperator: false lokiCanary: enabled: false # structuredConfig: # memberlist: # join_members: ["loki-memberlist"] ================================================ FILE: kubernetes/apps/base/observability/loki/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/observability/loki/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: loki namespace: observability spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 6.30.0 url: oci://ghcr.io/home-operations/charts-mirror/loki ================================================ FILE: kubernetes/apps/base/observability/loki/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: loki namespace: observability spec: path: "./apps/base/observability/loki/app" wait: false targetNamespace: observability sourceRef: kind: ExternalArtifact name: loki namespace: flux-system ================================================ FILE: kubernetes/apps/base/observability/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: observability labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/observability/otel/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: otel-operator namespace: observability spec: interval: 1h chartRef: kind: OCIRepository name: opentelemetry-operator ================================================ FILE: kubernetes/apps/base/observability/otel/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/observability/otel/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: opentelemetry-operator namespace: observability spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 0.113.1 url: oci://ghcr.io/open-telemetry/opentelemetry-helm-charts/opentelemetry-operator ================================================ FILE: kubernetes/apps/base/observability/otel/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: otel namespace: observability spec: path: "./apps/base/observability/otel/app" wait: false targetNamespace: observability sourceRef: kind: ExternalArtifact name: otel namespace: flux-system ================================================ FILE: kubernetes/apps/base/observability/silence-operator/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: silence-operator spec: interval: 1h chartRef: kind: OCIRepository name: silence-operator values: alertmanagerAddress: http://kube-prometheus-stack-alertmanager.observability.svc.cluster.local:9093 networkPolicy: enabled: false ================================================ FILE: kubernetes/apps/base/observability/silence-operator/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/observability/silence-operator/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: silence-operator spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 0.20.1 url: oci://gsoci.azurecr.io/charts/giantswarm/silence-operator ================================================ FILE: kubernetes/apps/base/observability/silence-operator/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: silence-operator namespace: observability spec: path: "./apps/base/observability/silence-operator/app" wait: true targetNamespace: observability sourceRef: kind: ExternalArtifact name: silence-operator namespace: flux-system ================================================ FILE: kubernetes/apps/base/observability/vpa/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: vpa spec: interval: 1h chart: spec: chart: vpa version: 4.11.0 sourceRef: kind: HelmRepository name: fairwinds-charts namespace: flux-system interval: 10m values: recommender: extraArgs: storage: prometheus prometheus-address: |- http://prometheus-operated.observability.svc.cluster.local:9090 ================================================ FILE: kubernetes/apps/base/observability/vpa/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml ================================================ FILE: kubernetes/apps/base/observability/vpa/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: vpa namespace: observability spec: path: "./apps/base/observability/vpa/app" wait: false targetNamespace: observability sourceRef: kind: ExternalArtifact name: vpa namespace: flux-system ================================================ FILE: kubernetes/apps/base/preview-system/app/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: github-auth spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: github-auth template: data: username: xunholy password: "{{ .FLUX_GITHUB_TOKEN }}" dataFrom: - extract: key: flux ================================================ FILE: kubernetes/apps/base/preview-system/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - externalsecret.yaml - resourcesetinputprovider.yaml - resourceset.yaml ================================================ FILE: kubernetes/apps/base/preview-system/app/resourceset.yaml ================================================ --- apiVersion: fluxcd.controlplane.io/v1 kind: ResourceSet metadata: name: emberstone-portal-preview spec: inputsFrom: - kind: ResourceSetInputProvider name: github-pr-previews resources: # Namespace per PR - apiVersion: v1 kind: Namespace metadata: name: preview-pr-<< inputs.id >> labels: pod-security.kubernetes.io/enforce: baseline preview: "true" annotations: preview.fluxcd.io/pr: << inputs.id | quote >> preview.fluxcd.io/branch: << inputs.branch | quote >> preview.fluxcd.io/author: << inputs.author | quote >> # ResourceQuota to limit preview resource usage - apiVersion: v1 kind: ResourceQuota metadata: name: preview-quota namespace: preview-pr-<< inputs.id >> spec: hard: requests.cpu: "500m" requests.memory: "512Mi" limits.memory: "1Gi" pods: "10" # Git source at the PR commit SHA - apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: pr-<< inputs.id >> namespace: preview-pr-<< inputs.id >> spec: interval: 5m url: https://github.com/xunholy/k8s-gitops ref: commit: << inputs.sha >> secretRef: name: github-auth # Copy the GitHub auth secret into the preview namespace - apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: github-auth namespace: preview-pr-<< inputs.id >> spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: github-auth template: data: username: xunholy password: "{{ .FLUX_GITHUB_TOKEN }}" dataFrom: - extract: key: flux # Kustomization deploying emberstone-portal from the PR branch - apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: emberstone-portal-pr-<< inputs.id >> namespace: preview-pr-<< inputs.id >> labels: gitops.owncloud.ai/defaults: disabled annotations: event.toolkit.fluxcd.io/change_request: << inputs.id | quote >> event.toolkit.fluxcd.io/commit: << inputs.sha | quote >> spec: interval: 5m retryInterval: 1m timeout: 10m prune: true wait: true path: ./kubernetes/apps/base/game-servers/emberstone-portal/app sourceRef: kind: GitRepository name: pr-<< inputs.id >> targetNamespace: preview-pr-<< inputs.id >> postBuild: substitute: CLUSTER_TIMEZONE: "Australia/Melbourne" CLUSTER_DOMAIN: "owncloud.ai" # Post preview URL as a PR comment - apiVersion: batch/v1 kind: Job metadata: name: preview-comment namespace: preview-pr-<< inputs.id >> spec: ttlSecondsAfterFinished: 300 backoffLimit: 3 template: spec: restartPolicy: Never containers: - name: comment image: curlimages/curl:8.20.0 resources: requests: cpu: 10m memory: 32Mi limits: memory: 64Mi command: ["sh", "-c"] args: - | curl -sf -X POST \ -H "Authorization: token $(cat /secrets/password)" \ -H "Accept: application/vnd.github+json" \ "https://api.github.com/repos/xunholy/k8s-gitops/issues/<< inputs.id >>/comments" \ -d "{\"body\":\"## Preview Environment\\n\\n| | |\\n|---|---|\\n| **URL** | [https://<< inputs.id >>.preview.owncloud.ai](https://<< inputs.id >>.preview.owncloud.ai) |\\n| **Branch** | \`<< inputs.branch >>\` |\\n| **Commit** | \`$(echo '<< inputs.sha >>' | cut -c1-7)\` |\\n\\n> This preview will be automatically destroyed when the PR is closed or the label is removed.\"}" volumeMounts: - name: github-auth mountPath: /secrets readOnly: true volumes: - name: github-auth secret: secretName: github-auth # HTTPRoute for internal-only preview access at {id}.preview.owncloud.ai - apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: emberstone-portal-preview namespace: preview-pr-<< inputs.id >> spec: parentRefs: - name: envoy-internal namespace: network-system sectionName: https hostnames: - << inputs.id >>.preview.owncloud.ai rules: - backendRefs: - name: emberstone-portal port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/preview-system/app/resourcesetinputprovider.yaml ================================================ --- apiVersion: fluxcd.controlplane.io/v1 kind: ResourceSetInputProvider metadata: name: github-pr-previews annotations: fluxcd.controlplane.io/reconcileEvery: "5m" spec: type: GitHubPullRequest url: https://github.com/xunholy/k8s-gitops secretRef: name: github-auth filter: labels: - "deploy/preview" limit: 3 ================================================ FILE: kubernetes/apps/base/preview-system/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: preview-system namespace: preview-system spec: dependsOn: - name: onepassword namespace: external-secrets path: "./apps/base/preview-system/app" wait: true targetNamespace: preview-system sourceRef: kind: ExternalArtifact name: preview-system namespace: flux-system ================================================ FILE: kubernetes/apps/base/preview-system/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: preview-system components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/preview-system/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: preview-system labels: kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/audit: baseline pod-security.kubernetes.io/enforce: baseline pod-security.kubernetes.io/warn: baseline ================================================ FILE: kubernetes/apps/base/rook-ceph/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: rook-ceph components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/rook-ceph/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: rook-ceph labels: kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/rook-ceph/rook-ceph/app/grafanadashboard.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: ceph-cluster spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/2842/revisions/18/download --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: ceph-osd spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/5336/revisions/9/download --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: ceph-pools spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/5342/revisions/9/download ================================================ FILE: kubernetes/apps/base/rook-ceph/rook-ceph/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app rook-ceph spec: interval: 5m chartRef: kind: OCIRepository name: rook-ceph valuesFrom: - kind: ConfigMap name: rook-ceph-values ================================================ FILE: kubernetes/apps/base/rook-ceph/rook-ceph/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - grafanadashboard.yaml - helmrelease.yaml - ocirepository.yaml - pdb.yaml configMapGenerator: - name: rook-ceph-values files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/rook-ceph/rook-ceph/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/rook-ceph/rook-ceph/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: rook-ceph spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: v1.19.5 url: oci://ghcr.io/rook/rook-ceph ================================================ FILE: kubernetes/apps/base/rook-ceph/rook-ceph/app/pdb.yaml ================================================ --- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: rook-ceph-operator spec: minAvailable: 1 selector: matchLabels: app: rook-ceph-operator ================================================ FILE: kubernetes/apps/base/rook-ceph/rook-ceph/app/values.yaml ================================================ priorityClassName: platform-cluster-critical csi: cephFSKernelMountOptions: ms_mode=prefer-crc enableLiveness: true provisionerPriorityClassName: platform-cluster-critical pluginPriorityClassName: platform-node-critical serviceMonitor: enabled: true image: repository: ghcr.io/rook/ceph monitoring: enabled: true resources: requests: memory: 128Mi # unchangable cpu: 100m # unchangable limits: {} ================================================ FILE: kubernetes/apps/base/rook-ceph/rook-ceph/cluster/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app rook-ceph-cluster spec: interval: 5m chartRef: kind: OCIRepository name: rook-ceph-cluster valuesFrom: - kind: ConfigMap name: rook-ceph-cluster-values ================================================ FILE: kubernetes/apps/base/rook-ceph/rook-ceph/cluster/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml configMapGenerator: - name: rook-ceph-cluster-values files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/rook-ceph/rook-ceph/cluster/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/rook-ceph/rook-ceph/cluster/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: rook-ceph-cluster spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: v1.19.5 url: oci://ghcr.io/rook/rook-ceph-cluster ================================================ FILE: kubernetes/apps/base/rook-ceph/rook-ceph/cluster/values.yaml ================================================ monitoring: enabled: true createPrometheusRules: true toolbox: enabled: true cephClusterSpec: cephConfig: global: bdev_enable_discard: "true" # quote bdev_async_discard_threads: "1" # quote osd_class_update_on_start: "false" # quote device_failure_prediction_mode: local # requires mgr module cleanupPolicy: wipeDevicesFromOtherClusters: true crashCollector: disable: false csi: readAffinity: enabled: true priorityClassNames: mon: platform-node-critical osd: platform-node-critical mgr: platform-cluster-critical resources: mon: requests: cpu: 250m memory: 1Gi limits: memory: 2Gi mgr: requests: cpu: 250m memory: 512Mi limits: memory: 2Gi osd: # Request matches default osd_memory_target (4 GiB); limit gives headroom for # backfill/recovery and bootstrap, where Ceph routinely doubles working set. requests: cpu: 500m memory: 4Gi limits: memory: 8Gi dashboard: enabled: true urlPrefix: / ssl: false prometheusEndpoint: http://prometheus-operated.observability.svc.cluster.local:9090 mgr: modules: - name: diskprediction_local enabled: true - name: insights enabled: true - name: pg_autoscaler enabled: true - name: rook enabled: true network: connections: requireMsgr2: true storage: useAllNodes: true useAllDevices: false devicePathFilter: /dev/disk/by-id/nvme-Micron_7450_MTFDKBA960TFR_.* config: osdsPerDevice: "1" cephBlockPools: - name: ceph-blockpool spec: failureDomain: host replicated: size: 3 storageClass: enabled: true name: ceph-block isDefault: true reclaimPolicy: Delete allowVolumeExpansion: true volumeBindingMode: Immediate mountOptions: - discard parameters: compression_mode: aggressive compression_algorithm: zstd imageFormat: "2" imageFeatures: layering,fast-diff,object-map,deep-flatten,exclusive-lock csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner csi.storage.k8s.io/provisioner-secret-namespace: "{{ .Release.Namespace }}" csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner csi.storage.k8s.io/controller-expand-secret-namespace: "{{ .Release.Namespace }}" csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node csi.storage.k8s.io/node-stage-secret-namespace: "{{ .Release.Namespace }}" csi.storage.k8s.io/fstype: ext4 cephBlockPoolsVolumeSnapshotClass: enabled: true name: csi-ceph-blockpool isDefault: false deletionPolicy: Delete cephFileSystems: - name: &cephFileSystemName ceph-filesystem spec: metadataPool: replicated: size: 3 dataPools: - failureDomain: host replicated: size: 3 name: data0 metadataServer: activeCount: 1 activeStandby: true priorityClassName: platform-cluster-critical placement: topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: app.kubernetes.io/name: ceph-mds app.kubernetes.io/part-of: *cephFileSystemName resources: requests: cpu: 100m memory: 1Gi limits: memory: 4Gi storageClass: enabled: true isDefault: false name: ceph-filesystem pool: data0 reclaimPolicy: Delete allowVolumeExpansion: true volumeBindingMode: Immediate parameters: csi.storage.k8s.io/provisioner-secret-name: rook-csi-cephfs-provisioner csi.storage.k8s.io/provisioner-secret-namespace: "{{ .Release.Namespace }}" csi.storage.k8s.io/controller-expand-secret-name: rook-csi-cephfs-provisioner csi.storage.k8s.io/controller-expand-secret-namespace: "{{ .Release.Namespace }}" csi.storage.k8s.io/node-stage-secret-name: rook-csi-cephfs-node csi.storage.k8s.io/node-stage-secret-namespace: "{{ .Release.Namespace }}" csi.storage.k8s.io/fstype: ext4 cephFileSystemVolumeSnapshotClass: enabled: true name: csi-ceph-filesystem isDefault: false deletionPolicy: Delete cephObjectStores: [] ================================================ FILE: kubernetes/apps/base/rook-ceph/rook-ceph/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: rook-ceph namespace: rook-ceph spec: path: "./apps/base/rook-ceph/rook-ceph/app" wait: true dependsOn: - name: snapshot-controller namespace: kube-system targetNamespace: rook-ceph sourceRef: kind: ExternalArtifact name: rook-ceph namespace: flux-system --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: rook-ceph-cluster namespace: rook-ceph spec: path: "./apps/base/rook-ceph/rook-ceph/cluster" wait: true targetNamespace: rook-ceph dependsOn: - name: rook-ceph namespace: rook-ceph # - name: volsync # namespace: volsync-system sourceRef: kind: ExternalArtifact name: rook-ceph-cluster namespace: flux-system ================================================ FILE: kubernetes/apps/base/security-system/crowdsec/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: crowdsec namespace: security-system spec: interval: 5m chart: spec: chart: crowdsec version: 0.24.0 sourceRef: kind: HelmRepository name: crowdsec-charts namespace: flux-system interval: 10m values: container_runtime: containerd lapi: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/arch operator: In values: - amd64 dashboard: # TODO: No arm64 images, raise a GH issue enabled: false metrics: enabled: true serviceMonitor: enabled: true persistentVolume: data: enabled: false accessModes: - ReadWriteOnce # storageClassName: "cstor-replica-raspberry-pi-pool" size: 1Gi config: enabled: true accessModes: - ReadWriteOnce # storageClassName: "cstor-replica-raspberry-pi-pool" size: 100Mi agent: acquisition: - namespace: nginx-ingress podName: ingress-nginx-controller-* program: nginx metrics: enabled: true serviceMonitor: enabled: true ================================================ FILE: kubernetes/apps/base/security-system/crowdsec/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: crowdsec namespace: security-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'metabase.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: crowdsec-service port: 3000 weight: 100 ================================================ FILE: kubernetes/apps/base/security-system/crowdsec/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml ================================================ FILE: kubernetes/apps/base/security-system/crowdsec/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: crowdsec namespace: flux-system spec: path: "./apps/base/security-system/crowdsec/app" wait: true targetNamespace: security-system sourceRef: kind: ExternalArtifact name: crowdsec namespace: flux-system ================================================ FILE: kubernetes/apps/base/security-system/falco/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: falco namespace: security-system spec: interval: 1h chartRef: kind: OCIRepository name: falco values: ebpf: enabled: true affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/arch operator: In values: - amd64 ================================================ FILE: kubernetes/apps/base/security-system/falco/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/security-system/falco/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: falco namespace: security-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 8.0.5 url: oci://ghcr.io/falcosecurity/charts/falco ================================================ FILE: kubernetes/apps/base/security-system/falco/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: falco namespace: flux-system spec: path: "./apps/base/security-system/falco/app" wait: true targetNamespace: security-system sourceRef: kind: ExternalArtifact name: falco namespace: flux-system ================================================ FILE: kubernetes/apps/base/security-system/falco-exporter/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: falco-exporter namespace: security-system spec: interval: 1h chartRef: kind: OCIRepository name: falco-exporter values: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/arch operator: In values: - amd64 serviceMonitor: enabled: true grafanaDashboard: enabled: false namespace: default prometheusRules: enabled: false ================================================ FILE: kubernetes/apps/base/security-system/falco-exporter/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/security-system/falco-exporter/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: falco-exporter namespace: security-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 0.12.2 url: oci://ghcr.io/falcosecurity/charts/falco-exporter ================================================ FILE: kubernetes/apps/base/security-system/falco-exporter/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: falco-exporter namespace: flux-system spec: path: "./apps/base/security-system/falco-exporter/app" wait: true targetNamespace: security-system sourceRef: kind: ExternalArtifact name: falco-exporter namespace: flux-system ================================================ FILE: kubernetes/apps/base/security-system/gatekeeper/app/grafanadashboard.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: gatekeeper-dashboard spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS url: https://grafana.com/api/dashboards/15763/revisions/1/download ================================================ FILE: kubernetes/apps/base/security-system/gatekeeper/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: gatekeeper namespace: security-system spec: interval: 5m chart: spec: chart: gatekeeper version: 3.22.2 sourceRef: kind: HelmRepository name: gatekeeper-charts namespace: flux-system interval: 10m values: psp: enabled: false ================================================ FILE: kubernetes/apps/base/security-system/gatekeeper/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - grafanadashboard.yaml - helmrelease.yaml ================================================ FILE: kubernetes/apps/base/security-system/gatekeeper/app/podmonitor.yaml ================================================ # This will scrap for both audit and controller-manager as the label is consistent in both pods. --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/podmonitor_v1.json apiVersion: monitoring.coreos.com/v1 kind: PodMonitor metadata: name: gatekeeper namespace: gatekeeper-system spec: namespaceSelector: matchNames: - gatekeeper-system selector: matchLabels: gatekeeper.sh/system: 'yes' podMetricsEndpoints: - port: metrics ================================================ FILE: kubernetes/apps/base/security-system/gatekeeper/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: gatekeeper namespace: flux-system spec: path: "./apps/base/security-system/gatekeeper/app" wait: true targetNamespace: security-system sourceRef: kind: ExternalArtifact name: gatekeeper namespace: flux-system ================================================ FILE: kubernetes/apps/base/security-system/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: security-system components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/security-system/kyverno/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: kyverno namespace: security-system spec: interval: 1h chartRef: kind: OCIRepository name: kyverno ================================================ FILE: kubernetes/apps/base/security-system/kyverno/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - ocirepository.yaml ================================================ FILE: kubernetes/apps/base/security-system/kyverno/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: kyverno namespace: security-system spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 3.6.1 url: oci://ghcr.io/kyverno/kyverno ================================================ FILE: kubernetes/apps/base/security-system/kyverno/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kyverno namespace: flux-system spec: path: "./apps/base/security-system/kyverno/app" wait: true targetNamespace: security-system sourceRef: kind: ExternalArtifact name: kyverno namespace: flux-system ================================================ FILE: kubernetes/apps/base/security-system/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: security-system labels: goldilocks.fairwinds.com/enabled: "true" kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/volsync-system/kopia/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app kopia spec: interval: 5m chartRef: kind: OCIRepository name: app-template namespace: flux-system valuesFrom: - kind: ConfigMap name: kopia-values ================================================ FILE: kubernetes/apps/base/volsync-system/kopia/app/httproute.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: kopia namespace: volsync-system spec: parentRefs: - name: envoy-external namespace: network-system sectionName: https - name: envoy-internal namespace: network-system sectionName: https hostnames: - 'kopia.${CLUSTER_DOMAIN}' rules: - backendRefs: - name: kopia port: 80 weight: 100 ================================================ FILE: kubernetes/apps/base/volsync-system/kopia/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml - httproute.yaml configMapGenerator: - name: kopia-values files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/volsync-system/kopia/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/volsync-system/kopia/app/values.yaml ================================================ controllers: kopia: containers: app: image: repository: ghcr.io/home-operations/kopia tag: 0.23.0@sha256:76865b421548b1d7bb26a8268f0f0bc828be4eec3f8d8b9c8ece991c99878f94 env: KOPIA_WEB_ENABLED: true KOPIA_WEB_PORT: &port 80 TZ: ${CLUSTER_TIMEZONE} envFrom: - secretRef: name: kopia-secret args: - --without-password probes: liveness: &probes enabled: true custom: true spec: httpGet: path: / port: *port initialDelaySeconds: 0 periodSeconds: 10 timeoutSeconds: 1 failureThreshold: 3 readiness: *probes securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: cpu: 10m limits: memory: 1Gi defaultPodOptions: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch service: app: ports: http: port: *port configMaps: config: data: repository.config: |- { "storage": { "type": "filesystem", "config": { "path": "/repository" } }, "hostname": "volsync.{{ .Release.Namespace }}.svc.cluster.local", "username": "volsync", "description": "volsync", "enableActions": false } persistence: config-file: type: configMap identifier: config globalMounts: - path: /config/repository.config subPath: repository.config repository: type: nfs server: ${CLUSTER_NFS_SERVER} path: /mnt/tank/volsynckopia globalMounts: - path: /repository tmpfs: type: emptyDir advancedMounts: kopia: app: - path: /config/cache subPath: cache - path: /config/logs subPath: logs - path: /tmp subPath: tmp ================================================ FILE: kubernetes/apps/base/volsync-system/kopia/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: kopia namespace: volsync-system spec: path: "./apps/base/volsync-system/kopia/app" wait: true targetNamespace: volsync-system sourceRef: kind: ExternalArtifact name: kopia namespace: flux-system ================================================ FILE: kubernetes/apps/base/volsync-system/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: volsync-system components: - ../../../components/common resources: - namespace.yaml ================================================ FILE: kubernetes/apps/base/volsync-system/namespace.yaml ================================================ --- apiVersion: v1 kind: Namespace metadata: name: volsync-system labels: kustomize.toolkit.fluxcd.io/prune: disabled pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged ================================================ FILE: kubernetes/apps/base/volsync-system/volsync/app/grafanadashboard.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/grafana.integreatly.org/grafanadashboard_v1beta1.json apiVersion: grafana.integreatly.org/v1beta1 kind: GrafanaDashboard metadata: name: volsync spec: allowCrossNamespaceImport: true instanceSelector: matchLabels: grafana.internal/instance: grafana datasources: - datasourceName: prometheus inputName: DS_PROMETHEUS envs: - name: VAR_REPLICATIONDESTNAME value: .*-dst url: https://grafana.com/api/dashboards/21356/revisions/3/download ================================================ FILE: kubernetes/apps/base/volsync-system/volsync/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/helm.toolkit.fluxcd.io/helmrelease_v2.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app volsync spec: interval: 5m chartRef: kind: OCIRepository name: volsync valuesFrom: - kind: ConfigMap name: volsync-values ================================================ FILE: kubernetes/apps/base/volsync-system/volsync/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - grafanadashboard.yaml - helmrelease.yaml - mutatingadmissionpolicy.yaml - ocirepository.yaml - prometheusrule.yaml configMapGenerator: - name: volsync-values files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/apps/base/volsync-system/volsync/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/apps/base/volsync-system/volsync/app/mutatingadmissionpolicy.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/refs/heads/master/v1.34.0/mutatingadmissionpolicybinding-admissionregistration-v1beta1.json apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingAdmissionPolicyBinding metadata: name: volsync-mover-jitter spec: policyName: volsync-mover-jitter --- # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/refs/heads/master/v1.34.0/mutatingadmissionpolicy-admissionregistration-v1beta1.json apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingAdmissionPolicy metadata: name: volsync-mover-jitter spec: matchConstraints: resourceRules: - apiGroups: - batch apiVersions: - v1 operations: - CREATE - UPDATE resources: - jobs matchConditions: - name: has-volsync-job-name-prefix expression: >- object.metadata.name.startsWith("volsync-src-") - name: has-volsync-created-by-labels expression: >- object.metadata.?labels["app.kubernetes.io/created-by"].orValue("") == "volsync" failurePolicy: Fail reinvocationPolicy: IfNeeded mutations: - patchType: JSONPatch jsonPatch: expression: >- [ JSONPatch{ op: "add", path: "/spec/template/spec/initContainers", value: [] }, JSONPatch{ op: "add", path: "/spec/template/spec/initContainers/-", value: Object.spec.template.spec.initContainers{ name: "jitter", image: "ghcr.io/home-operations/busybox:1.37.0@sha256:026ed7273270ec08f6902b4ae8334c23b473e5394bec3bbbdbfe580c710d50bc", imagePullPolicy: "IfNotPresent", command: ["sh", "-c", "sleep $(shuf -i 0-30 -n 1)"] } } ] --- # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/refs/heads/master/v1.34.0/mutatingadmissionpolicybinding-admissionregistration-v1beta1.json apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingAdmissionPolicyBinding metadata: name: volsync-mover-nfs spec: policyName: volsync-mover-nfs --- # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/refs/heads/master/v1.34.0/mutatingadmissionpolicy-admissionregistration-v1beta1.json apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingAdmissionPolicy metadata: name: volsync-mover-nfs spec: matchConstraints: resourceRules: - apiGroups: - batch apiVersions: - v1 operations: - CREATE - UPDATE resources: - jobs matchConditions: - name: has-volsync-job-name-prefix expression: >- object.metadata.name.startsWith("volsync-") - name: has-volsync-created-by-labels expression: >- object.metadata.?labels["app.kubernetes.io/created-by"].orValue("") == "volsync" - name: repository-volume-does-not-exist expression: >- !has(object.spec.template.spec.volumes) || !object.spec.template.spec.volumes.exists(item, item.name == "repository") failurePolicy: Fail reinvocationPolicy: IfNeeded mutations: - patchType: JSONPatch jsonPatch: expression: >- [ JSONPatch{ op: "add", path: "/spec/template/spec/containers/0/volumeMounts/-", value: Object.spec.template.spec.containers.volumeMounts{ name: "repository", mountPath: "/repository" } }, JSONPatch{ op: "add", path: "/spec/template/spec/volumes/-", value: Object.spec.template.spec.volumes{ name: "repository", nfs: Object.spec.template.spec.volumes.nfs{ server: "expanse.internal", path: "/mnt/tank/volsynckopia" } } } ] ================================================ FILE: kubernetes/apps/base/volsync-system/volsync/app/ocirepository.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/source.toolkit.fluxcd.io/ocirepository_v1.json apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: volsync spec: interval: 5m layerSelector: mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip operation: copy ref: tag: 0.18.5 url: oci://ghcr.io/home-operations/charts-mirror/volsync-perfectra1n ================================================ FILE: kubernetes/apps/base/volsync-system/volsync/app/prometheusrule.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/monitoring.coreos.com/prometheusrule_v1.json apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: name: volsync spec: groups: - name: volsync.rules rules: - alert: VolSyncComponentAbsent expr: |- absent(up{job="volsync-metrics"}) annotations: summary: >- VolSync component has disappeared from Prometheus target discovery for: 1h labels: severity: warning - alert: VolSyncVolumeOutOfSync expr: |- volsync_volume_out_of_sync == 1 annotations: summary: >- {{ $labels.obj_namespace }}/{{ $labels.obj_name }} volume is out of sync for: 6h labels: severity: warning ================================================ FILE: kubernetes/apps/base/volsync-system/volsync/app/values.yaml ================================================ fullnameOverride: volsync # Required for volsync-perfectra1n fork image: &image repository: ghcr.io/perfectra1n/volsync tag: v0.17.11 kopia: *image rclone: *image restic: *image rsync: *image rsync-tls: *image syncthing: *image manageCRDs: true metrics: disableAuth: true podSecurityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 ================================================ FILE: kubernetes/apps/base/volsync-system/volsync/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: volsync namespace: volsync-system spec: path: "./apps/base/volsync-system/volsync/app" wait: true targetNamespace: volsync-system sourceRef: kind: ExternalArtifact name: volsync namespace: flux-system --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: volsync-maintenance namespace: volsync-system spec: path: "./apps/base/volsync-system/volsync/maintenance" wait: true targetNamespace: volsync-system dependsOn: - name: volsync namespace: volsync-system sourceRef: kind: ExternalArtifact name: volsync-maintenance namespace: flux-system ================================================ FILE: kubernetes/apps/base/volsync-system/volsync/maintenance/kopiamaintenance.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/volsync.backube/kopiamaintenance_v1alpha1.json apiVersion: volsync.backube/v1alpha1 kind: KopiaMaintenance metadata: name: daily namespace: volsync spec: enabled: true trigger: schedule: 0 */8 * * * repository: repository: volsync-maintenance-secret ================================================ FILE: kubernetes/apps/base/volsync-system/volsync/maintenance/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: volsync-system resources: - ./kopiamaintenance.yaml - ./mutatingadmissionpolicy.yaml ================================================ FILE: kubernetes/apps/base/volsync-system/volsync/maintenance/mutatingadmissionpolicy.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/refs/heads/master/v1.34.0/mutatingadmissionpolicybinding-admissionregistration-v1beta1.json apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingAdmissionPolicyBinding metadata: name: kopia-maintenance-nfs spec: policyName: kopia-maintenance-nfs --- # yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/refs/heads/master/v1.34.0/mutatingadmissionpolicy-admissionregistration-v1beta1.json apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingAdmissionPolicy metadata: name: kopia-maintenance-nfs spec: matchConstraints: resourceRules: - apiGroups: - batch apiVersions: - v1 operations: - CREATE - UPDATE resources: - jobs matchConditions: - name: has-kopia-maint-job-name-prefix expression: > object.metadata.name.startsWith("kopia-maint-") - name: repository-volume-does-not-exist expression: > !has(object.spec.template.spec.volumes) || !object.spec.template.spec.volumes.exists(item, item.name == "repository") failurePolicy: Fail reinvocationPolicy: IfNeeded mutations: - patchType: JSONPatch jsonPatch: expression: >- [ JSONPatch{ op: "add", path: "/spec/template/spec/volumes/-", value: Object.spec.template.spec.volumes{ name: "repository", nfs: Object.spec.template.spec.volumes.nfs{ server: "expanse.internal", path: "/mnt/tank/volsynckopia" } } }, JSONPatch{ op: "add", path: "/spec/template/spec/containers/0/volumeMounts/-", value: Object.spec.template.spec.containers.volumeMounts{ name: "repository", mountPath: "/repository" } } ] ================================================ FILE: kubernetes/apps/overlays/cluster-00/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: # - ../../base/actions-runner-system - ../../base/ai-system - ../../base/crossplane-system - ../../base/democratic-csi - ../../base/development - ../../base/external-secrets - ../../base/game-servers - ../../base/harbor - ../../base/home-system - ../../base/kguardian - ../../base/kube-system - ../../base/network-system - ../../base/nginx-ingress - ../../base/observability - ../../base/preview-system - ../../base/rook-ceph - ../../base/security-system - ../../base/volsync-system # - ../../base/actions-runner-system/gha-runner-scale-set/ks.yaml # - ../../base/actions-runner-system/gha-runner-scale-set-controller/ks.yaml # - ../../base/ai-system/kagent/ks.yaml # - ../../base/ai-system/kgateway/ks.yaml # - ../../base/ai-system/kmcp/ks.yaml - ../../base/ai-system/n8n/ks.yaml - ../../base/ai-system/ollama/ks.yaml - ../../base/ai-system/open-webui/ks.yaml # - ../../base/crossplane-system/crossplane/ks.yaml - ../../base/democratic-csi/democratic-csi/ks.yaml # - ../../base/development/backstage/ks.yaml - ../../base/development/open-feature-operator/ks.yaml - ../../base/external-secrets/external-secrets/ks.yaml - ../../base/external-secrets/onepassword/ks.yaml - ../../base/flux-system/artifact-generator - ../../base/flux-system/flux-instance/ks.yaml - ../../base/flux-system/repositories - ../../base/harbor/harbor/ks.yaml - ../../base/game-servers/enemy-territory/ks.yaml - ../../base/game-servers/minecraft/ks.yaml # - ../../base/game-servers/minecraft-witherstorm/ks.yaml # Disabled: corrupted EXT4 on TrueNAS iSCSI PVC; needs fsck or PVC recreate before re-enabling - ../../base/game-servers/minecraft-bedrock/ks.yaml - ../../base/game-servers/minecraft-bedrock-broadcaster/ks.yaml # - ../../base/game-servers/minecraft-proxy/ks.yaml - ../../base/game-servers/minecraft-rcon-web/ks.yaml # - ../../base/game-servers/minecraft-router/ks.yaml - ../../base/game-servers/minecraft-pixelmon/ks.yaml - ../../base/game-servers/cmangos/ks.yaml - ../../base/game-servers/cmangos-ptr/ks.yaml - ../../base/game-servers/adminer/ks.yaml - ../../base/game-servers/azerothcore/ks.yaml - ../../base/game-servers/emberstone-portal/ks.yaml - ../../base/home-system/autobrr/ks.yaml - ../../base/home-system/bazarr/ks.yaml # - ../../base/home-system/emqx/ks.yaml - ../../base/home-system/home-assistant/ks.yaml - ../../base/home-system/jellyseerr/ks.yaml - ../../base/home-system/mosquitto/ks.yaml - ../../base/home-system/prowlarr/ks.yaml - ../../base/home-system/qbittorrent/ks.yaml - ../../base/home-system/qui/ks.yaml - ../../base/home-system/radarr/ks.yaml - ../../base/home-system/recyclarr/ks.yaml - ../../base/home-system/sabnzbd/ks.yaml - ../../base/home-system/smtp-relay/ks.yaml - ../../base/home-system/sonarr/ks.yaml - ../../base/home-system/tautulli/ks.yaml # - ../../base/home-system/zigbee2mqtt/ks.yaml - ../../base/kguardian/kguardian/ks.yaml - ../../base/kube-system/cilium/ks.yaml - ../../base/kube-system/descheduler/ks.yaml - ../../base/kube-system/keda/ks.yaml - ../../base/kube-system/kubelet-csr-approver/ks.yaml - ../../base/kube-system/metrics-server/ks.yaml - ../../base/kube-system/reflector/ks.yaml - ../../base/kube-system/snapshot-controller/ks.yaml - ../../base/kube-system/spegel/ks.yaml # - ../../base/kube-system/tetragon/ks.yaml # Disabled: requires debugfs/tracefs on Talos - ../../base/network-system/cert-manager/ks.yaml - ../../base/network-system/cloudflare-tunnel/ks.yaml - ../../base/network-system/dex/ks.yaml - ../../base/network-system/dex-k8s-authenticator/ks.yaml - ../../base/network-system/echo-server/ks.yaml - ../../base/network-system/envoy-gateway/ks.yaml - ../../base/network-system/external-dns/ks.yaml - ../../base/network-system/external-dns-unifi/ks.yaml # - ../../base/network-system/multus/ks.yaml - ../../base/network-system/oauth2-proxy/ks.yaml - ../../base/nginx-ingress/nginx-ingress/ks.yaml - ../../base/preview-system/ks.yaml - ../../base/observability/blackbox-exporter/ks.yaml - ../../base/observability/grafana/ks.yaml # - ../../base/observability/jaeger/ks.yaml # - ../../base/observability/kiali/ks.yaml - ../../base/observability/kromgo/ks.yaml - ../../base/observability/kube-prometheus-stack/ks.yaml # - ../../base/observability/loki/ks.yaml # - ../../base/observability/otel/ks.yaml - ../../base/observability/silence-operator/ks.yaml - ../../base/observability/vpa/ks.yaml - ../../base/rook-ceph/rook-ceph/ks.yaml - ../../base/volsync-system/kopia/ks.yaml - ../../base/volsync-system/volsync/ks.yaml # - ../../base/security-system/kyverno/ks.yaml # - ../../base/security-system/gatekeeper/ks.yaml ================================================ FILE: kubernetes/bootstrap/helmfile.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/helmfile helmDefaults: force: true timeout: 600 wait: true waitForJobs: true repositories: - name: kustomize-mutating-webhook url: https://xunholy.github.io/fluxcd-kustomize-mutating-webhook releases: - name: flux-operator namespace: flux-system chart: oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator version: 0.49.0 wait: true values: ['{{ requiredEnv "ROOT_DIR" }}/kubernetes/clusters/{{ requiredEnv "CLUSTER_ID"}}/flux-system/flux-operator/app/values.yaml'] - name: flux-instance namespace: flux-system chart: oci://ghcr.io/controlplaneio-fluxcd/charts/flux-instance version: 0.49.0 wait: true values: ['{{ requiredEnv "ROOT_DIR" }}/kubernetes/clusters/{{ requiredEnv "CLUSTER_ID"}}/flux-system/flux-instance/app/values.yaml'] needs: ['flux-system/flux-operator'] - name: cert-manager namespace: network-system chart: oci://quay.io/jetstack/charts/cert-manager version: v1.20.2 wait: true values: ['{{ requiredEnv "ROOT_DIR" }}/kubernetes/apps/base/network-system/cert-manager/app/values.yaml'] - name: kustomize-mutating-webhook namespace: flux-system chart: kustomize-mutating-webhook/kustomize-mutating-webhook version: 0.11.0 wait: false values: ['{{ requiredEnv "ROOT_DIR" }}/kubernetes/clusters/{{ requiredEnv "CLUSTER_ID"}}/flux-system/kustomize-mutating-webhook/app/values.yaml'] needs: ['network-system/cert-manager'] ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/flux-instance/app/helmrelease.yaml ================================================ --- apiVersion: fluxcd.controlplane.io/v1 kind: ResourceSet metadata: name: flux-instance namespace: flux-system spec: dependsOn: - apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition name: helmreleases.helm.toolkit.fluxcd.io - apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition name: ocirepositories.source.toolkit.fluxcd.io resources: - apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: flux-instance namespace: flux-system spec: interval: 10m url: oci://ghcr.io/controlplaneio-fluxcd/charts/flux-instance ref: # renovate: datasource=docker depName=ghcr.io/controlplaneio-fluxcd/charts/flux-instance tag: 0.49.0 verify: provider: cosign matchOIDCIdentity: - issuer: ^https://token\.actions\.githubusercontent\.com$ subject: ^https://github\.com/controlplaneio-fluxcd/charts/\.github/workflows/release\.yml@refs/tags/v\d+\.\d+\.\d+$ - apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: flux-instance namespace: flux-system spec: interval: 15m chartRef: kind: OCIRepository name: flux-instance install: timeout: 10m replace: true crds: CreateReplace createNamespace: true remediation: retries: -1 maxHistory: 3 rollback: cleanupOnFail: true force: true recreate: true test: enable: true uninstall: deletionPropagation: background keepHistory: false upgrade: cleanupOnFail: true crds: CreateReplace remediation: remediateLastFailure: true retries: 3 strategy: rollback driftDetection: mode: enabled dependsOn: - name: flux-operator namespace: flux-system valuesFrom: - kind: ConfigMap name: flux-instance-values ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/flux-instance/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: flux-system resources: - helmrelease.yaml configMapGenerator: - name: flux-instance-values namespace: flux-system files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/flux-instance/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/resources/spec/valuesFrom/name kind: ResourceSet ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/flux-instance/app/values.yaml ================================================ # Source: https://artifacthub.io/packages/helm/flux-instance/flux-instance --- instance: distribution: artifact: oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests:v0.49.0 storage: class: "ceph-block" size: "10Gi" components: - source-controller - kustomize-controller - helm-controller - notification-controller - source-watcher commonAnnotations: fluxcd.controlplane.io/reconcile: "enabled" fluxcd.controlplane.io/reconcileEvery: "1h" fluxcd.controlplane.io/reconcileTimeout: "3m" cluster: size: medium multitenant: false networkPolicy: true domain: "cluster.local" commonMetadata: labels: app.kubernetes.io/name: flux sync: kind: OCIRepository url: oci://ghcr.io/xunholy/manifests/k8s-gitops ref: main path: ./clusters/cluster-00 kustomize: patches: # Allow cluster-autoscaler to evict flux controllers if needed - patch: |- apiVersion: apps/v1 kind: Deployment metadata: name: all spec: template: metadata: annotations: cluster-autoscaler.kubernetes.io/safe-to-evict: "true" spec: containers: - name: manager imagePullPolicy: Always resources: limits: memory: 2Gi target: kind: Deployment # Use tmpfs for kustomize-controller builds and disable remote bases - patch: |- - op: replace path: /spec/template/spec/volumes/0 value: name: temp emptyDir: medium: Memory - op: add path: /spec/template/spec/containers/0/args/- value: --no-remote-bases=true target: kind: Deployment name: kustomize-controller # Enable Helm repositories caching - patch: |- - op: add path: /spec/template/spec/containers/0/args/- value: --helm-cache-max-size=10 - op: add path: /spec/template/spec/containers/0/args/- value: --helm-cache-ttl=60m - op: add path: /spec/template/spec/containers/0/args/- value: --helm-cache-purge-interval=5m target: kind: Deployment name: source-controller # Flux near OOM detection for Helm - patch: |- - op: add path: /spec/template/spec/containers/0/args/- value: --feature-gates=OOMWatch=true,DefaultToRetryOnFailure=true,CancelHealthCheckOnNewRevision=true - op: add path: /spec/template/spec/containers/0/args/- value: --oom-watch-memory-threshold=95 - op: add path: /spec/template/spec/containers/0/args/- value: --oom-watch-interval=500ms target: kind: Deployment name: helm-controller # Add postBuild substitution and SOPS decryption to flux-system Kustomization - patch: |- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: flux-system namespace: flux-system spec: decryption: provider: sops postBuild: substitute: {} substituteFrom: - kind: ConfigMap name: cluster-config - kind: Secret name: cluster-secrets target: kind: Kustomization name: flux-system # Controller-level SOPS decryption - patch: |- - op: add path: /spec/template/spec/containers/0/args/- value: --sops-age-secret=sops-age-secret target: kind: Deployment name: kustomize-controller # Watch configmaps and secrets attached to HelmReleases and Kustomizations - patch: |- - op: add path: /spec/template/spec/containers/0/args/- value: --watch-configs-label-selector=owner!=helm target: kind: Deployment name: (helm-controller|kustomize-controller) # Cancel health checks on new Kustomizations revisions - patch: |- - op: add path: /spec/template/spec/containers/0/args/- value: --feature-gates=CancelHealthCheckOnNewRevision=true target: kind: Deployment name: kustomize-controller ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/flux-instance/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: &app flux-instance namespace: flux-system spec: decryption: provider: sops interval: 30m path: ./clusters/cluster-00/flux-system/flux-instance/app prune: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: flux-system timeout: 5m wait: false postBuild: substituteFrom: - kind: ConfigMap name: cluster-config ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/flux-operator/app/helmrelease.yaml ================================================ --- apiVersion: fluxcd.controlplane.io/v1 kind: ResourceSet metadata: name: flux-operator namespace: flux-system spec: dependsOn: - apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition name: helmreleases.helm.toolkit.fluxcd.io - apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition name: ocirepositories.source.toolkit.fluxcd.io resources: - apiVersion: source.toolkit.fluxcd.io/v1 kind: OCIRepository metadata: name: flux-operator namespace: flux-system spec: interval: 10m url: oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator ref: # renovate: datasource=docker depName=ghcr.io/controlplaneio-fluxcd/charts/flux-operator tag: 0.49.0 verify: provider: cosign matchOIDCIdentity: - issuer: ^https://token\.actions\.githubusercontent\.com$ subject: ^https://github\.com/controlplaneio-fluxcd/charts/\.github/workflows/release\.yml@refs/tags/v\d+\.\d+\.\d+$ - apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: flux-operator namespace: flux-system spec: interval: 30m releaseName: flux-operator serviceAccountName: flux-operator chartRef: kind: OCIRepository name: flux-operator install: timeout: 10m replace: true crds: CreateReplace createNamespace: true remediation: retries: -1 maxHistory: 3 rollback: cleanupOnFail: true force: true recreate: true test: enable: true uninstall: deletionPropagation: background keepHistory: false upgrade: cleanupOnFail: true crds: CreateReplace remediation: remediateLastFailure: true retries: 3 strategy: rollback driftDetection: mode: enabled valuesFrom: - kind: ConfigMap name: flux-operator-values ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/flux-operator/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - helmrelease.yaml configMapGenerator: - name: flux-operator-values namespace: flux-system files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/flux-operator/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/resources/spec/valuesFrom/name kind: ResourceSet ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/flux-operator/app/values.yaml ================================================ --- serviceMonitor: create: true web: networkPolicy: create: false ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/flux-operator/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: &app flux-operator namespace: flux-system spec: decryption: provider: sops interval: 30m path: ./clusters/cluster-00/flux-system/flux-operator/app prune: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system targetNamespace: flux-system timeout: 5m wait: false postBuild: substituteFrom: - kind: ConfigMap name: cluster-config ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/kustomize-mutating-webhook/app/helmrelease.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: &app kustomize-mutating-webhook namespace: flux-system spec: interval: 5m chart: spec: version: 0.11.0 chart: kustomize-mutating-webhook sourceRef: kind: HelmRepository name: fluxcd-kustomize-mutating-webhook namespace: flux-system interval: 5m install: timeout: 10m replace: true crds: CreateReplace createNamespace: true strategy: name: RetryOnFailure retryInterval: 5m upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 valuesFrom: - kind: ConfigMap name: kustomization-mutating-webhook-values ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/kustomize-mutating-webhook/app/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ./helmrelease.yaml configMapGenerator: - name: kustomization-mutating-webhook-values namespace: flux-system files: - values.yaml=./values.yaml configurations: - kustomizeconfig.yaml ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/kustomize-mutating-webhook/app/kustomizeconfig.yaml ================================================ --- nameReference: - kind: ConfigMap version: v1 fieldSpecs: - path: spec/valuesFrom/name kind: HelmRelease ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/kustomize-mutating-webhook/app/values.yaml ================================================ --- image: repository: ghcr.io/xunholy/kustomize-mutating-webhook replicaCount: 1 certManager: enabled: true configMaps: - create: false name: cluster-config secrets: - create: false name: cluster-secrets env: LOG_LEVEL: debug podDisruptionBudget: enabled: false securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL seccompProfile: type: RuntimeDefault service: headless: false ================================================ FILE: kubernetes/clusters/cluster-00/flux-system/kustomize-mutating-webhook/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: &appname kustomize-mutating-webhook namespace: flux-system spec: decryption: provider: sops interval: 30m retryInterval: 1m timeout: 3m path: "./clusters/cluster-00/flux-system/kustomize-mutating-webhook/app" prune: true wait: false sourceRef: kind: OCIRepository name: flux-system namespace: flux-system ================================================ FILE: kubernetes/clusters/cluster-00/ks.yaml ================================================ --- # yaml-language-server: $schema=https://raw.githubusercontent.com/fluxcd-community/flux2-schemas/main/kustomization-kustomize-v1.json apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: cluster namespace: flux-system spec: decryption: provider: sops deletionPolicy: WaitForTermination interval: 30m timeout: 30m path: ./apps/overlays/cluster-00 prune: true wait: false sourceRef: kind: OCIRepository name: flux-system postBuild: substitute: {} substituteFrom: - kind: ConfigMap name: cluster-config - kind: Secret name: cluster-secrets patches: - # Set Kustomization defaults and HelmRelease defaults for all child Kustomizations patch: |- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: _ spec: decryption: provider: sops deletionPolicy: WaitForTermination interval: 30m retryInterval: 1m timeout: 3m prune: true patches: - patch: |- apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: _ spec: install: timeout: 10m replace: true crds: CreateReplace createNamespace: true upgrade: remediation: remediateLastFailure: true retries: 3 strategy: rollback cleanupOnFail: true crds: CreateReplace test: enable: true rollback: recreate: true force: true cleanupOnFail: true uninstall: keepHistory: false driftDetection: mode: enabled maxHistory: 3 target: group: helm.toolkit.fluxcd.io kind: HelmRelease labelSelector: gitops.owncloud.ai/defaults!=disabled target: group: kustomize.toolkit.fluxcd.io kind: Kustomization labelSelector: gitops.owncloud.ai/defaults!=disabled ================================================ FILE: kubernetes/clusters/cluster-00/secrets/.sops.pub.asc ================================================ -----BEGIN PGP PUBLIC KEY BLOCK----- mQINBGB2q3sBEADjCeB/XvSH5/AHpWAmwu9HcKH8VxXQYqBoGj9OrEjhzH9JL1jW Jv1+17kDbzkFYi9f8p4hTExxUgjOERACz/nRA8f3r1LZ46yht5cKJLpqi3y0wvho ADeP+IcZPex+75oqMJTTd28GeT7BVSoPkUKN6vsqtBmOL4l1BDLQh3dBiHpGgnMr RgId5hfgo8vjDHLBpFoCH5EjRV1i1YFwzRudwph2OVKVqCZADK9869LC1SG+TM9V Q4U/eGkNw2H/JW4FAdtroYseu5jJ7zFZbvaGU8Mc0IrLhwBGuE5BRuvk2xzvZCQn lbeLulsr5n6+u2RJSrk8BHhZsZUrdmpbfeQNmACddkmBGxv9+HuZF5dC11iYrs5s 3FF2tqhEi/OTyafI2cho5ICd4lnXMD5vOofaik2amn93TPhfkK0utaMwOJUdfusf tJn91T6J5azNnggaMAiSOy9cTIDc2CcW4FbUyNk6mBmoKVfHL3q+ZSrdubAfCnWl 0JbyTPcRKE/ZQcOd5OpmsjSRU/Ih8TmRYFcC2XzYsgRgIHCFANwu8SbALEe8VsSx Imt2sdCIPLr9VIHW8ZzYc/rOHcllXMJDhIER4GUZWwKxahURPeSr8gM1qsCrvnSx ISbDXwnep9hBtz4IjADEtdYcDxXTwik6NO0xDkDs8RH+Cz2Gu+8DP4c4aQARAQAB tCpwcm9kdWN0aW9uLnJhc3BiZXJuZXRlcy5jb20gKGZsdXggc2VjcmV0cymJAk4E EwEIADgWIQQGNbjTQDepRTAD+3uTyqaC/0yQFAUCYHarewIbLwULCQgHAgYVCgkI CwIEFgIDAQIeAQIXgAAKCRCTyqaC/0yQFLuREADbBdBc3YoFkt4bKElFPdhKdIQE 421Ocw0Eehk+/77i1/M8VWdG6yK5QM5eZerPFDT8Ma7b51Iz+jDiBATV3cZO39ls PXrfiFg9AB7KBB69/psK4DekmZQUBGJzxUzkzZFkv4LvOVt8W0ekVQ2KV/WXpSH9 k8pqJYGmeui4cpoLzBAOpbES3XhAWz0yQJ2LhT5pAQZItDRK2EhXsDEL5LFWq8tV KxEsiq01wQgjFiguGhi5yCjCkgy2Zkk3stFQOrHaEaUOaKtxanLdZ+0SxMOFVfpH UI+kJYsTbNz/QvAG1ypfuHljEjDLs5RaVBpeDraAxmYVTwDDyYZqhiTLtEBfb8ED bYcb7MFSWyCJrF0UtRocf5XV0QG/tPDB2EfeXOGgpRCAoWmNVVZkTkYJDT8Izq6U JkpOzNzoMrwgZ9vt3eKEffTANcV4EFHZcCw37xlWecb6Un93y8CXYLF3M4ia/9mo CGCs6nQdUjaGeslViYarHdgUD8XxJcCanX2iGMzK7m6bUe+CENdi/fik1m20HxjD xjCESqINydzGwkEt/YQ2jBpcNe0DLsRHbadI20IGcA/ZFhzZtPGBbKU556gVxSoE /dq4w/sW+2RMhXtO2gdbN+DIPTelnzyaEA2bsLQA7Wj9GVBK2UnTwMizigsueLb7 QL+lq+9yYwGpdP5PN7kCDQRgdqt7ARAA6g3jlUqyGPqNGv5mSKGbOWGHq70oQmdt L26bzpKk1fvpQIlJnHdz2pSgjAHquTgwkD4fgeJ+fW4qlfXk6b78gSdhhWySx6CD tW0AAtGwlgeBVvSmNPyLdqdMrfJw9VwYH/pY520q5e5Pb7ekf5U9GJPioXe37LME Hx6t2NCOonRHhtN4P1GfigJ+u12o+bh495NtQ8LXULaFQJlbQ6W+jkSDkA9mBRzi VN+loirnXw1jtneMpQofEGLdyg6NTXKQjb76GAVMUmp69d1QfCNEobGXvpfurpye EiC6IPiXh/sKMcei/sgkQhjELeB0rQH6maxVFYhmZjuXyEZe8dCwSCRkRk45fKrC 0ssGC1F434IWBOMMgfBdOzlPr12YWX2K66+53cRUteNpjiPh47exJwJ7Y2aNB9ZH gWzZJTzHKWFvFJs/uOw49i4BiWfWNtTxx7s2KrszRgptkFsDwwJPD5y6FCEm09kQ nma4YpYF/ELYSbEYMaZ9AytorUcmAR8X/NGjcgFE1HfhUTHjJGI188BT9/1Y/U5x b4SaMuU34KlcCqCrMhT5mP8BvMfxVupnLwJljNt2y5xuKF7Cz3jnzfOtvAz9kjis 1CRlC2uidlR2uP2ZeMGi/u0kYl2+T+aCEO2VT0QPzJy/PIyOZTe0AH27rrIu0GBi 9iDdO/OUe/8AEQEAAYkEbAQYAQgAIBYhBAY1uNNAN6lFMAP7e5PKpoL/TJAUBQJg dqt7AhsuAkAJEJPKpoL/TJAUwXQgBBkBCAAdFiEEVoxsIKvW/lYIGyuDHjaWYsfC hnAFAmB2q3sACgkQHjaWYsfChnD8xA//VY1dGBo4ThP7UdqqurAK1yHAJrjmmgk3 vyv9pnte+ESBK+S5Edxv3g1wH9HzEQC32ybEH1mAQ1YFzIrpJavs8NZlK00hnF8g oo1itJb6gBd6rVHyLjHtiIwCxSWVy2ZuIOgb+Pv9/XCJkW/hh6zH6H0DS4/aHuZu XLifhV8Yg89Sz/cG2qTLc/aFuWsagrFg1GtgiKt/FcubMyL/H74vcwO6wdDNbGh8 IrP4pk+0O5GDe3AXAyOfQtN++GXwziFSpG0ggOyXB+Vhy6wgwvqno/0MESp1v1Qz vJyya0Op5PP9R9LOGrU1xjPAug6HVMDqSz68etptTBYAcWjVWrWtkIPYvcg7uQVK g5+aXvy8UbTJ1jNd6ccpxdjQiKTtLjxT4UUcc2n5j1Tr7SzLFZhiK/N/DGxiyjVD cenoJ5zzy6OkQ85izy7jnAqQM006F+4CyagWZInWDDEme9e6oP0aYLIMYY8QwCG6 E/TA7vQvRFL2iY3jygrqwlLOTSufJL0W4NaYuUdrxdCf/JpkxptLamtcxvWmbSBO kHVnSY3hDh6nDYoVeUWdkx4z4wnCf9YtwpzKtmIY0hVkvXqyNUi8LqXZK3BzgcEF egQ+gtIC5lpChrf/rc1ND4E9K8HRujPopVSPWb+5Zzjy9LRPt2NGNJwHcS05l6Y+ iIfy7hJt8q1rpBAAshPuXX+8Pby+WcB5oZ8oNzAwlho2JssbXx91jQFxFBt/tRF2 eKVde7BbFPtuyKYjZ2MQ05j6ieiQ1Hs4Q41dBfFwxBt8jg99JfYTDO7+wkIQSqmz FFv5reoxuR+viFuI964VALHuKDzHI+eICaoxw8qdO/X/0pRaU3pKOcHjkIYpqVHU 8IsItyX+gmajbl8egK8KNmxPmekWMQs8uzNGgdPhCwmrJcfZ5mhH6bAoWUsd8GLc Eb5ZPhyBIuMiPzdiTzpmQAAILlNnAFrq/rZDbekth7TAP9Jifz7dCXlHtTas0Q1x NADyOB3eODniumHqS54paZnxIqB6cwgZHYui7d6xToCLFjT946AiMmCGFxFDQ3SX 5Aay7ybySQeNKf3X8fJaz3MOJ86SSjJ9A1kHKcZVxQslQc+atyUPt2K2b+fadedK mCVKe2Zz1PUsu94rjtA3ORR584UUtjsjwTEeIJuiIad8ZbEe/lqgChgh6pIq1uTZ zPVSmRk0dxiKX2vGdNyzDuUceAUXgHQIieluQttlFNS4cMzqtq25FQwFtbAKfx5g kK7Sw7vBagYUnzxHoOcD/HU76jM2S+CmTM+d6AQWWnWIrBzZ8ryu0BweU7MBMKJF hPLwoaJGpb+COl/c1CqXopLrvnVVPN2KjX68kLlXmSWeHIdBqYIsE8D2uYo= =gfGE -----END PGP PUBLIC KEY BLOCK----- ================================================ FILE: kubernetes/clusters/cluster-00/secrets/cluster-config.yaml ================================================ --- apiVersion: v1 kind: ConfigMap metadata: namespace: flux-system name: cluster-config data: CLUSTER_TIMEZONE: 'Australia/Melbourne' CLUSTER_NFS_SERVER: 'expanse.internal' CLUSTER_NFS_PATH: '/mnt/tank/media' CLUSTER_ID: 'cluster-00' CLUSTER_CONTROLPLANE_VIP: '192.168.50.200' CLUSTER_SUB_DOMAIN: 'prod' CLUSTER_DOMAIN: 'owncloud.ai' BEDROCK_BROADCASTER_DOMAIN: 'bedrockbroadcaster.com' CLUSTER_LB_MINECRAFT: '192.168.50.182' CLUSTER_LB_MINECRAFT_RCON: '192.168.50.183' CLUSTER_LB_MINECRAFT_ROUTER: '192.168.50.184' CLUSTER_LB_NGINX_INGRESS_GATEWAY: '192.168.50.185' CLUSTER_LB_K8S_GATEWAY: '192.168.50.188' CLUSTER_LB_OVERSEERR: '192.168.50.190' CLUSTER_LB_BLOCKY: '192.168.50.191' CLUSTER_LB_EMQX: '192.168.50.193' CLUSTER_LB_QB: '192.168.50.194' CLUSTER_LB_MOSQUITTO: '192.168.50.195' CLUSTER_LB_OPENCLAW: '192.168.50.192' CLUSTER_LB_INT_GATEWAY_API: '192.168.50.180' CLUSTER_LB_EXT_GATEWAY_API: '192.168.50.199' CLUSTER_LB_ENVOY_INT_GATEWAY_API: '192.168.50.181' CLUSTER_LB_ENVOY_EXT_GATEWAY_API: '192.168.50.186' CLUSTER_LB_ADDRESSES: '192.168.50.180-192.168.50.199' EXT_ZIGBEE_CONTROLLER_IP: '192.168.50.165' ================================================ FILE: kubernetes/clusters/cluster-00/secrets/cluster-secrets.enc.age.yaml ================================================ apiVersion: v1 kind: Secret metadata: namespace: flux-system name: cluster-secrets stringData: EXTERNAL_IP: ENC[AES256_GCM,data:HG/QAJtomSpBFBgl,iv:9J2Plep3mf7B9Qw6cBidunPbGiFd/83o2GF+30nQExA=,tag:ZDaCgh3T81DJGvvhQsWHVA==,type:str] DEX_GITHUB_CLIENT_ID: ENC[AES256_GCM,data:ZbbvY2uuh8cHlRQatFU43wDww3w=,iv:OjwI4tY31Qf72n0PfbwU51L6wbdud5LhMyyZCU5GgJA=,tag:vnmC7xcUmjfY4yqZf4tYSA==,type:str] DEX_GITHUB_CLIENT_SECRET: ENC[AES256_GCM,data:AIFhn7UhAG7mpYCDrB10TxtrvQ/Q0uAvXWxJxgMPLzbatoN+v3v9jQ==,iv:Xby2l4gA1D3RnpBZ+AN80jF73/wLyW04eYq23upYKRs=,tag:LHb9hKfAUWGkOgJRzgUErw==,type:str] DEX_K8S_CLIENT_ID: ENC[AES256_GCM,data:1s9+cvHqE3fXYYSq8aTg/aP39IgZ,iv:f4DuTvRMunvWOrVqb/Tky7OlAMou96uiEsJXt7uhzPk=,tag:N47Z3z17ye5+xD5b5YRf7A==,type:str] DEX_K8S_CLIENT_SECRET: ENC[AES256_GCM,data:0TmnfXaY6zWJPLqK4LhqjCD2AFYSRk84IyZTc0k5oZEpqRKdZPpq5d46,iv:wNFqZHcyH1lv8sNRA3PkYV/SuKx4V3vYyQh2XI7GdQA=,tag:rRQ2GanOCbHBJdlo1rUP+w==,type:str] DEX_OAUTH2_PROXY_SECRET: ENC[AES256_GCM,data:PtnObm3LndrHmUTFTWZmC2uTTJ0=,iv:NDZAi8vsjAJWcntVl16qDRBjCuM0h8MiRbe2yEvn7+8=,tag:HMeyQI7TMW+XcxtgiIRp8g==,type:str] DEX_GRAFANA_SECRET: ENC[AES256_GCM,data:L3rnANC2Z2lXsDrRuIQnIv+KxwB0qORE5kHlvEXhltiPVA==,iv:eHy1xFT2d0p/VmbB7ouYLqtXs5jBJ0t+F5QQmvv+u+c=,tag:rsNkS7BqeaCBn78AhYfrhw==,type:str] DEX_LITMUS_SECRET: ENC[AES256_GCM,data:bNs/U+DFkTUCDrA7u3IuuYjQoTzg1NNT,iv:LSRKKN7yBwFEzwKvXdpDHRnZPFSVDolCSL5vjpKLYd0=,tag:faoHbPnM9ER/U2C813mDAA==,type:str] DEX_WEAVE_GITOPS_SECRET: ENC[AES256_GCM,data:bjvKXMgvAGEsh10cdmcEtg==,iv:vUClQrCpSGNpbkLIfwwb2Kb2pnp8PfapEnV7fdvm1gA=,tag:rUpCabNvs/bfUPEiAfKtSw==,type:str] GRAFANA_AUTH_GITHUB_CLIENT_ID: ENC[AES256_GCM,data:vL/WwwTAOr/emKUJWygyb0BTVqk=,iv:I/wk53eeZ7Z5weqYK4y05quysT2lskncnl17jf4OuyY=,tag:NRqNPDgQKX+/6rU9QnsMmg==,type:str] GRAFANA_AUTH_GITHUB_CLIENT_SECRET: ENC[AES256_GCM,data:jdObYxhiyb+5zkTKFpP8FNZai4DWzfrGZRAkwt0tbqO/tsHesTxbRQ==,iv:MmYuNaIGvphHWGTp4wlsglYYUMaYQH3jkBpIziF63/k=,tag:AqP/PHNBkljUhreO/dTXSg==,type:str] GRAFANA_AUTH_GENERIC_CLIENT_ID: ENC[AES256_GCM,data:o92TjeErDQ==,iv:48qO4F0rIA6E8uTTD7F1jq8unV94xvTMQLWb9/K5aG4=,tag:bC/UtDY5JpbO8mvXbZ0Osw==,type:str] GRAFANA_AUTH_GENERIC_CLIENT_SECRET: ENC[AES256_GCM,data:VbndWckrnU+Jhhff33ZI/zk+k/lg40auswy4gZwIYIF3kQ==,iv:cTySCO3qLFrJ1sRyRAhMvVgEwya1JkZzPmJEGGk4j9Q=,tag:1Ms/jesK5Zxo9UC8EB8z/g==,type:str] GRAFANA_ADMIN_USER: ENC[AES256_GCM,data:4N9/low=,iv:0K1v5t9XWAfiUV5hDby0tDXVjY2nFYlF5Tk959W6Flk=,tag:ewhHe/GAkz8bglvOUsdFOw==,type:str] GRAFANA_ADMIN_PASSWORD: ENC[AES256_GCM,data:SH/QO/rncxk=,iv:4yKOLMrPGYIXYT5mCHW2WeCrnavTcP+WGXBAzQ/3qqE=,tag:w6jW9241XriqB9nNLs5TRg==,type:str] THANOS_GCP_SERVICE_ACCOUNT: "" GITHUB_ACTION_APP_ID: "" GITHUB_ACTION_APP_INSTALL_ID: "" GITHUB_ACTION_APP_PRIVATE_KEY: "" CLOUDFLARE_ORIGIN_CA_KEY: "" CLOUDFLARED_TUNNEL_ID: ENC[AES256_GCM,data:xEa9Ms0uo9dIaDBeIfnbsmrEyv8qIGBwhlUM923j+nRegV98,iv:dXosfnK9XGmTRqdza/Y6S1kJ53HM2hyYcguTAbAu/bI=,tag:LUJ6PWzzVDJ1F8my3TDtYg==,type:str] PRIVATE_EMAIL: ENC[AES256_GCM,data:vWZ8vTJhq5hnaJlV/hEhVKpuCjkj5j5S,iv:cHrdn9Ft2B0vKSSpXKsH8uT0ufmayCxRWPl2UmPJk6w=,tag:yq0vSjAj/N/f/CRTOcbDsA==,type:str] GITHUB_TOKEN: ENC[AES256_GCM,data:RAusWFjYjs9C6tgALZSVscLkDHSIWZ/1FzA6ogO2Vi7UTTAljWR3oQ==,iv:L7phiQyBpKlcOvigVzN+3MqPbbJaJFCr46pmuOP3sH0=,tag:veamaYUJ31eI8tW4iwc1Kg==,type:str] MQTT_USER_USERNAME: ENC[AES256_GCM,data:dWrMrw==,iv:1dkVW79CQIPjmFFTNtBvOVjM+s6rrd6Sphi6w0ikxPQ=,tag:Ebet7FrWm27K1NKEEyFkeg==,type:str] MQTT_USER_PASSWORD: ENC[AES256_GCM,data:T9nKPj5Mld/EeE7aP3JNo0ocPiqrpnNPGO4vf/ZqJ/87WA==,iv:dS+PAjxrO9ugcHJRV56PxZh9uKLpjrZPebCKQcVxZzI=,tag:vuTirKSN75BrCLRNeu9p8Q==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyeXF3dkZUVElyeVBoalBD WVdYM2lnc29GeFFicElROTZiU0xiSk9RQVI0Ck92YnM1dnpKaDJYTE1vRFF6emhG MmNlbkF4UXpZYmVoSVNwR1FoaDFVUWsKLS0tIGtCaFZFZVZOakZ0S0ljMUpmV3E4 VXdDME5ISHdDdUY0RFZYK1RtME4rcG8KTLrTE62ZhPq4AqGltINuoXOsWA+59xcs hDANcOVkzyizx9+J86cUnyhqMdTufkTeReDIkZgY9eI2JjZqkl/XIQ== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-03-01T01:50:31Z" mac: ENC[AES256_GCM,data:mwDEpffJ3iHgjry6RZAkftSVGodTvkIadDvL/sIZ/ohasTE46LsygorWpkHaxN0cdd1+4v4PDmmdUiZcN2K5fCz2WZP7R3aRIYJTS2fh9Fqd9UHNwqgew1f5F3eVTD6+Ba7mqwbr85wby9Qejtf2iry35dbyFFTiQ+V54Q6FFP0=,iv:DNErVskSsU+/6HAvpGwJD3NZb024pmU7DhgSfD4QMHE=,tag:IRb0kL/DnnyjPtD8A6kLIg==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.12.1 ================================================ FILE: kubernetes/clusters/cluster-00/secrets/github-auth.enc.age.yaml ================================================ apiVersion: v1 kind: Secret metadata: name: github-auth namespace: flux-system stringData: githubAppID: ENC[AES256_GCM,data:0vC2xlO4,iv:JhiQFonDvYORyyqyFxF1C37cffjg6TLibf5fXIMMtjk=,tag:mZDLaAdjnNv7JK6hMN5D2w==,type:str] githubAppInstallationID: ENC[AES256_GCM,data:ciZuppuaRoA=,iv:/blv2vqprD+eHK6220FkuL+6gMU4IFK6/9q97ZzTKUY=,tag:iFeMLsZoirPT/mPUlLvkrw==,type:str] githubAppPrivateKey: ENC[AES256_GCM,data:W8DwpspaW6jlwsah/4iMZdJ0d3mT9Yl814nZToYSuBna/ZYlGZstP3FqefpR+JfKukL9ytqfQyP5ZlyYaBiDTqlAqF/4OFwGPSt0Qn9ywCIAmwhKqMPvNVhdr12rJ/DkFnuDi4qfS3aV7k28oaX8ZbWLGlv6jp3qf+gm1LsLxDBaOofnaha3LZbhOP14HUuuxi/4Z4eiz6nncnBeXfl1mvdiuDqZDtxwNe+Fwy+ZAUZirDqm26qvCnuXkfFPbHd3Q+Jn/sA29Qblg901izMuDK+B7I17L3cDgx2Yymvm2bfXUsmtnQIPfigmA2zLQH2dT8/FV/Z/72UxYJWKBsljGA/QzMZQK8raFmcCITzFMG9YxqLeeyv1bI8EBV7iSsW30G8LyDn0s2+x/v7eM9kVhEEJlfhYYPfRDEwcMoPXYgo6oHzOraDBu3Hh2SJuEyApnTRXOJ/N83QfVMZ0BqRTQblUtl8W0InZNl7t2wDbQxPhN7rnsVTbiQgEXSGdYv2I0S0xWQH+Qzv5bRV0+4zuyQz9SJSWzYJ2pUAl6d3FW1swI1dpU+f4SI1cTSRRt/PGIoGEf6SGKbT0TKGAZYSKuSrDRfiplLkVIRc/P/Dp0xL5cFekIZStONmKjl7CzrddlL51+H4wYmzukjFGq8FwTNNIdrySU1HqkVRle3KgupnWuKE6rHiq3mFvGdZNOA6BVamb+lnWE2G0Xa9g9mGXxqBBKsnM0TFP01k7+QgOggAl5dnDN63RKamoNMYD/WQdVMQUFUukQ9iwM7Clyx4l411VoiRI8NqPi+4dh6ALlxVtnWIuacUkPXTXwbDoceSQetWafs0V12ocI20S3RzCezqGAXvmyzYPW+KLiYca/r0aU2XZwwhudSrpDRqgsHkY6nEj5VqoxSevdLSOb5HJYZTcNKlyae2nAVK+3ttD8DZvSWJD7eqrr8v0G6BUB/Mbz/sjkvl3Mb1Ro1a0u8YgugkjWv/tCiLVGGx3a25tKOoqtAEDce+wOjYWt6KF69/7VCGMuCuuxBdLkLZEgbZ8nsV7Pu99Hx9YnuZpSRwzaOZZ2QIv/YfqMmLWVaWazTrdAlWX6bYld4RdaCdhN29v2e2S7sDdI8lHfEvqP3JVA7oUT+SLarIQePSHgY0nu2gtz8jGS+BB3YWTW0TAm5pdh8rbbmHtD9C3VVax5/QBs5+3c86IGy0aDfRoCWhYtanNJP8lpiwujmhTikHH/QTIqDt3U4yJ5S/391ayApPCoMemhraQ45CqQiFa3BV9Ul4As2z2cpIdejtlMlVDIpanGdqDwZxc+f3bJZ3y+YxluTJD0q0cr+qF24pfHYybmuJ9ygnvNBzdh5e39YVVuFO3Z+B92FGqeSbTBX9S+QYi3ldDJB8+IailVPqgOe5YYF7WrvR45dVNktQgOec0x2W2RpMQqO/iJJZbVyxu1+y1RI7zfqICogYvP3iID5G+vSTBaeEoIQQbjCReGHgNxfjLBg2TsigxGR8OtTwZb2UdcGHY9Dqln1olywIwZqAzFLxGUqg+4FD/DAWL1bhFxXBhO9h+wx/xRJg5GUCaF3mO4juipySCSLdPM+pdUT4QYSlP5Os9frtDvyXUmo9tEP5IPQDtqjaMixp/0x83oqzsX5QmnfTySAw3QeTO3earJ0a/TU5W+sC3ftLpV4Hi8Ns/sAraUbtFTqbewxuBMEdLy8XOIqmiGKrtdfSsrRo/YDr+7xsKZp7Ow0iT75wO+oroqhekZa12B7lOwep8UpYl5KY5sOPWrsGlpuY9rVwS16JsSfQLHXrOrs6jenrkVYzFHVVq8avhpHQ7ShK4D2n0Py+a2FZfWSNEf+M3A52Kb8+xzQv46y3S70BmYIkH1nTKR5MPKWSkYC3dreX5mELKDVm3MpMepOjN85ellDHstYMCbEaydDFfJdS2bVb6MHEEaZzaJ9Hw7nwxMKXnRxq91cjCYdJ5SEfUKnGFz3K5LNnptYmVSsnA8/6VUxSP29/e42USGIlTARKdedK9ySY6dwmTyzJPLHZBA23lhk0GX7QyjEuywJ49aLwVKw5sWoXvJaF5niSPAPsqw4duhhSlktS8NEQbIH8uwSCsX10Tjs1LD/eMMVdAbhKrtI0sfLfutYUiRVPsRyxKgNsZrPeRhDpxGMMs7IQv9zyLBsXVwTxrmA3H+ca8d0ZlP3kIGBzWhFqISdG2Md+UFCQfeZ295y2AIBjV+eMyEb++Zg==,iv:CTYMlYy5MtdSVXAkp+NaHPxrB0qE3ZOhBkDD6L3dpyE=,tag:mtzQFpxWqSGY4/UfLRn96w==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKYnZkZEpXV3ovK3dyL1lV b0pJOHJSdjVldFRZS3Bnc1E0S1FyYy9ONlUwCnREa1UxU0xWRFIrMjd3NkdYanRw aVRYc3c4b2dZUHpuMkxvRWV0andZTGsKLS0tICtGQ0JBYktyMWtRNnlaeXZzNUhF NllMam53MVFyV2dRbHBrendPOFNFZncKM729SpIHkpSMSP4UjlbzOB1Xf7UxCFXT gv74AjVrTcqxXNpUT9f42rvf2uRq1dum6sk1azbyKAuLYPFSKXM7oA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:41:08Z" mac: ENC[AES256_GCM,data:oMGwTbAUcLbQgNzIu6zlPiJLg8VkR8SNDshQOQAEtNktOsQK32fikUToskRd8rfOSbrtscCew0llPn+6GxTlA1+8qVp1Vy/2DbdLG+0tksfIqSgE6MQCKjDMx74zDPIn7ZPEtU6ZA2YsoC8SWVUMShfQzAeO+Yv6RJypqvVPXuk=,iv:xTojCvCTymvto0H+PDvMROIoqkT5XfKz5GjF7JFAJi8=,tag:rHkjR8vZ0FXVjC0HLjJuQg==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 --- apiVersion: v1 kind: Secret metadata: name: onepassword-connect-token namespace: external-secrets type: Opaque stringData: token: ENC[AES256_GCM,data:s3beJIu5Qq52Ud4KKZdY6G6Z457LIbCYMU8MgwQbTJvHh3BzFDQIWpTAHjU3uE24L2UG0I6bUHBKPj6LDYi3l6+EHQ7WPDK/Nm4bqzaCQE0SB5sf1l0TndT4/ZlFIq7lo7dyhXy7QY4I2xahckKdnjTqG728pjcPhOvC1jUzHGePYNTkYL5hU4nXSBtv7qLUIKEFrJTKBR3DBpz7S4JehSXSx/AWBOPMt6ZeejvzuusbVvF/c2jglWyyTs/nPgnocJg6ujnB7+jqr07RZrWufPXVQHyFpdkpoNFaFHSQ3r3AK8AdVKvBU/hLd/MxVj3HvLlNY/9dBF7IhpjtXkER14txlsLvtPONmf8YTPVoCOLHKjzvbM0ClQW6nKVPAVllXlYe4xNQJe8y2K7GMp+pQpLPEINkD/OIHVRJdNer9HvO3k0CfJCKMdxaeHxCxPp6xseQA59Qmrcy2imhojDoHh7MtlGJAb+5VHp55PvQo87HUlczDYj3CiYXngbxbWMNHIZydUnpDNLzb974vPHPN69lMOVoBYRQhZZF7EkqTOuiE+LHeljePW8p1GSfKwWRqEsEj8VbnghC2vqgbMtiHpTiZMM6naBzdvSoouxmGiGWKFscQSUl3uYAtd7BsoDFShUyR0HzEDcmAnXVhXInuUo1UC9yRFBCy7h3vYtGY2BsMYmgSTe1jN4J2/yhDvN7qn9aidupb9jCk3ZR1FjnBC0xhwGEeDVC1QHmHHpog90FzW4PwM/3GauJxI1H2Suh1VXwnnmPQQL/VV2NEsXr3mXbyjdtMg4RTlH73beH0w/zorcyvVBaVJAeykQ/s6Uaz00upbQotWy8YaILu4+sYO9+,iv:NXZqFg/sXGTbxbJNW27g6BURSz/uF1a1OcsGlT0r1GA=,tag:YBKb8vUSt6ZotLqEPFL3hw==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKYnZkZEpXV3ovK3dyL1lV b0pJOHJSdjVldFRZS3Bnc1E0S1FyYy9ONlUwCnREa1UxU0xWRFIrMjd3NkdYanRw aVRYc3c4b2dZUHpuMkxvRWV0andZTGsKLS0tICtGQ0JBYktyMWtRNnlaeXZzNUhF NllMam53MVFyV2dRbHBrendPOFNFZncKM729SpIHkpSMSP4UjlbzOB1Xf7UxCFXT gv74AjVrTcqxXNpUT9f42rvf2uRq1dum6sk1azbyKAuLYPFSKXM7oA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:41:08Z" mac: ENC[AES256_GCM,data:oMGwTbAUcLbQgNzIu6zlPiJLg8VkR8SNDshQOQAEtNktOsQK32fikUToskRd8rfOSbrtscCew0llPn+6GxTlA1+8qVp1Vy/2DbdLG+0tksfIqSgE6MQCKjDMx74zDPIn7ZPEtU6ZA2YsoC8SWVUMShfQzAeO+Yv6RJypqvVPXuk=,iv:xTojCvCTymvto0H+PDvMROIoqkT5XfKz5GjF7JFAJi8=,tag:rHkjR8vZ0FXVjC0HLjJuQg==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 --- apiVersion: v1 kind: Secret metadata: name: connect-server-credentials namespace: external-secrets type: Opaque stringData: #ENC[AES256_GCM,data:2mdL0YubS+p1SGaxwaiSJOQIJWmfoCdJe62RgcYzntRh+zFWjHELRr3qCS06t2N/gGM5qF/KSRA2ZQLA7n1GpkSY6sb6bHUkY3spTZ/RpBe407T+ITGAGOUyNk5uugjbLUI9hGeK7/E2dbhTq7tmA8RRWcCbqjoG4Vi941dGYLIL3gHS6+H2YaUJMxe9xaA5tLPtGFmaSC8WcUnGsXNiv9t6O9VzOGpW36iKt3KtLZQT4nI2QkxWHvn+4A==,iv:rzfcfhcWUDOfUJWTGVzKNT00bx/mIAerp3M5aTIZWfU=,tag:ALn/+ZtlkELPzOsLxTJgQA==,type:comment] 1password-credentials.json: ENC[AES256_GCM,data:X4INLMMsjT5JJ52TkD2G0Ph18ju++3f6Unnl+LRdwQGpb+62UaRCM7uaoZEILlEu3P8Bc0CaqoISVi98pfQ2PQBjtj/DHS8fYz8sg039QYdfX7CDvBfKwqhFOsO2XoDTumaKxwUgJxK65NyNrQjDGc48928taiUHDxhgxt/F9cUbIxx0EkWJfN8HObbQwqsAmJsmjhGOuInpjXIghIUEo6Mv50P29MJqvsNLjgDCXw+EDeI/oO94+/Dv0Hhz1tjX9GhGdEkJtNHWn6I6PJaQYdozoKubfDtPni9HoJmeQHu7zykJABm2pQbTeY34OHkya2dbEO+LyV2E+wTxiZxwAI1zOacU2vkaLsFBM1IEAH9RJEqJ5VxZdnOokHujmzOxBjB5Ez0nfM5E5qX9kK8cmPWtSSwOsK6B5vRv7wqt6OrFweiDBFrdoaQblfbJLyQ4KJtfw/LZHsoZyxmKPlVnHqv1PvOImcKyoz2OnFf6hBKNKs3wULmeVc3Ir7kbPfrQdE74KCCusFEopwqSUzQJtuoBXPJQqKk4yxvl3NxEx3gwX/W72j4WXwEU1EFAIIDaN+ZoV2hg7Qfuf29keIMOHAesEpnC41zT1mB8FtQSSPTCCnQIQWDppUvg8K0O9kS85fpwZfJZV0ZUVEiNRWauLu8xWO6HyrXv1NE2r1spBj5IV5to2jS3h2HNjZccWL1JKE6S81XxILWFsj75p1dbSq7s/KKqSXw1yqs0TBgz0YJud8kAVcqtX+qcSj1n8L8wHS3PmPVXzDNFPqY7JsZc/5L2/CSm5QJrIdJ2sFIKB3QrcpB5/7odqwCz6dVkQ00gHO/BzLXRod9akb1TEqm6jsKJR00Lg9lpMQKN7+e7g9R4qfzN2DabQTlFoZNMLxTABJUAVFFNQjSvCtXpvXl5g+vruR0wivY4XMMo2s1t7k42b0QHk4IocsfsGHl8ifpf8eAsELHyWwEVKqwX3e4daqfyNE4Hc3oDKlryaugIrqpCeDcsIBqr0ejgTPdYtaX5Pen9tcl8yvLDgD9se0Lv7g8jtu0rA1j8fsgGwOwGpc23CE49iGYoEiVwZZCR6cpKiXknm93kd56fmcQsJnMezCsZu2DHeTvf9wUsLW0BqSbfkH9SprURtziIg+HmFNktVBLfO6IRZt2szzoRjg+L07m04yLRGwzPHcwLdERRrG5uZ0QXXCAcyEPVSsf4zFb1CzVW0/RZ9PePO7ge1C0h+E8K3f8jjAalTnE9CFzCVyQB0h9Zil89ZvakJviP7fdaUXMXOuIRPzZMX9T7ECypyW95tcs9T1dzGB8eMw7btPUSpAiaYKiIArg8x7INa+EdYGD8+g7PI5pcKIuSPFMAseg34m3cVTJKeMTc/qzR0rMG9NVbFY9F3wW5rUTx8iA0I8XgkFBIO8TCnVb/MT7wWCKI7cqLTKcK88UsJl+KlRN3qZH7+574yfjioE7i/8SuaCXMsuJs/iRW1Yg2rDkYZ1pm5Ls+7i/hip+M3HbJheULMTIGGmvJ5+wYF7vQiVrSlds3r5mjupbgeF5DQezK7CicnSmpCxnSZpO1hYnFqwXIYyUDwpfROcvL/dp0OwH4E/xMZFOYr35xBrLOL53RxqQJP/52e3LM5xkbDtMEoQtgmHj2JNoXndDx9GLIs38NogyzHLAup4O1D0fZSh+xseL09QScb+cdtUb+WKQcWYoM/3WpuxxAcNc0ZaRjtJKhY0+9YrlCwgOPh2RSEb/oVtlcf7muzpM8qe2Cslpq3rovC0U1vLboADtauZbmV9zcB6AiV0WpxZQSU+5FEPAz0ikaEPUW9KRT5VShkqij0yOeDOlR6uDQuBOVtgGY422sjstF4LJpmUp/Cqw6g4hEBBukS5qDsRKmgcsEFtwCTkhrXJrz4C++hBz+rkvLJPJUI7mVLSnTc5u1UPxx,iv:0Zo9ZpBGqWOtbqWbA5aJz52MQWF8+fj0CxS3bIY+5lU=,tag:O0o+0gNZ4/jrZVayiJyAeg==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKYnZkZEpXV3ovK3dyL1lV b0pJOHJSdjVldFRZS3Bnc1E0S1FyYy9ONlUwCnREa1UxU0xWRFIrMjd3NkdYanRw aVRYc3c4b2dZUHpuMkxvRWV0andZTGsKLS0tICtGQ0JBYktyMWtRNnlaeXZzNUhF NllMam53MVFyV2dRbHBrendPOFNFZncKM729SpIHkpSMSP4UjlbzOB1Xf7UxCFXT gv74AjVrTcqxXNpUT9f42rvf2uRq1dum6sk1azbyKAuLYPFSKXM7oA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:41:08Z" mac: ENC[AES256_GCM,data:oMGwTbAUcLbQgNzIu6zlPiJLg8VkR8SNDshQOQAEtNktOsQK32fikUToskRd8rfOSbrtscCew0llPn+6GxTlA1+8qVp1Vy/2DbdLG+0tksfIqSgE6MQCKjDMx74zDPIn7ZPEtU6ZA2YsoC8SWVUMShfQzAeO+Yv6RJypqvVPXuk=,iv:xTojCvCTymvto0H+PDvMROIoqkT5XfKz5GjF7JFAJi8=,tag:rHkjR8vZ0FXVjC0HLjJuQg==,type:str] encrypted_regex: ^(data|stringData)$ mac_only_encrypted: true version: 3.11.0 ================================================ FILE: kubernetes/clusters/cluster-00/secrets/sops-age.encrypted.yaml ================================================ apiVersion: v1 data: age.agekey: ENC[AES256_GCM,data:T0SIW1jH/L+sBx9x4iBFLtxSuiw5h47LfgHa+qNwXzw85n4RCq0qztEN/HGon7RhDFwkkcJuNTeGim3z4SYeoh3wmdoqwmWLVSyVHaiKvvOOM1cjKXK4wcY7ixy9Qd0bIAZR2fYdGKY+baIBfWiEgajv8a2SpmE6vHfCTVf0N5vl4DXoXKdAQnWrPvqkaur+NhAkLGLpWKMny3BLPnJWlcdRD6YGcfQxyX9JtgpMIvDFuLMVdBL4KM9nWiyjP05ofFIvSa6abzmyP+TIelVUc/eC9T+zBc2loTrnS2de8609H0xSADqKcQFF3KHY3C85Mn3JI3lw8V1RNuF3,iv:Nz7dlXcJi8kR4AfVQAsNvtjB2Gsd7er+e0HvUzxvueI=,tag:dNDKN06P3B89u1f6KGYCyQ==,type:str] kind: Secret metadata: name: sops-age-secret namespace: flux-system type: Opaque sops: gcp_kms: - resource_id: projects/raspbernetes/locations/global/keyRings/sops/cryptoKeys/sops-key created_at: "2021-04-14T09:56:06Z" enc: CiQAesqCOZISRRQTtLQ+hwyFXhAxPjfddIigwq/psm2fijO9cY0SSQA2cmGUMUZt4TJGNgqSOPLWe7w0nfFekhINR3Q45P6KEsWlr22cZZf0KygEOufqGOnmuFZyCqlSJmmbAgiqGgx5sUgu9rIwUWw= lastmodified: "2025-09-30T22:16:28Z" mac: ENC[AES256_GCM,data:CFLqmVBffFJ0VcQQj42cVmEScTXVX078oDviNl9CSUbLLuadVZ0jXOot3iVYO3qQwUoSfh7N4S1/EIipgOcwsnADMSbMp59DlCXofkye+n1JDebOUUOd49lrI4a7krNZgk7YTVOXHZXN9IszoQZrYilqIgdmTwogRGWjd6wMdr0=,iv:sySsvWKhbZua1wkhXoy7fIqSloUOayEWmNfsJuFnmZI=,tag:W06zQglZY0ulxy1dyVtVJw==,type:str] encrypted_regex: ^(data|stringData)$ version: 3.10.2 ================================================ FILE: kubernetes/components/common/alerts/github/alerts.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/notification.toolkit.fluxcd.io/alert_v1beta3.json apiVersion: notification.toolkit.fluxcd.io/v1beta3 kind: Alert metadata: name: github-status spec: providerRef: name: github-status eventSources: - kind: Kustomization name: "*" ================================================ FILE: kubernetes/components/common/alerts/github/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: github-status-token spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: github-status-token-secret template: data: token: "{{ .FLUX_GITHUB_TOKEN }}" dataFrom: - extract: key: flux ================================================ FILE: kubernetes/components/common/alerts/github/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - alerts.yaml - externalsecret.yaml - provider.yaml ================================================ FILE: kubernetes/components/common/alerts/github/provider.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/notification.toolkit.fluxcd.io/provider_v1beta2.json apiVersion: notification.toolkit.fluxcd.io/v1beta3 kind: Provider metadata: name: github-status namespace: flux-system spec: type: github address: https://github.com/xunholy/k8s-gitops secretRef: name: github-status-token-secret ================================================ FILE: kubernetes/components/common/alerts/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ./github ================================================ FILE: kubernetes/components/common/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component resources: - ./alerts ================================================ FILE: kubernetes/components/volsync/externalsecret.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/external-secrets.io/externalsecret_v1.json apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: "${APP}-volsync" spec: secretStoreRef: kind: ClusterSecretStore name: onepassword target: name: "${APP}-volsync-secret" template: data: KOPIA_FS_PATH: /repository KOPIA_PASSWORD: "{{ .KOPIA_PASSWORD }}" KOPIA_REPOSITORY: filesystem:///repository dataFrom: - extract: key: volsync-template ================================================ FILE: kubernetes/components/volsync/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component resources: - ./externalsecret.yaml - ./pvc.yaml - ./replicationdestination.yaml - ./replicationsource.yaml ================================================ FILE: kubernetes/components/volsync/pvc.yaml ================================================ --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ${APP} spec: accessModes: - ${VOLSYNC_ACCESSMODES:=ReadWriteOnce} dataSourceRef: kind: ReplicationDestination apiGroup: volsync.backube name: ${APP}-dst resources: requests: storage: ${VOLSYNC_CAPACITY:=5Gi} storageClassName: ${VOLSYNC_STORAGECLASS:=ceph-block} ================================================ FILE: kubernetes/components/volsync/replicationdestination.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/volsync.backube/replicationdestination_v1alpha1.json apiVersion: volsync.backube/v1alpha1 kind: ReplicationDestination metadata: name: "${APP}-dst" labels: kustomize.toolkit.fluxcd.io/ssa: IfNotPresent spec: trigger: manual: restore-once kopia: accessModes: - ${VOLSYNC_ACCESSMODES:=ReadWriteOnce} cacheAccessModes: - ${VOLSYNC_CACHE_ACCESSMODES:=ReadWriteOnce} cacheCapacity: ${VOLSYNC_CAPACITY:=5Gi} cacheStorageClassName: ${VOLSYNC_CACHE_SNAPSHOTCLASS:=openebs-hostpath} capacity: ${VOLSYNC_CAPACITY:=5Gi} cleanupCachePVC: true cleanupTempPVC: true copyMethod: Snapshot enableFileDeletion: true moverSecurityContext: runAsUser: ${VOLSYNC_PUID:=1000} runAsGroup: ${VOLSYNC_PGID:=1000} fsGroup: ${VOLSYNC_PGID:=1000} repository: ${APP}-volsync-secret sourceIdentity: sourceName: ${APP} storageClassName: ${VOLSYNC_STORAGECLASS:=ceph-block} volumeSnapshotClassName: ${VOLSYNC_SNAPSHOTCLASS:=csi-ceph-blockpool} ================================================ FILE: kubernetes/components/volsync/replicationsource.yaml ================================================ --- # yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/volsync.backube/replicationsource_v1alpha1.json apiVersion: volsync.backube/v1alpha1 kind: ReplicationSource metadata: name: ${APP} spec: sourcePVC: ${APP} trigger: schedule: 0 * * * * kopia: accessModes: - ${VOLSYNC_SNAP_ACCESSMODES:=ReadWriteOnce} cacheAccessModes: - ${VOLSYNC_CACHE_ACCESSMODES:=ReadWriteOnce} cacheCapacity: ${VOLSYNC_CAPACITY:=5Gi} cacheStorageClassName: ${VOLSYNC_CACHE_SNAPSHOTCLASS:=ceph-block} compression: zstd-fastest copyMethod: Snapshot moverSecurityContext: runAsUser: ${VOLSYNC_PUID:=1000} runAsGroup: ${VOLSYNC_PGID:=1000} fsGroup: ${VOLSYNC_PGID:=1000} parallelism: 2 repository: ${APP}-volsync-secret retain: hourly: 24 daily: 7 storageClassName: ${VOLSYNC_STORAGECLASS:=ceph-block} volumeSnapshotClassName: ${VOLSYNC_SNAPSHOTCLASS:=csi-ceph-blockpool} ================================================ FILE: kubernetes/tenants/.gitkeep ================================================ ================================================ FILE: talos/README.md ================================================ # Getting Started with Talos ## Step 1: Decide the Kubernetes API Endpoint Set the Kubernetes API endpoint, for example: ```bash https://192.168.50.200:6443 ``` ## Step 2: Generate Cluster Configuration Generate the cluster configuration using talosctl: ```bash talosctl gen config "talos-default" "https://192.168.50.200:6443" ``` Configure the endpoints and node: ```bash talosctl --talosconfig=./talosconfig \ config endpoint 192.168.50.131 192.168.50.132 192.168.50.133 talosctl --talosconfig=./talosconfig \ config node 192.168.50.131 ``` Merge the configuration: ```bash talosctl config merge ./talosconfig ``` ## Step 3: Configure Control Plane Nodes Apply the configuration to each control plane node: ```bash talosctl apply-config --insecure --nodes 192.168.50.121 --file controlplane.yaml ``` After applying the configuration to the first control plane node, bootstrap the cluster: ```bash talosctl bootstrap --nodes 192.168.50.121 ``` ## Step 4: Configure Other Nodes Apply the configuration to each node in the cluster that is not a control plane node: ```bash talosctl apply-config --insecure --nodes 192.168.50.121 --file node.yaml ``` If the `node.yaml` is encrypted first run the following command: ```bash sops -d talos/generated/node.enc.yaml > talos/generated/node.yaml ``` ## Step 5: Update Talos Client and Nodes Download the latest Talos binary by substituting the version in the download URL: ```bash curl -L https://github.com/siderolabs/talos/releases/download/v1.2.7/talosctl-linux-amd64 -o talosctl sudo mv talosctl /usr/local/bin/talosctl sudo chmod +x /usr/local/bin/talosctl ``` Verify the local client is updated: ```bash talosctl version ``` To upgrade nodes to the appropriate Talos version, follow the upgrade guide. ## Step 6: Adding Protectli AMD64 Devices To boot Talos onto a Protectli device, follow these steps: Flash Ubuntu onto a flash drive. Install Ubuntu onto the device and complete the setup. Run the following commands: ```bash wget https://github.com/siderolabs/talos/releases/download/v1.5.3/talos-amd64.iso dd if=talos-amd64.iso of=/dev/sda && sync ``` **Note:** *You might need to run the commands with sudo. Also, validate the block device using `lsblk` and `df -a` to ensure you're writing to the appropriate drive.* Restart the device with sudo restart. Enjoy running Talos! ================================================ FILE: talos/generated/controlplane.enc.age.yaml ================================================ version: v1alpha1 debug: false persist: true # Provides machine specific configuration options. machine: # Defines the role of the machine within the cluster. type: controlplane # The `token` is used by a machine to join the PKI of the cluster. token: ENC[AES256_GCM,data:CaORwG/g2cUd1cANVsLtA8YD+jmrHgM=,iv:Z8qV+DYmiTTtZNeholi8ixcOR8yqUBvRGZAk9qD9eXc=,tag:9FAb0OijJ95dj1MHWflL0g==,type:str] # The root certificate authority of the PKI. ca: crt: ENC[AES256_GCM,data:vHaig1m17I4VFpa3jSmjnwfOVySELh6Nj2EGFDdlgOf0mNHfwzYP6+oHQhrhSNDpEhl/4c51cfDNFxK5q4Pal6k+g4G5bjkv516scavz9V1Khs39E2O1vwem9pHHwd7yo35drLZQFoALQhYT1y+RCCiWiUtdMBk/2RyNh4FcEysy6fIdDzbh+H204pMzUJ+mVqLYKTu5VdLOT3j1lgCfKGsAV1C6A0hX8fuSvVSzzt8H7XjasaEUSyEXrtorIlVP5lpdw4G+nmOpTJL+vqfYsLlbgTt92jWkZEyxEjhu2Fjt2x4Ch5iZM7e1jgMZJ7UeHDLf9BJ+xzFXMIDwWYOYAQPnP2ABMpUMD5EAoPcOPhrm6sbJaE337aJl+Q5ulnwFcVsh6xaqG61K3oLSxpqEle9rZd8mebQUaGJ6mmn6wZWI01JahhuoeiAeoLXSdCf6ptg70qO2Ctbrkvq94PNwZzhSq9y2XhYliiD/kqf2RmGkQDqMeF6YwDLGtcEM8djPsaOEtuzGvIVC5rwfjJGOM49146IL76dDMT7hVMO0NCDcPxOQpJ3+Pq2pKfxm4K4iFAdYl1x80V/ZOv6KHzXy/Pkn+m4Q88SW45qfEOb0im+Fg/za0g5SQ92z0NqAWA8OSNLbKy0w7QMKMGPFkKVgYvTszBXkxKCt7xSqI5B4yiJRlzZIgN9MtJKpexECUiwdPT6NAjr9ALEfXDmo4BP9SyAbKyEhN+J/zNIRZpjYdrnVXykZZTSp6IThm+NI6yaJ5sM0pl39VM6DiibbLcaYWODID2kaf6mhYdTbIO2uYqadJejuqFzoB4U9U4hQZEUH3ru9VIuu2pdM+n6pnNTgmYWa1jMPDn+qLRzH9F6pt3EaJEWr,iv:NqjMVRVaUBT7rQlLHCYiWRG2Z6WKl/+QaNE5HC5jTzo=,tag:FUFFZ8o9s+v0+MExDK8odg==,type:str] key: ENC[AES256_GCM,data:+f+ZKW4ZLjrMTuTIpcix42Ryxwfo0h2+5pGNXPrttCZkpEs8nv47QT7cs+twPuOoXAGJu4xmCwsE+6mMbfIRplWMobqF5tcKhW0JEQQoW97kctwSToI6bWPm9gO5ITfJNRZIFXphGCwASTBlHlQIf9bcGg73yl09iG8iw6JPY+05VQZWR1/rslrJdbI62kDqkwCrt2C8d+VJJDXCv3hjgRn6pK0+3wUc3IrMyDHiws0EnXW5,iv:pWdF7PPFqx/c4oZ3Okr+Qm38YYSkvXeaVVcgSmL4YY0=,tag:5GYF6ccetCw/N/4vi4ecTQ==,type:str] # Extra certificate subject alternative names for the machine's certificate. certSANs: - api.owncloud.ai - talos.api.owncloud.ai - 192.168.50.200 kubelet: image: ghcr.io/siderolabs/kubelet:v1.34.1 defaultRuntimeSeccompProfileEnabled: true disableManifestsDirectory: true extraConfig: serializeImagePulls: false sysctls: # Inotify — required for K8s controllers/operators at scale fs.inotify.max_user_instances: "8192" fs.inotify.max_user_watches: "1048576" # TCP/Network performance — BBR congestion control + buffer tuning net.core.default_qdisc: fq net.core.rmem_max: "67108864" net.core.wmem_max: "67108864" net.ipv4.tcp_congestion_control: bbr net.ipv4.tcp_fastopen: "3" net.ipv4.tcp_mtu_probing: "1" net.ipv4.tcp_rmem: 4096 87380 33554432 net.ipv4.tcp_wmem: 4096 65536 33554432 net.ipv4.tcp_slow_start_after_idle: "0" net.ipv4.tcp_window_scaling: ENC[AES256_GCM,data:IA==,iv:d8fVhbnF+Ue4+8dM4LPTXWhAHV4FH5BmwBS8V5KGzco=,tag:nqCJ0VYb96NDHpcH467JEg==,type:str] network: interfaces: - deviceSelector: physical: ENC[AES256_GCM,data:jsxyww==,iv:brQwInLaLSmJLi/w8TMTBOF04mpLOKModbDfXyzVgJQ=,tag:QKkEEvDZ6lG6L4Y1aw0hmQ==,type:bool] dhcp: true mtu: 1450 vip: ip: 192.168.50.200 install: diskSelector: size: '>= 1TB' model: CT1000BX500SSD1 image: factory.talos.dev/installer/c9078f9419961640c712a8bf2bb9174933dfcf1da383fd8ea2b7dc21493f8bac:v1.11.3 wipe: true registries: {} features: rbac: true stableHostname: true apidCheckExtKeyUsage: ENC[AES256_GCM,data:AVoFYw==,iv:VFjONzVhuz0byvxRcMMovprGLhF103cgJgt3DqnrAKA=,tag:0khRMyZta7vphspH6MBW7g==,type:bool] diskQuotaSupport: true kubePrism: enabled: true port: 7445 kubernetesTalosAPIAccess: enabled: true allowedRoles: - os:reader - os:admin allowedKubernetesNamespaces: - kube-system - actions-runner-system hostDNS: enabled: true forwardKubeDNSToHost: false resolveMemberNames: true time: servers: - time.cloudflare.com - 0.pool.ntp.org - time.google.com files: # REQUIRED: The following documentation explains why these are needed. # https://spegel.dev/docs/getting-started/#talos - op: create path: /etc/cri/conf.d/20-customization.part content: | [plugins."io.containerd.cri.v1.images"] discard_unpacked_layers = false [plugins."io.containerd.cri.v1.runtime"] cdi_spec_dirs = ["/var/cdi/static", "/var/cdi/dynamic"] device_ownership_from_security_context = true [metrics] address = "0.0.0.0:11234" cluster: # Globally unique identifier for this cluster (base64 encoded random 32 bytes). id: GsSf9LerhTOpktH7JMlySUhdB4tdxlX1b6ZDGM7a8ZE= # Shared secret of cluster (base64 encoded random 32 bytes). secret: ENC[AES256_GCM,data:NpRTLs9PVOUcW9UTdTzhcoxbfLQaITm0lsb87eYtw5N6483cfl3Sx0HtCbM=,iv:mYsOdIxOzLowdl+1dpd/PAxBhZ85stRdFPS3+WbGjBk=,tag:oGdyAXj95QRMWVH3lydH8Q==,type:str] # Provides control plane specific configuration options. controlPlane: endpoint: https://192.168.50.200:6443 clusterName: cluster-00 network: dnsDomain: cluster.local podSubnets: - 10.244.0.0/16 serviceSubnets: - 10.96.0.0/12 cni: name: custom urls: - https://raw.githubusercontent.com/xUnholy/k8s-gitops/main/talos/integrations/cilium/cilium.yaml # The [bootstrap token](https://kubernetes.io/docs/reference/access-authn-authz/bootstrap-tokens/) used to join the cluster. token: ENC[AES256_GCM,data:hn3MsTRf/WzsGsAvVO1B8yItz6A9ExA=,iv:OXZOKUHnvbFg/JOj5ZDZOCIOJy89cJzXR/+1Qezryzs=,tag:JSvnBK6nsqAlxVxBfc++bQ==,type:str] # A key used for the [encryption of secret data at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/). secretboxEncryptionSecret: ENC[AES256_GCM,data:Fccm0ik7CkfGL4H9Qnz/tIxWG9deCES0y38QDj6b3byerNHS2lx24UnVFmY=,iv:/ga4iFHoEXET39Hl4eIGpUlEM9PuE437sfOW9ycezkY=,tag:SLI32h8Jq7YUFf/KNGRYCw==,type:str] # The base64 encoded root certificate authority used by Kubernetes. ca: crt: ENC[AES256_GCM,data:bfJ15RpcLIpHFIkNlf9R1U4I1UCIVNYl1QKItVLVjiEQxxT27BcgIG0l+DJGwkG60E+2ZDWbYmjSVB9BcFnvR1nQRmqDxejWGg0ZYfHi/pyiaUcxdjqUgNSG3uEmOurbEVJ0NTs60omg37YVShXztgNm5ix6xilhBp+m8NoA1YA1TAJTBa5os/YJhh0kRXvDN+VsII16beR5FAoRjCmDuqIU/FYsyMXfN5+l9HXFwYgax76JTpzgtBlzDEQWo7KdwQh4Qa3J/rN566/p9nRo80NFtchp7OSg5g4nl0ggCbPK/RJ3LMhAEzS9uFcc1roUDT2HaiRoZGRY6jHZGNnWW6hIE18NoAB4PjOtFgMby7Qg6e6Engl5EdP6nBh81qil15vnBZ+sa/1HTUWy4u46AnJRePNSV2Mq1Y67O6cLwVHkg44mDa3UZl5zMB8GzoO92Y3B0N9mHzDVhXal+aThsHHT5dC4JZEBwX0dlUls/vpYoHJ8MyDzNVaL1CN4E6Oo/01l54Ro58ULrXKRRfq+ac1r+fyJ0UbQlnGG4vbJKwPeG9uv5xAvbYhFH8Bt5OqVBMzaOEut7mbc+lIGIySuGq+hWkBtIQxNk0y92f5vzWSaitrAR678rYG8v+1Jv4zlglnm4qFqQ+uDLGogXy/ZrkIR9J26/BqHDtTURjVRjcO654gQle53OWJRwxMv0L+d4ET4q9Wdc1LXurmlVnBrfbGD6OzSfCoyjq/dISllevWnHAVOdnC+pvsFICFwc2Xh9sNVABJ+VWUfiXGibo4Dd2kgDMpBN1n2uG+wct/USGxtX29nyR2++5T6hABWA7kuMKpuWhx6ujwuRd95+/B80m0qiM9X5FZ0C8m9Zx3dHj2tmfLDhrni8Rw4jF7YsAvWe0xw1aPzjKA+cCOegYgdqJo8gkAEloOH8c3e9lj9TkCOFutrD6hOjonSKDxn+Pz1Bg8m3aZlll/pun+TCCz8PzTvhCqqJwanokBxjv8AuIxP7hrBK3gYS+thcGUfziEYETHmFRFxY4BXe35VDU+x12CmSZ4nA69vjoFl7g==,iv:x7zcTfixH1DMNexaAA80ZeGTtwOJTLHZLOFtTzzg0Lw=,tag:4MmoRAfh2ZqWIWbdnvFoCA==,type:str] key: ENC[AES256_GCM,data:Sx+CZU4TNHEon6hZ2eUct6m+JSFlf8JIdCREdgTXMrbKuiH+FBcxHF+OZFiBHp1S6+BygnWWwQVZcBxvW1IQulZD9gT7676qWJnRC3ZW0g36uEykO0CmuYqRWxbdIvC/7EmBNA+m3XVkm8QWp4uLdftLoRhVdEgYvQSEbGS0fkgIOJL6eu/FYwsAB8EMFpuy/gS/rL4vu01A6e1+srrSHoG8cuZnusu1J20Dr4laODJDMOCV+NcWFKQsvJUPxbWiNW/ZQLUkWdGxH0xaTb3UyDG3tjDD+KWULRocJfZBcWNy3a9j01cdekyBlJXBpk1wfyGU5PhgszxJ/+Od1mxSmx1jfGJjCLz38bPMshUHNAPUhwZAYwELnCZhMhQdp2qZn8j4oluICkFM9s3n2OLjcw==,iv:qwGvuFYUl2nN87DMG+IsOZdOy2UnimcMZWQQtpabbRQ=,tag:5cKeduMKp92gBi+VakEIww==,type:str] # The base64 encoded aggregator certificate authority used by Kubernetes for front-proxy certificate generation. aggregatorCA: crt: ENC[AES256_GCM,data:mW+5UMH9NlpO6S5HBJ832XTXahhQFZF/dXwuErlEXv0VIfnZPSMOxS94Sss5xZwCxGEgU28DhyBShXlIIbPmI67jdDvLnLao1tOl9INwtjYlbYP2oYUhLgNaDj/5eFMadua5QsViJiqQcIvkg3GVAzK/piCfcoJE27ATJbOh5TZumD9Wc/cLveWisEf9IiTXVRbBFNe7ed/vuVVWIdT9XFuLr/2lC0xLRUk9MkqbQX6fypwa61WfyoPacO++oaATYPUB+a9MPPfJ5a/ww71/nRn/mqmhMzKbgL6ZNmcw5V2Lmd0pJukuOuXgPOPT9nZaOnDGU7knvT3RQ4DH/NWsjGa2pirvSlRkHbUUzTNwk1y0VjwsN/xeV/rzqir0ZmuVLIBiSNKJwOgPMH0yZTphJLhDRSclVJGlpsbcRzaILJGzosbU9WfjSlYBsmjvTEL+B2J9pZWCVWwU2QSxOWuhqpyYoUDHzXujYpn3t4FDgIV10i3v0DKyYMcRTKnx347kUg5sTMx/4cVIOVMwF3FNGYAeUR6OzlU+0si9braIxhdJo4paM9J4StBxEyU9y9xgkPkXsJ4z7evGz/CRjCEgCS1PfQ/Hb4LdnMBCHbOjNAsU8K8mleyqPSG5ILExgzN3hEbdk6keGplusXg98+yH3ZSrtOBzB6M3T9lduJcx1GUNrdrLGZLqz/1w79AYc2R7ICKhsgiGl0T9caKszZnq16NaAkoM8r7IPMTWKBwAmJEG/i2scuRonfxYo7xzGSn43tETQktLzbcKuCv3LZW4RE0ZCI5Xbqz1iqtjZWf5ipOrOhaU3sO0eWncXNbxhRBHI/HGY214wP+p+KW2CkYbS7MknykEclS7yROCHtL2oe4wsuYRuGH+Tyxs/WH/T0OZxqL2kU0TKctO9DroMpIy9h4Bj4ABmM2jR65mH11Zztx5w8b9ga2nIUHXxFGoDcO7,iv:6WNApFnrwFveSNNzsiW9WHXWcvyjGLIBfLdCm09e9tc=,tag:QDWw9rsx4UpvwCOpQJhOtg==,type:str] key: ENC[AES256_GCM,data:S65KruU9QYJBsGjWI1tCqX6qiVqM5w1orY7X6zxxVSCOvFwCaOvWhn9dPrw8TIlbhJuTtTquNX/QR0PkXO96iGXkPIr33NM3MlEgP1S/V7FJRWOuPjYtwBwmpoBm1rUVaC1KQHGZAJ3/P9ZciDpkwgEqPjpoLNOGj2Jz1qD3IqbwgWgqs0q4XS/xPmc+gffiwm3Wbr+m9jEo7zhjzAJEMWD76V+h1v0Nju/Ip2XdSaSx+9BhYNmWOCeV/ShfnUx8vILzEvUC+zKpsoQWxabB/mCtwgygddBUxHSkVyTw7B3SUlFa1khysoS+V9K1iMAzcO98hKbM176xYp8VKrH0nDDeeJcKc+vx7Sbu1GByyDmwZds69WQy3ntnj986dqZhwHMSfy8jGigkqwz77tQz6g==,iv:0mWDy+hGOA67vobRV1Wld/2E6rJ6FyxWS8JEnY6Bk5c=,tag:o2t5Vkpd6hziLndxgNa2+A==,type:str] # The base64 encoded private key for service account token generation. serviceAccount: key: ENC[AES256_GCM,data:dlQoNOfe/x5/KgdOWz7VFB+iSc3GguA/srHBZs5XNKrb/NTjdIgXribBFBo8DRDBT2wUqvNU6Pa9gn6dykCPk3Q71Z5ANcWyYq41tLhblhRGXIVNTm08Y4G4P8kHIialLqUVkum3FD1rO8r1uO013VolZpEbHgY1GmOj0ayY50p5Ha6uB1y3u0CqtOdFr4WFQ23QunRahOU+jrT1LjXK3NebwYbITPq+U76zOhwP50mizU6+kfHFHlr5g8eGFZPT7fTxAYS5uuwXBDRKQlmbDg9uq5aaRrq6NgfKe9RBcRZ8sr7xQDF1O+lW+eUFrekOC6UX1nVVxVBlVZmX5BTMA+qX2Ec1iRGmZ/1fewFKYcCS7BeyFbKw4LSXCRS7TbZ9z7gtrRs41YpziQ04E2aq5wFEJaHn+g63dREBnvDRM7OMrSDjy+2OJNznMIxZbeEdn1JU1NzZFM6ZpMuIfnbCaKx0JLgd5H21Wiyk5NasInUzCMRLpdSx45wowKF7u9nhI7h08LGmsIttTS+mHWOdmh4KvAlnaJPPZx5vHPEFN4H2GVq5BNSlADJ7U+jrhM4xL/ursxuFQYUhXi685dzJk7Kk3w/hdRf/WvuCl2zmL29Q/QCK9pMIyOUceHUC4vEDs7GBqyUSpEQ0jAd3tTKkHGH+Z4tJXTn/Kx2GWbA062oiGvypZ+zZ7Zi4o0yrK5hLeFfvnaAtq5/5UL9Oz8Dj3JpMlhAOqlCvJs8UOZWFtqvrUX7u2V5sVAFggmNCmAkvdd5MgDlfqz1r32Iq7YcyQK2+hOS0ndXmEYsklFyfjYl681Cljel2hG4Dkfz+wsK+z52fhN8FO3gp4j9C3ArzOLvbYEEiVYHvug3X8w6vOul2oHhHSI9Yb0mkE8FoFD9l/LhBobSn3UpVgHqPbfptmvEduKTTb61AVKcLDcDGE9zWGBV4RgLGCFFVVkuQfXJNiSic3qSnj1mD58eC/tOcXrteNqPAPrDvK3Pb8j88Heyw9Gi3jWGKvEPmCMtJmUct0qwy7LIp987YB/0k8q43YlOZBNfn/0xIYFF/5MDsA6cMJnK4ZfjLpcBgUFdOe5mfKSnfQFyNZZDh6DHEALzxLmJBb3mk6M6hKK+rvTr1kv+vcQw+fbcwbuvvuXj4hcWQI+8R33OydNqsJN8VTqvc+/H2mA99uD5mCVdNM+adO8B+GVETCF+hmsgJpoS+vUK3Hr6pXX7oRqRN/qfwa9hhBpSDvZS0JMMyAokKppTzNvxIheJzzOn4HOG76c7phU0+oAoNi0B6/LSPjWl/LucHEiQmcV42YNlucjvdAfImTHMi6aF20LNqPpTiTED0yAQWhGPtOD2d5e18X3+ayS4JX1xjsz75yDZyK1J8W51UPy1WwetFlJexfy5ayc7MYFlCrE2bJTr9wgw2QDPDv9C/oUYtNSPbXDbTKrSvRCfAHovbXwt5KTHfX6ZHMQOSKYETlhMyA0aQpjScnMp/uJrI5wGzK8HB4s/ye5YXRrwy97aRlfvl0X2xLfL0eTEXNKXZ9a8u7kwjrMp8dfuuEcaNTM2Qc31Qx/X8wukcMC/UCbD9l/ByHqdfS6r2QisixL+MsJsVb6O8zZYfnqvSQGE+cQ9RRjLkZAeoCWYTcPIm82hgEjK9jw+0zTbPUWRQVCty7+SDaCocmHyjOYgxh5l0EQXTBVUKKgflyOQtrh4IdvQFj4hEV999X8eMqJOYIvCeuaKfN5SsY8slG2z/hiwUDdZrBtzuJAZNu0xl5luSYfgbHS2RGx0mv2XysqNE5l8qQbXqI6INrXw8bURPsPUxqmxqj0vTC0HSrR6wRMnkY5qIRdpf+4UBkIrJJo1EbEJQ4rtUwpgUqUJ08rJvuwp4QP/aXnlaNIAdGCqu8/7Akq3Y1gl3mYBPY1+CYTgBMwpYBxu+UKK8XWYjOjgsVS1TCiLeXV7s/cUijKslG5907PaedDw2TEQXrdub0R5nmwcvLXrSx4q/VLlbkDJf7eO+rpl7wSDfFWFy4aEY76MCGysc8FkleIKuIZ9pDnIJSMclPXnZ2zfNi+yBa/XGmrt0ARrvVNn3YC7hFrTOX7eU5Y0vQTBePZG4WQQ/C53O/Km1U5DWlVKjb8dJN9PwbP+sKlOKkRH4VWW2zQSE2MQzAbk/IYuiaRIF+hmsRa2LlyPgIoEUYYP2jjvesG1ypS69JqmQKQoVKd+JoMqDRIRRdqeELd3fKFYYEjsBUn1jaq7lVN+Ec3llSQnWwDdaVf8nVu+BCfJp1zUr5zmm4a2zaF2/CTdLRlzkNtFUjQattFbmp+9NmvwqOmujLsrM711sJn2lVp9p/DZMeQbBdXK48maxkrSSui8io2blqpc5wXVX8Kfrl5baQcbSMTtlAXbj/FuzCmH9Sm1dLbVXgVTBr5cwyupSpD7/jt6SdYW5hfbs7zW5j1FWfG+hJ1d1Mh/TIOSx+sPn82ayrL54dYWj6MPtM9DPcxdB1N7Xm6sz4mwY+CdNTbHIRJKjJbPVqJImN5XfCnLkZlyyx9VIxtPxJTGpdvraVHnTpHSPNAZ7TR5nQu2aN5mEeyikRDFwGPQg0MszJ9PyfxLp5Y//achNzfg+BoLK8s3wMcwGa26Zt7EDCL35r5aEs3khv4lPxeOo9I+wTtS9SgVAXeXPMHn9FdBP/gwoQPweAKpCgKtbu9WqZqoTTch6dJpwZUyQHfnMjx8V5wTxvOX2vvGeL90ftWsfuTVLxrKvfEqFHiplVe+YmhSSDK6bIqhGsFrNsaOMfJtzsUvwlNgIFmvbz32mKMGmGmJHlpiN1AGsQi7uJFOj5mTK8L1XA7hzsMTX/G30i9ZXLzRTMeDtA8omn9sSMB92cgcF2CR5conOriCH3StuuWOo8eNxZqi4Tyku/LwXj0g1pibVMmC5l0oNrXz/VuXO8U28O84gBf6jo/YlXFEjlplxND4rnWf30QkCxVP1+WjhJmHR1XF21//irbRtuYmrMHUx0X92konM4cwwXKjtRguvKM7M3BP9oyrXZX6xpEMQdTw2BRT9afXcAuQ4rSGmDaehhf9StYL1TZ9aMqaXIRJ7AcFnETAKYixNobeylKmU+9GGdEl1xAMnWVGtBWSbmftKdeVlTZo//cVTqBW7M+b629DMxz9VTKm8skhF4PRc4D0IC0rhOLvmsKyOEFrP+vRLgMhyYCpvYnWN8Us479RtXyky+YDRs8cCMDOPQdIYSVPAHSjjlHa9KApMnFLNPEWSh78bSOKsy6rJans9cTOTKLw01gY90Yz+1VG24w9pXYYbVS71DVBjks+7XnKwqaqShALG4VGtBCnp2pQbOszXpcoOHUkfkI0+xrSh/ipHalW6cp32RjS7lD5BCVBOVJz7kn8KOkDu+gXC6vufAbZXevNoSzpdZWsWj8p37FBFNyTPGnS7OcNof/vuvXpqw8ELTp3bgKqzm5hZ1sKTGgKc3O+lHIKYc3mjBYRuX3/6uvFfmQUQsh1/t0DxXNK62gzlst7UpJ5pJD/15NEM52v//xYlhpaC43vgUVBbptn7+aZ6K/hfwLXDNnsuxycd+cq4yOlgHfZJW9StAEN//VP65gk7YuRJF17Jb2/XvePWpR5MScKK/znRPIqhuODxr++cin8jzU7sgg7yIZHP0amSQUL2GWTB2dBbgJw+WRZt4gY3bxFIKgXxBGrIqjzHsZu+1NvPXcJEOcwsgVtB8eRup28e7gWPpre6ailZesubBQ0k7IzUNqNIBVh6JCX+ViTH4SpTs+/I6qZbB9Fl0cl9FOU41GCpXsbJciZM9BxMKhM60SgBPOskxU90cRrrhSUrXC6SM/rz11mN34HEtxZWAfjwTI+vUUyJ6EIsOZYDtYXNdOvQD0DEmzXIK/w5I+7dV8oLLMFE0Fvs5FO9ggqgltvkdR6BjYM6S9+pbtMDb96mViHWTMZZXqO0U+Ljfkfb/798jiVunaHVPTcaexOzk/g7nDMjXkbU38DVMc4BcGvr0MhWOdurvp1mLBO5/sffpn3D/FuMyFrr25kttwZjrL80IDyKuhtO2/GUATJP5M61QmrfiB5DJYk0CC9qwx/JlPvWw1S2b/QS3lrql59IQXdDzFIBa0xBhKhDykW9Ta+Fc9NsWwKUzv2T486Ut71CKtedDHy1egfljNNLPNghzeBMXL5cyyecbKSi90IKb1oVm6afrK3GExujMfcW1ksvYmKn1cyjSv+hEIL6RPE0GmrVfJ0Y+M60nqIPguJM/jFx0LPVf0W+Fg0zucefJgSDBO24yCssJV7bZVR0vwKUJj/Hl/14Q4Ty1ipTlJ/xA5NkPSfpkSQK3jFiLhVt5dKiAsMTcFydeykuKfeAJTu7ugAjAxlNmZenaGLNCcblysA6cnhYrIBybp1rtXYVsM9LWyPAYNKkKvr2VlAXcIQrS/UZIzLLybbsBg0264ZhC3XlaVmn+a6SESHNAXRl3tIHj8tHOoIi7OERJe2ux5aqisg0deTCQzvmX/jnOVGowvYc7Q/3qFpgG6NflKeB6dTUeH6Lzk2XmmJDSz90JGDbLMA3AEKOh1V8wGinNjalqHQhLXTy+ot7fPuXkWClKYlQ4cP8COHCz5fwSEdcKBid11BmbeF0e79fzeBn4WOeChdnk1dM1jmA8kayAsoU8CVfrQ92Rfljl2QqRAvjinnvwKluhYLDNx+YlrurnAK3tcG6Wp4rORbU6OuTClti31HWX0m67dm1CyMjVEN2hXTEP5AxwgcGK9Koq6UWmeYCjH+MSHO/+OmNt5suqAHz0rpA8ZcwUmYeEY7x46Vgvb2wpALTDJWAFmV5ooPt/jXlMNjMvfUMkDQv8dRl3JA4LMXJTXpFS1dm3q0LvFc3BghvDAe2HFK6B2tzEu9UcBf5tPQ9GTQTh+nwr1Lgc/0/C2LJZuWQmRE0kwEqvon4FnQy7fy3JT+kV0CGMObC84GgKxg2KptVKw9AyD48tY9+ZoZjuDRX5u9juAUeXF0/eFMqGgc217An2X0O05j31Loj8Dk/ZL9DFAFjDcAwYGR1BWcoMclpHpGVIY0EcNF1XI2t7SnNklmcSaO6IcPjE2o4IYuEXS9WONiMkWVL0fRKkybKXGLlbD3YqpmEKa1Jir4y9DtQ+A6ev19aXgu7eHZwa6vjaG1HvyYfSbS1Dy/oswopG3TjnG1VbLspewjDySQUR9iEGjekfj+myKDswiCjBw++t6BvvCz7v07wZQDJdGmDGqnQxfjXgrrEtpfJoi4oS9TsUM/hyE59ieY1cj5fJgp9nwZ6nniOjJxjidXBuqHiS2ZtanJ997TbvEVM243kcmFskRUR0DufD2TyOsODSPDldQ5XMunn7gOlcLNqX1lHhz81ylaR5mhWQP0yc7YDk4qhb7Uvg+uf8QNq6Gxq/26y43uhgZVvKjCwTcU8iUD8cJCPuJKrEvhz7xZ1NTZ+pqb9UcjWZLpYa9I4ekuhQmHSdldn4DSAy089Id6s6n5oJdrMke/GaTcD2CTrlljL4fOkgR0tp6hfvmzEwYE7zzBxNVaUWxT3m9Au0kxem/66Iep9RVZJwepE1LkhNZqmYVB3Ndiy+sU0uL/tJhmKLBgA5yqWepS2ytByApIkAAG/k8YuwOF4JjcAhruuOKORQJi5JKFXczZlcrEbl1wE+T19cSlXYwfIzSXAKAmq3V4yij3hRYR0UVPzof1bRkfTm05/WOuZqopAW7HagkPExT6jw64FC1xL76bX9BChDibEgpDsks8T74wvO9Zbzkqs6w==,iv:USzisipBcVIQzfHHcifPDU49QrdgLolJDpPe45YqM3M=,tag:FlXtRv79N+RoI7m/N7Vhpw==,type:str] # API server specific configuration options. apiServer: # The container image used in the API server manifest. image: registry.k8s.io/kube-apiserver:v1.34.1 # Extra certificate subject alternative names for the API server's certificate. certSANs: - api.owncloud.ai - talos.api.owncloud.ai - 192.168.50.200 extraArgs: enable-aggregator-routing: "true" feature-gates: MutatingAdmissionPolicy=true runtime-config: admissionregistration.k8s.io/v1beta1=true oidc-client-id: dex-k8s-authenticator oidc-issuer-url: https://dex.owncloud.ai oidc-username-claim: email oidc-groups-claim: groups oidc-required-claim: email_verified=true disablePodSecurityPolicy: true admissionControl: - name: PodSecurity configuration: apiVersion: pod-security.admission.config.k8s.io/v1 defaults: audit: restricted audit-version: latest enforce: baseline enforce-version: latest warn: restricted warn-version: latest exemptions: namespaces: - kube-system - gateway-system runtimeClasses: [] usernames: [] kind: PodSecurityConfiguration auditPolicy: apiVersion: audit.k8s.io/v1 kind: Policy rules: - level: Metadata controllerManager: extraArgs: bind-address: 0.0.0.0 image: registry.k8s.io/kube-controller-manager:v1.34.1 proxy: image: registry.k8s.io/kube-proxy:v1.34.1 disabled: true scheduler: extraArgs: bind-address: 0.0.0.0 image: registry.k8s.io/kube-scheduler:v1.34.1 discovery: enabled: true registries: kubernetes: disabled: true service: {} etcd: extraArgs: auto-compaction-retention: "1" listen-metrics-urls: http://0.0.0.0:2381 # Raised from the 100ms/1000ms defaults because this cluster's etcd # data lives on Crucial BX500 SATA SSDs (DRAM-less consumer TLC), # where fsync p99 reaches 127ms and backend-commit p99 reaches # 333ms. At the defaults, followers cannot commit heartbeats in # time and trigger spurious leader elections (12-46/hour). # election-timeout must be 5-10x heartbeat-interval per etcd docs. heartbeat-interval: "500" election-timeout: "5000" ca: crt: ENC[AES256_GCM,data:dGNp4/kIxSZjYRsY2a1jX2F5ZkuUkAvlZ/218YeFbNb4ViUO7YMTGXCpg5/RXfk0bLXRzWJwr9fU8C6QVbQ6Kc3TdHsvDnYXgNEkdFo8O8AwqrN4smFTbeEGW+m9No0ZfejuHKgbIj52JXqFC9duRNDJ7sAe3V+rnYK77bHJsDNlty7KSZDcTAxnAohOYKryXjHG0vnfjua/RK3Kl1IJn7IVtnK0ljS38NKmV4z4dlai57D+SlaLeeqMhOPvPROegOMPLAAEPflRdJ1VzWR3eMAOK4UrnwuZxdTFJm4dD+TuVi3urYW3zsXDkns+GKVh7POOcU9E6Ra/kNljjlJRUVzN4zG7RHl88/JYraR+fBjAG2ggvkupCp7f7D53t8JFWlKEeGeb24Agw3WI2mSCLqyXuKDDrN9rTR4KkVImI9F4B0SeTa/gpkzAJN7dRw8qoeyRBu8uMIij8HEjaN4IgYXMny1t/ymIhBoaOGbW2jWulapXLcXbiJdUZoyqnl08I/G0qgB3mSMf1b1PfV14PwPVOTkPD5MBVdev+q4ajupnfFqql3HIWTW2OOh5a0cipj3PuK90P7XwN+dYBIUDEjb/nVnsYqThQ5xAfAZjeoquiW4f01mLOUIZZ43Mb/WcNaZylFmfe3JJDDv1ObcsLNlAPRL8LcmsaV6GfwtgVPfACg/msEVl1vKE/9+cOsYrfJNKpJN6FNxZre17pkH+qpXwxRtK36SLt4mhSWTk7RUDnWlrO8Z+9cuKdEmqDczQMW+HIDAPHXZ1NE0O5vSciYXAKnEqObuHvOPTk0zs8Ce9bgQYlhhr4V9PHe8w+TMCGUCeNwg/lr+3SZyi+A7gTMO2+1eyx2ORvz3DBIo+SQSx4XNbKS6m3FtRGfse6ds1cgStdimvc2zzyd7rns/iKMPOXJplo2Ywryzi/rDBB9NJpqeVIeqhf8+rTjeR8BN0Psviy9CdFMHxUpu3A9KBhvTLVAc7hIE6Y+ml233CDzdDzD/sB8Nvs9SMTdvL7zei,iv:2OGAroS1xlxrfpYeT7C2VBvFFdnTJgSbdcvADGA324c=,tag:0fO8I+04dx2xycvUSsFjWA==,type:str] key: ENC[AES256_GCM,data:Wrmd1Yw6031zKraKkozc10JThkzlBMPNS1QAPqjew1V/tPhz5Lgq4ATa84BFjxLL3LCtjaGppuxPlo4exeoefZm5YbVcmrr9DmvfzDLDMdN+4B/NTk0KHQGzxw6mpfqVMWqWNOiLyY9iUlsgkFlZ30MH+9sOSmMlECBADA3enZygalxoSWHP0wmEBV3ebLmaZz6lISmgLHVQjWG4DW3qlW4q08TzU9lel/mqBVvKeJIWFDNNlE7DKhRqDvNpdtCRKEXx2cOOLzZuEqhKmeFgqJdtpzxK0Bt0yKBCSQbmGU4GoWtRXR+VDk7kfsaP504LNBOKuN03eoxVnaQg6r+qa9HENQbhTDHcTUPZEC/R+Lwek9Y+3TSP2DBGuZNNCplYIRK9LmTXgdSsPIAJOJuY5A==,iv:wnPsQ23i+mbqPWwONHPgXox8yT+Kvjj7SZ40d4+Lfig=,tag:4IlavwRghMnRAfvd5cF/jA==,type:str] extraManifests: - https://raw.githubusercontent.com/xUnholy/k8s-gitops/main/talos/integrations/cert-approver/cert-approver.yaml # renovate: datasource=github-releases depName=kubernetes-sigs/gateway-api - https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.1/experimental-install.yaml # renovate: datasource=github-releases depName=prometheus-operator/prometheus-operator - https://github.com/prometheus-operator/prometheus-operator/releases/download/v0.86.0/stripped-down-crds.yaml # renovate: datasource=github-releases depName=k8snetworkplumbingwg/network-attachment-definition-client - https://github.com/k8snetworkplumbingwg/network-attachment-definition-client/raw/refs/tags/v1.7.7/artifacts/networks-crd.yaml inlineManifests: [] allowSchedulingOnControlPlanes: true sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCQmlPdXJ0eHI0b29FSTM2 Unc3TldKVGVDdWd3U1ZIeFMzTlVsSEJBM0RJCklHWlBsS3ZocGlFWHFqK1Zsa1U2 bEZWVEhYQS85NEFUOUo1TFZlcFBBNkUKLS0tIG9CN0gzWFoxdnBOOEkyc0ZhZ2c5 aHoxbU5sVFdFUUc0MHhMeW1oQ0Z2aG8KUtfI19ZT0BHjAdBRzIjujpJaVxwIpd3Q gw/91gb8ePG5QuXhUBS4Ql0lxJZQwL0eCIu/DgRqtkQOFve4bTrY0w== -----END AGE ENCRYPTED FILE----- lastmodified: "2026-04-11T23:16:34Z" mac: ENC[AES256_GCM,data:qVE87d+yefvr02seo5/PSllpHFabU/6FGodae6Fq7Dti+IH+nDWNk3oNjgMtQ9LiCfjHbClaNc5RuyUVukGSE2SSJ3eXVDL/2gWlv/6cZ2UWmVKg2cqr2WO5K7I3Hv14S2c6eDvEfVXCwTAjG22lwQ8/bYOiW5c/gRG4Nm9JXwk=,iv:Z/U6wgdgzsxpxQZExZuXqi9liLOdt7XSw9i8cOUl8Bw=,tag:R+X66Dn8WQUC10yps1I2tg==,type:str] encrypted_regex: ((?i)(pass|secret($|[^N])|ca|crt|key|token|^data$|^stringData$)) mac_only_encrypted: true version: 3.12.1 ================================================ FILE: talos/generated/talosconfig.enc.age.yaml ================================================ context: cluster-00 contexts: cluster-00: endpoints: - 192.168.50.111 - 192.168.50.112 - 192.168.50.113 ca: ENC[AES256_GCM,data:JOIq3osnDgXIJNKmICED+rE8tZKgKgXQ/Wkhlpq7OMP+yOmzLjAwWMmwMqHoKxKWkMBmbPAAFvC1I7nt0ASiAWlXz0HcPLfgoLF2xol2guumX5VfU/R5hD8IWlWQEG6p/bR+AQuhqpLWWUR9NzVgGmdTYP4MKeOubtvVKXMCtNBY/CRml6sEyvFodLqvwCE/ZxJDDAjMNkZLxwzsgM0D3ijIndS9Rkma4yZ+knb5NIp5xjXwTH8Siw3ae/YXvDUZVxphh/KhAammp2dOYrY6AuNPc/ktNt9ruxtkN3x27+HTlsgpIUxEYQXkVydjtyPM6zuv6tuQUuCDFkJxBM/6Ei4bk7+eiN+59C7ik+P0eqy3B3ZxYdgKnF3l4wYw8g2/FPfwSlLtSJHYEPEgYRZg80cT570JPHnSA0lsohf8lYyPTjMP5ufe2WMWYWEFwrbFD0V2KB7jDqrDRtBRraCvXJ/i3ozItoNEtgy8jtUQHzP8ou6PFaFI6x28v361+LYvBgAMkFS6yijdeEpqIdF8S3yk/zKYQod/orkghl2YD/xp1A760S7NLemKiymrPzmKpEBSHdpgk5QZdlCMlIWCvF06j9+4Y5DwtpQ+RpK+R6VbsxXcrndLqgEWUCxRPxdZB+C4Hz/tmVkI5ZBdODsv4HE8IjwkFB87lbM1YSQ8MnkuB8txfhY2uoD2+h1DDXuFui3HquEMnSTgQumxGXW3afyqiv3UzxQ1OSRNmikTm3A22Ge6BJdMvCuadorxSXi/HcpOUYZenGKTtP5lnQCCdI2BOarOTJZlJDaBSSN1+qb6UF85jGuqCvSDW8m4rRW17Btktu6aOj6PA00tEl7+HoUbrjTG2O2dM0BJNVzA4ipuPWsV,iv:ywNLgj9iGSFL2ZCH3kaL5T+IZW1q1taCLqqz9DOA9Co=,tag:XuXPu3CQ7shVAH4kM41mqA==,type:str] crt: ENC[AES256_GCM,data:fe7CuwKhpswXNhNr2lqN+4y30QmOgcEssa3in2qP88KinkvxPRUalHpom6OYSKPn+eAEK7B7VwVxK++Btq0J15yV9tQS0D3KdBasJrsIialsF0+7EB5XXq6kEfUnliS+K8T9iA8yyrt6PFKgwKu9usNmpJjporhaOItGlsC1E+xXSoTRskB6XWEGele6b49luQtxMg0YTZpqzzsF5wqiRik1H+FRbW9hZJlqGZvWfnlAhr4LFEla0LP34kjkbxYarx1BbCZvg0hERl4mVdwqVQo4yh+FUvGC5OJjQWRSJnZ9TpTnAPw4CSk7cGqTc1FOtJtkrNeeLc9gkZJBS/1gJHkgivxkxKNUc4DSmy08ehHfT/FSrs10uL11cIk+/zvWrXDYb5+pDRFPVTbNLLmro7am4gBmzONe3fu7lAiGAf7TXu7C8esc110xgaCrl2wS0rc2V2bWCYElYDcoHluZl4OcKkHxckVWL+QC7FWyWcRw6ydJ1aoj8DSJLiaZbpwGM9V33UKChsqxznyZrvALBzod/eohLRatW0tcTN7JKlaAowDT2hQ4CKdW+n9wpavWyBlHZu6tOJCM5zGR6Ys9HHrPOrc0IsveXyZ+fYoDei2fUSg7hiLVFDTJ/3Gy/tyQUtSAxD7UUAgmtzzqWI0P4NbxNrNz3R4CCNnys+h+4/OIBCcQO73IxczJoN8GZc77tuYJphW5Sfkcr63zwK0m5dxrRruTCcBZiBVXTKPG5r8bn4tqz+vAUr2AFc4yGk0qOL+y/VCYQAWD8mYPfEgUl3z/ull7N8DcVQAg6GUFcH/NFByATOA+QQ==,iv:VflumnRSqiHBJbpXngNGtIt032sUPSJK2fCuhHmtQio=,tag:HcYzXwTdYVDBXRFoFz5o+Q==,type:str] key: ENC[AES256_GCM,data:GhA/5rd3PJea2FYy9qH+aLmd/LRchRl232bVs8Mp/U1iCNbEILXabWx5BxKbNv+KjciJPJnmUd5KX6q2fbxedrSU6z28NMQmhJsz8K9WA4vml9OUvpzBH/zUl+ZQjyVOKyR6eqbbUMCplMQiA9uyiaw4uEN3OyesyRZlLyBsr4YHY9sC40JI+m4I2uJ36gPMB0LDIw6jIrqmf9KLqeiCzlH+44emiGhAFgfUfSFiuc0EpyBs,iv:abLvDSPu9cXGHNIoVPKTUK67ogyhkJVhkPSyT+pB6sA=,tag:er6CbXBv2HszjUjGDp4OJQ==,type:str] sops: age: - recipient: age19gj66fq5v2veu940ftyj4pkw0w5tgxgddlyqnd00pnjzyndevurqx70g4t enc: | -----BEGIN AGE ENCRYPTED FILE----- YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvc3k4WS9Ed3h4WDFrcmRR d1RNQzdoVzdyMmcwTEF6am9aWGgyUzViS2lBCmJKL0J5dnNBQVRDYW44RHQyUlhC Qnp5empHSDBPV1AwR1Q5clhySitPdkkKLS0tIDRHcm5HdTg2ZGZvVjlCa3U4NkQ0 QVVka2owYkdKZnRReWZYT0x1WXNVMUUKdubinR+EZAwxMmxx6qsl7yj8MpzmsEIn 1HIw4bTkn7+tOUUUK6A3nkUJnENOlffoJ7hxOxykmqZF20uP5Md9qA== -----END AGE ENCRYPTED FILE----- lastmodified: "2025-12-22T01:34:33Z" mac: ENC[AES256_GCM,data:XBMGorZHg+KRAXFLo7sYKE7rWHX5Naq8nQu2xTiK8/2f18WzPD0lhyz/gzk0L4HR3A2qpcsHNQkcADUdWPTbHHlKWsrKKKRqD+xz1QzzYbK46jo88GxlAZE6Bi9vZxmodGvwtudPtpFDKHM9Z/RlVVt2aaPh0dhKDsmiOKy4BiE=,iv:Kpyw1FclLCErE0RaZCtrcWOez6rZX9ORKqd16Ny0/5I=,tag:AwmJJCWwXyNcukx8DAu55Q==,type:str] encrypted_regex: ((?i)(pass|secret($|[^N])|ca|crt|key|token|^data$|^stringData$)) mac_only_encrypted: true version: 3.11.0 ================================================ FILE: talos/integrations/cert-approver/.gitignore ================================================ # Kustomize helmChart transformer creates a charts/ dir that can be ignored charts/ ================================================ FILE: talos/integrations/cert-approver/README.md ================================================ # Kubelet CSR Approver ## Create Static Kubelet CSR Approver Locally For Talos ```bash echo "Removing old local chart cache" rm -rf talos/integrations/cert-approver/charts echo "# This manifest was generated by automation. DO NOT EDIT." > talos/integrations/cert-approver/cert-approver.yaml kustomize build \ --enable-helm \ --load-restrictor=LoadRestrictionsNone \ talos/integrations/cert-approver \ >> talos/integrations/cert-approver/cert-approver.yaml ``` ================================================ FILE: talos/integrations/cert-approver/cert-approver.yaml ================================================ # This manifest was generated by automation. DO NOT EDIT. # Chart: kubelet-csr-approver v1.2.13 # Source: oci://ghcr.io/postfinance/charts/kubelet-csr-approver # Values: kubernetes/apps/base/kube-system/kubelet-csr-approver/app/values.yaml --- apiVersion: v1 kind: ServiceAccount metadata: name: kubelet-csr-approver namespace: kube-system labels: helm.sh/chart: kubelet-csr-approver-1.2.13 app.kubernetes.io/name: kubelet-csr-approver app.kubernetes.io/instance: kubelet-csr-approver app.kubernetes.io/version: "v1.2.13" app.kubernetes.io/managed-by: Helm annotations: meta.helm.sh/release-name: kubelet-csr-approver meta.helm.sh/release-namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: kubelet-csr-approver labels: app.kubernetes.io/managed-by: Helm annotations: meta.helm.sh/release-name: kubelet-csr-approver meta.helm.sh/release-namespace: kube-system rules: - apiGroups: - coordination.k8s.io resources: - leases verbs: - create - get - update - apiGroups: - "" resources: - events verbs: - create - apiGroups: - certificates.k8s.io resources: - certificatesigningrequests verbs: - get - list - watch - apiGroups: - certificates.k8s.io resources: - certificatesigningrequests/approval verbs: - update - apiGroups: - certificates.k8s.io resourceNames: - kubernetes.io/kubelet-serving resources: - signers verbs: - approve --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: kubelet-csr-approver namespace: kube-system labels: app.kubernetes.io/managed-by: Helm annotations: meta.helm.sh/release-name: kubelet-csr-approver meta.helm.sh/release-namespace: kube-system roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: kubelet-csr-approver subjects: - kind: ServiceAccount name: kubelet-csr-approver namespace: kube-system --- apiVersion: v1 kind: Service metadata: name: kubelet-csr-approver namespace: kube-system labels: helm.sh/chart: kubelet-csr-approver-1.2.13 app.kubernetes.io/name: kubelet-csr-approver app.kubernetes.io/instance: kubelet-csr-approver app.kubernetes.io/version: "v1.2.13" app.kubernetes.io/managed-by: Helm annotations: meta.helm.sh/release-name: kubelet-csr-approver meta.helm.sh/release-namespace: kube-system prometheus.io/port: "8080" prometheus.io/scrape: "true" spec: type: ClusterIP ports: - port: 8080 targetPort: metrics protocol: TCP name: metrics selector: app.kubernetes.io/name: kubelet-csr-approver app.kubernetes.io/instance: kubelet-csr-approver --- apiVersion: apps/v1 kind: Deployment metadata: name: kubelet-csr-approver namespace: kube-system labels: helm.sh/chart: kubelet-csr-approver-1.2.13 app.kubernetes.io/name: kubelet-csr-approver app.kubernetes.io/instance: kubelet-csr-approver app.kubernetes.io/version: "v1.2.13" app.kubernetes.io/managed-by: Helm annotations: meta.helm.sh/release-name: kubelet-csr-approver meta.helm.sh/release-namespace: kube-system spec: replicas: 2 selector: matchLabels: app.kubernetes.io/name: kubelet-csr-approver app.kubernetes.io/instance: kubelet-csr-approver template: metadata: labels: app.kubernetes.io/name: kubelet-csr-approver app.kubernetes.io/instance: kubelet-csr-approver spec: serviceAccountName: kubelet-csr-approver securityContext: {} containers: - name: kubelet-csr-approver securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL privileged: false readOnlyRootFilesystem: true runAsGroup: 65532 runAsNonRoot: true runAsUser: 65532 seccompProfile: type: RuntimeDefault image: "ghcr.io/postfinance/kubelet-csr-approver:v1.2.13" imagePullPolicy: IfNotPresent args: - -metrics-bind-address - ":8080" - -health-probe-bind-address - ":8081" - -leader-election env: - name: PROVIDER_REGEX value: ^talos-\d$ - name: ALLOWED_DNS_NAMES value: "1" ports: - name: metrics containerPort: 8080 protocol: TCP livenessProbe: httpGet: path: /healthz port: 8081 resources: limits: cpu: 500m memory: 128Mi requests: cpu: 100m memory: 64Mi tolerations: - effect: NoSchedule key: node-role.kubernetes.io/control-plane operator: Equal --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: kubelet-csr-approver namespace: kube-system labels: helm.sh/chart: kubelet-csr-approver-1.2.13 app.kubernetes.io/name: kubelet-csr-approver app.kubernetes.io/instance: kubelet-csr-approver app.kubernetes.io/version: "v1.2.13" app.kubernetes.io/managed-by: Helm annotations: meta.helm.sh/release-name: kubelet-csr-approver meta.helm.sh/release-namespace: kube-system spec: endpoints: - interval: 1m path: /metrics port: metrics scheme: http scrapeTimeout: 10s jobLabel: kubelet-csr-approver namespaceSelector: matchNames: - kube-system selector: matchLabels: app.kubernetes.io/instance: kubelet-csr-approver app.kubernetes.io/name: kubelet-csr-approver ================================================ FILE: talos/integrations/cert-approver/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization helmCharts: - name: kubelet-csr-approver includeCRDs: true skipTests: true releaseName: kubelet-csr-approver namespace: kube-system valuesFile: ../../../kubernetes/apps/base/kube-system/kubelet-csr-approver/app/values.yaml # renovate: registryUrl=oci://ghcr.io/postfinance/charts version: 1.2.13 repo: oci://ghcr.io/postfinance/charts # REQUIRED: Use transformers to avoid creating the labels & annotations on all references rather than only metadata/annotations or metadata/labels respectively transformers: - transformers.yaml ================================================ FILE: talos/integrations/cert-approver/transformers.yaml ================================================ --- apiVersion: builtin kind: LabelTransformer metadata: name: labels labels: app.kubernetes.io/managed-by: Helm fieldSpecs: - path: metadata/labels create: true --- apiVersion: builtin kind: AnnotationsTransformer metadata: name: annotations annotations: meta.helm.sh/release-name: kubelet-csr-approver meta.helm.sh/release-namespace: kube-system fieldSpecs: - path: metadata/annotations create: true ================================================ FILE: talos/integrations/cilium/.gitignore ================================================ # Kustomize helmChart transformer creates a charts/ dir that can be ignored charts/ ================================================ FILE: talos/integrations/cilium/README.md ================================================ # Cilium ## Create Static Cilium Locally For Talos ```bash echo "Removing old local chart cache" rm -rf talos/integrations/cilium/charts echo "# This manifest was generated by automation. DO NOT EDIT." > talos/integrations/cilium/cilium.yaml kustomize build \ --enable-helm \ --load-restrictor=LoadRestrictionsNone \ talos/integrations/cilium \ >> talos/integrations/cilium/cilium.yaml ``` ================================================ FILE: talos/integrations/cilium/cilium.yaml ================================================ # This manifest was generated by automation. DO NOT EDIT. apiVersion: v1 kind: Namespace metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: cilium name: cilium-secrets --- apiVersion: v1 kind: ServiceAccount metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm name: cilium namespace: kube-system --- apiVersion: v1 kind: ServiceAccount metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm name: cilium-operator namespace: kube-system --- apiVersion: v1 automountServiceAccountToken: false kind: ServiceAccount metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm name: hubble-relay namespace: kube-system --- apiVersion: v1 kind: ServiceAccount metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm name: hubble-ui namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: cilium name: cilium-operator-tlsinterception-secrets namespace: cilium-secrets rules: - apiGroups: - "" resources: - secrets verbs: - create - delete - update - patch --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: cilium name: cilium-tlsinterception-secrets namespace: cilium-secrets rules: - apiGroups: - "" resources: - secrets verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: cilium name: cilium-config-agent namespace: kube-system rules: - apiGroups: - "" resources: - configmaps verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: cilium name: cilium rules: - apiGroups: - networking.k8s.io resources: - networkpolicies verbs: - get - list - watch - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - get - list - watch - apiGroups: - "" resources: - namespaces - services - pods - endpoints - nodes verbs: - get - list - watch - apiGroups: - "" resources: - nodes/status verbs: - patch - apiGroups: - coordination.k8s.io resources: - leases verbs: - create - get - update - list - delete - apiGroups: - apiextensions.k8s.io resources: - customresourcedefinitions verbs: - list - watch - get - apiGroups: - cilium.io resources: - ciliumloadbalancerippools - ciliumbgppeeringpolicies - ciliumbgpnodeconfigs - ciliumbgpadvertisements - ciliumbgppeerconfigs - ciliumclusterwideenvoyconfigs - ciliumclusterwidenetworkpolicies - ciliumegressgatewaypolicies - ciliumendpoints - ciliumendpointslices - ciliumenvoyconfigs - ciliumidentities - ciliumlocalredirectpolicies - ciliumnetworkpolicies - ciliumnodes - ciliumnodeconfigs - ciliumcidrgroups - ciliuml2announcementpolicies - ciliumpodippools verbs: - list - watch - apiGroups: - cilium.io resources: - ciliumidentities - ciliumendpoints - ciliumnodes verbs: - create - apiGroups: - cilium.io resources: - ciliumidentities verbs: - update - apiGroups: - cilium.io resources: - ciliumendpoints verbs: - delete - get - apiGroups: - cilium.io resources: - ciliumnodes - ciliumnodes/status verbs: - get - update - apiGroups: - cilium.io resources: - ciliumendpoints/status - ciliumendpoints - ciliuml2announcementpolicies/status - ciliumbgpnodeconfigs/status verbs: - patch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: cilium name: cilium-operator rules: - apiGroups: - "" resources: - pods verbs: - get - list - watch - delete - apiGroups: - "" resourceNames: - cilium-config resources: - configmaps verbs: - patch - apiGroups: - "" resources: - nodes verbs: - list - watch - apiGroups: - "" resources: - nodes - nodes/status verbs: - patch - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - get - list - watch - apiGroups: - "" resources: - services/status verbs: - update - patch - apiGroups: - "" resources: - namespaces - secrets verbs: - get - list - watch - apiGroups: - "" resources: - services - endpoints verbs: - get - list - watch - apiGroups: - cilium.io resources: - ciliumnetworkpolicies - ciliumclusterwidenetworkpolicies verbs: - create - update - deletecollection - patch - get - list - watch - apiGroups: - cilium.io resources: - ciliumnetworkpolicies/status - ciliumclusterwidenetworkpolicies/status verbs: - patch - update - apiGroups: - cilium.io resources: - ciliumendpoints - ciliumidentities verbs: - delete - list - watch - apiGroups: - cilium.io resources: - ciliumidentities verbs: - update - apiGroups: - cilium.io resources: - ciliumnodes verbs: - create - update - get - list - watch - delete - apiGroups: - cilium.io resources: - ciliumnodes/status verbs: - update - apiGroups: - cilium.io resources: - ciliumendpointslices - ciliumenvoyconfigs - ciliumbgppeerconfigs - ciliumbgpadvertisements - ciliumbgpnodeconfigs verbs: - create - update - get - list - watch - delete - patch - apiGroups: - cilium.io resources: - ciliumbgpclusterconfigs/status - ciliumbgppeerconfigs/status verbs: - update - apiGroups: - apiextensions.k8s.io resources: - customresourcedefinitions verbs: - create - get - list - watch - apiGroups: - apiextensions.k8s.io resourceNames: - ciliumloadbalancerippools.cilium.io - ciliumbgppeeringpolicies.cilium.io - ciliumbgpclusterconfigs.cilium.io - ciliumbgppeerconfigs.cilium.io - ciliumbgpadvertisements.cilium.io - ciliumbgpnodeconfigs.cilium.io - ciliumbgpnodeconfigoverrides.cilium.io - ciliumclusterwideenvoyconfigs.cilium.io - ciliumclusterwidenetworkpolicies.cilium.io - ciliumegressgatewaypolicies.cilium.io - ciliumendpoints.cilium.io - ciliumendpointslices.cilium.io - ciliumenvoyconfigs.cilium.io - ciliumidentities.cilium.io - ciliumlocalredirectpolicies.cilium.io - ciliumnetworkpolicies.cilium.io - ciliumnodes.cilium.io - ciliumnodeconfigs.cilium.io - ciliumcidrgroups.cilium.io - ciliuml2announcementpolicies.cilium.io - ciliumpodippools.cilium.io - ciliumgatewayclassconfigs.cilium.io resources: - customresourcedefinitions verbs: - update - apiGroups: - cilium.io resources: - ciliumloadbalancerippools - ciliumpodippools - ciliumbgppeeringpolicies - ciliumbgpclusterconfigs - ciliumbgpnodeconfigoverrides - ciliumbgppeerconfigs verbs: - get - list - watch - apiGroups: - cilium.io resources: - ciliumpodippools verbs: - create - apiGroups: - cilium.io resources: - ciliumloadbalancerippools/status verbs: - patch - apiGroups: - coordination.k8s.io resources: - leases verbs: - create - get - update --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: cilium name: hubble-ui rules: - apiGroups: - networking.k8s.io resources: - networkpolicies verbs: - get - list - watch - apiGroups: - "" resources: - componentstatuses - endpoints - namespaces - nodes - pods - services verbs: - get - list - watch - apiGroups: - apiextensions.k8s.io resources: - customresourcedefinitions verbs: - get - list - watch - apiGroups: - cilium.io resources: - '*' verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: cilium name: cilium-operator-tlsinterception-secrets namespace: cilium-secrets roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: cilium-operator-tlsinterception-secrets subjects: - kind: ServiceAccount name: cilium-operator namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: cilium name: cilium-tlsinterception-secrets namespace: cilium-secrets roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: cilium-tlsinterception-secrets subjects: - kind: ServiceAccount name: cilium namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: cilium name: cilium-config-agent namespace: kube-system roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: cilium-config-agent subjects: - kind: ServiceAccount name: cilium namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: cilium name: cilium roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cilium subjects: - kind: ServiceAccount name: cilium namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: cilium name: cilium-operator roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cilium-operator subjects: - kind: ServiceAccount name: cilium-operator namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/part-of: cilium name: hubble-ui roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: hubble-ui subjects: - kind: ServiceAccount name: hubble-ui namespace: kube-system --- apiVersion: v1 data: agent-not-ready-taint-key: node.cilium.io/agent-not-ready annotate-k8s-node: "true" auto-direct-node-routes: "true" bpf-distributed-lru: "false" bpf-events-drop-enabled: "true" bpf-events-policy-verdict-enabled: "true" bpf-events-trace-enabled: "true" bpf-lb-acceleration: disabled bpf-lb-algorithm: maglev bpf-lb-algorithm-annotation: "false" bpf-lb-external-clusterip: "false" bpf-lb-map-max: "65536" bpf-lb-mode: hybrid bpf-lb-mode-annotation: "false" bpf-lb-sock: "false" bpf-lb-source-range-all-types: "false" bpf-map-dynamic-size-ratio: "0.0025" bpf-policy-map-max: "16384" bpf-policy-stats-map-max: "65536" bpf-root: /sys/fs/bpf cgroup-root: /sys/fs/cgroup cilium-endpoint-gc-interval: 5m0s cluster-id: "0" cluster-name: default clustermesh-enable-endpoint-sync: "false" clustermesh-enable-mcs-api: "false" cni-exclusive: "false" cni-log-file: /var/run/cilium/cilium-cni.log controller-group-metrics: write-cni-file sync-host-ips sync-lb-maps-with-k8s-services custom-cni-conf: "false" datapath-mode: netkit debug: "false" debug-verbose: "" default-lb-service-ipam: lbipam direct-routing-skip-unreachable: "false" dnsproxy-enable-transparent-mode: "true" dnsproxy-socket-linger-timeout: "10" egress-gateway-reconciliation-trigger-interval: 1s enable-auto-protect-node-port-range: "true" enable-bandwidth-manager: "true" enable-bbr: "true" enable-bbr-hostns-only: "false" enable-bpf-clock-probe: "false" enable-bpf-masquerade: "true" enable-bpf-tproxy: "true" enable-endpoint-health-checking: "true" enable-endpoint-lockdown-on-policy-overflow: "false" enable-endpoint-routes: "true" enable-health-check-loadbalancer-ip: "false" enable-health-check-nodeport: "true" enable-health-checking: "true" enable-hubble: "true" enable-internal-traffic-policy: "true" enable-ipv4: "true" enable-ipv4-big-tcp: "false" enable-ipv4-masquerade: "true" enable-ipv6: "false" enable-ipv6-big-tcp: "false" enable-ipv6-masquerade: "true" enable-k8s-networkpolicy: "true" enable-l2-announcements: "true" enable-l2-neigh-discovery: "false" enable-l7-proxy: "true" enable-lb-ipam: "true" enable-local-redirect-policy: "true" enable-masquerade-to-route-source: "false" enable-metrics: "true" enable-node-selector-labels: "false" enable-non-default-deny-policies: "true" enable-pmtu-discovery: "true" enable-policy: default enable-policy-secrets-sync: "true" enable-sctp: "false" enable-source-ip-verification: "true" enable-svc-source-range-check: "true" enable-tcx: "true" enable-vtep: "false" enable-well-known-identities: "false" enable-xt-socket-fallback: "true" envoy-access-log-buffer-size: "4096" envoy-base-id: "0" envoy-keep-cap-netbindservice: "false" external-envoy-proxy: "false" health-check-icmp-failure-threshold: "3" http-retry-count: "3" hubble-disable-tls: "false" hubble-listen-address: :4244 hubble-network-policy-correlation-enabled: "true" hubble-socket-path: /var/run/cilium/hubble.sock hubble-tls-cert-file: /var/lib/cilium/tls/hubble/server.crt hubble-tls-client-ca-files: /var/lib/cilium/tls/hubble/client-ca.crt hubble-tls-key-file: /var/lib/cilium/tls/hubble/server.key identity-allocation-mode: crd identity-gc-interval: 15m0s identity-heartbeat-timeout: 30m0s identity-management-mode: agent install-no-conntrack-iptables-rules: "false" ipam: kubernetes ipam-cilium-node-update-rate: 15s iptables-random-fully: "false" ipv4-native-routing-cidr: 10.244.0.0/16 k8s-require-ipv4-pod-cidr: "false" k8s-require-ipv6-pod-cidr: "false" kube-proxy-replacement: "true" kube-proxy-replacement-healthz-bind-address: 0.0.0.0:10256 max-connected-clusters: "255" mesh-auth-enabled: "true" mesh-auth-gc-interval: 5m0s mesh-auth-queue-size: "1024" mesh-auth-rotated-identities-queue-size: "1024" metrics-sampling-interval: 5m monitor-aggregation: medium monitor-aggregation-flags: all monitor-aggregation-interval: 5s nat-map-stats-entries: "32" nat-map-stats-interval: 30s node-port-bind-protection: "true" nodeport-addresses: "" nodes-gc-interval: 5m0s operator-api-serve-addr: 127.0.0.1:9234 operator-prometheus-serve-addr: :9963 policy-cidr-match-mode: "" policy-default-local-cluster: "false" policy-secrets-namespace: cilium-secrets policy-secrets-only-from-secrets-namespace: "true" preallocate-bpf-maps: "true" procfs: /host/proc prometheus-serve-addr: :9962 proxy-connect-timeout: "2" proxy-idle-timeout-seconds: "60" proxy-initial-fetch-timeout: "30" proxy-max-concurrent-retries: "128" proxy-max-connection-duration-seconds: "0" proxy-max-requests-per-connection: "0" proxy-prometheus-port: "9964" proxy-xff-num-trusted-hops-egress: "0" proxy-xff-num-trusted-hops-ingress: "0" remove-cilium-node-taints: "true" routing-mode: native service-no-backend-response: reject set-cilium-is-up-condition: "true" set-cilium-node-taints: "true" synchronize-k8s-nodes: "true" tofqdns-dns-reject-response-code: refused tofqdns-enable-dns-compression: "true" tofqdns-endpoint-max-ip-per-hostname: "1000" tofqdns-idle-connection-grace-period: 0s tofqdns-max-deferred-connection-deletes: "10000" tofqdns-preallocate-identities: "true" tofqdns-proxy-response-max-delay: 100ms tunnel-protocol: vxlan tunnel-source-port-range: 0-0 unmanaged-pod-watcher-interval: "15" vtep-cidr: "" vtep-endpoint: "" vtep-mac: "" vtep-mask: "" write-cni-conf-when-ready: /host/etc/cni/net.d/05-cilium.conflist kind: ConfigMap metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm name: cilium-config namespace: kube-system --- apiVersion: v1 data: cilium-dashboard.json: |- { "annotations": { "list": [ { "builtIn": 1, "datasource": { "type": "datasource", "uid": "grafana" }, "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" } ] }, "description": "Dashboard for Cilium (https://cilium.io/) metrics", "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 1, "id": 1, "links": [], "panels": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "opm" }, "overrides": [ { "matcher": { "id": "byName", "options": "error" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "warning" }, "properties": [ { "id": "color", "value": { "fixedColor": "#c15c17", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 0, "y": 0 }, "id": 76, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "sum(rate(cilium_errors_warnings_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, level) * 60", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{level}}", "range": true, "refId": "A" } ], "title": "Errors & Warnings", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 35, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "percent" }, "overrides": [ { "matcher": { "id": "byName", "options": "avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#cffaff", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "custom.fillBelowTo", "value": "min" }, { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "custom.lineWidth", "value": 0 } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 0 }, "id": 96, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "min(irate(cilium_process_cpu_seconds_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod) * 100", "format": "time_series", "intervalFactor": 1, "legendFormat": "min", "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(irate(cilium_process_cpu_seconds_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod) * 100", "format": "time_series", "intervalFactor": 1, "legendFormat": "avg", "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(irate(cilium_process_cpu_seconds_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod) * 100", "format": "time_series", "intervalFactor": 1, "legendFormat": "max", "refId": "C" } ], "title": "CPU Usage per node", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 5 }, "id": 161, "panels": [], "title": "Generic", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 35, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byName", "options": "AVG_virtual_memory_bytes" }, "properties": [ { "id": "color", "value": { "fixedColor": "#508642", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Average Virtual Memory" }, "properties": [ { "id": "color", "value": { "fixedColor": "#f9d9f9", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "MAX_virtual_memory_bytes" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e5ac0e", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Max Virtual Memory" }, "properties": [ { "id": "color", "value": { "fixedColor": "#584477", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Max Virtual Memory" }, "properties": [ { "id": "custom.fillBelowTo", "value": "Min Virtual Memory" }, { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "Min Virtual Memory" }, "properties": [ { "id": "custom.lineWidth", "value": 0 } ] } ] }, "gridPos": { "h": 5, "w": 8, "x": 0, "y": 6 }, "id": 26, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "min(cilium_process_virtual_memory_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", "format": "time_series", "intervalFactor": 1, "legendFormat": "Min Virtual Memory", "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_process_virtual_memory_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", "format": "time_series", "intervalFactor": 1, "legendFormat": "Average Virtual Memory", "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_process_virtual_memory_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", "format": "time_series", "intervalFactor": 1, "legendFormat": "Max Virtual Memory", "refId": "C" } ], "title": "Virtual Memory Bytes", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byName", "options": "MAX_resident_memory_bytes_max" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e5ac0e", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 5, "w": 8, "x": 8, "y": 6 }, "id": 24, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_process_resident_memory_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "AVG_resident_memory_bytes", "refId": "C" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_process_resident_memory_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "MAX_resident_memory_bytes_max", "refId": "D" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "min(cilium_process_resident_memory_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", "format": "time_series", "intervalFactor": 1, "legendFormat": "MIN_resident_memory_bytes_min", "refId": "E" } ], "title": "Resident memory status", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byName", "options": "all nodes" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e5a8e2", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 5, "w": 8, "x": 16, "y": 6 }, "id": 98, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(cilium_process_open_fds{k8s_app=\"cilium\", pod=~\"$pod\"})", "format": "time_series", "intervalFactor": 1, "legendFormat": "all nodes", "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "min(cilium_process_open_fds{k8s_app=\"cilium\", pod=~\"$pod\"})", "format": "time_series", "intervalFactor": 1, "legendFormat": "min/node", "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_process_open_fds{k8s_app=\"cilium\", pod=~\"$pod\"})", "format": "time_series", "intervalFactor": 1, "legendFormat": "avg/node", "refId": "C" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_process_open_fds{k8s_app=\"cilium\", pod=~\"$pod\"})", "format": "time_series", "intervalFactor": 1, "legendFormat": "max/node", "refId": "D" } ], "title": "Open file descriptors", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "description": "BPF memory usage in the entire system including components not managed by Cilium.", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "bytes" }, "overrides": [ { "matcher": { "id": "byName", "options": "MAX_resident_memory_bytes_max" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e5ac0e", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 0, "y": 11 }, "id": 178, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_bpf_maps_virtual_memory_max_bytes{k8s_app=\"cilium\", pod=~\"$pod\"} + cilium_bpf_progs_virtual_memory_max_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", "format": "time_series", "hide": false, "interval": "", "intervalFactor": 1, "legendFormat": "AVG_bpf_memory_bytes_avg", "refId": "C" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_bpf_maps_virtual_memory_max_bytes{k8s_app=\"cilium\", pod=~\"$pod\"} + cilium_bpf_progs_virtual_memory_max_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", "format": "time_series", "hide": false, "interval": "", "intervalFactor": 1, "legendFormat": "MAX_bpf_memory_bytes_max", "refId": "D" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "min(cilium_bpf_maps_virtual_memory_max_bytes{k8s_app=\"cilium\", pod=~\"$pod\"} + cilium_bpf_progs_virtual_memory_max_bytes{k8s_app=\"cilium\", pod=~\"$pod\"})", "format": "time_series", "hide": false, "instant": false, "interval": "", "intervalFactor": 1, "legendFormat": "MIN_bpf_memory_bytes_min", "refId": "E" } ], "title": "System-wide BPF memory usage", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "description": "Fill percentage of BPF maps, tagged by map name", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "max": 1, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "percentunit" }, "overrides": [] }, "gridPos": { "h": 6, "w": 12, "x": 12, "y": 11 }, "id": 194, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "cilium_bpf_map_pressure{k8s_app=\"cilium\", pod=~\"$pod\"}", "interval": "", "legendFormat": "", "refId": "A" } ], "title": "BPF map pressure", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 17 }, "id": 155, "panels": [], "title": "API", "type": "row" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "s" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 0, "y": 18 }, "id": 152, "options": { "legend": { "calcs": [ "mean" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_agent_api_process_time_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])/rate(cilium_agent_api_process_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{method}} {{path}}", "refId": "A" } ], "title": "API call latency (average node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "s" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 12, "y": 18 }, "id": 153, "options": { "legend": { "calcs": [ "max" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(rate(cilium_agent_api_process_time_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])/rate(cilium_agent_api_process_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{method}} {{path}}", "refId": "A" } ], "title": "API call latency (max node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 0, "y": 24 }, "id": 156, "options": { "legend": { "calcs": [ "mean" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_agent_api_process_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{method}} {{path}} ", "refId": "A" } ], "title": "# API calls (average node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 12, "y": 24 }, "id": 157, "options": { "legend": { "calcs": [ "max" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(rate(cilium_agent_api_process_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{method}} {{path}} ", "refId": "A" } ], "title": "# API calls (max node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 0, "y": 30 }, "id": 159, "options": { "legend": { "calcs": [ "mean" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_agent_api_process_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path, return_code)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{return_code}} ({{method}} {{path}} )", "refId": "A" } ], "title": "API return codes (average node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 12, "y": 30 }, "id": 158, "options": { "legend": { "calcs": [ "mean" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_agent_api_process_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path, return_code)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{return_code}} ({{method}} {{path}} )", "refId": "A" } ], "title": "API return codes (sum all nodes)", "type": "timeseries" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 36 }, "id": 72, "panels": [], "title": "Cilium", "type": "row" }, { "fieldConfig": { "defaults": {}, "overrides": [] }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 37 }, "id": 144, "options": { "code": { "language": "plaintext", "showLineNumbers": false, "showMiniMap": false }, "content": "", "mode": "markdown" }, "pluginVersion": "11.3.1", "title": "BPF", "type": "text" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 38 }, "id": 146, "options": { "legend": { "calcs": [ "mean", "max" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "avg(rate(cilium_bpf_syscall_duration_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, operation)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{operation}}", "range": true, "refId": "A" } ], "title": "# system calls (average node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "decimals": 0, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 38 }, "id": 145, "options": { "legend": { "calcs": [ "mean", "max" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(rate(cilium_bpf_syscall_duration_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, operation)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{operation}}", "refId": "A" } ], "title": "# system calls (max node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "s" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 0, "y": 46 }, "id": 140, "options": { "legend": { "calcs": [ "mean", "max" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_bpf_syscall_duration_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])/ rate(cilium_bpf_syscall_duration_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, operation)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{operation}}", "refId": "A" } ], "title": "system call latency (avg node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 6, "w": 12, "x": 12, "y": 46 }, "id": 148, "options": { "legend": { "calcs": [ "mean", "max" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(rate(cilium_bpf_syscall_duration_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])/ rate(cilium_bpf_syscall_duration_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, operation)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{operation}}", "refId": "A" } ], "title": "system call latency (max node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 6, "w": 8, "x": 0, "y": 52 }, "id": 142, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "topk(5, avg(rate(cilium_bpf_map_ops_total{k8s_app=\"cilium\", pod=~\"$pod\"}[5m])) by (pod, map_name, operation))", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{map_name}} {{operation}}", "refId": "A" } ], "title": "map ops (average node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 6, "w": 8, "x": 8, "y": 52 }, "id": 147, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "topk(5, max(rate(cilium_bpf_map_ops_total{k8s_app=\"cilium\", pod=~\"$pod\"}[5m])) by (pod, map_name, operation))", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{map_name}} {{operation}}", "refId": "A" } ], "title": "map ops (max node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 6, "w": 8, "x": 16, "y": 52 }, "id": 143, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_bpf_map_ops_total{k8s_app=\"cilium\",outcome=\"fail\", pod=~\"$pod\"}[5m])) by (pod, map_name, operation)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{map_name}} {{operation}}", "refId": "A" } ], "title": "map ops (sum failures)", "type": "timeseries" }, { "fieldConfig": { "defaults": {}, "overrides": [] }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 58 }, "id": 182, "options": { "code": { "language": "plaintext", "showLineNumbers": false, "showMiniMap": false }, "content": "", "mode": "markdown" }, "pluginVersion": "11.3.1", "title": "kvstore", "type": "text" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "decimals": 0, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 0, "y": 59 }, "id": 184, "options": { "legend": { "calcs": [ "mean", "max" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(kvstore_operations_total{pod=~\"$pod\"}[1m])) by (pod, scope, action)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{scope}} {{action}}", "refId": "A" } ], "title": "# operations (sum all nodes)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "decimals": 0, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 59 }, "id": 186, "options": { "legend": { "calcs": [ "mean", "max" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(rate(kvstore_operations_total{pod=~\"$pod\"}[1m])) by (pod, scope, action)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{scope}} {{action}}", "refId": "A" } ], "title": "# operations (max node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "s" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 0, "y": 64 }, "id": 188, "options": { "legend": { "calcs": [ "mean", "max" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "topk(5, avg(rate(cilium_kvstore_operations_duration_seconds_sum{pod=~\"$pod\"}[1m])) by (pod, action, scope) / avg(rate(cilium_kvstore_operations_duration_seconds_count{pod=~\"$pod\"}[1m])) by (pod, action, scope))", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}} {{scope}}", "refId": "A" } ], "title": "latency (average node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "s" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 64 }, "id": 190, "options": { "legend": { "calcs": [ "mean", "max" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "topk(5, max(rate(cilium_kvstore_operations_duration_seconds_sum{pod=~\"$pod\"}[1m])) by (pod, action, scope) / avg(rate(cilium_kvstore_operations_duration_seconds_count{pod=~\"$pod\"}[1m])) by (pod, action, scope))", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}} {{scope}}", "refId": "A" } ], "title": "latency (max node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 0, "y": 69 }, "id": 192, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_kvstore_events_queue_seconds_count{pod=~\"$pod\"}[1m])) by (pod, scope, action)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}} {{scope}}", "refId": "B" } ], "title": "Events received (average node)", "type": "timeseries" }, { "fieldConfig": { "defaults": {}, "overrides": [] }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 75 }, "id": 47, "options": { "code": { "language": "plaintext", "showLineNumbers": false, "showMiniMap": false }, "content": "", "mode": "markdown" }, "pluginVersion": "11.3.1", "title": "Cilium network information", "type": "text" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "pps" }, "overrides": [] }, "gridPos": { "h": 6, "w": 12, "x": 0, "y": 76 }, "id": 81, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_forward_count_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, direction)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{direction}}", "refId": "A" } ], "title": "Forwarded Packets", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "bps" }, "overrides": [] }, "gridPos": { "h": 6, "w": 12, "x": 12, "y": 76 }, "id": 111, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_forward_bytes_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, direction) * 8", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{direction}}", "refId": "A" } ], "title": "Forwarded Traffic", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 35, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byName", "options": "Alive ipv4" }, "properties": [ { "id": "color", "value": { "fixedColor": "#0a50a1", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv4 non-TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#f9d9f9", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv6" }, "properties": [ { "id": "color", "value": { "fixedColor": "#614d93", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv6 TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#806eb7", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv6 non-TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#614d93", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive CT entries ipv6" }, "properties": [ { "id": "color", "value": { "fixedColor": "#badff4", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted CT entries ipv4" }, "properties": [ { "id": "color", "value": { "fixedColor": "#bf1b00", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted ipv4" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted ipv4 non-TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted ipv6" }, "properties": [ { "id": "color", "value": { "fixedColor": "#bf1b00", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "L7 denied request" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "L7 forwarded request" }, "properties": [ { "id": "color", "value": { "fixedColor": "#7eb26d", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e0f9d7", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "deleted" }, "properties": [ { "id": "color", "value": { "fixedColor": "#6ed0e0", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "deleted max" }, "properties": [ { "id": "color", "value": { "fixedColor": "#447ebc", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "color", "value": { "fixedColor": "#629e51", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "color", "value": { "fixedColor": "#629e51", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "custom.fillBelowTo", "value": "min" }, { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "custom.lineWidth", "value": 0 } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 0, "y": 82 }, "id": 56, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "min(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv4\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "min", "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv4\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "avg", "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv4\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "max", "refId": "C" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv4\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "deleted", "refId": "D" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv4\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "deleted max", "refId": "E" } ], "title": "IPv4 Conntrack TCP", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 35, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byName", "options": "Alive ipv4" }, "properties": [ { "id": "color", "value": { "fixedColor": "#0a50a1", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv4 non-TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#f9d9f9", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv6" }, "properties": [ { "id": "color", "value": { "fixedColor": "#614d93", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv6 TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#806eb7", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv6 non-TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#614d93", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive CT entries ipv6" }, "properties": [ { "id": "color", "value": { "fixedColor": "#badff4", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted CT entries ipv4" }, "properties": [ { "id": "color", "value": { "fixedColor": "#bf1b00", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted ipv4" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted ipv4 non-TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted ipv6" }, "properties": [ { "id": "color", "value": { "fixedColor": "#bf1b00", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "L7 denied request" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "L7 forwarded request" }, "properties": [ { "id": "color", "value": { "fixedColor": "#7eb26d", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e0f9d7", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "deleted" }, "properties": [ { "id": "color", "value": { "fixedColor": "#6ed0e0", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "deleted max" }, "properties": [ { "id": "color", "value": { "fixedColor": "#447ebc", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "color", "value": { "fixedColor": "#629e51", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "color", "value": { "fixedColor": "#629e51", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "custom.fillBelowTo", "value": "min" }, { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "custom.lineWidth", "value": 0 } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 12, "y": 82 }, "id": 128, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "min(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv6\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "min", "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv6\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "avg", "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv6\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "max", "refId": "C" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv6\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "deleted", "refId": "D" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv6\", protocol=\"TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "deleted max", "refId": "E" } ], "title": "IPv6 Conntrack TCP", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 35, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byName", "options": "Alive ipv4" }, "properties": [ { "id": "color", "value": { "fixedColor": "#0a50a1", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv4 non-TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#f9d9f9", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv6" }, "properties": [ { "id": "color", "value": { "fixedColor": "#614d93", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv6 TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#806eb7", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv6 non-TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#614d93", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive CT entries ipv6" }, "properties": [ { "id": "color", "value": { "fixedColor": "#badff4", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted CT entries ipv4" }, "properties": [ { "id": "color", "value": { "fixedColor": "#bf1b00", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted ipv4" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted ipv4 non-TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted ipv6" }, "properties": [ { "id": "color", "value": { "fixedColor": "#bf1b00", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "L7 denied request" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "L7 forwarded request" }, "properties": [ { "id": "color", "value": { "fixedColor": "#7eb26d", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e0f9d7", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "deleted" }, "properties": [ { "id": "color", "value": { "fixedColor": "#6ed0e0", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "deleted max" }, "properties": [ { "id": "color", "value": { "fixedColor": "#447ebc", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "color", "value": { "fixedColor": "#629e51", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "color", "value": { "fixedColor": "#629e51", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "custom.fillBelowTo", "value": "min" }, { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "custom.lineWidth", "value": 0 } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 0, "y": 88 }, "id": 129, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "min(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv4\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "min", "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv4\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "avg", "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv4\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "max", "refId": "C" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv4\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "deleted", "refId": "D" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv4\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "deleted max", "refId": "E" } ], "title": "IPv4 Conntrack Non-TCP", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 35, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byName", "options": "Alive ipv4" }, "properties": [ { "id": "color", "value": { "fixedColor": "#0a50a1", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv4 non-TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#f9d9f9", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv6" }, "properties": [ { "id": "color", "value": { "fixedColor": "#614d93", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv6 TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#806eb7", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive ipv6 non-TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#614d93", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Alive CT entries ipv6" }, "properties": [ { "id": "color", "value": { "fixedColor": "#badff4", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted CT entries ipv4" }, "properties": [ { "id": "color", "value": { "fixedColor": "#bf1b00", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted ipv4" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted ipv4 non-TCP" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Deleted ipv6" }, "properties": [ { "id": "color", "value": { "fixedColor": "#bf1b00", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "L7 denied request" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "L7 forwarded request" }, "properties": [ { "id": "color", "value": { "fixedColor": "#7eb26d", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e0f9d7", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "deleted" }, "properties": [ { "id": "color", "value": { "fixedColor": "#6ed0e0", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "deleted max" }, "properties": [ { "id": "color", "value": { "fixedColor": "#447ebc", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "color", "value": { "fixedColor": "#629e51", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "color", "value": { "fixedColor": "#629e51", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "custom.fillBelowTo", "value": "min" }, { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "custom.lineWidth", "value": 0 } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 12, "y": 88 }, "id": 130, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "min(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv6\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "min", "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv6\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "avg", "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"alive\", family=\"ipv6\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "max", "refId": "C" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv6\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "deleted", "refId": "D" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_datapath_conntrack_gc_entries{k8s_app=\"cilium\", status=\"deleted\", family=\"ipv6\", protocol=\"non-TCP\", pod=~\"$pod\"}) by (family,status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "deleted max", "refId": "E" } ], "title": "IPv6 Conntrack Non-TCP", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byName", "options": "ipv4" }, "properties": [ { "id": "color", "value": { "fixedColor": "#5195ce", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "ipv6" }, "properties": [ { "id": "color", "value": { "fixedColor": "#6d1f62", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 0, "y": 94 }, "id": 87, "options": { "legend": { "calcs": [ "mean", "lastNotNull", "max", "min" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(cilium_ip_addresses{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod, family)\n", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{family}}", "refId": "A" } ], "title": "Allocated Addresses", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byName", "options": "dump_interrupts conntrack ipv4" }, "properties": [ { "id": "color", "value": { "fixedColor": "#ea6460", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "dump_interrupts conntrack ipv6" }, "properties": [ { "id": "color", "value": { "fixedColor": "#58140c", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 94 }, "id": 79, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(cilium_datapath_conntrack_dump_resets_total{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod, area, family, name)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{name}} {{area}} {{family}}", "refId": "A" } ], "title": "Datapath Conntrack Dump Resets", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 5, "w": 12, "x": 0, "y": 99 }, "id": 106, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_services_events_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, action)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}}", "refId": "A" } ], "title": "Service Updates", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [] }, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 99 }, "id": 89, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(cilium_unreachable_nodes{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "unreachable nodes", "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(cilium_unreachable_health_endpoints{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "unreachable health endpoints", "refId": "B" } ], "title": "Connectivity Health", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 5, "w": 12, "x": 0, "y": 104 }, "id": 39, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_drop_count_total{direction=\"EGRESS\", k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (reason)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{reason}}", "refId": "A" } ], "title": "Dropped Egress Packets", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 35, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "opm" }, "overrides": [ { "matcher": { "id": "byName", "options": "Avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#cca300", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Max" }, "properties": [ { "id": "color", "value": { "fixedColor": "rgb(167, 150, 111)", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Max" }, "properties": [ { "id": "custom.fillBelowTo", "value": "Min" }, { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "Min" }, "properties": [ { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "add k8s" }, "properties": [ { "id": "unit", "value": "short" } ] }, { "matcher": { "id": "byName", "options": "delete k8s" }, "properties": [ { "id": "unit", "value": "short" } ] }, { "matcher": { "id": "byName", "options": "update k8s" }, "properties": [ { "id": "unit", "value": "short" } ] }, { "matcher": { "id": "byName", "options": "add local-node" }, "properties": [ { "id": "unit", "value": "short" } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 104 }, "id": 93, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_nodes_all_events_received_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, event_type, source) * 60", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{eventType}} {{source}}", "refId": "B" } ], "title": "Node Events", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "bps" }, "overrides": [] }, "gridPos": { "h": 5, "w": 12, "x": 0, "y": 109 }, "id": 113, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_drop_bytes_total{direction=\"EGRESS\", k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (reason) * 8", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{reason}}", "refId": "A" } ], "title": "Dropped Egress Traffic", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 35, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byName", "options": "Average Nodes" }, "properties": [ { "id": "color", "value": { "fixedColor": "#eab839", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Max Nodes" }, "properties": [ { "id": "color", "value": { "fixedColor": "#c15c17", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Max Nodes" }, "properties": [ { "id": "custom.fillBelowTo", "value": "Min Nodes" }, { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "Min Nodes" }, "properties": [ { "id": "custom.lineWidth", "value": 0 } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 109 }, "id": 91, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_nodes_all_num{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "Average Nodes", "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "min(cilium_nodes_all_num{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "Min Nodes", "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_nodes_all_num{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "Max Nodes", "refId": "C" } ], "title": "Nodes", "type": "timeseries" }, { "fieldConfig": { "defaults": {}, "overrides": [] }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 114 }, "id": 28, "options": { "code": { "language": "plaintext", "showLineNumbers": false, "showMiniMap": false }, "content": "", "mode": "markdown" }, "pluginVersion": "11.3.1", "title": "Policy", "type": "text" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "reqps" }, "overrides": [ { "matcher": { "id": "byName", "options": "L7 denied request" }, "properties": [ { "id": "color", "value": { "fixedColor": "#ea6460", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "L7 forwarded request" }, "properties": [ { "id": "color", "value": { "fixedColor": "#7eb26d", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "denied" }, "properties": [ { "id": "color", "value": { "fixedColor": "#bf1b00", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 0, "y": 115 }, "id": 53, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "sum by(rule, proxy_type) (rate(cilium_policy_l7_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m]))", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{proxy_type}} - {{rule}}", "range": true, "refId": "A" } ], "title": "L7 forwarded request", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "description": "99th percentile of DNS proxy request processing latency, by span", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 34, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineStyle": { "fill": "solid" }, "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 115 }, "id": 123, "options": { "legend": { "calcs": [ "mean" ], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "histogram_quantile(0.99, sum by(scope, le) (rate(cilium_proxy_upstream_reply_seconds_bucket{protocol_l7=\"dns\", k8s_app=\"cilium\", pod=~\"$pod\", scope!=\"totalTime\"}[5m]))) \n", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{scope}}", "range": true, "refId": "B" } ], "title": "DNS proxy request latency", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "pps" }, "overrides": [] }, "gridPos": { "h": 5, "w": 12, "x": 0, "y": 120 }, "id": 114, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_drop_count_total{k8s_app=\"cilium\", pod=~\"$pod\", reason=\"Policy denied\"}[1m])) by (direction)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{direction}}", "range": true, "refId": "A" } ], "title": "Policy Denies: L3/L4", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "ops" }, "overrides": [] }, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 120 }, "id": 37, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_policy_l7_total{rule=\"denied\", k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (proxy_type)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{reason}}", "range": true, "refId": "A" } ], "title": "Policy Denies: L7", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "description": "End-to-end duration to apply incremental identity updates to the policy control and data planes.", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 35, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "s" }, "overrides": [ { "matcher": { "id": "byName", "options": "avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#64b0c8", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "count" }, "properties": [ { "id": "color", "value": { "fixedColor": "#9ac48a", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "color", "value": { "fixedColor": "#5195ce", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "color", "value": { "fixedColor": "#6ed0e0", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "custom.fillBelowTo", "value": "min" }, { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "avg count" }, "properties": [ { "id": "unit", "value": "opm" } ] }, { "matcher": { "id": "byName", "options": "max count" }, "properties": [ { "id": "unit", "value": "opm" } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 0, "y": 125 }, "id": 104, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "histogram_quantile(0.99, sum by(le) (rate(cilium_policy_incremental_update_duration_bucket{k8s_app=\"cilium\", pod=~\"$pod\"}[5m])))", "format": "time_series", "intervalFactor": 1, "legendFormat": "99%", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "histogram_quantile(0.5, sum by(le) (rate(cilium_policy_incremental_update_duration_bucket{k8s_app=\"cilium\", pod=~\"$pod\"}[5m])))", "format": "time_series", "intervalFactor": 1, "legendFormat": "50%", "range": true, "refId": "B" } ], "title": "Policy Identity Update Latency", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "description": "The time taken for new or updated network policy to be applied to all affected endpoints", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 35, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "s" }, "overrides": [ { "matcher": { "id": "byName", "options": "average duration" }, "properties": [ { "id": "color", "value": { "fixedColor": "#d683ce", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "folds" }, "properties": [ { "id": "color", "value": { "fixedColor": "#614d93", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max duration" }, "properties": [ { "id": "color", "value": { "fixedColor": "#614d93", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max trigger" }, "properties": [ { "id": "color", "value": { "fixedColor": "#967302", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "min duration" }, "properties": [ { "id": "color", "value": { "fixedColor": "#584477", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "min trigger" }, "properties": [ { "id": "color", "value": { "fixedColor": "#fceaca", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "custom.fillBelowTo", "value": "min trigger" }, { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "min trigger" }, "properties": [ { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "folds" }, "properties": [ { "id": "unit", "value": "short" } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 125 }, "id": 102, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "histogram_quantile(0.99, sum by(le) (rate(cilium_policy_implementation_delay_bucket{k8s_app=\"cilium\", pod=~\"$pod\"}[5m])))", "format": "time_series", "intervalFactor": 1, "legendFormat": "99%", "range": true, "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "histogram_quantile(0.5, sum by(le) (rate(cilium_policy_implementation_delay_bucket{k8s_app=\"cilium\", pod=~\"$pod\"}[5m]))) ", "format": "time_series", "intervalFactor": 1, "legendFormat": "50%", "range": true, "refId": "B" } ], "title": "Policy Apply Latency", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byName", "options": "both" }, "properties": [ { "id": "color", "value": { "fixedColor": "#7eb26d", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "egress" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e5ac0e", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "ingress" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e0752d", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "none" }, "properties": [ { "id": "color", "value": { "fixedColor": "#bf1b00", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 5, "w": 6, "x": 0, "y": 130 }, "id": 33, "options": { "legend": { "calcs": [ "lastNotNull" ], "displayMode": "list", "placement": "right", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(cilium_policy_endpoint_enforcement_status{k8s_app=\"cilium\", pod=~\"$pod\"}) by (enforcement)", "format": "time_series", "hide": false, "instant": true, "interval": "1s", "intervalFactor": 1, "legendFormat": "{{enforcement}}", "refId": "B" } ], "title": "Endpoints policy enforcement status", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 35, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byName", "options": "avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#b7dbab", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "color", "value": { "fixedColor": "rgba(89, 132, 76, 0.54)", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "color", "value": { "fixedColor": "#2f575e", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "custom.fillBelowTo", "value": "min" }, { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "custom.lineWidth", "value": 0 } ] } ] }, "gridPos": { "h": 5, "w": 6, "x": 6, "y": 130 }, "id": 100, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "min(cilium_proxy_redirects{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "min", "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_proxy_redirects{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "avg", "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_proxy_redirects{k8s_app=\"cilium\", pod=~\"$pod\"}) by (pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "max", "refId": "C" } ], "title": "Proxy Redirects", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "description": "Endpoint policy calculation time by stage. Shows the 99th-percentile.", "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 35, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "s" }, "overrides": [ { "matcher": { "id": "byName", "options": "avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#f9d9f9", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "color", "value": { "fixedColor": "#806eb7", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "color", "value": { "fixedColor": "#806eb7", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "custom.fillBelowTo", "value": "min" }, { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "custom.lineWidth", "value": 0 } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 130 }, "id": 117, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", "expr": "histogram_quantile(0.99, sum by(scope, le) (rate(cilium_endpoint_regeneration_time_stats_seconds_bucket{scope=~\"proxyConfiguration|endpointPolicyCalculation|selectorPolicyCalculation|proxyPolicyCalculation\",k8s_app=\"cilium\",status=\"success\",pod=~\"$pod\"}[5m])))", "format": "time_series", "intervalFactor": 1, "legendFormat": "__auto", "range": true, "refId": "A" } ], "title": "Policy Calculation Time", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 35, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "color", "value": { "fixedColor": "#f2c96d", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "policy change errors" }, "properties": [ { "id": "color", "value": { "fixedColor": "#bf1b00", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "policy errors" }, "properties": [ { "id": "color", "value": { "fixedColor": "#bf1b00", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "max" }, "properties": [ { "id": "custom.fillBelowTo", "value": "min" }, { "id": "custom.lineWidth", "value": 0 } ] }, { "matcher": { "id": "byName", "options": "min" }, "properties": [ { "id": "custom.lineWidth", "value": 0 } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 0, "y": 135 }, "id": 85, "options": { "legend": { "calcs": [ "lastNotNull" ], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "min(cilium_policy{k8s_app=\"cilium\", pod=~\"$pod\"}) by(pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "min", "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(cilium_policy{k8s_app=\"cilium\", pod=~\"$pod\"}) by(pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "avg", "refId": "B" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(cilium_policy{k8s_app=\"cilium\", pod=~\"$pod\"}) by(pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "max", "refId": "C" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(cilium_policy_change_total{k8s_app=\"cilium\", pod=~\"$pod\", outcome=\"fail\"}) by (pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "policy change errors", "refId": "D" } ], "title": "Policies Per Node", "type": "timeseries" }, { "fieldConfig": { "defaults": {}, "overrides": [] }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 140 }, "id": 73, "options": { "code": { "language": "plaintext", "showLineNumbers": false, "showMiniMap": false }, "content": "", "mode": "markdown" }, "pluginVersion": "11.3.1", "title": "Endpoints", "type": "text" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 141 }, "id": 55, "options": { "legend": { "calcs": [ "mean" ], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(histogram_quantile(0.90, rate(cilium_endpoint_regeneration_time_stats_seconds_bucket{k8s_app=\"cilium\", scope!=\"total\", pod=~\"$pod\"}[5m]))) by (scope)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{scope}}", "refId": "A" } ], "title": "Endpoint regeneration time (90th percentile)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "s" }, "overrides": [] }, "gridPos": { "h": 9, "w": 12, "x": 12, "y": 141 }, "id": 115, "options": { "legend": { "calcs": [ "mean" ], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(histogram_quantile(0.99, rate(cilium_endpoint_regeneration_time_stats_seconds_bucket{k8s_app=\"cilium\", scope!=\"total\", pod=~\"$pod\"}[5m]))) by (scope)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{scope}}", "refId": "A" } ], "title": "Endpoint regeneration time (99th percentile)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 2, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "opm" }, "overrides": [ { "matcher": { "id": "byName", "options": "fail" }, "properties": [ { "id": "color", "value": { "fixedColor": "#bf1b00", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "fail/min" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "success" }, "properties": [ { "id": "color", "value": { "fixedColor": "#447ebc", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "success/min" }, "properties": [ { "id": "color", "value": { "fixedColor": "#3f6833", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 0, "y": 150 }, "id": 49, "options": { "legend": { "calcs": [ "mean", "max" ], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_endpoint_regenerations_total{k8s_app=\"cilium\", pod=~\"$pod\"}[30s])) by(outcome)", "format": "time_series", "instant": false, "intervalFactor": 1, "legendFormat": "{{outcome}}", "refId": "A" } ], "title": "Endpoint regenerations", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 2, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": true, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byName", "options": "disconnecting" }, "properties": [ { "id": "color", "value": { "fixedColor": "#614d93", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "ready" }, "properties": [ { "id": "color", "value": { "fixedColor": "rgba(81, 220, 95, 0.52)", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "waiting-to-regenerate" }, "properties": [ { "id": "color", "value": { "fixedColor": "#0a50a1", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 150 }, "id": 51, "options": { "legend": { "calcs": [ "lastNotNull" ], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "single", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(cilium_endpoint_state{k8s_app=\"cilium\", pod=~\"$pod\"}) by (endpoint_state)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{endpoint_state}}", "refId": "A" } ], "title": "Cilium endpoint state", "type": "timeseries" }, { "fieldConfig": { "defaults": {}, "overrides": [] }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 155 }, "id": 74, "options": { "code": { "language": "plaintext", "showLineNumbers": false, "showMiniMap": false }, "content": "", "mode": "markdown" }, "pluginVersion": "11.3.1", "title": "Controllers", "type": "text" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 30, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "opm" }, "overrides": [ { "matcher": { "id": "byName", "options": "Failed" }, "properties": [ { "id": "color", "value": { "fixedColor": "#bf1b00", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Failing" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "Runs" }, "properties": [ { "id": "color", "value": { "fixedColor": "#5195ce", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 0, "y": 156 }, "id": 70, "options": { "legend": { "calcs": [ "mean", "max" ], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_controllers_runs_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "Runs", "refId": "A" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(cilium_controllers_failing{k8s_app=\"cilium\", pod=~\"$pod\"}) by(pod)", "format": "time_series", "intervalFactor": 1, "legendFormat": "Failed", "refId": "B" } ], "title": "Controllers", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "s" }, "overrides": [ { "matcher": { "id": "byName", "options": "duration failure" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "duration success" }, "properties": [ { "id": "color", "value": { "fixedColor": "#508642", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "failure" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "runs failure" }, "properties": [ { "id": "color", "value": { "fixedColor": "#890f02", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "runs success" }, "properties": [ { "id": "color", "value": { "fixedColor": "#7eb26d", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "success" }, "properties": [ { "id": "color", "value": { "fixedColor": "#508642", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 156 }, "id": 68, "options": { "legend": { "calcs": [ "mean", "max", "min" ], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_controllers_runs_duration_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, status) / sum(rate(cilium_controllers_runs_duration_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{status}}", "refId": "A" } ], "title": "Controller Durations", "type": "timeseries" }, { "fieldConfig": { "defaults": {}, "overrides": [] }, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 161 }, "id": 60, "options": { "code": { "language": "plaintext", "showLineNumbers": false, "showMiniMap": false }, "content": "", "mode": "markdown" }, "pluginVersion": "11.3.1", "title": "Kubernetes integration", "type": "text" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "s" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 162 }, "id": 163, "options": { "legend": { "calcs": [], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_k8s_client_api_latency_time_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])/rate(cilium_k8s_client_api_latency_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{method}} {{path}}", "refId": "A" } ], "title": "apiserver latency (average node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 10, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "s" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 162 }, "id": 165, "options": { "legend": { "calcs": [], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "max(rate(cilium_k8s_client_api_latency_time_seconds_sum{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])/rate(cilium_k8s_client_api_latency_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{method}} {{path}}", "refId": "A" } ], "title": "apiserver latency (max node)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 169 }, "id": 168, "options": { "legend": { "calcs": [ "mean", "max" ], "displayMode": "table", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_k8s_client_api_latency_time_seconds_count{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, path)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{method}} {{path}}", "refId": "A" } ], "title": "apiserver #calls (sum all nodes)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 169 }, "id": 166, "options": { "legend": { "calcs": [ "max" ], "displayMode": "table", "placement": "right", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_k8s_client_api_calls_total{k8s_app=\"cilium\", pod=~\"$pod\"}[1m])) by (pod, method, return_code)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{method}} {{return_code}}", "refId": "A" } ], "title": "apiserver calls (sum all nodes)", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 0, "y": 177 }, "id": 172, "options": { "legend": { "calcs": [ "mean" ], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_kubernetes_events_received_total{k8s_app=\"cilium\", equal=\"true\", valid=\"true\", pod=~\"$pod\"}[5m])) by (pod, scope, action)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}} {{scope}}", "refId": "A" } ], "title": "Valid, Unnecessary K8s Events Received", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "short" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 6, "w": 12, "x": 12, "y": 177 }, "id": 174, "options": { "legend": { "calcs": [ "mean" ], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_kubernetes_events_received_total{k8s_app=\"cilium\", equal=\"true\", valid=\"false\", pod=~\"$pod\"}[5m])) by (pod, scope, action)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}} {{scope}}", "refId": "A" } ], "title": "Invalid, Unnecessary K8s Events Received", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 183 }, "id": 175, "options": { "legend": { "calcs": [ "mean" ], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_kubernetes_events_received_total{k8s_app=\"cilium\", equal=\"false\", valid=\"true\", pod=~\"$pod\"}[5m])) by (pod, scope, action, valid)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}} {{scope}}", "refId": "A" } ], "title": "Valid, Necessary K8s Events Received", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "ops" }, "overrides": [ { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsZero", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] }, { "matcher": { "id": "byValue", "options": { "op": "gte", "reducer": "allIsNull", "value": 0 } }, "properties": [ { "id": "custom.hideFrom", "value": { "legend": true, "tooltip": true, "viz": false } } ] } ] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 183 }, "id": 173, "options": { "legend": { "calcs": [ "mean" ], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "sum(rate(cilium_kubernetes_events_received_total{k8s_app=\"cilium\", equal=\"false\", valid=\"false\", pod=~\"$pod\"}[5m])) by (pod, scope, action)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}} {{scope}}", "refId": "A" } ], "title": "Invalid, Necessary K8s Events Received", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "opm" }, "overrides": [] }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 191 }, "id": 108, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_kubernetes_events_total{k8s_app=\"cilium\", scope=\"CiliumNetworkPolicy\", pod=~\"$pod\"}[1m])) by (pod, action) * 60", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}} avg", "refId": "B" } ], "title": "CiliumNetworkPolicy Events", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "opm" }, "overrides": [ { "matcher": { "id": "byName", "options": "create avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#70dbed", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "delete avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e24d42", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "update avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e0f9d7", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 191 }, "id": 119, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_kubernetes_events_total{k8s_app=\"cilium\", scope=\"NetworkPolicy\", pod=~\"$pod\"}[1m])) by (pod, action) * 60", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}} avg", "refId": "B" } ], "title": "NetworkPolicy Events", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "opm" }, "overrides": [ { "matcher": { "id": "byName", "options": "create avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#70dbed", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "delete avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e24d42", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "update avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e0f9d7", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 198 }, "id": 109, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_kubernetes_events_total{k8s_app=\"cilium\", scope=\"Pod\", pod=~\"$pod\"}[1m])) by (pod, action) * 60", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}} avg", "refId": "B" } ], "title": "Pod Events", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "opm" }, "overrides": [ { "matcher": { "id": "byName", "options": "create avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#70dbed", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "delete avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e24d42", "mode": "fixed" } } ] }, { "matcher": { "id": "byName", "options": "update avg" }, "properties": [ { "id": "color", "value": { "fixedColor": "#e0f9d7", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 198 }, "id": 122, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_kubernetes_events_total{k8s_app=\"cilium\", scope=\"Node\", pod=~\"$pod\"}[1m])) by (pod, action) * 60", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}} avg", "refId": "B" } ], "title": "Node Events", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "opm" }, "overrides": [] }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 205 }, "id": 118, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_kubernetes_events_total{k8s_app=\"cilium\", scope=\"Service\", pod=~\"$pod\"}[1m])) by (pod, action) * 60", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}}", "refId": "B" } ], "title": "Service Events", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "opm" }, "overrides": [] }, "gridPos": { "h": 7, "w": 12, "x": 12, "y": 205 }, "id": 120, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_kubernetes_events_total{k8s_app=\"cilium\", scope=\"Endpoint\", pod=~\"$pod\"}[1m])) by (pod, action) * 60", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}}", "refId": "B" } ], "title": "Endpoints Events", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "bars", "fillOpacity": 100, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "never", "spanNulls": false, "stacking": { "group": "A", "mode": "normal" }, "thresholdsStyle": { "mode": "off" } }, "links": [], "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "red", "value": 80 } ] }, "unit": "opm" }, "overrides": [] }, "gridPos": { "h": 7, "w": 12, "x": 0, "y": 212 }, "id": 121, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "none" } }, "pluginVersion": "11.3.1", "targets": [ { "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "expr": "avg(rate(cilium_kubernetes_events_total{k8s_app=\"cilium\", scope=\"Namespace\", pod=~\"$pod\"}[1m])) by (pod, action) * 60", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{action}}", "refId": "B" } ], "title": "Namespace Events", "type": "timeseries" } ], "preload": false, "refresh": "", "schemaVersion": 40, "tags": [], "templating": { "list": [ { "current": {}, "includeAll": false, "label": "Prometheus", "name": "DS_PROMETHEUS", "options": [], "query": "prometheus", "refresh": 1, "regex": "", "type": "datasource" }, { "allValue": "cilium.*", "current": { "text": "All", "value": "$__all" }, "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "definition": "label_values(cilium_version, pod)", "includeAll": true, "name": "pod", "options": [], "query": "label_values(cilium_version, pod)", "refresh": 2, "regex": "", "sort": 1, "type": "query" } ] }, "time": { "from": "now-30m", "to": "now" }, "timepicker": { "refresh_intervals": [ "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d" ] }, "timezone": "utc", "title": "Cilium Metrics", "uid": "vtuWtdumz", "version": 1, "weekStart": "" } kind: ConfigMap metadata: annotations: grafana_folder: kube-system meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cilium-agent app.kubernetes.io/part-of: cilium grafana_dashboard: "1" k8s-app: cilium name: cilium-dashboard namespace: kube-system --- apiVersion: v1 data: cilium-operator-dashboard.json: | { "__inputs": [ { "name": "DS_PROMETHEUS", "label": "prometheus", "description": "", "type": "datasource", "pluginId": "prometheus", "pluginName": "Prometheus" } ], "annotations": { "list": [ { "builtIn": 1, "datasource": { "type": "datasource", "uid": "grafana" }, "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" } ] }, "editable": true, "gnetId": null, "graphTooltip": 0, "id": 8, "links": [], "panels": [ { "aliasColors": { "avg": "#cffaff" }, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 0, "fillGradient": 0, "gridPos": { "h": 5, "w": 12, "x": 0, "y": 0 }, "hiddenSeries": false, "id": 24, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "nullPointMode": "null", "options": { "dataLinks": [] }, "paceLength": 10, "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", "seriesOverrides": [ { "alias": "max", "fillBelowTo": "min", "lines": false }, { "alias": "min", "lines": false } ], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "min(irate(cilium_operator_process_cpu_seconds_total{io_cilium_app=\"operator\"}[1m])) by (pod) * 100", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "min", "refId": "A" }, { "expr": "avg(irate(cilium_operator_process_cpu_seconds_total{io_cilium_app=\"operator\"}[1m])) by (pod) * 100", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "avg", "refId": "B" }, { "expr": "max(irate(cilium_operator_process_cpu_seconds_total{io_cilium_app=\"operator\"}[1m])) by (pod) * 100", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "max", "refId": "C" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "CPU Usage per node", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "percent", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": { "MAX_resident_memory_bytes_max": "#e5ac0e" }, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 5, "w": 12, "x": 12, "y": 0 }, "hiddenSeries": false, "id": 26, "legend": { "alignAsTable": false, "avg": false, "current": false, "max": false, "min": false, "rightSide": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "nullPointMode": "null", "options": { "dataLinks": [] }, "paceLength": 10, "percentage": false, "pointradius": 5, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "avg(cilium_operator_process_resident_memory_bytes{io_cilium_app=\"operator\"})", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "AVG_resident_memory_bytes", "refId": "C" }, { "expr": "max(cilium_operator_process_resident_memory_bytes{io_cilium_app=\"operator\"})", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "MAX_resident_memory_bytes_max", "refId": "D" }, { "expr": "min(cilium_operator_process_resident_memory_bytes{io_cilium_app=\"operator\"})", "format": "time_series", "interval": "", "intervalFactor": 1, "legendFormat": "MIN_resident_memory_bytes_min", "refId": "E" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Resident memory status", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "bytes", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "collapsed": false, "datasource": null, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 5 }, "id": 6, "panels": [], "title": "IPAM", "type": "row" }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 6 }, "hiddenSeries": false, "id": 8, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "nullPointMode": "null", "options": { "dataLinks": [] }, "paceLength": 10, "percentage": false, "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "expr": "avg(cilium_operator_ipam_ips) by (type)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{type}}", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "IP Addresses", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 6 }, "hiddenSeries": false, "id": 10, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "nullPointMode": "null", "options": { "dataLinks": [] }, "paceLength": 10, "percentage": false, "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "rate(cilium_operator_ec2_api_duration_seconds_sum[1m])/rate(cilium_operator_ec2_api_duration_seconds_count[1m])", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{operation}} {{response_code}}", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "EC2 API Interactions", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "dtdurations", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 7, "w": 8, "x": 0, "y": 14 }, "hiddenSeries": false, "id": 4, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "nullPointMode": "null", "options": { "dataLinks": [] }, "paceLength": 10, "percentage": false, "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "cilium_operator_ipam_nodes", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{category}}", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Number of nodes", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 7, "w": 8, "x": 8, "y": 14 }, "hiddenSeries": false, "id": 12, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "nullPointMode": "null", "options": { "dataLinks": [] }, "paceLength": 10, "percentage": false, "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "cilium_operator_ipam_available", "format": "time_series", "intervalFactor": 1, "legendFormat": "interfaces", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "# interfaces with addresses available", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 7, "w": 8, "x": 16, "y": 14 }, "hiddenSeries": false, "id": 16, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "nullPointMode": "null", "options": { "dataLinks": [] }, "paceLength": 10, "percentage": false, "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "rate(cilium_operator_ipam_resync_total[1m])", "format": "time_series", "intervalFactor": 1, "legendFormat": "operations", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Metadata Resync Operations", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "ops", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 21 }, "hiddenSeries": false, "id": 14, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "nullPointMode": "null", "options": { "dataLinks": [] }, "paceLength": 10, "percentage": false, "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": true, "steppedLine": false, "targets": [ { "expr": "rate(cilium_operator_ec2_api_rate_limit_duration_seconds_sum[1m])/rate(cilium_operator_ec2_api_rate_limit_duration_seconds_count[1m])", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{operation}}", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "EC2 client side rate limiting", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "reqps", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 21 }, "hiddenSeries": false, "id": 2, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "links": [], "nullPointMode": "null", "options": { "dataLinks": [] }, "paceLength": 10, "percentage": false, "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "avg(rate(cilium_operator_ipam_interface_creation_ops[1m])) by (subnetId, status)", "format": "time_series", "intervalFactor": 1, "legendFormat": "{{status}} ({{subnetId}})", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Interface Creation", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "ops", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } } ], "refresh": false, "schemaVersion": 25, "style": "dark", "tags": [], "templating": { "list": [ { "type": "datasource", "name": "DS_PROMETHEUS", "query": "prometheus" } ] }, "time": { "from": "now-30m", "to": "now" }, "timepicker": { "refresh_intervals": [ "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d" ], "time_options": [ "5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d" ] }, "timezone": "", "title": "Cilium Operator", "uid": "1GC0TT4Wz", "version": 2 } kind: ConfigMap metadata: annotations: grafana_folder: kube-system meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cilium-operator app.kubernetes.io/part-of: cilium grafana_dashboard: "1" k8s-app: cilium name: cilium-operator-dashboard namespace: kube-system --- apiVersion: v1 data: config.yaml: "cluster-name: default\npeer-service: \"hubble-peer.kube-system.svc.cluster.local.:443\"\nlisten-address: :4245\ngops: true\ngops-port: \"9893\"\nretry-timeout: \nsort-buffer-len-max: \nsort-buffer-drain-timeout: \ntls-hubble-client-cert-file: /var/lib/hubble-relay/tls/client.crt\ntls-hubble-client-key-file: /var/lib/hubble-relay/tls/client.key\ntls-hubble-server-ca-files: /var/lib/hubble-relay/tls/hubble-server-ca.crt\n\ndisable-server-tls: true\n" kind: ConfigMap metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm name: hubble-relay-config namespace: kube-system --- apiVersion: v1 data: nginx.conf: |- server { listen 8081; listen [::]:8081; server_name localhost; root /app; index index.html; client_max_body_size 1G; location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; location /api { proxy_http_version 1.1; proxy_pass_request_headers on; proxy_pass http://127.0.0.1:8090; } location / { if ($http_user_agent ~* "kube-probe") { access_log off; } # double `/index.html` is required here try_files $uri $uri/ /index.html /index.html; } # Liveness probe location /healthz { access_log off; add_header Content-Type text/plain; return 200 'ok'; } } } kind: ConfigMap metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm name: hubble-ui-nginx namespace: kube-system --- apiVersion: v1 data: ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURFekNDQWZ1Z0F3SUJBZ0lRR05WSERhd1ZsVU5TajJYOGx6dWZtekFOQmdrcWhraUc5dzBCQVFzRkFEQVUKTVJJd0VBWURWUVFERXdsRGFXeHBkVzBnUTBFd0hoY05NalV4TURJek1ESTFNakUxV2hjTk1qZ3hNREl5TURJMQpNakUxV2pBVU1SSXdFQVlEVlFRREV3bERhV3hwZFcwZ1EwRXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ2dpMG1FZ3pQVk5NRXAxUVMzZDl0bzBPTkZPMndpK1RYa28zcEFFNDJsQ2NGNWlWM3QKUnB2N3BlWHRMN05CU2NsTkRDSHNiRHNKQm9kRWU3N3BUbkNGcWNkZXgyUk1aV3B4Vmk4akd5V2FrdTdLdTFiRwoyRmFJcDM4RnZFQnNVRk1uY3RpMTBaMFJFYnNkUWJYcXZqRk0wQ0xxWmVPZlVGQ1pSU0VXWndOWjhraEg2V2J2CkhsSkExNjRjbjYydlNHY0htVDA2bk5FZjJ2dUFUZmhyYnZqYWdSQjFMK1dwbHRPNGlNUjVYU3UyVTNSMFB0Y0YKQ3JhNTlCdTN0K0lUc2c4dGMwaHRpc0gySjI4dWNWNndDMUtNQ3JPUWhwNUwzc3RXeTBoS01KT3RYclVXd1R0OApoUHBWREhBR0RxeHBoai9HUzVjRWdWNTlFM1pBeVRWMXpudlZBZ01CQUFHallUQmZNQTRHQTFVZER3RUIvd1FFCkF3SUNwREFkQmdOVkhTVUVGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUQVFIL0JBVXcKQXdFQi96QWRCZ05WSFE0RUZnUVVCT04rOWY0NHExRk9MUmdnV3VTWTdLdEFOaUV3RFFZSktvWklodmNOQVFFTApCUUFEZ2dFQkFFU2xRTWs4blMvVWpnOURlVnNaT21ZRnJsQUFpK3NuN21JZ2x4eFJJWFRjamVOMkR6QUZjSW9pCktXcC9wajlKdmhFdHJ3b29KUkJSUCtzUnp3MjEwS3Z3ZlpJV1BZRU85MGREb2d0N2U2bTh6TFN3V0xDQ2EwWVgKK29sVjhMdHJOdjZXTElBVExpZWxQNDErZlVvSVJnZ0VGaitIcklUU1EzYjQ0Nng1UUZVa2pyYnprdmowMHNXaAoxeXBha21OWENlZFI1UEZKK3p0a05jL2VZQlU4MURGN0QxYW9jOVMwSXlRdkloa1Z1dHg3VzNIQUh4K2ZCUVJkClBBcGpvcGp5QzNhbTJMRHJUbFVJeU1hZWFZaUtvZGo5aFZuYzZKa3RrNXAwZFRsVnJZeU9nMnlsM2VVakI1ZDIKUmhQZ3lxTnU3R0xKenZmZzFoNHpkbGpZZ3pYcXo0VT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= ca.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBb0l0SmhJTXoxVFRCS2RVRXQzZmJhTkRqUlR0c0l2azE1S042UUJPTnBRbkJlWWxkCjdVYWIrNlhsN1MrelFVbkpUUXdoN0d3N0NRYUhSSHUrNlU1d2hhbkhYc2RrVEdWcWNWWXZJeHNsbXBMdXlydFcKeHRoV2lLZC9CYnhBYkZCVEozTFl0ZEdkRVJHN0hVRzE2cjR4VE5BaTZtWGpuMUJRbVVVaEZtY0RXZkpJUitsbQo3eDVTUU5ldUhKK3RyMGhuQjVrOU9welJIOXI3Z0UzNGEyNzQyb0VRZFMvbHFaYlR1SWpFZVYwcnRsTjBkRDdYCkJRcTJ1ZlFidDdmaUU3SVBMWE5JYllyQjlpZHZMbkZlc0F0U2pBcXprSWFlUzk3TFZzdElTakNUclY2MUZzRTcKZklUNlZReHdCZzZzYVlZL3hrdVhCSUZlZlJOMlFNazFkYzU3MVFJREFRQUJBb0lCQUFuSnBDQkhqWFBzcFBBagpkQWVwYjM5NjZMZ3lVTHZySEoyRlYvRXJJQUlWVDYzVXNaekRKc1JYVDJhLzl6bytRTjhKSTlKUm9PSENlNkd4CnQ2aHFwMUtHME1oVytLYnRzZWtaKzRLMDUzeCtnNzlwWDNkOC9mMlQxSnNwYUhZU0NaZkltU3l3akZaYmtlQk4KUHNXQ2RlZjhjbngrM0xzOFBzV3hZTHlJYUR4bC84QmgySFBFSFRsVEhVUzNMMkRXZGcybE1abjhaV1pCdVUycApET1pWVnB6WWlub3B1ekpJeFRvYk1TeDlMeFJGNVVDYnQ4MW0xRVNsT3R4YkEyTnRXSm9GQWs4VGhITnN3ZEFRCmU3dkt3NWdoKzYwbHhid2VjS1ViMjZGWnNSQzlOZXVFSy9TT1VTQ2ZGcURKU3o3eEkyWGthQVVncGZsbWFaM0IKOTRoREpaRUNnWUVBMVk0YnF3SzEvcVVSNC80NkhqdHJuSHVJRXRqY2dxaEpRamU1aVA1T1gxN0RWamsyU2pPOApSL2ZNTm9lMWhQUGZ6NmNlNC9JMmczS1dzTjVsWjVtMjhta3hWbmlITmRkNEcvQXhRdnFWeUZrS2d3bHFsd2FMCktIeVJwVWMxaFZLYmgxMDdSN3Fxd3N5ZTAwMlZaMnpDb055TDJzZXBvam5QM0xiNWhLazBQRTBDZ1lFQXdIUHQKUktWcFVnSzIrNkFVNHpteC8zN3l6OFc4WDVpMytJL213NWVuN0ZsSzQ3MXJXQjZmSm42dTlBZitQWTVVcWN4MApOY1BSMFpvK0JZdWtramdSVi9JZ1NVZ29sRXJ5QWt5dUFUcTZyazk1ejRPbkl1ekVsQXgxSE1Scyswd3JGK1RFCkdwbzAxY3QvY0xZTFFYTENvMHpSSXZGclNYRkdhdnFqQzd3ZjRha0NnWUJkYW5oMzZndXFoSks2NU82UFl2YkQKME5YSlNNdk02OGlBQ3RoQ01Od2ZvOWhXMDFnSVJYRkxHZjVlckNhZkxmN3RXdkdNVE52RHpGQld0akl0aTNRWAp2aVF5Nnk1YVF4THJSYnFHemc3UFFRUDBKaDVXU2lwOVgyQm1xQ3VsVW1sdVlUNFpObktVRytZdUVIWVdjK0QvCmRQcElqYWFLckRkZEdUMDA1cjlPMFFLQmdRQ3dIMmRjRXlTM2NOU1Vvb043RHluZWNBYzJMZmVlWk55NEZMbFMKOWs4dTlPaWNVcFVTSjdQdVByRk5rcU1SSWxoSXJGc05lUTlqaW95SDlxdTlSS0phb2JMNlhaY0ZYekRxK2RHawpQbUxwY3NJL0xuU2VlWi9NL1RtUUFoTGFSM0tJZzBzVUxWdDg3S2JNTjAxRnNBaC8rYVRMSGJUWm1WaWdQbzlJCkJmb0hRUUtCZ0UyaktBQVhXbi85bHhnZGh3aC9sRzBBYXIrSlErZVhVYW9nTFgveGJWeG5xQk5iMUFwYzhQRU4Ka09sUGJqKzlvQSthenpQaW9FY1F0bUpLR1p2VEp4K3FqUG9OdDZ3NUZhTzNJK1pvMzNwUlIxZkFqS3hGMDV2OApsV2huNG5kZWE5anpNKy9lOEJITGVaMG0vYkxoOWwzay9VckFNUGxGMDJCcDV1VTh6RFNqCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== kind: Secret metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm name: cilium-ca namespace: kube-system --- apiVersion: v1 data: ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURFekNDQWZ1Z0F3SUJBZ0lRR05WSERhd1ZsVU5TajJYOGx6dWZtekFOQmdrcWhraUc5dzBCQVFzRkFEQVUKTVJJd0VBWURWUVFERXdsRGFXeHBkVzBnUTBFd0hoY05NalV4TURJek1ESTFNakUxV2hjTk1qZ3hNREl5TURJMQpNakUxV2pBVU1SSXdFQVlEVlFRREV3bERhV3hwZFcwZ1EwRXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ2dpMG1FZ3pQVk5NRXAxUVMzZDl0bzBPTkZPMndpK1RYa28zcEFFNDJsQ2NGNWlWM3QKUnB2N3BlWHRMN05CU2NsTkRDSHNiRHNKQm9kRWU3N3BUbkNGcWNkZXgyUk1aV3B4Vmk4akd5V2FrdTdLdTFiRwoyRmFJcDM4RnZFQnNVRk1uY3RpMTBaMFJFYnNkUWJYcXZqRk0wQ0xxWmVPZlVGQ1pSU0VXWndOWjhraEg2V2J2CkhsSkExNjRjbjYydlNHY0htVDA2bk5FZjJ2dUFUZmhyYnZqYWdSQjFMK1dwbHRPNGlNUjVYU3UyVTNSMFB0Y0YKQ3JhNTlCdTN0K0lUc2c4dGMwaHRpc0gySjI4dWNWNndDMUtNQ3JPUWhwNUwzc3RXeTBoS01KT3RYclVXd1R0OApoUHBWREhBR0RxeHBoai9HUzVjRWdWNTlFM1pBeVRWMXpudlZBZ01CQUFHallUQmZNQTRHQTFVZER3RUIvd1FFCkF3SUNwREFkQmdOVkhTVUVGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUQVFIL0JBVXcKQXdFQi96QWRCZ05WSFE0RUZnUVVCT04rOWY0NHExRk9MUmdnV3VTWTdLdEFOaUV3RFFZSktvWklodmNOQVFFTApCUUFEZ2dFQkFFU2xRTWs4blMvVWpnOURlVnNaT21ZRnJsQUFpK3NuN21JZ2x4eFJJWFRjamVOMkR6QUZjSW9pCktXcC9wajlKdmhFdHJ3b29KUkJSUCtzUnp3MjEwS3Z3ZlpJV1BZRU85MGREb2d0N2U2bTh6TFN3V0xDQ2EwWVgKK29sVjhMdHJOdjZXTElBVExpZWxQNDErZlVvSVJnZ0VGaitIcklUU1EzYjQ0Nng1UUZVa2pyYnprdmowMHNXaAoxeXBha21OWENlZFI1UEZKK3p0a05jL2VZQlU4MURGN0QxYW9jOVMwSXlRdkloa1Z1dHg3VzNIQUh4K2ZCUVJkClBBcGpvcGp5QzNhbTJMRHJUbFVJeU1hZWFZaUtvZGo5aFZuYzZKa3RrNXAwZFRsVnJZeU9nMnlsM2VVakI1ZDIKUmhQZ3lxTnU3R0xKenZmZzFoNHpkbGpZZ3pYcXo0VT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURTVENDQWpHZ0F3SUJBZ0lSQUp0Rm03REQwby9ZcFVIVDNyRUszbmN3RFFZSktvWklodmNOQVFFTEJRQXcKRkRFU01CQUdBMVVFQXhNSlEybHNhWFZ0SUVOQk1CNFhEVEkxTVRBeU16QXlOVEl4TlZvWERUSTJNVEF5TXpBeQpOVEl4TlZvd0l6RWhNQjhHQTFVRUF3d1lLaTVvZFdKaWJHVXRjbVZzWVhrdVkybHNhWFZ0TG1sdk1JSUJJakFOCkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXZLTUFKZmt2dmhuMjZ3VXlpT1VUU3RIeFNxaVIKQkJsNlRBOHpBNHZVdk9XVGh5dGF5bGhjU2ZZZFBCemQ3SzkwdWFtdXhQNU1ZT3ltMHZaYlcxMVFnTE5rNDZtTgppM1Z2SVBwSEZyZ2lDeXM2ME1QY1Rra2QxVEZUT2FIWVJyeURIQU5SSzM5WVBjeWJ6ajlEc203NE9LeHRVTVlPCjdvYkphS2ZWbHZNSWMrUVJZTDNMdHQwMUcrOGpoRXFzM3ljbkRPRDU1SGVjMmlGZm5MQkpVendxR1FHVG55K3oKQ3NETG9OdlQ5Y0VDRXVMbjAwVkVaTGNjclUxdFROVDB1NzVUcnQ5STFWa3N1Q3lqYWlRZlRxblhNbEdDdHZjNgpKYXlPdW8xaWREYTNyanlEbEtUVE9mbjRNaXhwTmM3bHhpS3VUMURCakQ4WmhOa1h6ekh6UlZxOWxRSURBUUFCCm80R0dNSUdETUE0R0ExVWREd0VCL3dRRUF3SUZvREFkQmdOVkhTVUVGakFVQmdnckJnRUZCUWNEQVFZSUt3WUIKQlFVSEF3SXdEQVlEVlIwVEFRSC9CQUl3QURBZkJnTlZIU01FR0RBV2dCUUU0MzcxL2ppclVVNHRHQ0JhNUpqcwpxMEEySVRBakJnTlZIUkVFSERBYWdoZ3FMbWgxWW1Kc1pTMXlaV3hoZVM1amFXeHBkVzB1YVc4d0RRWUpLb1pJCmh2Y05BUUVMQlFBRGdnRUJBQ3lkNnA0YjYyd1U0WkQxNmtJRjhhM3owRXZyak9OTDAxaHFucWRtVW5QdTNwenYKRGpGQ2FKYm1iMkljWUpKc09rQTJRQVg5UnUvTGR4RHdMQlUzalk4dXFvazBOVFZySzRBcktQVGx2ZUlYcW9UYwpWSFovY1ZpREFRMFRLbjlEc0FWVjZvVWFxMXkxTFYrV2VXWWVuSWRCR0ZFT3JGVGQxVkE5R2pUd2pscGtoWXpZCks4OUl0V2JOdFQ4YnUvbEljeGJFMjZmT29HUlEvaWxLSDdBVzdBOEwwemY1Rk9xRlVqbHBPeVluMmlLSHdNVU8KWVlrVThVcUNEbmFRWmJCTXQ4cnVoRjRqUmRmVjFMamMyRDI0YnpMcFlQRlZIblAxaUNCTXpBdFAwdjJMczdUMAp5dXc4UFlGZ01FQXZqdFNtcW53WllEN0tMV2s3MU9VUXY4VWNDTzg9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdktNQUpma3Z2aG4yNndVeWlPVVRTdEh4U3FpUkJCbDZUQTh6QTR2VXZPV1RoeXRhCnlsaGNTZllkUEJ6ZDdLOTB1YW11eFA1TVlPeW0wdlpiVzExUWdMTms0Nm1OaTNWdklQcEhGcmdpQ3lzNjBNUGMKVGtrZDFURlRPYUhZUnJ5REhBTlJLMzlZUGN5YnpqOURzbTc0T0t4dFVNWU83b2JKYUtmVmx2TUljK1FSWUwzTAp0dDAxRys4amhFcXMzeWNuRE9ENTVIZWMyaUZmbkxCSlV6d3FHUUdUbnkrekNzRExvTnZUOWNFQ0V1TG4wMFZFClpMY2NyVTF0VE5UMHU3NVRydDlJMVZrc3VDeWphaVFmVHFuWE1sR0N0dmM2SmF5T3VvMWlkRGEzcmp5RGxLVFQKT2ZuNE1peHBOYzdseGlLdVQxREJqRDhaaE5rWHp6SHpSVnE5bFFJREFRQUJBb0lCQUZkK3k0elJmaUdRN1lTcApUbjFNczV3YXNPN09MU1ZYby9BdmhKdjZlZHg4Sitla1ptSkFoZDRRZUJMdjJNZjF3aEJ6OGdxUllWLzdwSTFwCms0cFhTQVhLTDl1aFEzUVNMazkvaHdXMHRxV3prWDVQdXBuZE5DYzB6OE9GbkVtREd0VWRmTUxPT0dIQnkrcm8KVVVBc1ZKb0U4RmRzNW5RZ3RMOEVTZi9RRG5XaDRKNzg1NDF1dTM1akE0aEEzZ3pTVnZ3R1duUStUTzN1T3IrbwpKZ2d3SWM0Z1ljT0FMa1dzTldqRCtXNHNMbzhxY1lnV2RhaEhSRUNMeVFqazd2WVhzUG5TbXdJUFNwZnFKRTRTCjJyejl2NTV6cGwyLzIrdm9iWHRMTHFIcTB6RjhnMGFZbXdHdWp3VVZ5em5uUUhWMEVJNjFCTlZqWldwR1Y0WS8KV0hqcnhha0NnWUVBOUpDaFk1K0ZSSXdvUlpDR1FnTlVKczFHTkFPNHR0NGRjL1hyZjI4dTlYRUdBR25vZitSRQo5UkFCTUdLcWhvOG1oN3BWU0RDcEFwRkFLb2VVWndJMXhrVnpkMVlFSFlRbnMrMWhmU0VUb3Y3SEFZR01KOWNlCkk4KzRRZWhZRmNHRlhrS241R2I0YXYvZHYwVTd3T1NXWVRRU25BR2cyWEF0SXpQVC9oak9BOHNDZ1lFQXhYVHQKQVZoQlBueGFNZjA2MHBsQnJlcHZISDllWk11SDRhRjBuaGg3cmkyRG5sdjcrdHlPQ1Z0VTNsYmNHUVZlbnNRNwpwYVBOVVlyTHJVZ0JuSnNDRE9LbE1qanMwLzA0M0h5RHhJNXVYVlN0Zzg2OWVLWHZtNjVHak1uWEpSQTAzN3RLCjlEcCtrcVBPalQzUVVNa051Vzk2cjEyMlZFL3RuSzRzYnI3LzJCOENnWUVBclZ3NGl0M3hJZjRZTGZlY3MvNlkKRUVsQ2tteHc2Mi9YZ1BPNTA4T0VqZ2RvTWJMaFZJY0RPcFAxdzg2dEFtVkc4cjlxNUpsWnRMQXh3L1FIaGwxUwpzUkZhSUNXaEZTc3cyYUpUa05kNWkvaitLRnNrZHJsT2JDUTZnTDJxY3dHVEFKWlBYT0NCQjVnSUlDVjdqZWg3CmtMdlExVFZ5UjYvMHp4ZFdGckNPbUxFQ2dZQUszdDBOYmVacG9qNzA4WlFEZEJ5QmpwNS9XeU8vT05WS1ByRkUKNHVRc09xVThXcVFNczRlK1RDRG4vTEF4VUhKZEcwQ05aZTh2eGd4Z2hjNVE2TmU4RGQ0NlhaZnNNOHlsbHRWSwpSTzBlaGtMbk5zS0htZHNQSHhFVFB5bHhDT3RnUmRkaWlyWGRMTmQ2UHlUd3phREx6SzljYURSWmYrejg2em5XCi92em0wUUtCZ1FEZjljNlNtc1VHcGJYQTNHZ2xDQnBOUjIwK2dKVDBpUk1WdDVLcUtlNGxWUzF1aC9GUUJKcFYKbUxGUmQwR2ppakxPWG5TNEZxZ2R3OHd0Sm9UVnljUWpBbmowaXFLMG1MTklHdTJRNlpSQ291cWYxTlRudysyMwpWcDhwTit2ZWpKdGFEQnR1NnlzcVkvVE9wcm1ramc2ZGZvTDRRMVdua2Z2ZDh3T3NFWnRzK1E9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= kind: Secret metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm name: hubble-relay-client-certs namespace: kube-system type: kubernetes.io/tls --- apiVersion: v1 data: ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURFekNDQWZ1Z0F3SUJBZ0lRR05WSERhd1ZsVU5TajJYOGx6dWZtekFOQmdrcWhraUc5dzBCQVFzRkFEQVUKTVJJd0VBWURWUVFERXdsRGFXeHBkVzBnUTBFd0hoY05NalV4TURJek1ESTFNakUxV2hjTk1qZ3hNREl5TURJMQpNakUxV2pBVU1SSXdFQVlEVlFRREV3bERhV3hwZFcwZ1EwRXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRQ2dpMG1FZ3pQVk5NRXAxUVMzZDl0bzBPTkZPMndpK1RYa28zcEFFNDJsQ2NGNWlWM3QKUnB2N3BlWHRMN05CU2NsTkRDSHNiRHNKQm9kRWU3N3BUbkNGcWNkZXgyUk1aV3B4Vmk4akd5V2FrdTdLdTFiRwoyRmFJcDM4RnZFQnNVRk1uY3RpMTBaMFJFYnNkUWJYcXZqRk0wQ0xxWmVPZlVGQ1pSU0VXWndOWjhraEg2V2J2CkhsSkExNjRjbjYydlNHY0htVDA2bk5FZjJ2dUFUZmhyYnZqYWdSQjFMK1dwbHRPNGlNUjVYU3UyVTNSMFB0Y0YKQ3JhNTlCdTN0K0lUc2c4dGMwaHRpc0gySjI4dWNWNndDMUtNQ3JPUWhwNUwzc3RXeTBoS01KT3RYclVXd1R0OApoUHBWREhBR0RxeHBoai9HUzVjRWdWNTlFM1pBeVRWMXpudlZBZ01CQUFHallUQmZNQTRHQTFVZER3RUIvd1FFCkF3SUNwREFkQmdOVkhTVUVGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUQVFIL0JBVXcKQXdFQi96QWRCZ05WSFE0RUZnUVVCT04rOWY0NHExRk9MUmdnV3VTWTdLdEFOaUV3RFFZSktvWklodmNOQVFFTApCUUFEZ2dFQkFFU2xRTWs4blMvVWpnOURlVnNaT21ZRnJsQUFpK3NuN21JZ2x4eFJJWFRjamVOMkR6QUZjSW9pCktXcC9wajlKdmhFdHJ3b29KUkJSUCtzUnp3MjEwS3Z3ZlpJV1BZRU85MGREb2d0N2U2bTh6TFN3V0xDQ2EwWVgKK29sVjhMdHJOdjZXTElBVExpZWxQNDErZlVvSVJnZ0VGaitIcklUU1EzYjQ0Nng1UUZVa2pyYnprdmowMHNXaAoxeXBha21OWENlZFI1UEZKK3p0a05jL2VZQlU4MURGN0QxYW9jOVMwSXlRdkloa1Z1dHg3VzNIQUh4K2ZCUVJkClBBcGpvcGp5QzNhbTJMRHJUbFVJeU1hZWFZaUtvZGo5aFZuYzZKa3RrNXAwZFRsVnJZeU9nMnlsM2VVakI1ZDIKUmhQZ3lxTnU3R0xKenZmZzFoNHpkbGpZZ3pYcXo0VT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURWakNDQWo2Z0F3SUJBZ0lRZXZ0TVhBTTc3R01sZnZ4QUROY1F0ekFOQmdrcWhraUc5dzBCQVFzRkFEQVUKTVJJd0VBWURWUVFERXdsRGFXeHBkVzBnUTBFd0hoY05NalV4TURJek1ESTFNakUxV2hjTk1qWXhNREl6TURJMQpNakUxV2pBcU1TZ3dKZ1lEVlFRRERCOHFMbVJsWm1GMWJIUXVhSFZpWW14bExXZHljR011WTJsc2FYVnRMbWx2Ck1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBdm9VVDFrMWlUMzJSWkdxMVRhTisKQ0gxMzNCaEFFS0NMY3ZsbFRsZHZISGY0a2VOR2k4YlpOeHZ1Rk5ULzJIdU5wSGVjTnJ1VWlPL1R3YVRDMThOSApCZ3p6Y0pxMjdyQnZGTGN3b2pLYUFLcTN5VTVSYy9wZkVBc2U3WkRsQy9Id0NMc0gxdUpOMmdyaEFDd0pyY3k3ClM4SG04Z05wUlNwY2Z4eXd6bkthRHdDdXQ0RlFMRzFrOW1SaHkxR0Y4Q2xPV3NITEtReTRXN2ZmdDFvT0FWRWsKWUpzRlUxMzRjSnJESkpEUDBzSlBCbjZETlAvOGozZEtsWWczOHVaMUVjNTNsRzN1K0htcjZzRkNpdm5SYzc5NgpzTWllQTROWlV0UHNMaDZRcGkzTzI2N3dBMVdETWxxMmFHdlFMV3BOZXhCTlNMK21xT01iVWV3c1EwR2NkVG51CjF3SURBUUFCbzRHTk1JR0tNQTRHQTFVZER3RUIvd1FFQXdJRm9EQWRCZ05WSFNVRUZqQVVCZ2dyQmdFRkJRY0QKQVFZSUt3WUJCUVVIQXdJd0RBWURWUjBUQVFIL0JBSXdBREFmQmdOVkhTTUVHREFXZ0JRRTQzNzEvamlyVVU0dApHQ0JhNUpqc3EwQTJJVEFxQmdOVkhSRUVJekFoZ2g4cUxtUmxabUYxYkhRdWFIVmlZbXhsTFdkeWNHTXVZMmxzCmFYVnRMbWx2TUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFDVmNwSGZPYjBoaGpIa2ZWT3J3dE9CRU0vaEpuRWQKTnFwSHpLWGZXQU9YYTUvV0piQnFaVWt0bFdDME9nT2RoT2ZvaEl5cVErVks5Z3hYWDUwejVFUHpSYzQ5bGwrdApjbWJsaG5JVS9HbGpYeWhwRHM0Qit5Q2JYOUN0djJkNmxTS216M1RCSmF0TUxUeXBvRG85aWxUVFp0cXJ2T1dtClF2dzRsUmxLc0FLVW5PeDN4cGExenNxRTVJaENod1REeXkyU1FJbmtGYVhkdE0wbm9hckM2Vk9VaXhJOEo3Q0EKZEhWRVFtR2VCK045TnFjV1oyN3duTWNQL1RSb3ZFVTBMdFpULzVHUzgyNm1pV2dyM1E2MXkvQU4yZ3QwRXZXRApoRS8wMWxOWENMenJjNjN3K09mN05HYmFWWDgrK0xUSFRXQWdBY0k3eXNDbXFQa2VXUkpGZEl6UAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBdm9VVDFrMWlUMzJSWkdxMVRhTitDSDEzM0JoQUVLQ0xjdmxsVGxkdkhIZjRrZU5HCmk4YlpOeHZ1Rk5ULzJIdU5wSGVjTnJ1VWlPL1R3YVRDMThOSEJnenpjSnEyN3JCdkZMY3dvakthQUtxM3lVNVIKYy9wZkVBc2U3WkRsQy9Id0NMc0gxdUpOMmdyaEFDd0pyY3k3UzhIbThnTnBSU3BjZnh5d3puS2FEd0N1dDRGUQpMRzFrOW1SaHkxR0Y4Q2xPV3NITEtReTRXN2ZmdDFvT0FWRWtZSnNGVTEzNGNKckRKSkRQMHNKUEJuNkROUC84CmozZEtsWWczOHVaMUVjNTNsRzN1K0htcjZzRkNpdm5SYzc5NnNNaWVBNE5aVXRQc0xoNlFwaTNPMjY3d0ExV0QKTWxxMmFHdlFMV3BOZXhCTlNMK21xT01iVWV3c1EwR2NkVG51MXdJREFRQUJBb0lCQUJNWnI3Y2JibEMrZ1FDMQpPMVNtU3h0a3kzWElXZkU3ZHpUaFVKNW9ZUE9xQ2hudUtZTnRQY0pWb3RVa2Z1WGdOU29ZOG1pcnFQbzFqbUEvCjVCSW5qMkQwUHNVUG1HbHVUTTlNaDZ3QWhnb0NhTnlJdW9mTEZtbGxyckJ0M0s0Smo3YXJCdC9YTTZ1T3phZEIKR0ZOUlR0eGdlekVtS3hGTHdaYmVIeWV1RVBNOGw2ZEJsWHhxbVNiOHk3YWRkQ3lOTkNJQ1JMNU01VDQ3M2JxbwprN2tXWWpVUENkQThXdWUxRHM1YXZoLzcxZEFiZG1NREFTTHNONXJMdGRHSzNKZlhWOVd3dzhKemc5cVJsSGJLCktuT01oTFJRU21RN3pLOW1iK3BrY054MHFDTkF0VnBkSWhSNnozRU4zbjhGL2taT25MWmlzdzB4d0F0QVM4RmUKOU94eGxFa0NnWUVBMkFCNVdTc1VtQy9DcXVIWEdSVjdPcTluWU9ZNmFPZXR3VkdPYUNrLy9RMkFkMFN1QzUrUwpmUDVBMXN0ZUNNak9rbE5NdGZGTGRaMm9XUVVFYTg2QzBtWGRoTnFrbnlucnhKZmxuMHdKb0Y2Y1VCc2xMWEYrCjdQL0NqcFUwSTdPN0VycDVIOWxWMTlkcjU1Tjc1anJkdVlsSkF2cTQvMXhLSnB3cDNrOEltTVVDZ1lFQTRjeWkKSTNtY0E5SWd1RGlEd2pJdEc4cVYvSGVReDRUdXByakdXTlBEa1JlTHNneHJ1S2ZXUFE0aVNoaDQxMzlROUxITQpySWp5MVozOHp6Uk5OSVg5V3U0WWowcTArS3ZLUGs3N0tNYXhrZXZYNksvMGQ4a05wS25sc1lpbVE3MGZPNHZiCnZBRHczeGRZVWZsMlpndFE4UW5YUE5YSTNIbklQcHFJS21MR0N1c0NnWUFjRzNPdTlyd25VWSt6VE5BQW81cjEKZC8ycnprbXJmUHBQUFoyYVVFUFRXZjV0aHJKZk1OU1BEMGJBckpYLzdxRnl5UVFpYU5PNDZsc051bWxvM2VhSQpHbGxKQUdxTGk1anliQkdsT08vSHZvZjRwSStoNmpMcUJCMzlEODFKR0FvdjFiUU5RT3E2dTMxL0ZPSDZnNDUyCnBqYXAvSlkySkh4QnFmQ0l6U0FCUVFLQmdGanozcVFQRW5GRzVIRHVncW1NVHN6MkFDUlhqZ2Vyek1DTlprWTAKRm9VZ08zNUcrbURpYmJuYnlaSmJGYS8vamdyM3lHUG9CNUkwRFJZcnlvWjRpcGk1MTU4TGxVT3BtYUQyU0dlRgo3d3BIV09WbisrejhuWTFUQ1JQcGUyYVFLSyt5cHp2bk92MElHMWtmNTQ3SHdubFNvU0pzTGhiOU91Kyt2UW5GCm83TkZBb0dBR0luV1NMMjZDeWdqQWNLY2ZwMXN5TFlEeWVsUXc4U0lEV2tUNjVUbmlObldkNWZSLzlybTRBQzUKQXRtVitDMGpkMHJPZGJTUGYxMnNzakRDZk5icjJJdmVPWENobHJVVTN5ZUlmK09xTkkvdXcxWVZsOHBya2duNgpQdFRBdjh4RVNuUTFHWkVIZzlvcGlSVXczNWNaYXVCOVc3MlhpNU5YTU8wZ3lHdnJmWlE9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== kind: Secret metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm name: hubble-server-certs namespace: kube-system type: kubernetes.io/tls --- apiVersion: v1 kind: Service metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cilium-agent app.kubernetes.io/part-of: cilium k8s-app: cilium name: cilium-agent namespace: kube-system spec: clusterIP: None ports: - name: metrics port: 9962 protocol: TCP targetPort: prometheus - name: envoy-metrics port: 9964 protocol: TCP targetPort: envoy-metrics selector: k8s-app: cilium type: ClusterIP --- apiVersion: v1 kind: Service metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cilium-operator app.kubernetes.io/part-of: cilium io.cilium/app: operator name: cilium-operator name: cilium-operator namespace: kube-system spec: clusterIP: None ports: - name: metrics port: 9963 protocol: TCP targetPort: prometheus selector: io.cilium/app: operator name: cilium-operator type: ClusterIP --- apiVersion: v1 kind: Service metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: hubble-peer app.kubernetes.io/part-of: cilium k8s-app: cilium name: hubble-peer namespace: kube-system spec: internalTrafficPolicy: Local ports: - name: peer-service port: 443 protocol: TCP targetPort: 4244 selector: k8s-app: cilium --- apiVersion: v1 kind: Service metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: hubble-relay app.kubernetes.io/part-of: cilium k8s-app: hubble-relay name: hubble-relay namespace: kube-system spec: ports: - port: 80 protocol: TCP targetPort: grpc selector: k8s-app: hubble-relay type: ClusterIP --- apiVersion: v1 kind: Service metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: hubble-ui app.kubernetes.io/part-of: cilium k8s-app: hubble-ui name: hubble-ui namespace: kube-system spec: ports: - name: http port: 80 targetPort: 8081 selector: k8s-app: hubble-ui type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cilium-operator app.kubernetes.io/part-of: cilium io.cilium/app: operator name: cilium-operator name: cilium-operator namespace: kube-system spec: replicas: 2 selector: matchLabels: io.cilium/app: operator name: cilium-operator strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 50% type: RollingUpdate template: metadata: annotations: cilium.io/cilium-configmap-checksum: 247029c5d7a8d1277a2d60ee776629b6941eeb9c26eeb0ec407ff96803e89333 labels: app.kubernetes.io/name: cilium-operator app.kubernetes.io/part-of: cilium io.cilium/app: operator name: cilium-operator spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: io.cilium/app: operator topologyKey: kubernetes.io/hostname automountServiceAccountToken: true containers: - args: - --config-dir=/tmp/cilium/config-map - --debug=$(CILIUM_DEBUG) command: - cilium-operator-generic env: - name: K8S_NODE_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName - name: CILIUM_K8S_NAMESPACE valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.namespace - name: CILIUM_DEBUG valueFrom: configMapKeyRef: key: debug name: cilium-config optional: true - name: KUBERNETES_SERVICE_HOST value: 127.0.0.1 - name: KUBERNETES_SERVICE_PORT value: "7445" image: quay.io/cilium/operator-generic:v1.18.2@sha256:cb4e4ffc5789fd5ff6a534e3b1460623df61cba00f5ea1c7b40153b5efb81805 imagePullPolicy: IfNotPresent livenessProbe: httpGet: host: 127.0.0.1 path: /healthz port: 9234 scheme: HTTP initialDelaySeconds: 60 periodSeconds: 10 timeoutSeconds: 3 name: cilium-operator ports: - containerPort: 9963 hostPort: 9963 name: prometheus protocol: TCP readinessProbe: failureThreshold: 5 httpGet: host: 127.0.0.1 path: /healthz port: 9234 scheme: HTTP initialDelaySeconds: 0 periodSeconds: 5 timeoutSeconds: 3 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL terminationMessagePolicy: FallbackToLogsOnError volumeMounts: - mountPath: /tmp/cilium/config-map name: cilium-config-path readOnly: true hostNetwork: true nodeSelector: kubernetes.io/os: linux priorityClassName: system-cluster-critical restartPolicy: Always securityContext: seccompProfile: type: RuntimeDefault serviceAccountName: cilium-operator tolerations: - key: node-role.kubernetes.io/control-plane operator: Exists - key: node-role.kubernetes.io/master operator: Exists - key: node.kubernetes.io/not-ready operator: Exists - key: node.cloudprovider.kubernetes.io/uninitialized operator: Exists - key: node.cilium.io/agent-not-ready operator: Exists volumes: - configMap: name: cilium-config name: cilium-config-path --- apiVersion: apps/v1 kind: Deployment metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: hubble-relay app.kubernetes.io/part-of: cilium k8s-app: hubble-relay name: hubble-relay namespace: kube-system spec: replicas: 1 selector: matchLabels: k8s-app: hubble-relay strategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate template: metadata: annotations: null labels: app.kubernetes.io/name: hubble-relay app.kubernetes.io/part-of: cilium k8s-app: hubble-relay spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: k8s-app: cilium topologyKey: kubernetes.io/hostname automountServiceAccountToken: false containers: - args: - serve command: - hubble-relay image: quay.io/cilium/hubble-relay:v1.18.2@sha256:6079308ee15e44dff476fb522612732f7c5c4407a1017bc3470916242b0405ac imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 12 grpc: port: 4222 initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 10 name: hubble-relay ports: - containerPort: 4245 name: grpc readinessProbe: grpc: port: 4222 timeoutSeconds: 3 securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL runAsGroup: 65532 runAsNonRoot: true runAsUser: 65532 seccompProfile: type: RuntimeDefault startupProbe: failureThreshold: 20 grpc: port: 4222 initialDelaySeconds: 10 periodSeconds: 3 terminationMessagePolicy: FallbackToLogsOnError volumeMounts: - mountPath: /etc/hubble-relay name: config readOnly: true - mountPath: /var/lib/hubble-relay/tls name: tls readOnly: true nodeSelector: kubernetes.io/os: linux priorityClassName: null restartPolicy: Always securityContext: fsGroup: 65532 seccompProfile: type: RuntimeDefault serviceAccountName: hubble-relay terminationGracePeriodSeconds: 1 volumes: - configMap: items: - key: config.yaml path: config.yaml name: hubble-relay-config name: config - name: tls projected: defaultMode: 256 sources: - secret: items: - key: tls.crt path: client.crt - key: tls.key path: client.key - key: ca.crt path: hubble-server-ca.crt name: hubble-relay-client-certs --- apiVersion: apps/v1 kind: Deployment metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: hubble-ui app.kubernetes.io/part-of: cilium k8s-app: hubble-ui name: hubble-ui namespace: kube-system spec: replicas: 1 selector: matchLabels: k8s-app: hubble-ui strategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate template: metadata: annotations: null labels: app.kubernetes.io/name: hubble-ui app.kubernetes.io/part-of: cilium k8s-app: hubble-ui spec: automountServiceAccountToken: true containers: - image: quay.io/cilium/hubble-ui:v0.13.3@sha256:661d5de7050182d495c6497ff0b007a7a1e379648e60830dd68c4d78ae21761d imagePullPolicy: IfNotPresent livenessProbe: httpGet: path: /healthz port: 8081 name: frontend ports: - containerPort: 8081 name: http readinessProbe: httpGet: path: / port: 8081 securityContext: allowPrivilegeEscalation: false terminationMessagePolicy: FallbackToLogsOnError volumeMounts: - mountPath: /etc/nginx/conf.d/default.conf name: hubble-ui-nginx-conf subPath: nginx.conf - mountPath: /tmp name: tmp-dir - env: - name: EVENTS_SERVER_PORT value: "8090" - name: FLOWS_API_ADDR value: hubble-relay:80 image: quay.io/cilium/hubble-ui-backend:v0.13.3@sha256:db1454e45dc39ca41fbf7cad31eec95d99e5b9949c39daaad0fa81ef29d56953 imagePullPolicy: IfNotPresent name: backend ports: - containerPort: 8090 name: grpc securityContext: allowPrivilegeEscalation: false terminationMessagePolicy: FallbackToLogsOnError volumeMounts: null nodeSelector: kubernetes.io/os: linux priorityClassName: null securityContext: fsGroup: 1001 runAsGroup: 1001 runAsUser: 1001 serviceAccountName: hubble-ui volumes: - configMap: defaultMode: 420 name: hubble-ui-nginx name: hubble-ui-nginx-conf - emptyDir: {} name: tmp-dir --- apiVersion: apps/v1 kind: DaemonSet metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cilium-agent app.kubernetes.io/part-of: cilium k8s-app: cilium name: cilium namespace: kube-system spec: selector: matchLabels: k8s-app: cilium template: metadata: annotations: cilium.io/cilium-configmap-checksum: 247029c5d7a8d1277a2d60ee776629b6941eeb9c26eeb0ec407ff96803e89333 kubectl.kubernetes.io/default-container: cilium-agent labels: app.kubernetes.io/name: cilium-agent app.kubernetes.io/part-of: cilium k8s-app: cilium spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: k8s-app: cilium topologyKey: kubernetes.io/hostname automountServiceAccountToken: true containers: - args: - --config-dir=/tmp/cilium/config-map command: - cilium-agent env: - name: K8S_NODE_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName - name: CILIUM_K8S_NAMESPACE valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.namespace - name: CILIUM_CLUSTERMESH_CONFIG value: /var/lib/cilium/clustermesh/ - name: GOMEMLIMIT valueFrom: resourceFieldRef: divisor: "1" resource: limits.memory - name: KUBERNETES_SERVICE_HOST value: 127.0.0.1 - name: KUBERNETES_SERVICE_PORT value: "7445" - name: KUBE_CLIENT_BACKOFF_BASE value: "1" - name: KUBE_CLIENT_BACKOFF_DURATION value: "120" image: quay.io/cilium/cilium:v1.18.2@sha256:858f807ea4e20e85e3ea3240a762e1f4b29f1cb5bbd0463b8aa77e7b097c0667 imagePullPolicy: IfNotPresent lifecycle: postStart: exec: command: - bash - -c - | set -o errexit set -o pipefail set -o nounset # When running in AWS ENI mode, it's likely that 'aws-node' has # had a chance to install SNAT iptables rules. These can result # in dropped traffic, so we should attempt to remove them. # We do it using a 'postStart' hook since this may need to run # for nodes which might have already been init'ed but may still # have dangling rules. This is safe because there are no # dependencies on anything that is part of the startup script # itself, and can be safely run multiple times per node (e.g. in # case of a restart). if [[ "$(iptables-save | grep -E -c 'AWS-SNAT-CHAIN|AWS-CONNMARK-CHAIN')" != "0" ]]; then echo 'Deleting iptables rules created by the AWS CNI VPC plugin' iptables-save | grep -E -v 'AWS-SNAT-CHAIN|AWS-CONNMARK-CHAIN' | iptables-restore fi echo 'Done!' preStop: exec: command: - /cni-uninstall.sh livenessProbe: failureThreshold: 10 httpGet: host: 127.0.0.1 httpHeaders: - name: brief value: "true" - name: require-k8s-connectivity value: "false" path: /healthz port: 9879 scheme: HTTP periodSeconds: 30 successThreshold: 1 timeoutSeconds: 5 name: cilium-agent ports: - containerPort: 4244 hostPort: 4244 name: peer-service protocol: TCP - containerPort: 9962 hostPort: 9962 name: prometheus protocol: TCP - containerPort: 9964 hostPort: 9964 name: envoy-metrics protocol: TCP readinessProbe: failureThreshold: 3 httpGet: host: 127.0.0.1 httpHeaders: - name: brief value: "true" path: /healthz port: 9879 scheme: HTTP periodSeconds: 30 successThreshold: 1 timeoutSeconds: 5 securityContext: capabilities: add: - CHOWN - KILL - NET_ADMIN - NET_RAW - IPC_LOCK - SYS_ADMIN - SYS_RESOURCE - PERFMON - BPF - DAC_OVERRIDE - FOWNER - SETGID - SETUID drop: - ALL seLinuxOptions: level: s0 type: spc_t startupProbe: failureThreshold: 300 httpGet: host: 127.0.0.1 httpHeaders: - name: brief value: "true" path: /healthz port: 9879 scheme: HTTP initialDelaySeconds: 5 periodSeconds: 2 successThreshold: 1 terminationMessagePolicy: FallbackToLogsOnError volumeMounts: - mountPath: /host/proc/sys/net name: host-proc-sys-net - mountPath: /host/proc/sys/kernel name: host-proc-sys-kernel - mountPath: /sys/fs/bpf mountPropagation: HostToContainer name: bpf-maps - mountPath: /sys/fs/cgroup name: cilium-cgroup - mountPath: /var/run/cilium name: cilium-run - mountPath: /var/run/cilium/netns mountPropagation: HostToContainer name: cilium-netns - mountPath: /host/etc/cni/net.d name: etc-cni-netd - mountPath: /var/lib/cilium/clustermesh name: clustermesh-secrets readOnly: true - mountPath: /lib/modules name: lib-modules readOnly: true - mountPath: /run/xtables.lock name: xtables-lock - mountPath: /var/lib/cilium/tls/hubble name: hubble-tls readOnly: true - mountPath: /tmp name: tmp hostNetwork: true initContainers: - command: - cilium-dbg - build-config env: - name: K8S_NODE_NAME valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName - name: CILIUM_K8S_NAMESPACE valueFrom: fieldRef: apiVersion: v1 fieldPath: metadata.namespace - name: KUBERNETES_SERVICE_HOST value: 127.0.0.1 - name: KUBERNETES_SERVICE_PORT value: "7445" image: quay.io/cilium/cilium:v1.18.2@sha256:858f807ea4e20e85e3ea3240a762e1f4b29f1cb5bbd0463b8aa77e7b097c0667 imagePullPolicy: IfNotPresent name: config terminationMessagePolicy: FallbackToLogsOnError volumeMounts: - mountPath: /tmp name: tmp - command: - sh - -ec - | cp /usr/bin/cilium-sysctlfix /hostbin/cilium-sysctlfix; nsenter --mount=/hostproc/1/ns/mnt "${BIN_PATH}/cilium-sysctlfix"; rm /hostbin/cilium-sysctlfix env: - name: BIN_PATH value: /opt/cni/bin image: quay.io/cilium/cilium:v1.18.2@sha256:858f807ea4e20e85e3ea3240a762e1f4b29f1cb5bbd0463b8aa77e7b097c0667 imagePullPolicy: IfNotPresent name: apply-sysctl-overwrites securityContext: capabilities: add: - SYS_ADMIN - SYS_CHROOT - SYS_PTRACE drop: - ALL seLinuxOptions: level: s0 type: spc_t terminationMessagePolicy: FallbackToLogsOnError volumeMounts: - mountPath: /hostproc name: hostproc - mountPath: /hostbin name: cni-path - args: - mount | grep "/sys/fs/bpf type bpf" || mount -t bpf bpf /sys/fs/bpf command: - /bin/bash - -c - -- image: quay.io/cilium/cilium:v1.18.2@sha256:858f807ea4e20e85e3ea3240a762e1f4b29f1cb5bbd0463b8aa77e7b097c0667 imagePullPolicy: IfNotPresent name: mount-bpf-fs securityContext: privileged: true terminationMessagePolicy: FallbackToLogsOnError volumeMounts: - mountPath: /sys/fs/bpf mountPropagation: Bidirectional name: bpf-maps - command: - /init-container.sh env: - name: CILIUM_ALL_STATE valueFrom: configMapKeyRef: key: clean-cilium-state name: cilium-config optional: true - name: CILIUM_BPF_STATE valueFrom: configMapKeyRef: key: clean-cilium-bpf-state name: cilium-config optional: true - name: WRITE_CNI_CONF_WHEN_READY valueFrom: configMapKeyRef: key: write-cni-conf-when-ready name: cilium-config optional: true - name: KUBERNETES_SERVICE_HOST value: 127.0.0.1 - name: KUBERNETES_SERVICE_PORT value: "7445" image: quay.io/cilium/cilium:v1.18.2@sha256:858f807ea4e20e85e3ea3240a762e1f4b29f1cb5bbd0463b8aa77e7b097c0667 imagePullPolicy: IfNotPresent name: clean-cilium-state securityContext: capabilities: add: - NET_ADMIN - SYS_ADMIN - SYS_RESOURCE drop: - ALL seLinuxOptions: level: s0 type: spc_t terminationMessagePolicy: FallbackToLogsOnError volumeMounts: - mountPath: /sys/fs/bpf name: bpf-maps - mountPath: /sys/fs/cgroup mountPropagation: HostToContainer name: cilium-cgroup - mountPath: /var/run/cilium name: cilium-run - command: - /install-plugin.sh image: quay.io/cilium/cilium:v1.18.2@sha256:858f807ea4e20e85e3ea3240a762e1f4b29f1cb5bbd0463b8aa77e7b097c0667 imagePullPolicy: IfNotPresent name: install-cni-binaries resources: requests: cpu: 100m memory: 10Mi securityContext: capabilities: drop: - ALL seLinuxOptions: level: s0 type: spc_t terminationMessagePolicy: FallbackToLogsOnError volumeMounts: - mountPath: /host/opt/cni/bin name: cni-path nodeSelector: kubernetes.io/os: linux priorityClassName: system-node-critical restartPolicy: Always securityContext: appArmorProfile: type: Unconfined seccompProfile: type: Unconfined serviceAccountName: cilium terminationGracePeriodSeconds: 1 tolerations: - operator: Exists volumes: - emptyDir: {} name: tmp - hostPath: path: /var/run/cilium type: DirectoryOrCreate name: cilium-run - hostPath: path: /var/run/netns type: DirectoryOrCreate name: cilium-netns - hostPath: path: /sys/fs/bpf type: DirectoryOrCreate name: bpf-maps - hostPath: path: /proc type: Directory name: hostproc - hostPath: path: /sys/fs/cgroup type: DirectoryOrCreate name: cilium-cgroup - hostPath: path: /opt/cni/bin type: DirectoryOrCreate name: cni-path - hostPath: path: /etc/cni/net.d type: DirectoryOrCreate name: etc-cni-netd - hostPath: path: /lib/modules name: lib-modules - hostPath: path: /run/xtables.lock type: FileOrCreate name: xtables-lock - name: clustermesh-secrets projected: defaultMode: 256 sources: - secret: name: cilium-clustermesh optional: true - secret: items: - key: tls.key path: common-etcd-client.key - key: tls.crt path: common-etcd-client.crt - key: ca.crt path: common-etcd-client-ca.crt name: clustermesh-apiserver-remote-cert optional: true - secret: items: - key: tls.key path: local-etcd-client.key - key: tls.crt path: local-etcd-client.crt - key: ca.crt path: local-etcd-client-ca.crt name: clustermesh-apiserver-local-cert optional: true - hostPath: path: /proc/sys/net type: Directory name: host-proc-sys-net - hostPath: path: /proc/sys/kernel type: Directory name: host-proc-sys-kernel - name: hubble-tls projected: defaultMode: 256 sources: - secret: items: - key: tls.crt path: server.crt - key: tls.key path: server.key - key: ca.crt path: client-ca.crt name: hubble-server-certs optional: true updateStrategy: rollingUpdate: maxUnavailable: 2 type: RollingUpdate --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cilium-agent app.kubernetes.io/part-of: cilium name: cilium-agent namespace: kube-system spec: endpoints: - honorLabels: true interval: 10s path: /metrics port: metrics relabelings: - action: replace replacement: ${1} sourceLabels: - __meta_kubernetes_pod_node_name targetLabel: node namespaceSelector: matchNames: - kube-system selector: matchLabels: app.kubernetes.io/name: cilium-agent targetLabels: - k8s-app --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system labels: app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: cilium-operator app.kubernetes.io/part-of: cilium name: cilium-operator namespace: kube-system spec: endpoints: - honorLabels: true interval: 10s path: /metrics port: metrics namespaceSelector: matchNames: - kube-system selector: matchLabels: io.cilium/app: operator name: cilium-operator targetLabels: - io.cilium/app ================================================ FILE: talos/integrations/cilium/kustomization.yaml ================================================ --- # yaml-language-server: $schema=https://json.schemastore.org/kustomization apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization helmCharts: - name: cilium includeCRDs: true releaseName: cilium namespace: kube-system valuesFile: ../../../kubernetes/apps/base/kube-system/cilium/app/values.yaml version: 1.19.4 repo: https://helm.cilium.io/ # REQUIRED: Use transformers to avoid creating the labels & annotations on all references rather than only metadata/annotations or metadata/labels respectively transformers: - transformers.yaml ================================================ FILE: talos/integrations/cilium/transformers.yaml ================================================ --- apiVersion: builtin kind: LabelTransformer metadata: name: labels labels: app.kubernetes.io/managed-by: Helm fieldSpecs: - path: metadata/labels create: true --- apiVersion: builtin kind: AnnotationsTransformer metadata: name: annotations annotations: meta.helm.sh/release-name: cilium meta.helm.sh/release-namespace: kube-system fieldSpecs: - path: metadata/annotations create: true ================================================ FILE: talos/patches/iscsi.yaml ================================================ # https://www.talos.dev/v1.9/kubernetes-guides/configuration/replicated-local-storage-with-openebs/ machine: sysctls: vm.nr_hugepages: "1024" nodeLabels: openebs.io/engine: mayastor kubelet: extraMounts: - destination: /var/openebs/local type: bind source: /var/openebs/local options: - rbind - rshared - rw ================================================ FILE: talos/patches/metric-server.yaml ================================================ # https://www.talos.dev/v1.9/kubernetes-guides/configuration/deploy-metrics-server/ - op: add path: /machine/kubelet/extraArgs value: rotate-server-certificates: true ================================================ FILE: talos/patches/metrics.yaml ================================================ # https://www.talos.dev/v1.9/talos-guides/configuration/containerd/#exposing-metrics machine: files: - content: | [metrics] address = "0.0.0.0:11234" path: /etc/cri/conf.d/20-customization.part op: create ================================================ FILE: terraform/gcp/README.md ================================================ # Cloud Infrastructure ## Existing Project Use [terraformer](https://github.com/GoogleCloudPlatform/terraformer) to import existing cloud resources that have been created into TF files. GCP Example: ```bash terraformer import google --resources=gcs,forwardingRules,httpHealthChecks --connect=true --regions=europe-west1,europe-west4 --projects=aaa,fff ``` ## Tips Consider terraform repository structure [best practices](https://www.terraform-best-practices.com/code-structure) ================================================ FILE: terraform/gcp/_backend.tf ================================================ terraform { backend "gcs" { bucket = "raspbernetes-gitops-terraform-state" prefix = "terraform/state" } } ================================================ FILE: terraform/gcp/_provider.tf ================================================ provider "google" { project = var.project_id region = var.region } ================================================ FILE: terraform/gcp/install.sh ================================================ #!/bin/bash set -euo pipefail # Notes: # - Billing must be activated for the project # - Post install "terraform init" must be executed to configure against the remote state in GCS # TODO: Reuse variables for PROJECT_ID to avoid users having to set these in multile locations # TODO: Create an uninstall script to remove these resources that are not managed via Terraform # TODO: Make script idemopotent so it can be re-run without error # TODO: QUOTAS default for IN_USE_ADDRESSES is 8 and needs to be 9 # Error: error creating NodePool: googleapi: Error 403: Insufficient regional quota to satisfy request: resource "IN_USE_ADDRESSES": request requires '9.0' and is short '1.0'. project has a quota of '8.0' with '8.0' available. View and manage quotas at https://console.cloud.google.com/iam-admin/quotas?usage=USED&project=raspbernetes., forbidden export TF_VAR_PROJ_ID="${TF_VAR_PROJ_ID:-raspbernetes}" export TF_CREDS=~/.config/gcloud/${TF_VAR_PROJ_ID}-terraform-admin.json # Create the service account in the Terraform admin project and download the JSON credentials gcloud iam service-accounts create terraform \ --display-name "Terraform admin account" gcloud iam service-accounts keys create "${TF_CREDS}" \ --iam-account "terraform@${TF_VAR_PROJ_ID}.iam.gserviceaccount.com" # Grant the service account permission to view the Admin Project and manage Cloud Storage gcloud projects add-iam-policy-binding "${TF_VAR_PROJ_ID}" \ --member "serviceAccount:terraform@${TF_VAR_PROJ_ID}.iam.gserviceaccount.com" \ --role roles/owner gcloud projects add-iam-policy-binding "${TF_VAR_PROJ_ID}" \ --member "serviceAccount:terraform@${TF_VAR_PROJ_ID}.iam.gserviceaccount.com" \ --role roles/storage.admin # Any actions that Terraform performs require that the API be enabled to do so gcloud services enable cloudresourcemanager.googleapis.com gcloud services enable cloudbilling.googleapis.com gcloud services enable iam.googleapis.com gcloud services enable compute.googleapis.com gcloud services enable serviceusage.googleapis.com gcloud services enable container.googleapis.com # Create the remote backend bucket in Cloud Storage and the backend.tf file for storage of the terraform.tfstate file gsutil mb -p "${TF_VAR_PROJ_ID}" "gs://${TF_VAR_PROJ_ID}-gitops-terraform-state" # TODO: Make sure backend.tf is located under the infrastructure/ directory cat > _backend.tf << EOF terraform { backend "gcs" { bucket = "${TF_VAR_PROJ_ID}-gitops-terraform-state" prefix = "terraform/state" } } EOF # Enable versioning for the remote bucket gsutil versioning set on "gs://${TF_VAR_PROJ_ID}-gitops-terraform-state" # Configure your environment for the Google Cloud Terraform provider export GOOGLE_APPLICATION_CREDENTIALS=${TF_CREDS} export GOOGLE_PROJECT=${TF_VAR_PROJ_ID} ================================================ FILE: terraform/gcp/sops.tf ================================================ locals { sops_permissions = [ "cloudkms.cryptoKeys.list", "cloudkms.cryptoKeys.get", "cloudkms.cryptoKeyVersions.get", "cloudkms.cryptoKeyVersions.list", "cloudkms.cryptoKeyVersions.useToDecrypt", "cloudkms.cryptoKeyVersions.useToEncrypt", "cloudkms.cryptoKeyVersions.viewPublicKey", "cloudkms.keyRings.get", "cloudkms.keyRings.list", "resourcemanager.projects.get" ] } resource "google_kms_key_ring" "sops" { name = "sops" location = "global" } resource "google_kms_crypto_key" "sops" { name = "sops-key" key_ring = google_kms_key_ring.sops.id purpose = "ENCRYPT_DECRYPT" lifecycle { prevent_destroy = true } } resource "google_project_iam_custom_role" "sops" { role_id = "sops" title = "SOPS Role" description = "This role grants all required SOPS permissions" permissions = local.sops_permissions } # Approved list of GCP users with the ability to encrypt/decrypt project secret resource "google_project_iam_binding" "sops" { project = var.project_id role = "projects/raspbernetes/roles/${google_project_iam_custom_role.sops.role_id}" members = [ "user:saurabh.c.pandit@gmail.com", ] } ================================================ FILE: terraform/gcp/thanos.tf ================================================ locals { thanos_permissions = [ "compute.snapshots.create", "compute.snapshots.delete", "compute.snapshots.get", "compute.snapshots.list", "compute.snapshots.useReadOnly", "compute.zones.get", "compute.zones.list", "resourcemanager.projects.get", "storage.objects.create", "storage.objects.delete", "storage.objects.get", "storage.objects.getIamPolicy", "storage.objects.list", "storage.objects.setIamPolicy", "storage.objects.update" ] } resource "google_service_account" "thanos" { account_id = "thanos" display_name = "Service account for Thanos" } resource "google_project_iam_custom_role" "thanos" { role_id = "thanos" title = "Thanos Role" description = "This role grants all required Thanos permissions" permissions = local.thanos_permissions } resource "google_project_iam_binding" "thanos" { project = var.project_id role = google_project_iam_custom_role.thanos.name members = [ "serviceAccount:${google_service_account.thanos.email}", ] } resource "google_storage_bucket" "thanos" { default_event_based_hold = "false" force_destroy = "false" location = "ASIA" name = "thanos-raspbernetes-storage" project = "raspbernetes" requester_pays = "false" storage_class = "STANDARD" } ================================================ FILE: terraform/gcp/variables.tf ================================================ variable "project_id" { description = "(OPTIONAL) The GCP project ID to use for the cluster. (default: raspbernetes)" default = "raspbernetes" type = string } variable "region" { description = "(OPTIONAL) The GCP region to use for the cluster. (default: us-central1)" default = "us-central1" type = string } ================================================ FILE: terraform/gcp/velero.tf ================================================ locals { velero_permissions = [ "compute.snapshots.create", "compute.snapshots.delete", "compute.snapshots.get", "compute.snapshots.list", "compute.snapshots.useReadOnly", "compute.zones.get", "compute.zones.list", "resourcemanager.projects.get", "storage.objects.create", "storage.objects.delete", "storage.objects.get", "storage.objects.getIamPolicy", "storage.objects.list", "storage.objects.setIamPolicy", "storage.objects.update" ] } resource "google_service_account" "velero" { account_id = "velero" display_name = "Service account for Velero" } resource "google_project_iam_custom_role" "velero" { role_id = "velero" title = "Velero Role" description = "This role grants all required Velero permissions" permissions = local.velero_permissions } resource "google_project_iam_binding" "velero" { project = var.project_id role = google_project_iam_custom_role.velero.name members = [ "serviceAccount:${google_service_account.velero.email}", ] } resource "google_storage_bucket_iam_binding" "binding" { bucket = google_storage_bucket.openebs.name role = "projects/raspbernetes/roles/${google_project_iam_custom_role.velero.role_id}" members = [ "serviceAccount:${google_service_account.velero.email}", ] } resource "google_storage_bucket" "velero" { default_event_based_hold = "false" force_destroy = "false" location = "US" name = "raspbernetes-velero-backups" project = "raspbernetes" requester_pays = "false" storage_class = "STANDARD" } resource "google_storage_bucket" "openebs" { default_event_based_hold = "false" force_destroy = "false" location = "US" name = "raspbernetes-openebs-backups" project = "raspbernetes" requester_pays = "false" storage_class = "STANDARD" } ================================================ FILE: wrangler.toml ================================================ name = "k8s-gitops" compatibility_date = "2026-02-23" [assets] directory = "./docs"