From d2852ab9c545681b64ed199586d60959c8cc091d Mon Sep 17 00:00:00 2001 From: Astra Logical Date: Thu, 9 Apr 2026 10:46:12 -0400 Subject: [PATCH] Switch external services to k3s-managed SSL certs using cert-manager --- .DS_Store | Bin 0 -> 6148 bytes cert-manager/letsencrypt-cluster-issuer.yaml | 16 +++++++++ external-secrets/.DS_Store | Bin 0 -> 6148 bytes external-secrets/cloudflare-api-token.yaml | 18 ++++++++++ .../secretstores/vault-secretstore.yaml | 18 ++++++++++ .../audiobookshelf-ingress.yaml | 18 ++++++++++ .../calibre-web/calibre-web-deployment.yaml | 2 ++ services/calibre-web/calibre-web-ingress.yaml | 17 ++++++++++ .../foundryvtt/foundry-vtt-deployment.yaml | 31 +++++++----------- .../foundry-vtt-external-secrets.yaml | 30 +++++++++++++++++ services/foundryvtt/foundry-vtt-ingress.yaml | 17 ++++++++++ services/jellyfin/jellyfin-ingress.yaml | 17 ++++++++++ services/navidrome/navidrome-ingress.yaml | 17 ++++++++++ services/vaultwarden/vaultwarden-ingress.yaml | 18 ++++++++++ 14 files changed, 199 insertions(+), 20 deletions(-) create mode 100644 .DS_Store create mode 100644 cert-manager/letsencrypt-cluster-issuer.yaml create mode 100644 external-secrets/.DS_Store create mode 100644 external-secrets/cloudflare-api-token.yaml create mode 100644 external-secrets/secretstores/vault-secretstore.yaml create mode 100644 services/foundryvtt/foundry-vtt-external-secrets.yaml diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d78416b1d9b06e0d85457a11755dd3feedfbca41 GIT binary patch literal 6148 zcmeHKyG{c^3>-rwB0-Uoa({q=KR89<3-|%@f+i4&M}Hl^&G-Sj=#G{GjU#(*y`Ej& z6z3R#EkAa*zyiRW?ubthWAlCYk)2h>(c+97JY$U)`qQX-I^o_}dJ(rcYK@3P=GdAO)m=6qr(gJ=<-5nW!iQq<|FoQNX_sjqcbL z_KET7V2BZbIAc1D&oN67n;|*-fJ8Ef&Oi* ojdF%)#l&dETzD(K9@I5|=6+Y$CkCDQpcC~+z;%&Hfxl4T3-pB>L;wH) literal 0 HcmV?d00001 diff --git a/cert-manager/letsencrypt-cluster-issuer.yaml b/cert-manager/letsencrypt-cluster-issuer.yaml new file mode 100644 index 0000000..4bbace6 --- /dev/null +++ b/cert-manager/letsencrypt-cluster-issuer.yaml @@ -0,0 +1,16 @@ +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-prod +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: nest@mynest.love + privateKeySecretRef: + name: letsencrypt-prod-account-key + solvers: + - dns01: + cloudflare: + apiTokenSecretRef: + name: cloudflare-api-token-secret + key: api-token diff --git a/external-secrets/.DS_Store b/external-secrets/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..f404c7ae87d45c1d1c2efea1ef7b72210e318cd6 GIT binary patch literal 6148 zcmeHKJ8r`;3?t#5<_x;V1XjFg-Pys4H1*pIx3S?Pbzb$ea51|57;F%P#??Ztb*2FQ;KOGpn1puxP zcEj9z31G1RuqKXyh`==;as- fE5}<;io9ZT?AOFG(CLUf9mt;n(}hL_9<9JH(C!wl literal 0 HcmV?d00001 diff --git a/external-secrets/cloudflare-api-token.yaml b/external-secrets/cloudflare-api-token.yaml new file mode 100644 index 0000000..8c5b795 --- /dev/null +++ b/external-secrets/cloudflare-api-token.yaml @@ -0,0 +1,18 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: cloudflare-api-token + namespace: cert-manager +spec: + refreshInterval: "1h" + secretStoreRef: + name: vault-external-secrets-store + kind: ClusterSecretStore + target: + name: cloudflare-api-token-secret + creationPolicy: Owner + data: + - secretKey: api-token + remoteRef: + key: cloudflare + property: api-key diff --git a/external-secrets/secretstores/vault-secretstore.yaml b/external-secrets/secretstores/vault-secretstore.yaml new file mode 100644 index 0000000..324c9f1 --- /dev/null +++ b/external-secrets/secretstores/vault-secretstore.yaml @@ -0,0 +1,18 @@ +apiVersion: external-secrets.io/v1 +kind: ClusterSecretStore +metadata: + name: vault-external-secrets-store + namespace: external-secrets +spec: + provider: + vault: + server: "http://vault.vault.svc.cluster.local:8200" + path: "secret" + version: "v2" + auth: + kubernetes: + mountPath: "kubernetes" + role: "eso-role" + serviceAccountRef: + name: "external-secrets" + namespace: "external-secrets" diff --git a/services/audiobookshelf/audiobookshelf-ingress.yaml b/services/audiobookshelf/audiobookshelf-ingress.yaml index d143317..5cfe65d 100644 --- a/services/audiobookshelf/audiobookshelf-ingress.yaml +++ b/services/audiobookshelf/audiobookshelf-ingress.yaml @@ -1,11 +1,29 @@ +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: audiobookshelf-proxy-headers + namespace: default +spec: + headers: + customRequestHeaders: + X-Forwarded-Proto: "https" +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: audiobookshelf-ingress namespace: default annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.tls: "true" + traefik.ingress.kubernetes.io/router.middlewares: default-audiobookshelf-proxy-headers@kubernetescrd + spec: + tls: + - hosts: + - lyrebird.mynest.love + secretName: audiobookshelf-tls rules: - host: lyrebird.mynest.love http: diff --git a/services/calibre-web/calibre-web-deployment.yaml b/services/calibre-web/calibre-web-deployment.yaml index cb9284a..db3d1e2 100644 --- a/services/calibre-web/calibre-web-deployment.yaml +++ b/services/calibre-web/calibre-web-deployment.yaml @@ -4,6 +4,8 @@ metadata: labels: io.kompose.service: calibre-web name: calibre-web + annotations: + reloader.stakater.com/auto: "true" spec: replicas: 1 selector: diff --git a/services/calibre-web/calibre-web-ingress.yaml b/services/calibre-web/calibre-web-ingress.yaml index ad01b0f..bc718ed 100644 --- a/services/calibre-web/calibre-web-ingress.yaml +++ b/services/calibre-web/calibre-web-ingress.yaml @@ -1,11 +1,28 @@ +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: calibre-web-proxy-headers + namespace: default +spec: + headers: + customRequestHeaders: + X-Forwarded-Proto: "https" +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: calibre-web-ingress namespace: default annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.tls: "true" + traefik.ingress.kubernetes.io/router.middlewares: default-calibre-web-proxy-headers@kubernetescrd spec: + tls: + - hosts: + - rookery.mynest.love + secretName: calibre-web-tls rules: - host: rookery.mynest.love http: diff --git a/services/foundryvtt/foundry-vtt-deployment.yaml b/services/foundryvtt/foundry-vtt-deployment.yaml index af3d79f..5dc75f2 100644 --- a/services/foundryvtt/foundry-vtt-deployment.yaml +++ b/services/foundryvtt/foundry-vtt-deployment.yaml @@ -1,12 +1,11 @@ apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: kompose convert -f foundry-compose.yml - kompose.version: 1.38.0 (HEAD) labels: io.kompose.service: foundry-vtt name: foundry-vtt + annotations: + reloader.stakater.com/auto: "true" spec: replicas: 1 selector: @@ -16,23 +15,9 @@ spec: type: Recreate template: metadata: - annotations: - kompose.cmd: kompose convert -f foundry-compose.yml - kompose.version: 1.38.0 (HEAD) - vault.hashicorp.com/agent-inject: "true" - vault.hashicorp.com/role: "foundry-role" - vault.hashicorp.com/agent-inject-secret-credentials: "secret/data/foundry-vtt/config" - vault.hashicorp.com/agent-inject-template-credentials: | - {{- with secret "secret/data/foundry-vtt/config" -}} - export FOUNDRY_ADMIN_KEY="{{ .Data.data.admin_key }}" - export FOUNDRY_LICENSE_KEY="{{ .Data.data.license_key }}" - export FOUNDRY_PASSWORD="{{ .Data.data.password }}" - export FOUNDRY_USERNAME="{{ .Data.data.username }}" - {{- end -}} labels: io.kompose.service: foundry-vtt spec: - serviceAccountName: foundry-vtt-sa containers: - name: foundry-vtt image: felddy/foundryvtt:release @@ -40,15 +25,21 @@ spec: - containerPort: 30000 protocol: TCP name: web-ui + envFrom: + - secretRef: + name: foundry-vtt-secret env: - - name: CONTAINER_PRESERVE_CONFIG - value: "true" - name: FOUNDRY_MINIFY_STATIC_FILES value: "true" + - name: FOUNDRY_HOSTNAME + value: "foundry.mynest.love" + - name: FOUNDRY_PROXY_PORT + value: "443" + - name: FOUNDRY_PROXY_SSL + value: "true" volumeMounts: - mountPath: /data name: foundry-vtt-volume - hostname: 8a7c791facf9 restartPolicy: Always volumes: - name: foundry-vtt-volume diff --git a/services/foundryvtt/foundry-vtt-external-secrets.yaml b/services/foundryvtt/foundry-vtt-external-secrets.yaml new file mode 100644 index 0000000..04af5c6 --- /dev/null +++ b/services/foundryvtt/foundry-vtt-external-secrets.yaml @@ -0,0 +1,30 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: foundry-vtt-credentials + namespace: default +spec: + refreshInterval: "1h" + secretStoreRef: + name: vault-external-secrets-store + kind: ClusterSecretStore + target: + name: foundry-vtt-secret + creationPolicy: Owner + data: + - secretKey: FOUNDRY_ADMIN_KEY + remoteRef: + key: foundry-vtt/config + property: admin_key + - secretKey: FOUNDRY_LICENSE_KEY + remoteRef: + key: foundry-vtt/config + property: license_key + - secretKey: FOUNDRY_PASSWORD + remoteRef: + key: foundry-vtt/config + property: password + - secretKey: FOUNDRY_USERNAME + remoteRef: + key: foundry-vtt/config + property: username diff --git a/services/foundryvtt/foundry-vtt-ingress.yaml b/services/foundryvtt/foundry-vtt-ingress.yaml index c0163b0..1399f67 100644 --- a/services/foundryvtt/foundry-vtt-ingress.yaml +++ b/services/foundryvtt/foundry-vtt-ingress.yaml @@ -1,11 +1,28 @@ +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: foundry-proxy-headers + namespace: default +spec: + headers: + customRequestHeaders: + X-Forwarded-Proto: "https" +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: foundry-ingress namespace: default annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.tls: "true" + traefik.ingress.kubernetes.io/router.middlewares: default-foundry-proxy-headers@kubernetescrd spec: + tls: + - hosts: + - foundry.mynest.love + secretName: foundry-vtt-tls rules: - host: foundry.mynest.love http: diff --git a/services/jellyfin/jellyfin-ingress.yaml b/services/jellyfin/jellyfin-ingress.yaml index 8c6b0a1..79eb2d5 100644 --- a/services/jellyfin/jellyfin-ingress.yaml +++ b/services/jellyfin/jellyfin-ingress.yaml @@ -1,11 +1,28 @@ +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: jellyfin-proxy-headers + namespace: default +spec: + headers: + customRequestHeaders: + X-Forwarded-Proto: "https" +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: jellyfin-ingress namespace: default annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.tls: "true" + traefik.ingress.kubernetes.io/router.middlewares: default-jellyfin-proxy-headers@kubernetescrd spec: + tls: + - hosts: + - beak.mynest.love + secretName: jellyfin-tls rules: - host: beak.mynest.love http: diff --git a/services/navidrome/navidrome-ingress.yaml b/services/navidrome/navidrome-ingress.yaml index 9b68ab9..cd21f35 100644 --- a/services/navidrome/navidrome-ingress.yaml +++ b/services/navidrome/navidrome-ingress.yaml @@ -1,11 +1,28 @@ +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: navidrome-proxy-headers + namespace: default +spec: + headers: + customRequestHeaders: + X-Forwarded-Proto: "https" +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: navidrome-ingress namespace: default annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.tls: "true" + traefik.ingress.kubernetes.io/router.middlewares: default-navidrome-proxy-headers@kubernetescrd spec: + tls: + - hosts: + - chirp.mynest.love + secretName: navidrome-tls rules: - host: chirp.mynest.love http: diff --git a/services/vaultwarden/vaultwarden-ingress.yaml b/services/vaultwarden/vaultwarden-ingress.yaml index 10f300d..681f0ee 100644 --- a/services/vaultwarden/vaultwarden-ingress.yaml +++ b/services/vaultwarden/vaultwarden-ingress.yaml @@ -1,11 +1,29 @@ +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: vaultwarden-proxy-headers + namespace: default +spec: + headers: + customRequestHeaders: + X-Forwarded-Proto: "https" +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: vaultwarden-ingress namespace: default annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" traefik.ingress.kubernetes.io/router.entrypoints: web + traefik.ingress.kubernetes.io/router.tls: "true" + traefik.ingress.kubernetes.io/router.middlewares: default-vaultwarden-proxy-headers@kubernetescrd + spec: + tls: + - hosts: + - vault.mynest.love + secretName: vaultwarden-tls rules: - host: vault.mynest.love http: