From aac7544c96973621db83914a6142633ab9b53ae5 Mon Sep 17 00:00:00 2001 From: Laur IVAN Date: Wed, 4 Feb 2026 16:21:02 +0100 Subject: [PATCH] chore: initial commit :rocket: --- .sops.yaml | 12 ++ .yamlfmt.yaml | 18 ++ bootstrap/helmfile.d/00-crds.yaml | 25 +++ bootstrap/helmfile.d/01-apps.yaml | 48 +++++ .../helmfile.d/templates/values.yaml.gotmpl | 1 + bootstrap/helmfile.yaml | 27 +++ bootstrap/sops-age.sops.yaml | 23 +++ bootstrap/templates/values.yaml.gotmpl | 3 + cluster.sample.yaml | 84 --------- .../cert-manager/app/clusterissuer.yaml | 19 ++ .../cert-manager/app/helmrelease.yaml | 20 +++ .../cert-manager/app/kustomization.yaml | 8 + .../cert-manager/app/ocirepository.yaml | 13 ++ .../cert-manager/app/secret.sops.yaml | 22 +++ .../apps/cert-manager/cert-manager/ks.yaml | 31 ++++ .../apps/cert-manager/kustomization.yaml | 11 ++ kubernetes/apps/cert-manager/namespace.yaml | 7 + .../apps/default/echo/app/helmrelease.yaml | 71 ++++++++ .../apps/default/echo/app/kustomization.yaml | 6 + .../apps/default/echo/app/ocirepository.yaml | 13 ++ kubernetes/apps/default/echo/ks.yaml | 19 ++ kubernetes/apps/default/kustomization.yaml | 11 ++ kubernetes/apps/default/namespace.yaml | 7 + .../flux-instance/app/helmrelease.yaml | 133 ++++++++++++++ .../flux-instance/app/httproute.yaml | 20 +++ .../flux-instance/app/kustomization.yaml | 9 + .../flux-instance/app/ocirepository.yaml | 13 ++ .../flux-instance/app/receiver.yaml | 19 ++ .../flux-instance/app/secret.sops.yaml | 22 +++ .../apps/flux-system/flux-instance/ks.yaml | 21 +++ .../flux-operator/app/helmrelease.yaml | 13 ++ .../flux-operator/app/kustomization.yaml | 6 + .../flux-operator/app/ocirepository.yaml | 13 ++ .../apps/flux-system/flux-operator/ks.yaml | 19 ++ .../apps/flux-system/kustomization.yaml | 12 ++ kubernetes/apps/flux-system/namespace.yaml | 7 + .../kube-system/cilium/app/helmrelease.yaml | 87 +++++++++ .../kube-system/cilium/app/kustomization.yaml | 7 + .../apps/kube-system/cilium/app/networks.yaml | 23 +++ .../kube-system/cilium/app/ocirepository.yaml | 13 ++ kubernetes/apps/kube-system/cilium/ks.yaml | 19 ++ .../kube-system/coredns/app/helmrelease.yaml | 67 +++++++ .../coredns/app/kustomization.yaml | 6 + .../coredns/app/ocirepository.yaml | 13 ++ kubernetes/apps/kube-system/coredns/ks.yaml | 19 ++ .../apps/kube-system/kustomization.yaml | 15 ++ .../metrics-server/app/helmrelease.yaml | 21 +++ .../metrics-server/app/kustomization.yaml | 6 + .../metrics-server/app/ocirepository.yaml | 13 ++ .../apps/kube-system/metrics-server/ks.yaml | 19 ++ kubernetes/apps/kube-system/namespace.yaml | 7 + .../kube-system/reloader/app/helmrelease.yaml | 17 ++ .../reloader/app/kustomization.yaml | 6 + .../reloader/app/ocirepository.yaml | 13 ++ kubernetes/apps/kube-system/reloader/ks.yaml | 19 ++ .../kube-system/spegel/app/helmrelease.yaml | 19 ++ .../kube-system/spegel/app/kustomization.yaml | 6 + .../kube-system/spegel/app/ocirepository.yaml | 13 ++ kubernetes/apps/kube-system/spegel/ks.yaml | 19 ++ .../cloudflare-dns/app/helmrelease.yaml | 35 ++++ .../cloudflare-dns/app/kustomization.yaml | 7 + .../cloudflare-dns/app/ocirepository.yaml | 13 ++ .../cloudflare-dns/app/secret.sops.yaml | 22 +++ .../apps/network/cloudflare-dns/ks.yaml | 19 ++ .../cloudflare-tunnel/app/dnsendpoint.yaml | 10 ++ .../cloudflare-tunnel/app/helmrelease.yaml | 84 +++++++++ .../cloudflare-tunnel/app/kustomization.yaml | 8 + .../cloudflare-tunnel/app/ocirepository.yaml | 13 ++ .../cloudflare-tunnel/app/secret.sops.yaml | 22 +++ .../apps/network/cloudflare-tunnel/ks.yaml | 19 ++ .../envoy-gateway/app/certificate.yaml | 18 ++ .../apps/network/envoy-gateway/app/envoy.yaml | 170 ++++++++++++++++++ .../envoy-gateway/app/helmrelease.yaml | 20 +++ .../envoy-gateway/app/kustomization.yaml | 9 + .../envoy-gateway/app/ocirepository.yaml | 13 ++ .../network/envoy-gateway/app/podmonitor.yaml | 18 ++ kubernetes/apps/network/envoy-gateway/ks.yaml | 19 ++ .../network/k8s-gateway/app/helmrelease.yaml | 21 +++ .../k8s-gateway/app/kustomization.yaml | 6 + .../k8s-gateway/app/ocirepository.yaml | 13 ++ kubernetes/apps/network/k8s-gateway/ks.yaml | 19 ++ kubernetes/apps/network/kustomization.yaml | 14 ++ kubernetes/apps/network/namespace.yaml | 7 + .../components/sops/cluster-secrets.sops.yaml | 22 +++ kubernetes/components/sops/kustomization.yaml | 5 + kubernetes/flux/cluster/ks.yaml | 57 ++++++ nodes.sample.yaml | 13 -- talos/patches/README.md | 15 ++ talos/patches/controller/cluster.yaml | 23 +++ talos/patches/global/machine-files.yaml | 9 + talos/patches/global/machine-kubelet.yaml | 7 + talos/patches/global/machine-network.yaml | 7 + talos/patches/global/machine-sysctls.yaml | 11 ++ talos/patches/global/machine-time.yaml | 6 + talos/talconfig.yaml | 94 ++++++++++ talos/talenv.yaml | 4 + 96 files changed, 2028 insertions(+), 97 deletions(-) create mode 100644 .sops.yaml create mode 100644 .yamlfmt.yaml create mode 100644 bootstrap/helmfile.d/00-crds.yaml create mode 100644 bootstrap/helmfile.d/01-apps.yaml create mode 100644 bootstrap/helmfile.d/templates/values.yaml.gotmpl create mode 100644 bootstrap/helmfile.yaml create mode 100644 bootstrap/sops-age.sops.yaml create mode 100644 bootstrap/templates/values.yaml.gotmpl delete mode 100644 cluster.sample.yaml create mode 100644 kubernetes/apps/cert-manager/cert-manager/app/clusterissuer.yaml create mode 100644 kubernetes/apps/cert-manager/cert-manager/app/helmrelease.yaml create mode 100644 kubernetes/apps/cert-manager/cert-manager/app/kustomization.yaml create mode 100644 kubernetes/apps/cert-manager/cert-manager/app/ocirepository.yaml create mode 100644 kubernetes/apps/cert-manager/cert-manager/app/secret.sops.yaml create mode 100644 kubernetes/apps/cert-manager/cert-manager/ks.yaml create mode 100644 kubernetes/apps/cert-manager/kustomization.yaml create mode 100644 kubernetes/apps/cert-manager/namespace.yaml create mode 100644 kubernetes/apps/default/echo/app/helmrelease.yaml create mode 100644 kubernetes/apps/default/echo/app/kustomization.yaml create mode 100644 kubernetes/apps/default/echo/app/ocirepository.yaml create mode 100644 kubernetes/apps/default/echo/ks.yaml create mode 100644 kubernetes/apps/default/kustomization.yaml create mode 100644 kubernetes/apps/default/namespace.yaml create mode 100644 kubernetes/apps/flux-system/flux-instance/app/helmrelease.yaml create mode 100644 kubernetes/apps/flux-system/flux-instance/app/httproute.yaml create mode 100644 kubernetes/apps/flux-system/flux-instance/app/kustomization.yaml create mode 100644 kubernetes/apps/flux-system/flux-instance/app/ocirepository.yaml create mode 100644 kubernetes/apps/flux-system/flux-instance/app/receiver.yaml create mode 100644 kubernetes/apps/flux-system/flux-instance/app/secret.sops.yaml create mode 100644 kubernetes/apps/flux-system/flux-instance/ks.yaml create mode 100644 kubernetes/apps/flux-system/flux-operator/app/helmrelease.yaml create mode 100644 kubernetes/apps/flux-system/flux-operator/app/kustomization.yaml create mode 100644 kubernetes/apps/flux-system/flux-operator/app/ocirepository.yaml create mode 100644 kubernetes/apps/flux-system/flux-operator/ks.yaml create mode 100644 kubernetes/apps/flux-system/kustomization.yaml create mode 100644 kubernetes/apps/flux-system/namespace.yaml create mode 100644 kubernetes/apps/kube-system/cilium/app/helmrelease.yaml create mode 100644 kubernetes/apps/kube-system/cilium/app/kustomization.yaml create mode 100644 kubernetes/apps/kube-system/cilium/app/networks.yaml create mode 100644 kubernetes/apps/kube-system/cilium/app/ocirepository.yaml create mode 100644 kubernetes/apps/kube-system/cilium/ks.yaml create mode 100644 kubernetes/apps/kube-system/coredns/app/helmrelease.yaml create mode 100644 kubernetes/apps/kube-system/coredns/app/kustomization.yaml create mode 100644 kubernetes/apps/kube-system/coredns/app/ocirepository.yaml create mode 100644 kubernetes/apps/kube-system/coredns/ks.yaml create mode 100644 kubernetes/apps/kube-system/kustomization.yaml create mode 100644 kubernetes/apps/kube-system/metrics-server/app/helmrelease.yaml create mode 100644 kubernetes/apps/kube-system/metrics-server/app/kustomization.yaml create mode 100644 kubernetes/apps/kube-system/metrics-server/app/ocirepository.yaml create mode 100644 kubernetes/apps/kube-system/metrics-server/ks.yaml create mode 100644 kubernetes/apps/kube-system/namespace.yaml create mode 100644 kubernetes/apps/kube-system/reloader/app/helmrelease.yaml create mode 100644 kubernetes/apps/kube-system/reloader/app/kustomization.yaml create mode 100644 kubernetes/apps/kube-system/reloader/app/ocirepository.yaml create mode 100644 kubernetes/apps/kube-system/reloader/ks.yaml create mode 100644 kubernetes/apps/kube-system/spegel/app/helmrelease.yaml create mode 100644 kubernetes/apps/kube-system/spegel/app/kustomization.yaml create mode 100644 kubernetes/apps/kube-system/spegel/app/ocirepository.yaml create mode 100644 kubernetes/apps/kube-system/spegel/ks.yaml create mode 100644 kubernetes/apps/network/cloudflare-dns/app/helmrelease.yaml create mode 100644 kubernetes/apps/network/cloudflare-dns/app/kustomization.yaml create mode 100644 kubernetes/apps/network/cloudflare-dns/app/ocirepository.yaml create mode 100644 kubernetes/apps/network/cloudflare-dns/app/secret.sops.yaml create mode 100644 kubernetes/apps/network/cloudflare-dns/ks.yaml create mode 100644 kubernetes/apps/network/cloudflare-tunnel/app/dnsendpoint.yaml create mode 100644 kubernetes/apps/network/cloudflare-tunnel/app/helmrelease.yaml create mode 100644 kubernetes/apps/network/cloudflare-tunnel/app/kustomization.yaml create mode 100644 kubernetes/apps/network/cloudflare-tunnel/app/ocirepository.yaml create mode 100644 kubernetes/apps/network/cloudflare-tunnel/app/secret.sops.yaml create mode 100644 kubernetes/apps/network/cloudflare-tunnel/ks.yaml create mode 100644 kubernetes/apps/network/envoy-gateway/app/certificate.yaml create mode 100644 kubernetes/apps/network/envoy-gateway/app/envoy.yaml create mode 100644 kubernetes/apps/network/envoy-gateway/app/helmrelease.yaml create mode 100644 kubernetes/apps/network/envoy-gateway/app/kustomization.yaml create mode 100644 kubernetes/apps/network/envoy-gateway/app/ocirepository.yaml create mode 100644 kubernetes/apps/network/envoy-gateway/app/podmonitor.yaml create mode 100644 kubernetes/apps/network/envoy-gateway/ks.yaml create mode 100644 kubernetes/apps/network/k8s-gateway/app/helmrelease.yaml create mode 100644 kubernetes/apps/network/k8s-gateway/app/kustomization.yaml create mode 100644 kubernetes/apps/network/k8s-gateway/app/ocirepository.yaml create mode 100644 kubernetes/apps/network/k8s-gateway/ks.yaml create mode 100644 kubernetes/apps/network/kustomization.yaml create mode 100644 kubernetes/apps/network/namespace.yaml create mode 100644 kubernetes/components/sops/cluster-secrets.sops.yaml create mode 100644 kubernetes/components/sops/kustomization.yaml create mode 100644 kubernetes/flux/cluster/ks.yaml delete mode 100644 nodes.sample.yaml create mode 100644 talos/patches/README.md create mode 100644 talos/patches/controller/cluster.yaml create mode 100644 talos/patches/global/machine-files.yaml create mode 100644 talos/patches/global/machine-kubelet.yaml create mode 100644 talos/patches/global/machine-network.yaml create mode 100644 talos/patches/global/machine-sysctls.yaml create mode 100644 talos/patches/global/machine-time.yaml create mode 100644 talos/talconfig.yaml create mode 100644 talos/talenv.yaml diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..6af6f96 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,12 @@ +--- +creation_rules: + - path_regex: talos/.*\.sops\.ya?ml + mac_only_encrypted: true + age: "age1yzrqhl9dk8ljswpmzsqme3enad5kxxhsptdvecy3lwlq0ms80gaqxrctst" + - path_regex: (bootstrap|kubernetes)/.*\.sops\.ya?ml + encrypted_regex: "^(data|stringData)$" + mac_only_encrypted: true + age: "age1yzrqhl9dk8ljswpmzsqme3enad5kxxhsptdvecy3lwlq0ms80gaqxrctst" +stores: + yaml: + indent: 2 diff --git a/.yamlfmt.yaml b/.yamlfmt.yaml new file mode 100644 index 0000000..d7bd57f --- /dev/null +++ b/.yamlfmt.yaml @@ -0,0 +1,18 @@ +--- +doublestar: true + +exclude: + - "**/*.sops.yaml" + - "**/*/clusterconfig/*.yaml" + +formatter: + type: basic + indent: 2 + include_document_start: true + eof_newline: true + retain_line_breaks_single: true + max_line_length: 200 + drop_merge_tag: true + disable_alias_key_correction: true + scan_folded_as_literal: true + trim_trailing_whitespace: true \ No newline at end of file diff --git a/bootstrap/helmfile.d/00-crds.yaml b/bootstrap/helmfile.d/00-crds.yaml new file mode 100644 index 0000000..28d81e6 --- /dev/null +++ b/bootstrap/helmfile.d/00-crds.yaml @@ -0,0 +1,25 @@ +--- + +# This helmfile is for extracting and installing Custom Resource Definitions (CRDs) from Helm charts. +# It is not intended to be used with helmfile apply or helmfile sync. + +helmDefaults: + args: + - --include-crds + - --no-hooks + +releases: + - name: cloudflare-dns + namespace: network + chart: oci://ghcr.io/home-operations/charts-mirror/external-dns + version: 1.20.0 + + - name: envoy-gateway + namespace: network + chart: oci://mirror.gcr.io/envoyproxy/gateway-helm + version: v1.6.2 + + - name: kube-prometheus-stack + namespace: observability + chart: oci://ghcr.io/prometheus-community/charts/kube-prometheus-stack + version: 81.2.2 diff --git a/bootstrap/helmfile.d/01-apps.yaml b/bootstrap/helmfile.d/01-apps.yaml new file mode 100644 index 0000000..6b3ebdb --- /dev/null +++ b/bootstrap/helmfile.d/01-apps.yaml @@ -0,0 +1,48 @@ +--- + +helmDefaults: + cleanupOnFail: true + wait: true + waitForJobs: true + +releases: + - name: cilium + namespace: kube-system + chart: oci://quay.io/cilium/charts/cilium + version: 1.18.6 + values: ['./templates/values.yaml.gotmpl'] + + - name: coredns + namespace: kube-system + chart: oci://ghcr.io/coredns/charts/coredns + version: 1.45.2 + values: ['./templates/values.yaml.gotmpl'] + needs: ['kube-system/cilium'] + + - name: spegel + namespace: kube-system + chart: oci://ghcr.io/spegel-org/helm-charts/spegel + version: 0.6.0 + values: ['./templates/values.yaml.gotmpl'] + needs: ['kube-system/coredns'] + + - name: cert-manager + namespace: cert-manager + chart: oci://quay.io/jetstack/charts/cert-manager + version: v1.19.2 + values: ['./templates/values.yaml.gotmpl'] + needs: ['kube-system/spegel'] + + - name: flux-operator + namespace: flux-system + chart: oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator + version: 0.40.0 + values: ['./templates/values.yaml.gotmpl'] + needs: ['cert-manager/cert-manager'] + + - name: flux-instance + namespace: flux-system + chart: oci://ghcr.io/controlplaneio-fluxcd/charts/flux-instance + version: 0.40.0 + values: ['./templates/values.yaml.gotmpl'] + needs: ['flux-system/flux-operator'] diff --git a/bootstrap/helmfile.d/templates/values.yaml.gotmpl b/bootstrap/helmfile.d/templates/values.yaml.gotmpl new file mode 100644 index 0000000..2a046fa --- /dev/null +++ b/bootstrap/helmfile.d/templates/values.yaml.gotmpl @@ -0,0 +1 @@ +{{ (fromYaml (readFile (printf "../../../kubernetes/apps/%s/%s/app/helmrelease.yaml" .Release.Namespace .Release.Name))).spec.values | toYaml }} diff --git a/bootstrap/helmfile.yaml b/bootstrap/helmfile.yaml new file mode 100644 index 0000000..8f28cbd --- /dev/null +++ b/bootstrap/helmfile.yaml @@ -0,0 +1,27 @@ +--- +helmDefaults: + wait: true + waitForJobs: true + timeout: 600 + +releases: + - name: cilium + namespace: kube-system + chart: oci://quay.io/cilium/charts/cilium + version: 1.18.6 + values: ["templates/values.yaml.gotmpl"] + + - name: flux-operator + namespace: flux-system + chart: oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator + version: 0.40.0 + values: ["templates/values.yaml.gotmpl"] + createNamespace: true + needs: ["kube-system/cilium"] + + - name: flux-instance + namespace: flux-system + chart: oci://ghcr.io/controlplaneio-fluxcd/charts/flux-instance + version: 0.40.0 + needs: ["flux-system/flux-operator"] + values: ["templates/values.yaml.gotmpl"] \ No newline at end of file diff --git a/bootstrap/sops-age.sops.yaml b/bootstrap/sops-age.sops.yaml new file mode 100644 index 0000000..40ed513 --- /dev/null +++ b/bootstrap/sops-age.sops.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Secret +metadata: + name: sops-age + namespace: flux-system +stringData: + age.agekey: ENC[AES256_GCM,data:8Tmc5bJBbS8/qrUGKO7TzIekw/R3+D54Yhw1KlAyN9HQ0cYXoqyE7e4MRBXP1NT15rFMdvXWaoFzVq78Zr1h24rFenAk3PginaQ=,iv:KbPTRblvQfU2ntTEyfE7/WNQQlDbRkj//ek/O8c3vU8=,tag:TWsJIqIElvkA5tz27y8pJQ==,type:str] +sops: + age: + - recipient: age1yzrqhl9dk8ljswpmzsqme3enad5kxxhsptdvecy3lwlq0ms80gaqxrctst + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaOHpZakU0QklrV3JhU0Zn + MHlzS1pBL1JBWXBNd0U4MWZ4NHhFMWUzTWhZCmkwMzFFMk1lZVg2ekcxNEpBMk1p + czFaYy90c21LV3Avd2x2LzQ2cXpTL28KLS0tIHh5MWx4ZHdoTXF0b2pjdWZ3YUZv + WkUwK2pNbnNBZWpMSmFyVDcwb2RpVlUKeCXX25YHLe5GFYIwBemtvu5Hn+JqMlTM + mKRPTEpRsYFaiIeWkJIWVwCRZLcufXqLW5023AIqPYZs4saoZj0B5w== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-02-04T15:11:58Z" + mac: ENC[AES256_GCM,data:dOvZERpq3RqfiBi8tC1/SmCV32g2ioHo358Z+hmXv8coQyy4A0eQ+rCbCslR5pXgf4z3Hy5M2YpjyOYkAcpPAQQAx0H9UHzVEbvKc5I4h+v2urPU0bzuL8AgvlzYkYviVSQQc5Eu+OzXFBwU1TecFqNGL+a5wUzAQjh/PB35Fkw=,iv:h6OLj7j/ERgh04iL5eMqQ9FmcuPM+fPR7pCQD0uswN4=,tag:/bq9yY7P30kRjz2W5ivD3Q==,type:str] + encrypted_regex: ^(data|stringData)$ + mac_only_encrypted: true + version: 3.11.0 diff --git a/bootstrap/templates/values.yaml.gotmpl b/bootstrap/templates/values.yaml.gotmpl new file mode 100644 index 0000000..4196643 --- /dev/null +++ b/bootstrap/templates/values.yaml.gotmpl @@ -0,0 +1,3 @@ +{{ $helmReleasePath := printf "../../apps/%s/%s/app/helm-release.yaml" .Release.Namespace .Release.Name }} +{{ $helmRelease := fromYaml (readFile $helmReleasePath) }} +{{ $helmRelease.spec.values | toYaml }} \ No newline at end of file diff --git a/cluster.sample.yaml b/cluster.sample.yaml deleted file mode 100644 index 83a188b..0000000 --- a/cluster.sample.yaml +++ /dev/null @@ -1,84 +0,0 @@ ---- -# -- The network CIDR for the nodes. -# (REQUIRED) / (e.g. 192.168.1.0/24) -node_cidr: "" - -# -- DNS servers to use for the cluster. -# (OPTIONAL) / (DEFAULT: ["1.1.1.1", "1.0.0.1"]) / (Cloudflare DNS) -# node_dns_servers: [] - -# -- NTP servers to use for the cluster. -# (OPTIONAL) / (DEFAULT: ["162.159.200.1", "162.159.200.123"]) / (Cloudflare NTP) -# node_ntp_servers: [] - -# -- The default gateway for the nodes. -# (OPTIONAL) / (DEFAULT: the first IP in the node_cidr) -# node_default_gateway: "" - -# -- Attach a vlan tag to the Talos nodes. Not needed if ports on your switch are tagged or you are not using VLANs. -# (OPTIONAL) / (REF: https://www.talos.dev/latest/advanced/advanced-networking/#vlans) -# node_vlan_tag: "" - -# -- The IP address of the Kube API. -# (REQUIRED) / (NOTE: Choose an unused IP in node_cidr) -cluster_api_addr: "" - -# -- Additional SANs to add to the Kube API cert. This is useful if you want to call the Kube API by hostname rather than IP -# (OPTIONAL) / (e.g. ["mycluster.example.com"]) -# cluster_api_tls_sans: [] - -# -- The pod CIDR for the cluster, this must NOT overlap with any existing networks and should be a /16 (64K IPs). -# (OPTIONAL) / (DEFAULT: "10.42.0.0/16") -# cluster_pod_cidr: "" - -# -- The service CIDR for the cluster, this must NOT overlap with any existing networks and should be a /16 (64K IPs). -# (OPTIONAL) / (DEFAULT: "10.43.0.0/16") -# cluster_svc_cidr: "" - -# -- The Load balancer IP for k8s_gateway, this provides DNS to all your gateways when split DNS is configured on your internal DNS server (Dnsmasq, Pi-hole, etc) -# (REQUIRED) / (NOTE: Choose an unused IP in node_cidr) -cluster_dns_gateway_addr: "" - -# -- The Load balancer IP for the internal gateway -# (REQUIRED) / (NOTE: Choose an unused IP in node_cidr) -cluster_gateway_addr: "" - -# -- GitHub repository -# (REQUIRED) / (e.g. "onedr0p/cluster-template") -repository_name: "" - -# -- GitHub repository branch -# (OPTIONAL) / (DEFAULT: "main") -# repository_branch: "" - -# -- Repository visibility (public or private) -# (OPTIONAL) / (DEFAULT: "public") / (NOTE: See the README for information when set private) -# repository_visibility: "" - -# -- Domain you wish to use from your Cloudflare account -# (REQUIRED) / (e.g. "example.com") -cloudflare_domain: "" - -# -- API Token for Cloudflare with the 'Zone:DNS:Edit' and 'Account:Cloudflare Tunnel:Read' permissions -# (REQUIRED) (NOTE: See the README for information on creating this) -cloudflare_token: "" - -# -- The Load balancer IP for the external gateway -# (REQUIRED) / (NOTE: Choose an unused IP in node_cidr) -cloudflare_gateway_addr: "" - -# -- The load balancer mode for cilium. -# (OPTIONAL) / (DEFAULT: "dsr") / (NOTE: accepted values are 'dsr' or 'snat') / (REF: https://docs.cilium.io/en/stable/network/kubernetes/kubeproxy-free/) -# cilium_loadbalancer_mode: "" - -# -- The IP address of the BGP router, to keep things simple, node network will be used for BGP peering. -# (OPTIONAL) / (e.g. "192.168.1.1") / (REF: https://docs.cilium.io/en/latest/network/bgp-control-plane/bgp-control-plane/) -# cilium_bgp_router_addr: "" - -# -- The BGP router ASN -# (OPTIONAL) / (e.g. "64513") -# cilium_bgp_router_asn: "" - -# -- The BGP node ASN -# (OPTIONAL) / (e.g. "64514") -# cilium_bgp_node_asn: "" diff --git a/kubernetes/apps/cert-manager/cert-manager/app/clusterissuer.yaml b/kubernetes/apps/cert-manager/cert-manager/app/clusterissuer.yaml new file mode 100644 index 0000000..42bbd48 --- /dev/null +++ b/kubernetes/apps/cert-manager/cert-manager/app/clusterissuer.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-production +spec: + acme: + privateKeySecretRef: + name: letsencrypt-production + profile: shortlived + server: https://acme-v02.api.letsencrypt.org/directory + solvers: + - dns01: + cloudflare: + apiTokenSecretRef: + name: cert-manager-secret + key: api-token + selector: + dnsZones: ["${SECRET_DOMAIN}"] diff --git a/kubernetes/apps/cert-manager/cert-manager/app/helmrelease.yaml b/kubernetes/apps/cert-manager/cert-manager/app/helmrelease.yaml new file mode 100644 index 0000000..c6dd026 --- /dev/null +++ b/kubernetes/apps/cert-manager/cert-manager/app/helmrelease.yaml @@ -0,0 +1,20 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: cert-manager +spec: + chartRef: + kind: OCIRepository + name: cert-manager + interval: 1h + values: + crds: + enabled: true + replicaCount: 1 + dns01RecursiveNameservers: https://1.1.1.1:443/dns-query,https://1.0.0.1:443/dns-query + dns01RecursiveNameserversOnly: true + prometheus: + enabled: true + servicemonitor: + enabled: true diff --git a/kubernetes/apps/cert-manager/cert-manager/app/kustomization.yaml b/kubernetes/apps/cert-manager/cert-manager/app/kustomization.yaml new file mode 100644 index 0000000..353783a --- /dev/null +++ b/kubernetes/apps/cert-manager/cert-manager/app/kustomization.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./clusterissuer.yaml + - ./helmrelease.yaml + - ./ocirepository.yaml + - ./secret.sops.yaml diff --git a/kubernetes/apps/cert-manager/cert-manager/app/ocirepository.yaml b/kubernetes/apps/cert-manager/cert-manager/app/ocirepository.yaml new file mode 100644 index 0000000..53ec44f --- /dev/null +++ b/kubernetes/apps/cert-manager/cert-manager/app/ocirepository.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: cert-manager +spec: + interval: 15m + layerSelector: + mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip + operation: copy + ref: + tag: v1.19.2 + url: oci://quay.io/jetstack/charts/cert-manager diff --git a/kubernetes/apps/cert-manager/cert-manager/app/secret.sops.yaml b/kubernetes/apps/cert-manager/cert-manager/app/secret.sops.yaml new file mode 100644 index 0000000..82cc5eb --- /dev/null +++ b/kubernetes/apps/cert-manager/cert-manager/app/secret.sops.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Secret +metadata: + name: cert-manager-secret +stringData: + api-token: ENC[AES256_GCM,data:t13V8NLUI0E4hr7Z6uQ1liYFg9zqvqk=,iv:5if5UZzzVMFv5XPAFph811GPv8CG+werjquIfV+s7DU=,tag:0mFJ9Wg14No7pzs/XQs6nQ==,type:str] +sops: + age: + - recipient: age1yzrqhl9dk8ljswpmzsqme3enad5kxxhsptdvecy3lwlq0ms80gaqxrctst + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyZHJyWTA4azIvRVJIT2E5 + VmdBdVEvU0F5WVVPcEhoTllOKzZGakR5TkFzCnVBLzBQUzk2YlFGOFlUdVpLQ1p0 + Yy91WnUwNWpSL3lOWnBHejNRSXdyeFEKLS0tIDEvSmk0Q2dXODFQdTU0VTY2RVJC + TTd5QSt5RDk3bisxdmZDcitVVzJ1SEkKpe8IRsNrlNZEr40HULJc54S2IetE9zGN + cHWW7OhKqNOzryGFgQzlSz6CcJx0dtF57AT+URPFTJ2220YPkEdZLQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-02-04T15:11:58Z" + mac: ENC[AES256_GCM,data:EdGaHtdrRF92JZf2zVph9nUbA0juqvEP48B63HBuAuC8YbnjKLpn1aTqUmEKt2CZQvtXbZ00TAP10TXy/mF3LBY+3dKAo8VMaUVzlqFZzIXmQhks4vWaEJ+F41K+Hz2rGXdei+DT1hnyehDjW5k0koeNeDLC1CDNaQquPg58WeA=,iv:aAXfbAWo9sXsFrrRqS4zyipN2PUI0HKVOHuMJ68cgSI=,tag:xBAFOOInnEklMuRtbZpQjw==,type:str] + encrypted_regex: ^(data|stringData)$ + mac_only_encrypted: true + version: 3.11.0 diff --git a/kubernetes/apps/cert-manager/cert-manager/ks.yaml b/kubernetes/apps/cert-manager/cert-manager/ks.yaml new file mode 100644 index 0000000..c0a08eb --- /dev/null +++ b/kubernetes/apps/cert-manager/cert-manager/ks.yaml @@ -0,0 +1,31 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: cert-manager +spec: + healthChecks: + - apiVersion: helm.toolkit.fluxcd.io/v2 + kind: HelmRelease + name: cert-manager + namespace: cert-manager + - apiVersion: cert-manager.io/v1 + kind: ClusterIssuer + name: letsencrypt-production + 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') + interval: 1h + path: ./kubernetes/apps/cert-manager/cert-manager/app + postBuild: + substituteFrom: + - name: cluster-secrets + kind: Secret + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + targetNamespace: cert-manager diff --git a/kubernetes/apps/cert-manager/kustomization.yaml b/kubernetes/apps/cert-manager/kustomization.yaml new file mode 100644 index 0000000..e24fb0b --- /dev/null +++ b/kubernetes/apps/cert-manager/kustomization.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: cert-manager + +components: + - ../../components/sops + +resources: + - ./namespace.yaml + - ./cert-manager/ks.yaml diff --git a/kubernetes/apps/cert-manager/namespace.yaml b/kubernetes/apps/cert-manager/namespace.yaml new file mode 100644 index 0000000..6e34540 --- /dev/null +++ b/kubernetes/apps/cert-manager/namespace.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: cert-manager + annotations: + kustomize.toolkit.fluxcd.io/prune: disabled diff --git a/kubernetes/apps/default/echo/app/helmrelease.yaml b/kubernetes/apps/default/echo/app/helmrelease.yaml new file mode 100644 index 0000000..b6c34cd --- /dev/null +++ b/kubernetes/apps/default/echo/app/helmrelease.yaml @@ -0,0 +1,71 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: echo +spec: + chartRef: + kind: OCIRepository + name: echo + interval: 1h + values: + controllers: + echo: + strategy: RollingUpdate + containers: + app: + image: + repository: ghcr.io/mendhak/http-https-echo + tag: 39 + 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"] } + resources: + requests: + cpu: 10m + limits: + memory: 64Mi + defaultPodOptions: + securityContext: + runAsNonRoot: true + runAsUser: 65534 + runAsGroup: 65534 + service: + app: + ports: + http: + port: *port + serviceMonitor: + app: + endpoints: + - port: http + route: + app: + hostnames: ["{{ .Release.Name }}.${SECRET_DOMAIN}"] + parentRefs: + - name: envoy-external + namespace: network + sectionName: https + rules: + - backendRefs: + - identifier: app + port: *port diff --git a/kubernetes/apps/default/echo/app/kustomization.yaml b/kubernetes/apps/default/echo/app/kustomization.yaml new file mode 100644 index 0000000..2ccd5a8 --- /dev/null +++ b/kubernetes/apps/default/echo/app/kustomization.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./helmrelease.yaml + - ./ocirepository.yaml diff --git a/kubernetes/apps/default/echo/app/ocirepository.yaml b/kubernetes/apps/default/echo/app/ocirepository.yaml new file mode 100644 index 0000000..ff5d836 --- /dev/null +++ b/kubernetes/apps/default/echo/app/ocirepository.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: echo +spec: + interval: 15m + 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 diff --git a/kubernetes/apps/default/echo/ks.yaml b/kubernetes/apps/default/echo/ks.yaml new file mode 100644 index 0000000..f942a81 --- /dev/null +++ b/kubernetes/apps/default/echo/ks.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: echo +spec: + interval: 1h + path: ./kubernetes/apps/default/echo/app + postBuild: + substituteFrom: + - name: cluster-secrets + kind: Secret + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + targetNamespace: default + wait: false diff --git a/kubernetes/apps/default/kustomization.yaml b/kubernetes/apps/default/kustomization.yaml new file mode 100644 index 0000000..d7271b1 --- /dev/null +++ b/kubernetes/apps/default/kustomization.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: default + +components: + - ../../components/sops + +resources: + - ./namespace.yaml + - ./echo/ks.yaml diff --git a/kubernetes/apps/default/namespace.yaml b/kubernetes/apps/default/namespace.yaml new file mode 100644 index 0000000..e3f8a49 --- /dev/null +++ b/kubernetes/apps/default/namespace.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: default + annotations: + kustomize.toolkit.fluxcd.io/prune: disabled diff --git a/kubernetes/apps/flux-system/flux-instance/app/helmrelease.yaml b/kubernetes/apps/flux-system/flux-instance/app/helmrelease.yaml new file mode 100644 index 0000000..ef26fff --- /dev/null +++ b/kubernetes/apps/flux-system/flux-instance/app/helmrelease.yaml @@ -0,0 +1,133 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: flux-instance +spec: + chartRef: + kind: OCIRepository + name: flux-instance + interval: 1h + values: + instance: + distribution: + artifact: oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests:v0.40.0 + cluster: + networkPolicy: false + components: + - source-controller + - kustomize-controller + - helm-controller + - notification-controller + sync: + kind: GitRepository + url: "https://git.laurivan.com/Dev/cluster.git" + ref: "refs/heads/main" + path: kubernetes/flux/cluster + commonMetadata: + labels: + app.kubernetes.io/name: flux + kustomize: + patches: + - # Increase the number of workers + patch: | + - op: add + path: /spec/template/spec/containers/0/args/- + value: --concurrent=10 + - op: add + path: /spec/template/spec/containers/0/args/- + value: --requeue-dependency=5s + target: + kind: Deployment + name: (kustomize-controller|helm-controller|source-controller) + - # Increase the memory limits + patch: | + apiVersion: apps/v1 + kind: Deployment + metadata: + name: all + spec: + template: + spec: + containers: + - name: manager + resources: + limits: + memory: 1Gi + target: + kind: Deployment + name: (kustomize-controller|helm-controller|source-controller) + - # Enable in-memory kustomize builds + patch: | + - op: add + path: /spec/template/spec/containers/0/args/- + value: --concurrent=20 + - op: replace + path: /spec/template/spec/volumes/0 + value: + name: temp + emptyDir: + medium: Memory + 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 + - 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 + - # Disable chart digest tracking + patch: | + - op: add + path: /spec/template/spec/containers/0/args/- + value: --feature-gates=DisableChartDigestTracking=true + target: + kind: Deployment + name: helm-controller + - # Controller-level SOPS decryption + patch: | + - op: add + path: /spec/template/spec/containers/0/args/- + value: --sops-age-secret=sops-age + 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 diff --git a/kubernetes/apps/flux-system/flux-instance/app/httproute.yaml b/kubernetes/apps/flux-system/flux-instance/app/httproute.yaml new file mode 100644 index 0000000..2f089a0 --- /dev/null +++ b/kubernetes/apps/flux-system/flux-instance/app/httproute.yaml @@ -0,0 +1,20 @@ +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: github-webhook +spec: + hostnames: ["flux-webhook.${SECRET_DOMAIN}"] + parentRefs: + - name: envoy-external + namespace: network + sectionName: https + rules: + - backendRefs: + - name: webhook-receiver + namespace: flux-system + port: 80 + matches: + - path: + type: PathPrefix + value: /hook/ diff --git a/kubernetes/apps/flux-system/flux-instance/app/kustomization.yaml b/kubernetes/apps/flux-system/flux-instance/app/kustomization.yaml new file mode 100644 index 0000000..09ae970 --- /dev/null +++ b/kubernetes/apps/flux-system/flux-instance/app/kustomization.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./helmrelease.yaml + - ./ocirepository.yaml + - ./secret.sops.yaml + - ./httproute.yaml + - ./receiver.yaml diff --git a/kubernetes/apps/flux-system/flux-instance/app/ocirepository.yaml b/kubernetes/apps/flux-system/flux-instance/app/ocirepository.yaml new file mode 100644 index 0000000..618bae6 --- /dev/null +++ b/kubernetes/apps/flux-system/flux-instance/app/ocirepository.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: flux-instance +spec: + interval: 15m + layerSelector: + mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip + operation: copy + ref: + tag: 0.40.0 + url: oci://ghcr.io/controlplaneio-fluxcd/charts/flux-instance diff --git a/kubernetes/apps/flux-system/flux-instance/app/receiver.yaml b/kubernetes/apps/flux-system/flux-instance/app/receiver.yaml new file mode 100644 index 0000000..d7d2942 --- /dev/null +++ b/kubernetes/apps/flux-system/flux-instance/app/receiver.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: notification.toolkit.fluxcd.io/v1 +kind: Receiver +metadata: + name: github-webhook +spec: + type: github + events: ["ping", "push"] + secretRef: + name: github-webhook-token-secret + resources: + - apiVersion: source.toolkit.fluxcd.io/v1 + kind: GitRepository + name: flux-system + namespace: flux-system + - apiVersion: kustomize.toolkit.fluxcd.io/v1 + kind: Kustomization + name: flux-system + namespace: flux-system diff --git a/kubernetes/apps/flux-system/flux-instance/app/secret.sops.yaml b/kubernetes/apps/flux-system/flux-instance/app/secret.sops.yaml new file mode 100644 index 0000000..0519dfe --- /dev/null +++ b/kubernetes/apps/flux-system/flux-instance/app/secret.sops.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Secret +metadata: + name: github-webhook-token-secret +stringData: + token: ENC[AES256_GCM,data:tLNHubXDxl1N78+Xbvx5MnjkwmunVmkSx5PJfDFI3lM=,iv:FrBOejFWHlw+/e36xhubNNVaL7CzF80VBZAs3mdRsfo=,tag:OWsTo+s5s0mnVyJYgAIRsA==,type:str] +sops: + age: + - recipient: age1yzrqhl9dk8ljswpmzsqme3enad5kxxhsptdvecy3lwlq0ms80gaqxrctst + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEZWtUdEF2dmlHNjN6MGND + N056RUU0QlNrR1lncTNSSkhMUGtHMFF5Sms0Cjl3TWVrZ3JyakhDQ0IzcHpFcVNq + SGZQZ2dDSlcwWkVYY3JrWjFFRnVFR1kKLS0tIFNldFhQNTBJME4xclZUOElDYUVu + akQ1cXFzR3UvMEsvRFBEVlREWmdZd2MK66s7WhNU8Nzw57JX8VSVfQj5ZLRLYFWu + KelG/NMpGRiMm5nNcriAjNas1IpGB6C19qMA/V0k/UPcxZYla5MvqA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-02-04T15:11:58Z" + mac: ENC[AES256_GCM,data:uneVTP2R42tjVtzZhTF85YUDw38uOzHmnBxP/VctwEGFHoZkAEqQmNo2pZOHgfLFdMMKYJYTx6E6WqBDnU5YS/5DxfOZyQa/zhfYVWddL1do42tOAwfM89KgLx2rtxWOV3Ztimb6ZAM8zPnUuuGgMJX7GLetoqOxJLa4frZLKnk=,iv:2RH6X6dgSOXPRHWiHgmJGyY4HdepDoVtKRu/c1Aex4E=,tag:0wdRlHAxJg2rE2oR3M+vpA==,type:str] + encrypted_regex: ^(data|stringData)$ + mac_only_encrypted: true + version: 3.11.0 diff --git a/kubernetes/apps/flux-system/flux-instance/ks.yaml b/kubernetes/apps/flux-system/flux-instance/ks.yaml new file mode 100644 index 0000000..1a35461 --- /dev/null +++ b/kubernetes/apps/flux-system/flux-instance/ks.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: flux-instance +spec: + dependsOn: + - name: flux-operator + interval: 1h + path: ./kubernetes/apps/flux-system/flux-instance/app + postBuild: + substituteFrom: + - name: cluster-secrets + kind: Secret + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + targetNamespace: flux-system + wait: false diff --git a/kubernetes/apps/flux-system/flux-operator/app/helmrelease.yaml b/kubernetes/apps/flux-system/flux-operator/app/helmrelease.yaml new file mode 100644 index 0000000..08fba38 --- /dev/null +++ b/kubernetes/apps/flux-system/flux-operator/app/helmrelease.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: flux-operator +spec: + chartRef: + kind: OCIRepository + name: flux-operator + interval: 1h + values: + serviceMonitor: + create: true diff --git a/kubernetes/apps/flux-system/flux-operator/app/kustomization.yaml b/kubernetes/apps/flux-system/flux-operator/app/kustomization.yaml new file mode 100644 index 0000000..2ccd5a8 --- /dev/null +++ b/kubernetes/apps/flux-system/flux-operator/app/kustomization.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./helmrelease.yaml + - ./ocirepository.yaml diff --git a/kubernetes/apps/flux-system/flux-operator/app/ocirepository.yaml b/kubernetes/apps/flux-system/flux-operator/app/ocirepository.yaml new file mode 100644 index 0000000..701f9d9 --- /dev/null +++ b/kubernetes/apps/flux-system/flux-operator/app/ocirepository.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: flux-operator +spec: + interval: 15m + layerSelector: + mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip + operation: copy + ref: + tag: 0.40.0 + url: oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator diff --git a/kubernetes/apps/flux-system/flux-operator/ks.yaml b/kubernetes/apps/flux-system/flux-operator/ks.yaml new file mode 100644 index 0000000..2e39824 --- /dev/null +++ b/kubernetes/apps/flux-system/flux-operator/ks.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: flux-operator +spec: + interval: 1h + path: ./kubernetes/apps/flux-system/flux-operator/app + postBuild: + substituteFrom: + - name: cluster-secrets + kind: Secret + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + targetNamespace: flux-system + wait: true diff --git a/kubernetes/apps/flux-system/kustomization.yaml b/kubernetes/apps/flux-system/kustomization.yaml new file mode 100644 index 0000000..4b0dd43 --- /dev/null +++ b/kubernetes/apps/flux-system/kustomization.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: flux-system + +components: + - ../../components/sops + +resources: + - ./namespace.yaml + - ./flux-instance/ks.yaml + - ./flux-operator/ks.yaml diff --git a/kubernetes/apps/flux-system/namespace.yaml b/kubernetes/apps/flux-system/namespace.yaml new file mode 100644 index 0000000..120760a --- /dev/null +++ b/kubernetes/apps/flux-system/namespace.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: flux-system + annotations: + kustomize.toolkit.fluxcd.io/prune: disabled diff --git a/kubernetes/apps/kube-system/cilium/app/helmrelease.yaml b/kubernetes/apps/kube-system/cilium/app/helmrelease.yaml new file mode 100644 index 0000000..808d8b1 --- /dev/null +++ b/kubernetes/apps/kube-system/cilium/app/helmrelease.yaml @@ -0,0 +1,87 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: cilium +spec: + chartRef: + kind: OCIRepository + name: cilium + interval: 1h + values: + autoDirectNodeRoutes: true + bpf: + masquerade: true + # Ref: https://github.com/siderolabs/talos/issues/10002 + hostLegacyRouting: true + cni: + # Required for pairing with Multus CNI + exclusive: false + cgroup: + automount: + enabled: false + hostRoot: /sys/fs/cgroup + # NOTE: devices might need to be set if you have more than one active NIC on your hosts + # devices: eno+ eth+ + dashboards: + enabled: true + endpointRoutes: + enabled: true + envoy: + enabled: false + gatewayAPI: + enabled: false + hubble: + enabled: false + ipam: + mode: kubernetes + ipv4NativeRoutingCIDR: "10.42.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: "dsr" + localRedirectPolicy: true + operator: + dashboards: + enabled: true + prometheus: + enabled: true + serviceMonitor: + enabled: true + replicas: 1 + rollOutPods: true + prometheus: + enabled: true + serviceMonitor: + enabled: true + trustCRDsExist: true + 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 diff --git a/kubernetes/apps/kube-system/cilium/app/kustomization.yaml b/kubernetes/apps/kube-system/cilium/app/kustomization.yaml new file mode 100644 index 0000000..791e352 --- /dev/null +++ b/kubernetes/apps/kube-system/cilium/app/kustomization.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./helmrelease.yaml + - ./ocirepository.yaml + - ./networks.yaml diff --git a/kubernetes/apps/kube-system/cilium/app/networks.yaml b/kubernetes/apps/kube-system/cilium/app/networks.yaml new file mode 100644 index 0000000..a12ea35 --- /dev/null +++ b/kubernetes/apps/kube-system/cilium/app/networks.yaml @@ -0,0 +1,23 @@ +--- +apiVersion: cilium.io/v2alpha1 +kind: CiliumLoadBalancerIPPool +metadata: + name: pool +spec: + allowFirstLastIPs: "No" + blocks: + - cidr: "10.0.50.0/24" +--- +apiVersion: cilium.io/v2alpha1 +kind: CiliumL2AnnouncementPolicy +metadata: + name: l2-policy +spec: + loadBalancerIPs: true + # NOTE: interfaces might need to be set if you have more than one active NIC on your hosts + # interfaces: + # - ^eno[0-9]+ + # - ^eth[0-9]+ + nodeSelector: + matchLabels: + kubernetes.io/os: linux diff --git a/kubernetes/apps/kube-system/cilium/app/ocirepository.yaml b/kubernetes/apps/kube-system/cilium/app/ocirepository.yaml new file mode 100644 index 0000000..dd68c52 --- /dev/null +++ b/kubernetes/apps/kube-system/cilium/app/ocirepository.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: cilium +spec: + interval: 15m + layerSelector: + mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip + operation: copy + ref: + tag: 1.18.6 + url: oci://quay.io/cilium/charts/cilium diff --git a/kubernetes/apps/kube-system/cilium/ks.yaml b/kubernetes/apps/kube-system/cilium/ks.yaml new file mode 100644 index 0000000..ea0a835 --- /dev/null +++ b/kubernetes/apps/kube-system/cilium/ks.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: cilium +spec: + interval: 1h + path: ./kubernetes/apps/kube-system/cilium/app + postBuild: + substituteFrom: + - name: cluster-secrets + kind: Secret + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + targetNamespace: kube-system + wait: false diff --git a/kubernetes/apps/kube-system/coredns/app/helmrelease.yaml b/kubernetes/apps/kube-system/coredns/app/helmrelease.yaml new file mode 100644 index 0000000..af58f6a --- /dev/null +++ b/kubernetes/apps/kube-system/coredns/app/helmrelease.yaml @@ -0,0 +1,67 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: coredns +spec: + chartRef: + kind: OCIRepository + name: coredns + interval: 1h + values: + fullnameOverride: coredns + image: + repository: mirror.gcr.io/coredns/coredns + k8sAppLabelOverride: kube-dns + serviceAccount: + create: true + service: + name: kube-dns + clusterIP: "10.43.0.10" + replicaCount: 2 + servers: + - zones: + - zone: . + scheme: dns:// + use_tcp: true + port: 53 + plugins: + - name: errors + - name: health + configBlock: |- + lameduck 5s + - name: ready + - name: kubernetes + parameters: cluster.local in-addr.arpa ip6.arpa + configBlock: |- + pods verified + fallthrough in-addr.arpa ip6.arpa + - name: autopath + parameters: "@kubernetes" + - name: forward + parameters: . /etc/resolv.conf + - name: cache + configBlock: |- + prefetch 20 + serve_stale + - name: loop + - name: reload + - name: loadbalance + - name: prometheus + parameters: 0.0.0.0:9153 + - name: log + configBlock: |- + class error + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node-role.kubernetes.io/control-plane + operator: Exists + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - key: node-role.kubernetes.io/control-plane + operator: Exists + effect: NoSchedule diff --git a/kubernetes/apps/kube-system/coredns/app/kustomization.yaml b/kubernetes/apps/kube-system/coredns/app/kustomization.yaml new file mode 100644 index 0000000..2ccd5a8 --- /dev/null +++ b/kubernetes/apps/kube-system/coredns/app/kustomization.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./helmrelease.yaml + - ./ocirepository.yaml diff --git a/kubernetes/apps/kube-system/coredns/app/ocirepository.yaml b/kubernetes/apps/kube-system/coredns/app/ocirepository.yaml new file mode 100644 index 0000000..5c40bea --- /dev/null +++ b/kubernetes/apps/kube-system/coredns/app/ocirepository.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: coredns +spec: + interval: 15m + layerSelector: + mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip + operation: copy + url: oci://ghcr.io/coredns/charts/coredns + ref: + tag: 1.45.2 diff --git a/kubernetes/apps/kube-system/coredns/ks.yaml b/kubernetes/apps/kube-system/coredns/ks.yaml new file mode 100644 index 0000000..5ac2a87 --- /dev/null +++ b/kubernetes/apps/kube-system/coredns/ks.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: coredns +spec: + interval: 1h + path: ./kubernetes/apps/kube-system/coredns/app + postBuild: + substituteFrom: + - name: cluster-secrets + kind: Secret + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + targetNamespace: kube-system + wait: false diff --git a/kubernetes/apps/kube-system/kustomization.yaml b/kubernetes/apps/kube-system/kustomization.yaml new file mode 100644 index 0000000..c52fff4 --- /dev/null +++ b/kubernetes/apps/kube-system/kustomization.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: kube-system + +components: + - ../../components/sops + +resources: + - ./namespace.yaml + - ./cilium/ks.yaml + - ./coredns/ks.yaml + - ./metrics-server/ks.yaml + - ./reloader/ks.yaml + - ./spegel/ks.yaml diff --git a/kubernetes/apps/kube-system/metrics-server/app/helmrelease.yaml b/kubernetes/apps/kube-system/metrics-server/app/helmrelease.yaml new file mode 100644 index 0000000..befc886 --- /dev/null +++ b/kubernetes/apps/kube-system/metrics-server/app/helmrelease.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: metrics-server +spec: + chartRef: + kind: OCIRepository + name: metrics-server + interval: 1h + values: + args: + - --kubelet-insecure-tls + - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname + - --kubelet-use-node-status-port + - --metric-resolution=10s + - --kubelet-request-timeout=2s + metrics: + enabled: true + serviceMonitor: + enabled: true diff --git a/kubernetes/apps/kube-system/metrics-server/app/kustomization.yaml b/kubernetes/apps/kube-system/metrics-server/app/kustomization.yaml new file mode 100644 index 0000000..2ccd5a8 --- /dev/null +++ b/kubernetes/apps/kube-system/metrics-server/app/kustomization.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./helmrelease.yaml + - ./ocirepository.yaml diff --git a/kubernetes/apps/kube-system/metrics-server/app/ocirepository.yaml b/kubernetes/apps/kube-system/metrics-server/app/ocirepository.yaml new file mode 100644 index 0000000..d86e7a5 --- /dev/null +++ b/kubernetes/apps/kube-system/metrics-server/app/ocirepository.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: metrics-server +spec: + interval: 15m + 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 diff --git a/kubernetes/apps/kube-system/metrics-server/ks.yaml b/kubernetes/apps/kube-system/metrics-server/ks.yaml new file mode 100644 index 0000000..60042b7 --- /dev/null +++ b/kubernetes/apps/kube-system/metrics-server/ks.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: metrics-server +spec: + interval: 1h + path: ./kubernetes/apps/kube-system/metrics-server/app + postBuild: + substituteFrom: + - name: cluster-secrets + kind: Secret + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + targetNamespace: kube-system + wait: false diff --git a/kubernetes/apps/kube-system/namespace.yaml b/kubernetes/apps/kube-system/namespace.yaml new file mode 100644 index 0000000..7f6e64f --- /dev/null +++ b/kubernetes/apps/kube-system/namespace.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: kube-system + annotations: + kustomize.toolkit.fluxcd.io/prune: disabled diff --git a/kubernetes/apps/kube-system/reloader/app/helmrelease.yaml b/kubernetes/apps/kube-system/reloader/app/helmrelease.yaml new file mode 100644 index 0000000..100b095 --- /dev/null +++ b/kubernetes/apps/kube-system/reloader/app/helmrelease.yaml @@ -0,0 +1,17 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: reloader +spec: + chartRef: + kind: OCIRepository + name: reloader + interval: 1h + values: + fullnameOverride: reloader + reloader: + readOnlyRootFileSystem: true + podMonitor: + enabled: true + namespace: "{{ .Release.Namespace }}" diff --git a/kubernetes/apps/kube-system/reloader/app/kustomization.yaml b/kubernetes/apps/kube-system/reloader/app/kustomization.yaml new file mode 100644 index 0000000..2ccd5a8 --- /dev/null +++ b/kubernetes/apps/kube-system/reloader/app/kustomization.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./helmrelease.yaml + - ./ocirepository.yaml diff --git a/kubernetes/apps/kube-system/reloader/app/ocirepository.yaml b/kubernetes/apps/kube-system/reloader/app/ocirepository.yaml new file mode 100644 index 0000000..0c87ef7 --- /dev/null +++ b/kubernetes/apps/kube-system/reloader/app/ocirepository.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: reloader +spec: + interval: 15m + layerSelector: + mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip + operation: copy + ref: + tag: 2.2.7 + url: oci://ghcr.io/stakater/charts/reloader diff --git a/kubernetes/apps/kube-system/reloader/ks.yaml b/kubernetes/apps/kube-system/reloader/ks.yaml new file mode 100644 index 0000000..5f5c65a --- /dev/null +++ b/kubernetes/apps/kube-system/reloader/ks.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: reloader +spec: + interval: 1h + path: ./kubernetes/apps/kube-system/reloader/app + postBuild: + substituteFrom: + - name: cluster-secrets + kind: Secret + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + targetNamespace: kube-system + wait: false diff --git a/kubernetes/apps/kube-system/spegel/app/helmrelease.yaml b/kubernetes/apps/kube-system/spegel/app/helmrelease.yaml new file mode 100644 index 0000000..9a150b5 --- /dev/null +++ b/kubernetes/apps/kube-system/spegel/app/helmrelease.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: spegel +spec: + chartRef: + kind: OCIRepository + name: spegel + interval: 1h + values: + spegel: + containerdSock: /run/containerd/containerd.sock + containerdRegistryConfigPath: /etc/cri/conf.d/hosts + service: + registry: + hostPort: 29999 + serviceMonitor: + enabled: true diff --git a/kubernetes/apps/kube-system/spegel/app/kustomization.yaml b/kubernetes/apps/kube-system/spegel/app/kustomization.yaml new file mode 100644 index 0000000..2ccd5a8 --- /dev/null +++ b/kubernetes/apps/kube-system/spegel/app/kustomization.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./helmrelease.yaml + - ./ocirepository.yaml diff --git a/kubernetes/apps/kube-system/spegel/app/ocirepository.yaml b/kubernetes/apps/kube-system/spegel/app/ocirepository.yaml new file mode 100644 index 0000000..ff4c7e2 --- /dev/null +++ b/kubernetes/apps/kube-system/spegel/app/ocirepository.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: spegel +spec: + interval: 15m + layerSelector: + mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip + operation: copy + ref: + tag: 0.6.0 + url: oci://ghcr.io/spegel-org/helm-charts/spegel diff --git a/kubernetes/apps/kube-system/spegel/ks.yaml b/kubernetes/apps/kube-system/spegel/ks.yaml new file mode 100644 index 0000000..f6a6a48 --- /dev/null +++ b/kubernetes/apps/kube-system/spegel/ks.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: spegel +spec: + interval: 1h + path: ./kubernetes/apps/kube-system/spegel/app + postBuild: + substituteFrom: + - name: cluster-secrets + kind: Secret + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + targetNamespace: kube-system + wait: false diff --git a/kubernetes/apps/network/cloudflare-dns/app/helmrelease.yaml b/kubernetes/apps/network/cloudflare-dns/app/helmrelease.yaml new file mode 100644 index 0000000..3aa14a9 --- /dev/null +++ b/kubernetes/apps/network/cloudflare-dns/app/helmrelease.yaml @@ -0,0 +1,35 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: &app cloudflare-dns +spec: + chartRef: + kind: OCIRepository + name: cloudflare-dns + interval: 1h + values: + fullnameOverride: *app + provider: cloudflare + env: + - name: CF_API_TOKEN + valueFrom: + secretKeyRef: + name: &secret cloudflare-dns-secret + key: api-token + extraArgs: + - --cloudflare-dns-records-per-page=1000 + - --cloudflare-proxied + - --crd-source-apiversion=externaldns.k8s.io/v1alpha1 + - --crd-source-kind=DNSEndpoint + - --gateway-name=envoy-external + triggerLoopOnEvent: true + policy: sync + sources: ["crd", "gateway-httproute"] + txtPrefix: k8s. + txtOwnerId: default + domainFilters: ["${SECRET_DOMAIN}"] + serviceMonitor: + enabled: true + podAnnotations: + secret.reloader.stakater.com/reload: *secret diff --git a/kubernetes/apps/network/cloudflare-dns/app/kustomization.yaml b/kubernetes/apps/network/cloudflare-dns/app/kustomization.yaml new file mode 100644 index 0000000..0684e08 --- /dev/null +++ b/kubernetes/apps/network/cloudflare-dns/app/kustomization.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./secret.sops.yaml + - ./helmrelease.yaml + - ./ocirepository.yaml diff --git a/kubernetes/apps/network/cloudflare-dns/app/ocirepository.yaml b/kubernetes/apps/network/cloudflare-dns/app/ocirepository.yaml new file mode 100644 index 0000000..e57e928 --- /dev/null +++ b/kubernetes/apps/network/cloudflare-dns/app/ocirepository.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: cloudflare-dns +spec: + interval: 15m + layerSelector: + mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip + operation: copy + ref: + tag: 1.20.0 + url: oci://ghcr.io/home-operations/charts-mirror/external-dns diff --git a/kubernetes/apps/network/cloudflare-dns/app/secret.sops.yaml b/kubernetes/apps/network/cloudflare-dns/app/secret.sops.yaml new file mode 100644 index 0000000..398c9c2 --- /dev/null +++ b/kubernetes/apps/network/cloudflare-dns/app/secret.sops.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Secret +metadata: + name: cloudflare-dns-secret +stringData: + api-token: ENC[AES256_GCM,data:frBQb25KoVTFgZynCo53dCsqZjwrTEw=,iv:PoDzL7jGaUTX3haNKOpvlHix3iy1JmB3r17P5gNeM7Q=,tag:TvV3ukjbCJYmuky4DnHeFQ==,type:str] +sops: + age: + - recipient: age1yzrqhl9dk8ljswpmzsqme3enad5kxxhsptdvecy3lwlq0ms80gaqxrctst + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3ZjZZVHEyS3lJOGxPbUg1 + YWJ2bE9Sb09LTURKSXNYRktRQzhTV2s4bGc0CloxRURDcGR6Slk5OEhYbXNiMDlh + aVFVU2t6UzFMWmtxdTBhUzdMa3VaeFkKLS0tIGpqM3JrZkpMaXcrd25CckMzTVJY + bTFZTkpENlNvcVJZdFFKei9SanBsWFkKaNVws0/+DWbJkWiIbHOVWMyLEs0+u/EP + fhKLTq19y3BFcpQ/I+fUIMv1RAM625pMHWVgbrLjTsd3oUcNfkwqBg== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-02-04T15:11:58Z" + mac: ENC[AES256_GCM,data:5jljEilHlV3sPbFB+s3T86gjr7R0RKKLJjud1/GhwzcjAT3eYhIEsXWcaEAaA6MDzVxs2iTCWSzYC3zZFzBfjvjX37WFL45sHtWqbcHTDjeWbCFW6HxNzSzb/HHZhIUwYdC/7gU0QjeiDrJ5JObQFo9vnTsD+uCboXAVeRYKSgM=,iv:I/DUujV01ih78fIjge3dgPCGPRxtEej3rRTR7f4gXT8=,tag:dZXeULPGscc7r9KzhMDa+Q==,type:str] + encrypted_regex: ^(data|stringData)$ + mac_only_encrypted: true + version: 3.11.0 diff --git a/kubernetes/apps/network/cloudflare-dns/ks.yaml b/kubernetes/apps/network/cloudflare-dns/ks.yaml new file mode 100644 index 0000000..18d5db5 --- /dev/null +++ b/kubernetes/apps/network/cloudflare-dns/ks.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: cloudflare-dns +spec: + interval: 1h + path: ./kubernetes/apps/network/cloudflare-dns/app + postBuild: + substituteFrom: + - name: cluster-secrets + kind: Secret + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + targetNamespace: network + wait: true diff --git a/kubernetes/apps/network/cloudflare-tunnel/app/dnsendpoint.yaml b/kubernetes/apps/network/cloudflare-tunnel/app/dnsendpoint.yaml new file mode 100644 index 0000000..c4470df --- /dev/null +++ b/kubernetes/apps/network/cloudflare-tunnel/app/dnsendpoint.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: externaldns.k8s.io/v1alpha1 +kind: DNSEndpoint +metadata: + name: cloudflare-tunnel +spec: + endpoints: + - dnsName: "external.${SECRET_DOMAIN}" + recordType: CNAME + targets: ["7246088b-1c4b-4097-833f-a8995ac71265.cfargotunnel.com"] diff --git a/kubernetes/apps/network/cloudflare-tunnel/app/helmrelease.yaml b/kubernetes/apps/network/cloudflare-tunnel/app/helmrelease.yaml new file mode 100644 index 0000000..fa3196c --- /dev/null +++ b/kubernetes/apps/network/cloudflare-tunnel/app/helmrelease.yaml @@ -0,0 +1,84 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: cloudflare-tunnel +spec: + chartRef: + kind: OCIRepository + name: cloudflare-tunnel + interval: 1h + values: + controllers: + cloudflare-tunnel: + strategy: RollingUpdate + annotations: + reloader.stakater.com/auto: "true" + containers: + app: + image: + repository: docker.io/cloudflare/cloudflared + tag: 2026.1.1 + env: + NO_AUTOUPDATE: true + TUNNEL_METRICS: 0.0.0.0:8080 + TUNNEL_POST_QUANTUM: true # disable when using http2 + TUNNEL_TRANSPORT_PROTOCOL: quic # or http2 + 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: 10m + limits: + memory: 256Mi + defaultPodOptions: + securityContext: + runAsNonRoot: true + runAsUser: 65534 + runAsGroup: 65534 + service: + app: + ports: + http: + port: *port + serviceMonitor: + app: + endpoints: + - port: http + configMaps: + config: + data: + config.yaml: |- + ingress: + - hostname: "*.${SECRET_DOMAIN}" + originRequest: + http2Origin: true + originServerName: external.${SECRET_DOMAIN} + service: https://envoy-external.{{ .Release.Namespace }}.svc.cluster.local:443 + - service: http_status:404 + persistence: + config-file: + type: configMap + identifier: config + globalMounts: + - path: /etc/cloudflared/config.yaml + subPath: config.yaml diff --git a/kubernetes/apps/network/cloudflare-tunnel/app/kustomization.yaml b/kubernetes/apps/network/cloudflare-tunnel/app/kustomization.yaml new file mode 100644 index 0000000..dbc11de --- /dev/null +++ b/kubernetes/apps/network/cloudflare-tunnel/app/kustomization.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./dnsendpoint.yaml + - ./secret.sops.yaml + - ./helmrelease.yaml + - ./ocirepository.yaml diff --git a/kubernetes/apps/network/cloudflare-tunnel/app/ocirepository.yaml b/kubernetes/apps/network/cloudflare-tunnel/app/ocirepository.yaml new file mode 100644 index 0000000..67904bd --- /dev/null +++ b/kubernetes/apps/network/cloudflare-tunnel/app/ocirepository.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: cloudflare-tunnel +spec: + interval: 15m + 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 diff --git a/kubernetes/apps/network/cloudflare-tunnel/app/secret.sops.yaml b/kubernetes/apps/network/cloudflare-tunnel/app/secret.sops.yaml new file mode 100644 index 0000000..e8328ba --- /dev/null +++ b/kubernetes/apps/network/cloudflare-tunnel/app/secret.sops.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Secret +metadata: + name: cloudflare-tunnel-secret +stringData: + TUNNEL_TOKEN: ENC[AES256_GCM,data:BuY1/ot7Qixot6FsoJ4Tn6AiHCHcquI5tiL3iowd9WLJoOndmvsWxgQqNE6e3z1nvApvtaHZi0liaSAz+un6Zp0R29AP7nvQ6yuoeK2DmoY4rJy2i+TeSZ/Ujpqcqle8gvlEa/B6Bymy0ZTuRN2quXBcDkNWQkeOIQgyNR9wLW7fQ4ooyNwULV9rQDIatbGJMnIVdTZexvcrs5V2xjTnA9L1afj9rkl0ec0nZiRG0+XI9YKM,iv:qUzKCKelWXYgNKVVWPDwu3ltpiSb8U/7/nYjSx9zfX0=,tag:ZScQ16WQY1pyiiuAlAWBfw==,type:str] +sops: + age: + - recipient: age1yzrqhl9dk8ljswpmzsqme3enad5kxxhsptdvecy3lwlq0ms80gaqxrctst + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5RFJDSmRvQlZOMHd4c3Av + YTNxTjkwS0NNbXRZVmZQdWhvVmE0RU84TXlzCi9SUk43K3hpVDRINTZzZHBEc0No + aVpWbkVKamVBUkZDNTRtNjd2bWFHd2cKLS0tIEQ5SXRyUUVKZkhJbWtOMXRtQkFv + WlVYU2RpV2orcTZBbzNCeXhQREluSEkKbG1YJdBs1XkVATm84UgtIO2CxBNooZOy + xjBBexS13Ro3ujIWDu3yRcWnduUcSljY7AV9fs6sDbBWfBWF2Pzhiw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-02-04T15:11:58Z" + mac: ENC[AES256_GCM,data:AJ3BkZ0pe+XVjTnX4Y53LxhAoKmfP65wIFnBqkiV9cpGvio5fOxx9tvbWIo8+vge9zS2DWXdCSCln5gJavm+i1+gvU3pm6b0BEV+mhPMKb9wS8wU0D1Z9sE1RM8K+jDXMHGLBZ5Cr9ZHFXbfmGqV8/t+Jp189YHAdy94qfsxZb8=,iv:MNDtIwXQhxwjw64aXnDaMtmrIBpYhSm2nsE10KuCdUo=,tag:weIKaGfdtNvY4cn3bPEFEg==,type:str] + encrypted_regex: ^(data|stringData)$ + mac_only_encrypted: true + version: 3.11.0 diff --git a/kubernetes/apps/network/cloudflare-tunnel/ks.yaml b/kubernetes/apps/network/cloudflare-tunnel/ks.yaml new file mode 100644 index 0000000..10ef301 --- /dev/null +++ b/kubernetes/apps/network/cloudflare-tunnel/ks.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: cloudflare-tunnel +spec: + interval: 1h + path: ./kubernetes/apps/network/cloudflare-tunnel/app + postBuild: + substituteFrom: + - name: cluster-secrets + kind: Secret + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + targetNamespace: network + wait: false diff --git a/kubernetes/apps/network/envoy-gateway/app/certificate.yaml b/kubernetes/apps/network/envoy-gateway/app/certificate.yaml new file mode 100644 index 0000000..1f02d1f --- /dev/null +++ b/kubernetes/apps/network/envoy-gateway/app/certificate.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: "${SECRET_DOMAIN/./-}-production" +spec: + dnsNames: + - "${SECRET_DOMAIN}" + - "*.${SECRET_DOMAIN}" + duration: 160h + issuerRef: + name: letsencrypt-production + kind: ClusterIssuer + privateKey: + algorithm: ECDSA + secretName: "${SECRET_DOMAIN/./-}-production-tls" + usages: + - digital signature diff --git a/kubernetes/apps/network/envoy-gateway/app/envoy.yaml b/kubernetes/apps/network/envoy-gateway/app/envoy.yaml new file mode 100644 index 0000000..6be05c8 --- /dev/null +++ b/kubernetes/apps/network/envoy-gateway/app/envoy.yaml @@ -0,0 +1,170 @@ +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyProxy +metadata: + name: envoy +spec: + logging: + level: + default: info + provider: + type: Kubernetes + kubernetes: + envoyDeployment: + replicas: 2 + container: + imageRepository: mirror.gcr.io/envoyproxy/envoy + resources: + requests: + cpu: 100m + limits: + memory: 1Gi + envoyService: + externalTrafficPolicy: Cluster + shutdown: + drainTimeout: 180s + telemetry: + metrics: + prometheus: + compression: + type: Zstd +--- +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 +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: envoy-external + annotations: + external-dns.alpha.kubernetes.io/target: external.${SECRET_DOMAIN} +spec: + gatewayClassName: envoy + infrastructure: + annotations: + external-dns.alpha.kubernetes.io/hostname: external.${SECRET_DOMAIN} + lbipam.cilium.io/ips: "10.0.50.110" + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: Same + - name: https + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: All + tls: + certificateRefs: + - kind: Secret + name: ${SECRET_DOMAIN/./-}-production-tls +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: envoy-internal + annotations: + external-dns.alpha.kubernetes.io/target: internal.${SECRET_DOMAIN} +spec: + gatewayClassName: envoy + infrastructure: + annotations: + external-dns.alpha.kubernetes.io/hostname: internal.${SECRET_DOMAIN} + lbipam.cilium.io/ips: "10.0.50.102" + listeners: + - name: http + protocol: HTTP + port: 80 + allowedRoutes: + namespaces: + from: Same + - name: https + protocol: HTTPS + port: 443 + allowedRoutes: + namespaces: + from: All + tls: + certificateRefs: + - kind: Secret + name: ${SECRET_DOMAIN/./-}-production-tls +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: BackendTrafficPolicy +metadata: + name: envoy +spec: + compressor: + - type: Zstd + zstd: {} + - type: Brotli + brotli: {} + - type: Gzip + gzip: {} + retry: + numRetries: 2 + retryOn: + triggers: + - reset + targetSelectors: + - group: gateway.networking.k8s.io + kind: Gateway + tcpKeepalive: {} + timeout: + http: + requestTimeout: 0s +--- +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: ClientTrafficPolicy +metadata: + name: envoy +spec: + clientIPDetection: + xForwardedFor: + trustedCIDRs: + - "10.42.0.0/16" + http2: + onInvalidMessage: TerminateStream + http3: {} + targetSelectors: + - group: gateway.networking.k8s.io + kind: Gateway + tcpKeepalive: {} + tls: + minVersion: "1.2" + alpnProtocols: + - h2 + - http/1.1 +--- +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 + sectionName: http + - name: envoy-internal + namespace: network + sectionName: http + rules: + - filters: + - type: RequestRedirect + requestRedirect: + scheme: https + statusCode: 301 diff --git a/kubernetes/apps/network/envoy-gateway/app/helmrelease.yaml b/kubernetes/apps/network/envoy-gateway/app/helmrelease.yaml new file mode 100644 index 0000000..55f3dea --- /dev/null +++ b/kubernetes/apps/network/envoy-gateway/app/helmrelease.yaml @@ -0,0 +1,20 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: envoy-gateway +spec: + chartRef: + kind: OCIRepository + name: envoy-gateway + interval: 1h + values: + global: + imageRegistry: mirror.gcr.io + config: + envoyGateway: + provider: + type: Kubernetes + kubernetes: + deploy: + type: GatewayNamespace diff --git a/kubernetes/apps/network/envoy-gateway/app/kustomization.yaml b/kubernetes/apps/network/envoy-gateway/app/kustomization.yaml new file mode 100644 index 0000000..545ef59 --- /dev/null +++ b/kubernetes/apps/network/envoy-gateway/app/kustomization.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./certificate.yaml + - ./envoy.yaml + - ./helmrelease.yaml + - ./ocirepository.yaml + - ./podmonitor.yaml diff --git a/kubernetes/apps/network/envoy-gateway/app/ocirepository.yaml b/kubernetes/apps/network/envoy-gateway/app/ocirepository.yaml new file mode 100644 index 0000000..abc4672 --- /dev/null +++ b/kubernetes/apps/network/envoy-gateway/app/ocirepository.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: envoy-gateway +spec: + interval: 15m + layerSelector: + mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip + operation: copy + ref: + tag: v1.6.2 + url: oci://mirror.gcr.io/envoyproxy/gateway-helm diff --git a/kubernetes/apps/network/envoy-gateway/app/podmonitor.yaml b/kubernetes/apps/network/envoy-gateway/app/podmonitor.yaml new file mode 100644 index 0000000..b199aa8 --- /dev/null +++ b/kubernetes/apps/network/envoy-gateway/app/podmonitor.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + name: envoy-proxy +spec: + jobLabel: envoy-proxy + namespaceSelector: + matchNames: + - network + podMetricsEndpoints: + - port: metrics + path: /stats/prometheus + honorLabels: true + selector: + matchLabels: + app.kubernetes.io/component: proxy + app.kubernetes.io/name: envoy diff --git a/kubernetes/apps/network/envoy-gateway/ks.yaml b/kubernetes/apps/network/envoy-gateway/ks.yaml new file mode 100644 index 0000000..78a3ce9 --- /dev/null +++ b/kubernetes/apps/network/envoy-gateway/ks.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: envoy-gateway +spec: + interval: 1h + path: ./kubernetes/apps/network/envoy-gateway/app + postBuild: + substituteFrom: + - name: cluster-secrets + kind: Secret + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + targetNamespace: network + wait: false diff --git a/kubernetes/apps/network/k8s-gateway/app/helmrelease.yaml b/kubernetes/apps/network/k8s-gateway/app/helmrelease.yaml new file mode 100644 index 0000000..a357e83 --- /dev/null +++ b/kubernetes/apps/network/k8s-gateway/app/helmrelease.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: k8s-gateway +spec: + chartRef: + kind: OCIRepository + name: k8s-gateway + interval: 1h + values: + fullnameOverride: k8s-gateway + domain: "${SECRET_DOMAIN}" + ttl: 1 + service: + type: LoadBalancer + port: 53 + annotations: + lbipam.cilium.io/ips: "10.0.50.101" + externalTrafficPolicy: Cluster + watchedResources: ["HTTPRoute", "Service"] diff --git a/kubernetes/apps/network/k8s-gateway/app/kustomization.yaml b/kubernetes/apps/network/k8s-gateway/app/kustomization.yaml new file mode 100644 index 0000000..2ccd5a8 --- /dev/null +++ b/kubernetes/apps/network/k8s-gateway/app/kustomization.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./helmrelease.yaml + - ./ocirepository.yaml diff --git a/kubernetes/apps/network/k8s-gateway/app/ocirepository.yaml b/kubernetes/apps/network/k8s-gateway/app/ocirepository.yaml new file mode 100644 index 0000000..5e108a9 --- /dev/null +++ b/kubernetes/apps/network/k8s-gateway/app/ocirepository.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: k8s-gateway +spec: + interval: 1h + layerSelector: + mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip + operation: copy + ref: + tag: 3.4.1 + url: oci://ghcr.io/k8s-gateway/charts/k8s-gateway diff --git a/kubernetes/apps/network/k8s-gateway/ks.yaml b/kubernetes/apps/network/k8s-gateway/ks.yaml new file mode 100644 index 0000000..844476f --- /dev/null +++ b/kubernetes/apps/network/k8s-gateway/ks.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: k8s-gateway +spec: + interval: 1h + path: ./kubernetes/apps/network/k8s-gateway/app + postBuild: + substituteFrom: + - name: cluster-secrets + kind: Secret + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + targetNamespace: network + wait: false diff --git a/kubernetes/apps/network/kustomization.yaml b/kubernetes/apps/network/kustomization.yaml new file mode 100644 index 0000000..6e9cf9c --- /dev/null +++ b/kubernetes/apps/network/kustomization.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: network + +components: + - ../../components/sops + +resources: + - ./namespace.yaml + - ./cloudflare-dns/ks.yaml + - ./cloudflare-tunnel/ks.yaml + - ./envoy-gateway/ks.yaml + - ./k8s-gateway/ks.yaml diff --git a/kubernetes/apps/network/namespace.yaml b/kubernetes/apps/network/namespace.yaml new file mode 100644 index 0000000..17866ba --- /dev/null +++ b/kubernetes/apps/network/namespace.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: network + annotations: + kustomize.toolkit.fluxcd.io/prune: disabled diff --git a/kubernetes/components/sops/cluster-secrets.sops.yaml b/kubernetes/components/sops/cluster-secrets.sops.yaml new file mode 100644 index 0000000..95bb357 --- /dev/null +++ b/kubernetes/components/sops/cluster-secrets.sops.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Secret +metadata: + name: cluster-secrets +stringData: + SECRET_DOMAIN: ENC[AES256_GCM,data:8zu1WoVNAIYIOgpP,iv:xqaUWgoGqm9aPiVl7DtOpzWfecEDrTg/UZp2FM47FM4=,tag:Zt42iFk9jtj4aZcfo3ssnw==,type:str] +sops: + age: + - recipient: age1yzrqhl9dk8ljswpmzsqme3enad5kxxhsptdvecy3lwlq0ms80gaqxrctst + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3Nzc5aWljcEM3ak9FK3c5 + ZU9sK3VhTjZZNTBKQ1ZRdUZEM1g1MmVwb3dZCjFnSi9ISDRSYnRNOWh2anVZN3Z6 + QzhXSVR5b0tKMkFwOEhvRmEwZ0o0UnMKLS0tIFpyS0paWEpqNTQ4NWR6bUZoYklM + cE5Bb28wTThSZ00zNC9xazdvMTcwd3cKI8Am278zmY2BG5EqEKtVmpp/+ONrYMwt + GsFfU512VdI9crWgVhSrX3uyD+tmEQrL+YywqpOlOvx/KeANYzjhCA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-02-04T15:11:58Z" + mac: ENC[AES256_GCM,data:7+MlxiwapEYZDUANip+m8/jZTz9aKh8KHhJMXZbD/C4M2ZS8oe5Vkhf9iTDM1ok378s15Prucjg1x4CtmhsvJQeQtOeT0kvCews0KAerknWXW9nQOM+faL+PV6MelUGrA/6UzxgtRAHcQF159fvfCpprBzJjoCe3vFL6XOAu3+0=,iv:preefTi9qilhq3e4HtNFqALLFMVnwtGoSK6K4PCROV0=,tag:DtckcjV3nune5pnOaJrnxg==,type:str] + encrypted_regex: ^(data|stringData)$ + mac_only_encrypted: true + version: 3.11.0 diff --git a/kubernetes/components/sops/kustomization.yaml b/kubernetes/components/sops/kustomization.yaml new file mode 100644 index 0000000..1948b44 --- /dev/null +++ b/kubernetes/components/sops/kustomization.yaml @@ -0,0 +1,5 @@ +--- +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component +resources: + - ./cluster-secrets.sops.yaml diff --git a/kubernetes/flux/cluster/ks.yaml b/kubernetes/flux/cluster/ks.yaml new file mode 100644 index 0000000..77d76e8 --- /dev/null +++ b/kubernetes/flux/cluster/ks.yaml @@ -0,0 +1,57 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: cluster-apps + namespace: flux-system +spec: + decryption: + provider: sops + deletionPolicy: WaitForTermination + interval: 1h + path: ./kubernetes/apps + prune: true + sourceRef: + kind: GitRepository + name: flux-system + namespace: flux-system + wait: false + patches: + - # Add Kustomization defaults for all child Kustomizations + patch: |- + apiVersion: kustomize.toolkit.fluxcd.io/v1 + kind: Kustomization + metadata: + name: _ + spec: + decryption: + provider: sops + deletionPolicy: WaitForTermination + patches: + - patch: |- + apiVersion: helm.toolkit.fluxcd.io/v2 + kind: HelmRelease + metadata: + name: _ + spec: + install: + crds: CreateReplace + strategy: + name: RetryOnFailure + rollback: + cleanupOnFail: true + recreate: true + upgrade: + cleanupOnFail: true + crds: CreateReplace + strategy: + name: RemediateOnFailure + remediation: + remediateLastFailure: true + retries: 2 + target: + group: helm.toolkit.fluxcd.io + kind: HelmRelease + target: + group: kustomize.toolkit.fluxcd.io + kind: Kustomization diff --git a/nodes.sample.yaml b/nodes.sample.yaml deleted file mode 100644 index 1bd67ed..0000000 --- a/nodes.sample.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -nodes: [] - # - name: "" # (REQUIRED) Name of the node (must match [a-z0-9-\]+) - # address: "" # (REQUIRED) IP address of the node (must be in the node_cidr) - # controller: true # (REQUIRED) Set to true if this is a controller node - # disk: "" # (REQUIRED) Device path or serial number of the disk for this node (talosctl get disks -n --insecure) - # mac_addr: "" # (REQUIRED) MAC address of the NIC for this node (talosctl get links -n --insecure) - # schematic_id: "" # (REQUIRED) Schematic ID from https://factory.talos.dev/ - # mtu: 1500 # (ADVANCED/OPTIONAL) MTU for the NIC. DEFAULT: 1500 - # secureboot: false # (ADVANCED/OPTIONAL) SecureBoot mode on UEFI platforms. Ref: https://www.talos.dev/latest/talos-guides/install/bare-metal-platforms/secureboot - # encrypt_disk: false # (ADVANCED/OPTIONAL) TPM-based disk encryption. Ref: https://www.talos.dev/latest/talos-guides/install/bare-metal-platforms/secureboot - # kernel_modules: [] # (ADVANCED/OPTIONAL) Only applicable if the `schematic_id` you've provided contains system extensions that require kernel modules to correctly load - Example: ["nvidia", "nvidia_uvm", "nvidia_drm", "nvidia_modeset", "zfs"] - # ... diff --git a/talos/patches/README.md b/talos/patches/README.md new file mode 100644 index 0000000..b968188 --- /dev/null +++ b/talos/patches/README.md @@ -0,0 +1,15 @@ +# Talos Patching + +This directory contains Kustomization patches that are added to the talhelper configuration file. + + + +## Patch Directories + +Under this `patches` directory, there are several sub-directories that can contain patches that are added to the talhelper configuration file. +Each directory is optional and therefore might not created by default. + +- `global/`: patches that are applied to both the controller and worker configurations +- `controller/`: patches that are applied to the controller configurations +- `worker/`: patches that are applied to the worker configurations +- `${node-hostname}/`: patches that are applied to the node with the specified name diff --git a/talos/patches/controller/cluster.yaml b/talos/patches/controller/cluster.yaml new file mode 100644 index 0000000..5179e0a --- /dev/null +++ b/talos/patches/controller/cluster.yaml @@ -0,0 +1,23 @@ +cluster: + allowSchedulingOnControlPlanes: true + apiServer: + admissionControl: + $$patch: delete + extraArgs: + # https://kubernetes.io/docs/tasks/extend-kubernetes/configure-aggregation-layer/ + enable-aggregator-routing: true + controllerManager: + extraArgs: + bind-address: 0.0.0.0 + coreDNS: + disabled: true + etcd: + extraArgs: + listen-metrics-urls: http://0.0.0.0:2381 + advertisedSubnets: + - 10.0.50.0/24 + proxy: + disabled: true + scheduler: + extraArgs: + bind-address: 0.0.0.0 diff --git a/talos/patches/global/machine-files.yaml b/talos/patches/global/machine-files.yaml new file mode 100644 index 0000000..327c8e3 --- /dev/null +++ b/talos/patches/global/machine-files.yaml @@ -0,0 +1,9 @@ +machine: + files: + - 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"] + device_ownership_from_security_context = true diff --git a/talos/patches/global/machine-kubelet.yaml b/talos/patches/global/machine-kubelet.yaml new file mode 100644 index 0000000..e7b93cd --- /dev/null +++ b/talos/patches/global/machine-kubelet.yaml @@ -0,0 +1,7 @@ +machine: + kubelet: + extraConfig: + serializeImagePulls: false + nodeIP: + validSubnets: + - 10.0.50.0/24 diff --git a/talos/patches/global/machine-network.yaml b/talos/patches/global/machine-network.yaml new file mode 100644 index 0000000..6e8e45f --- /dev/null +++ b/talos/patches/global/machine-network.yaml @@ -0,0 +1,7 @@ +machine: + network: + disableSearchDomain: true + nameservers: + - 10.0.0.1 # Local DNS from PiHole first + - 1.1.1.1 + - 1.0.0.1 diff --git a/talos/patches/global/machine-sysctls.yaml b/talos/patches/global/machine-sysctls.yaml new file mode 100644 index 0000000..c56aa6d --- /dev/null +++ b/talos/patches/global/machine-sysctls.yaml @@ -0,0 +1,11 @@ +machine: + sysctls: + fs.inotify.max_user_watches: "1048576" # Watchdog + fs.inotify.max_user_instances: "8192" # Watchdog + net.core.rmem_max: "7500000" # Cloudflared | QUIC + net.core.wmem_max: "7500000" # Cloudflared | QUIC + net.ipv4.neigh.default.gc_thresh1: "4096" # Prevent ARP cache overflows + net.ipv4.neigh.default.gc_thresh2: "8192" # Prevent ARP cache overflows + net.ipv4.neigh.default.gc_thresh3: "16384" # Prevent ARP cache overflows + net.ipv4.tcp_slow_start_after_idle: "0" # Preserve congestion window after idle + user.max_user_namespaces: "11255" # User Namespaces diff --git a/talos/patches/global/machine-time.yaml b/talos/patches/global/machine-time.yaml new file mode 100644 index 0000000..b7d6594 --- /dev/null +++ b/talos/patches/global/machine-time.yaml @@ -0,0 +1,6 @@ +machine: + time: + disabled: false + servers: + - 162.159.200.1 + - 162.159.200.123 diff --git a/talos/talconfig.yaml b/talos/talconfig.yaml new file mode 100644 index 0000000..8d17528 --- /dev/null +++ b/talos/talconfig.yaml @@ -0,0 +1,94 @@ +--- +clusterName: kubernetes + +talosVersion: "${talosVersion}" +kubernetesVersion: "${kubernetesVersion}" + +endpoint: https://10.0.50.100:6443 +additionalApiServerCertSans: &sans + - "127.0.0.1" + - "10.0.50.100" +additionalMachineCertSans: *sans + +clusterPodNets: ["10.42.0.0/16"] +clusterSvcNets: ["10.43.0.0/16"] + +# Disable built-in CNI to use Cilium +cniConfig: + name: none + +nodes: + - hostname: "blade-cm4-001" + ipAddress: "10.0.50.7" + installDiskSelector: + serial: "0x0f750869" + machineSpec: + secureboot: false + talosImageURL: factory.talos.dev/installer/ee21ef4a5ef808a9b7484cc0dda0f25075021691c8c09a276591eedb638ea1f9 + controlPlane: true + networkInterfaces: + - deviceSelector: + hardwareAddr: "dc:a6:32:a6:75:ba" + dhcp: false + addresses: + - "10.0.50.7/24" + routes: + - gateway: "10.0.50.1" + network: 0.0.0.0/0 + mtu: 1500 + vip: + ip: "10.0.50.100" + - hostname: "esxi-2cu-8g-02" + ipAddress: "10.0.0.145" + installDiskSelector: + serial: "Virtual disk" + machineSpec: + secureboot: false + talosImageURL: factory.talos.dev/installer/376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba + controlPlane: true + networkInterfaces: + - deviceSelector: + hardwareAddr: "34:97:87:58:7b:00" + dhcp: false + addresses: + - "10.0.0.145/24" + routes: + - gateway: "10.0.50.1" + network: 0.0.0.0/0 + mtu: 1500 + vip: + ip: "10.0.50.100" + - hostname: "esxi-2cu-8g-01" + ipAddress: "10.0.0.146" + installDiskSelector: + serial: "Virtual disk" + machineSpec: + secureboot: false + talosImageURL: factory.talos.dev/installer/376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba + controlPlane: true + networkInterfaces: + - deviceSelector: + hardwareAddr: "34:97:87:58:7b:01" + dhcp: false + addresses: + - "10.0.0.146/24" + routes: + - gateway: "10.0.50.1" + network: 0.0.0.0/0 + mtu: 1500 + vip: + ip: "10.0.50.100" + +# Global patches +patches: + - "@./patches/global/machine-files.yaml" + - "@./patches/global/machine-kubelet.yaml" + - "@./patches/global/machine-network.yaml" + - "@./patches/global/machine-sysctls.yaml" + - "@./patches/global/machine-time.yaml" + +# Controller patches +controlPlane: + patches: + - "@./patches/controller/cluster.yaml" + diff --git a/talos/talenv.yaml b/talos/talenv.yaml new file mode 100644 index 0000000..d64ee92 --- /dev/null +++ b/talos/talenv.yaml @@ -0,0 +1,4 @@ +# renovate: datasource=docker depName=ghcr.io/siderolabs/installer +talosVersion: v1.12.2 +# renovate: datasource=docker depName=ghcr.io/siderolabs/kubelet +kubernetesVersion: v1.35.0