From c28540cd44560fe98c6306abcb88ea2d3bf9d4e4 Mon Sep 17 00:00:00 2001 From: Grant Hunter <5445379+grantdhunter@users.noreply.github.com> Date: Sun, 14 Dec 2025 22:27:45 -0700 Subject: [PATCH] update certs --- 53ll/values.yaml.gotmpl | 20 +++- .../values.yaml.gotmpl | 11 +++ cert-manager-issuers/Chart.yaml | 5 + .../templates/clusterissuers.yaml | 88 +++++++++++++++++ cert-manager-issuers/values.yaml.gotmpl | 5 + cert-manager/values.yaml.gotmpl | 27 +++++ gitea/values.yaml.gotmpl | 29 +++--- helmfile.d/01-infrastructure.lock | 10 +- helmfile.d/01-infrastructure.yaml | 22 +++++ helmfile.d/02-datastore.lock | 2 +- helmfile.d/03-apps.lock | 4 +- helmfile.d/03-apps.yaml | 12 +-- immich/values.yaml.gotmpl | 8 +- incngrnt-web/values.yaml.gotmpl | 7 +- kgnot/values.yaml.gotmpl | 20 +++- rook-ceph-cluster/values.yaml.gotmpl | 19 +++- synapse/values.yaml.gotmpl | 6 +- traefik/values.yaml.gotmpl | 98 ++++++++++++++----- 18 files changed, 334 insertions(+), 59 deletions(-) create mode 100644 cert-manager-hetzner-webhook/values.yaml.gotmpl create mode 100644 cert-manager-issuers/Chart.yaml create mode 100644 cert-manager-issuers/templates/clusterissuers.yaml create mode 100644 cert-manager-issuers/values.yaml.gotmpl create mode 100644 cert-manager/values.yaml.gotmpl diff --git a/53ll/values.yaml.gotmpl b/53ll/values.yaml.gotmpl index a3616d6..9e2c69e 100644 --- a/53ll/values.yaml.gotmpl +++ b/53ll/values.yaml.gotmpl @@ -48,5 +48,21 @@ ingress: enabled: true hostname: 53ll.ca tls: true - annotations: - "traefik.ingress.kubernetes.io/router.tls.certresolver": "letsencrypt" \ No newline at end of file + extraTls: + - secretName: 53ll-ca-tls + hosts: + - 53ll.ca + +extraDeploy: + - apiVersion: cert-manager.io/v1 + kind: Certificate + metadata: + name: 53ll-ca + namespace: ghost + spec: + secretName: 53ll-ca-tls + issuerRef: + name: letsencrypt-53ll + kind: ClusterIssuer + dnsNames: + - 53ll.ca \ No newline at end of file diff --git a/cert-manager-hetzner-webhook/values.yaml.gotmpl b/cert-manager-hetzner-webhook/values.yaml.gotmpl new file mode 100644 index 0000000..dba1e72 --- /dev/null +++ b/cert-manager-hetzner-webhook/values.yaml.gotmpl @@ -0,0 +1,11 @@ +groupName: acme.hetzner.com + +certManager: + namespace: cert-manager + serviceAccountName: cert-manager + +secretName: + - hetzner-dns-credentials + +secrets: + apiToken: {{ requiredEnv "HETZNER_API_KEY" }} diff --git a/cert-manager-issuers/Chart.yaml b/cert-manager-issuers/Chart.yaml new file mode 100644 index 0000000..8a12931 --- /dev/null +++ b/cert-manager-issuers/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: cert-manager-issuers +description: cert-manager ClusterIssuers for Let's Encrypt +type: application +version: 0.1.0 diff --git a/cert-manager-issuers/templates/clusterissuers.yaml b/cert-manager-issuers/templates/clusterissuers.yaml new file mode 100644 index 0000000..b2b04b4 --- /dev/null +++ b/cert-manager-issuers/templates/clusterissuers.yaml @@ -0,0 +1,88 @@ +apiVersion: v1 +kind: Secret +metadata: + name: hetzner-dns-credentials + namespace: cert-manager +type: Opaque +stringData: + api-key: {{ .Values.hetzner.apiToken }} +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-incngrnt +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: {{ .Values.acme.email }} + privateKeySecretRef: + name: letsencrypt-incngrnt-private-key + solvers: + - dns01: + webhook: + groupName: acme.hetzner.com + solverName: hetzner + config: + secretName: hetzner-dns-credentials + zoneName: incngrnt.ca + apiUrl: https://dns.hetzner.com/api/v1 +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-goatchat +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: {{ .Values.acme.email }} + privateKeySecretRef: + name: letsencrypt-goatchat-private-key + solvers: + - dns01: + webhook: + groupName: acme.hetzner.com + solverName: hetzner + config: + secretName: hetzner-dns-credentials + zoneName: goatchat.ca + apiUrl: https://dns.hetzner.com/api/v1 +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-53ll +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: {{ .Values.acme.email }} + privateKeySecretRef: + name: letsencrypt-53ll-private-key + solvers: + - dns01: + webhook: + groupName: acme.hetzner.com + solverName: hetzner + config: + secretName: hetzner-dns-credentials + zoneName: 53ll.ca + apiUrl: https://dns.hetzner.com/api/v1 +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-kgnot +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: {{ .Values.acme.email }} + privateKeySecretRef: + name: letsencrypt-kgnot-private-key + solvers: + - dns01: + webhook: + groupName: acme.hetzner.com + solverName: hetzner + config: + secretName: hetzner-dns-credentials + zoneName: kgnot.ca + apiUrl: https://dns.hetzner.com/api/v1 diff --git a/cert-manager-issuers/values.yaml.gotmpl b/cert-manager-issuers/values.yaml.gotmpl new file mode 100644 index 0000000..7b94f71 --- /dev/null +++ b/cert-manager-issuers/values.yaml.gotmpl @@ -0,0 +1,5 @@ +hetzner: + apiToken: {{ requiredEnv "HETZNER_API_KEY" }} + +acme: + email: {{ requiredEnv "ACME_EMAIL" }} diff --git a/cert-manager/values.yaml.gotmpl b/cert-manager/values.yaml.gotmpl new file mode 100644 index 0000000..b1b560a --- /dev/null +++ b/cert-manager/values.yaml.gotmpl @@ -0,0 +1,27 @@ +installCRDs: true + +resources: + requests: + cpu: 10m + memory: 64Mi + limits: + cpu: 1 + memory: 128Mi + +webhook: + resources: + requests: + cpu: 10m + memory: 32Mi + limits: + cpu: 1 + memory: 64Mi + +cainjector: + resources: + requests: + cpu: 10m + memory: 64Mi + limits: + cpu: 1 + memory: 128Mi diff --git a/gitea/values.yaml.gotmpl b/gitea/values.yaml.gotmpl index e26e185..5482aa4 100644 --- a/gitea/values.yaml.gotmpl +++ b/gitea/values.yaml.gotmpl @@ -48,24 +48,17 @@ ingress: paths: - path: "/" pathType: Prefix - annotations: - "traefik.ingress.kubernetes.io/router.tls.certresolver": "letsencrypt" + tls: + - secretName: git-incngrnt-ca-tls + hosts: + - git.incngrnt.ca service: ssh: type: ClusterIP port: 22 clusterIP: - -actions: - enabled: true - giteaRootURL: https://git.incngrnt.ca - existingSecret: gitea-runner-token - existingSecretKey: token - provisioning: - enabled: false - persistence: - enabled: false + redis: enabled: true redis-cluster: @@ -77,6 +70,18 @@ postgresql-ha: extraDeploy: +- apiVersion: cert-manager.io/v1 + kind: Certificate + metadata: + name: git-incngrnt-ca + namespace: gitea + spec: + secretName: git-incngrnt-ca-tls + issuerRef: + name: letsencrypt-incngrnt + kind: ClusterIssuer + dnsNames: + - git.incngrnt.ca - apiVersion: traefik.io/v1alpha1 kind: IngressRouteTCP metadata: diff --git a/helmfile.d/01-infrastructure.lock b/helmfile.d/01-infrastructure.lock index 3e62ffe..fc16aa4 100644 --- a/helmfile.d/01-infrastructure.lock +++ b/helmfile.d/01-infrastructure.lock @@ -1,5 +1,11 @@ version: 0.170.1 dependencies: +- name: cert-manager + repository: https://charts.jetstack.io + version: v1.19.2 +- name: cert-manager-webhook-hetzner + repository: https://vadimkim.github.io/cert-manager-webhook-hetzner + version: 1.4.0 - name: rook-ceph repository: https://charts.rook.io/release version: v1.18.8 @@ -12,5 +18,5 @@ dependencies: - name: traefik repository: https://traefik.github.io/charts version: 37.4.0 -digest: sha256:66b2e4b590af3ee51f97d61435400977ceb8d70ddfc50d638ccfaeede79e8a6f -generated: "2025-12-07T13:19:28.002423348-07:00" +digest: sha256:23d6b70fcb5e17bfa1e8fdc576a8057128b3bec68020fa8275a553b5caa23e99 +generated: "2025-12-14T14:13:45.546956484-07:00" diff --git a/helmfile.d/01-infrastructure.yaml b/helmfile.d/01-infrastructure.yaml index 0a8fede..8dd5758 100644 --- a/helmfile.d/01-infrastructure.yaml +++ b/helmfile.d/01-infrastructure.yaml @@ -5,6 +5,10 @@ repositories: url: https://traefik.github.io/charts - name: tailscale url: https://pkgs.tailscale.com/helmcharts + - name: jetstack + url: https://charts.jetstack.io + - name: cert-manager-webhook-hetzner + url: https://vadimkim.github.io/cert-manager-webhook-hetzner releases: # networking @@ -14,6 +18,24 @@ releases: chart: ../metallb values: - ../metallb/values.yaml.gotmpl + - name: cert-manager + namespace: cert-manager + createNamespace: true + chart: jetstack/cert-manager + values: + - ../cert-manager/values.yaml.gotmpl + - name: cert-manager-webhook-hetzner + namespace: cert-manager + createNamespace: true + chart: cert-manager-webhook-hetzner/cert-manager-webhook-hetzner + values: + - ../cert-manager-hetzner-webhook/values.yaml.gotmpl + - name: cert-manager-issuers + namespace: cert-manager + createNamespace: true + chart: ../cert-manager-issuers + values: + - ../cert-manager-issuers/values.yaml.gotmpl - name: traefik namespace: traefik createNamespace: true diff --git a/helmfile.d/02-datastore.lock b/helmfile.d/02-datastore.lock index 692150c..72b3f15 100644 --- a/helmfile.d/02-datastore.lock +++ b/helmfile.d/02-datastore.lock @@ -13,4 +13,4 @@ dependencies: repository: git+https://github.com/grantdhunter/postgres-operator@helm?ref=main version: 5.7.4 digest: sha256:f8989df670b3574b6d87438486b66fdaf44bc1ed379d3a98e00963a27703003a -generated: "2025-12-14T12:59:10.595864383-07:00" +generated: "2025-12-14T14:14:05.060998516-07:00" diff --git a/helmfile.d/03-apps.lock b/helmfile.d/03-apps.lock index d4cf40a..38283a0 100644 --- a/helmfile.d/03-apps.lock +++ b/helmfile.d/03-apps.lock @@ -30,5 +30,5 @@ dependencies: - name: static-site repository: git+https://github.com/cfpb/static-site@charts?ref=main version: 0.1.1 -digest: sha256:94f6df708ccbabc40cb875caa57f44f1be7bac60190dea00a24ffdc80925e8ec -generated: "2025-12-14T12:59:30.49543268-07:00" +digest: sha256:e957d861b7351e1e89af29b29e8de19621c9069131669d32217276e8118e634b +generated: "2025-12-14T14:14:24.483935436-07:00" diff --git a/helmfile.d/03-apps.yaml b/helmfile.d/03-apps.yaml index 3191e7f..d49decd 100644 --- a/helmfile.d/03-apps.yaml +++ b/helmfile.d/03-apps.yaml @@ -56,12 +56,12 @@ releases: - ../53ll/values.yaml.gotmpl # dev tools - # - name: gitea - # namespace: gitea - # createNamespace: true - # chart: gitea/gitea - # values: - # - ../gitea/values.yaml.gotmpl + - name: gitea + namespace: gitea + createNamespace: true + chart: gitea/gitea + values: + - ../gitea/values.yaml.gotmpl # backups - name: ghost-backup diff --git a/immich/values.yaml.gotmpl b/immich/values.yaml.gotmpl index e3cc2d6..30b8f41 100644 --- a/immich/values.yaml.gotmpl +++ b/immich/values.yaml.gotmpl @@ -48,8 +48,10 @@ server: ingress: main: enabled: true - annotations: - traefik.ingress.kubernetes.io/router.tls.certresolver: "letsencrypt" + tls: + - secretName: photos-incngrnt-ca-tls + hosts: + - photos.incngrnt.ca hosts: - host: photos.incngrnt.ca paths: @@ -70,3 +72,5 @@ machine-learning: limits: cpu: 1 memory: 384Mi + + diff --git a/incngrnt-web/values.yaml.gotmpl b/incngrnt-web/values.yaml.gotmpl index 57156e8..2e6a97d 100644 --- a/incngrnt-web/values.yaml.gotmpl +++ b/incngrnt-web/values.yaml.gotmpl @@ -13,10 +13,13 @@ resources: ingress: enabled: true - annotations: - "traefik.ingress.kubernetes.io/router.tls.certresolver": "letsencrypt" + tls: + - secretName: incngrnt-ca-tls + hosts: + - incngrnt.ca hosts: - host: incngrnt.ca paths: - path: / pathType: ImplementationSpecific + diff --git a/kgnot/values.yaml.gotmpl b/kgnot/values.yaml.gotmpl index 0b1d7cc..c9a76c6 100644 --- a/kgnot/values.yaml.gotmpl +++ b/kgnot/values.yaml.gotmpl @@ -50,5 +50,21 @@ ingress: enabled: true hostname: kgnot.ca tls: true - annotations: - "traefik.ingress.kubernetes.io/router.tls.certresolver": "letsencrypt" \ No newline at end of file + extraTls: + - secretName: kgnot-ca-tls + hosts: + - kgnot.ca + +extraDeploy: + - apiVersion: cert-manager.io/v1 + kind: Certificate + metadata: + name: kgnot-ca + namespace: ghost + spec: + secretName: kgnot-ca-tls + issuerRef: + name: letsencrypt-kgnot + kind: ClusterIssuer + dnsNames: + - kgnot.ca \ No newline at end of file diff --git a/rook-ceph-cluster/values.yaml.gotmpl b/rook-ceph-cluster/values.yaml.gotmpl index 46a1627..64d6883 100644 --- a/rook-ceph-cluster/values.yaml.gotmpl +++ b/rook-ceph-cluster/values.yaml.gotmpl @@ -37,10 +37,27 @@ ingress: name: fog.incngrnt.ca path: /fog/ceph pathType: Prefix + tls: + - secretName: fog-incngrnt-ca-tls + hosts: + - fog.incngrnt.ca annotations: - "traefik.ingress.kubernetes.io/router.tls.certresolver": "letsencrypt" "traefik.ingress.kubernetes.io/router.middlewares": "rook-ceph-ceph-stripprefix@kubernetescrd" +extraDeploy: + - apiVersion: cert-manager.io/v1 + kind: Certificate + metadata: + name: fog-ceph-incngrnt-ca + namespace: rook-ceph + spec: + secretName: fog-incngrnt-ca-tls + issuerRef: + name: letsencrypt-incngrnt + kind: ClusterIssuer + dnsNames: + - fog.incngrnt.ca + cephFileSystems: - name: ceph-filesystem # see https://github.com/rook/rook/blob/master/Documentation/ceph-filesystem-crd.md#filesystem-settings for available configuration diff --git a/synapse/values.yaml.gotmpl b/synapse/values.yaml.gotmpl index 3060d96..a677467 100644 --- a/synapse/values.yaml.gotmpl +++ b/synapse/values.yaml.gotmpl @@ -69,8 +69,10 @@ extraConfig: ingress: traefikPaths: true - annotations: - "traefik.ingress.kubernetes.io/router.tls.certresolver": "letsencrypt" + tls: + - secretName: goatchat-ca-tls + hosts: + - goatchat.ca persistence: diff --git a/traefik/values.yaml.gotmpl b/traefik/values.yaml.gotmpl index d640344..d58b1a3 100644 --- a/traefik/values.yaml.gotmpl +++ b/traefik/values.yaml.gotmpl @@ -1,11 +1,5 @@ deployment: - initContainers: - - name: volume-permissions - image: busybox:latest - command: ["sh", "-c", "touch /data/acme.json; chmod -v 600 /data/acme.json"] - volumeMounts: - - name: data - mountPath: /data + replicas: 2 resources: requests: @@ -16,20 +10,33 @@ resources: memory: 128Mi updateStrategy: - type: Recreate - -env: - - name: HETZNER_API_KEY - valueFrom: - secretKeyRef: - name: hetzner-api-key - key: token + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + maxSurge: 1 +podDisruptionBudget: + enabled: true + minAvailable: 1 + +affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - traefik + topologyKey: kubernetes.io/hostname + additionalArguments: - "--api.basePath=/fog/traefik" persistence: - enabled: true + enabled: false logs: format: json @@ -49,7 +56,7 @@ ingressRoute: middlewares: - name: traefik-dashboard-auth tls: - certResolver: letsencrypt + secretName: fog-incngrnt-ca-tls ports: websecure: @@ -99,12 +106,53 @@ extraObjects: redirectScheme: scheme: https permanent: true + - apiVersion: cert-manager.io/v1 + kind: Certificate + metadata: + name: fog-incngrnt-ca + namespace: traefik + spec: + secretName: fog-incngrnt-ca-tls + issuerRef: + name: letsencrypt-incngrnt + kind: ClusterIssuer + dnsNames: + - fog.incngrnt.ca -certificatesResolvers: - letsencrypt: - acme: - dnschallenge: - provider: hetzner - delaybeforecheck: 30 - email: {{ requiredEnv "ACME_EMAIL" }} - storage: /data/acme.json +# other certs + - apiVersion: cert-manager.io/v1 + kind: Certificate + metadata: + name: goatchat-ca + namespace: goatchat + spec: + secretName: goatchat-ca-tls + issuerRef: + name: letsencrypt-goatchat + kind: ClusterIssuer + dnsNames: + - goatchat.ca + - apiVersion: cert-manager.io/v1 + kind: Certificate + metadata: + name: incngrnt-ca + namespace: incngrnt-web + spec: + secretName: incngrnt-ca-tls + issuerRef: + name: letsencrypt-incngrnt + kind: ClusterIssuer + dnsNames: + - incngrnt.ca + - apiVersion: cert-manager.io/v1 + kind: Certificate + metadata: + name: photos-incngrnt-ca + namespace: immich + spec: + secretName: photos-incngrnt-ca-tls + issuerRef: + name: letsencrypt-incngrnt + kind: ClusterIssuer + dnsNames: + - photos.incngrnt.ca