Migrate navidrome to keycloak

This commit is contained in:
Astra Logical 2026-06-13 11:05:56 -04:00
parent d36431f7ef
commit 98c244ec0d
14 changed files with 291 additions and 170 deletions

View file

@ -2,16 +2,16 @@ apiVersion: v1
kind: Pod kind: Pod
metadata: metadata:
name: data-restorer name: data-restorer
namespace: vault namespace: default
spec: spec:
containers: containers:
- name: alpine - name: alpine
image: alpine:latest image: alpine:latest
command: ["sleep", "infinity"] command: ["/bin/sh", "-c", "apk add --no-cache vim && sleep infinity"]
volumeMounts: volumeMounts:
- mountPath: /restore - mountPath: /restore
name: target-volume name: target-volume
volumes: volumes:
- name: target-volume - name: target-volume
persistentVolumeClaim: persistentVolumeClaim:
claimName: keykeeper-data-pvc claimName: jellyfin-config-pvc

View file

@ -1,19 +0,0 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: foundry-vtt-sa
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: foundry-vtt-auth-delegator
subjects:
- kind: ServiceAccount
name: foundry-vtt-sa
namespace: default
roleRef:
kind: ClusterRole
name: system:auth-delegator
apiGroup: rbac.authorization.k8s.io

View file

@ -2,8 +2,6 @@ apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: foundry-vtt name: foundry-vtt
annotations:
reloader.stakater.com/auto: "true"
spec: spec:
replicas: 1 replicas: 1
selector: selector:
@ -18,7 +16,7 @@ spec:
spec: spec:
containers: containers:
- name: foundry-vtt - name: foundry-vtt
image: felddy/foundryvtt:release image: felddy/foundryvtt:latest
ports: ports:
- containerPort: 30000 - containerPort: 30000
protocol: TCP protocol: TCP

View file

@ -14,17 +14,17 @@ spec:
data: data:
- secretKey: FOUNDRY_ADMIN_KEY - secretKey: FOUNDRY_ADMIN_KEY
remoteRef: remoteRef:
key: foundry-vtt/config key: foundryvtt
property: admin_key property: admin-key
- secretKey: FOUNDRY_LICENSE_KEY - secretKey: FOUNDRY_LICENSE_KEY
remoteRef: remoteRef:
key: foundry-vtt/config key: foundryvtt
property: license_key property: license-key
- secretKey: FOUNDRY_PASSWORD - secretKey: FOUNDRY_PASSWORD
remoteRef: remoteRef:
key: foundry-vtt/config key: foundryvtt
property: password property: password
- secretKey: FOUNDRY_USERNAME - secretKey: FOUNDRY_USERNAME
remoteRef: remoteRef:
key: foundry-vtt/config key: foundryvtt
property: username property: username

View file

@ -1,27 +1,3 @@
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: foundry-proxy-headers
namespace: default
spec:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: foundry-vtt-oauth-auth
namespace: default
spec:
forwardAuth:
address: http://foundry-vtt-oauth2-proxy.default.svc.cluster.local:4180/
trustForwardHeader: true
authResponseHeaders:
- X-Auth-Request-User
- X-Auth-Request-Email
- X-Auth-Request-Access-Token
---
apiVersion: networking.k8s.io/v1 apiVersion: networking.k8s.io/v1
kind: Ingress kind: Ingress
metadata: metadata:
@ -30,8 +6,7 @@ metadata:
annotations: annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod" cert-manager.io/cluster-issuer: "letsencrypt-prod"
traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true" traefik.ingress.kubernetes.io/router.middlewares: security-auth-foundryvtt@kubernetescrd
traefik.ingress.kubernetes.io/router.middlewares: default-foundry-proxy-headers@kubernetescrd, default-foundry-vtt-oauth-auth@kubernetescrd
spec: spec:
ingressClassName: traefik ingressClassName: traefik
tls: tls:
@ -53,13 +28,11 @@ spec:
apiVersion: networking.k8s.io/v1 apiVersion: networking.k8s.io/v1
kind: Ingress kind: Ingress
metadata: metadata:
name: foundry-oauth-ingress name: foundry-auth-ingress
namespace: default namespace: security # MOVED TO SECURITY NAMESPACE
annotations: annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod" cert-manager.io/cluster-issuer: "letsencrypt-prod"
traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.middlewares: default-foundry-proxy-headers@kubernetescrd
spec: spec:
ingressClassName: traefik ingressClassName: traefik
tls: tls:
@ -74,6 +47,6 @@ spec:
pathType: Prefix pathType: Prefix
backend: backend:
service: service:
name: foundry-vtt-oauth2-proxy name: oauth2-proxy-foundryvtt
port: port:
number: 4180 number: 4180

View file

@ -1,39 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: foundry-vtt-oauth2-proxy
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: foundry-vtt-oauth2-proxy
template:
metadata:
labels:
app: foundry-vtt-oauth2-proxy
spec:
containers:
- name: oauth2-proxy
image: quay.io/oauth2-proxy/oauth2-proxy:latest
args:
- --provider=oidc
- --oidc-issuer-url=https://sso.mynest.love/realms/nest
- --redirect-url=https://foundry.mynest.love/oauth2/callback
- --email-domain=*
- --upstream=static://200
- --http-address=0.0.0.0:4180
- --pass-authorization-header=true
- --pass-access-token=true
- --set-xauthrequest=true
- --skip-provider-button=true
- --reverse-proxy=true
- --cookie-secure=true
- --cookie-domain=.mynest.love
- --whitelist-domain=.mynest.love
- --cookie-name=_oauth2_proxy_foundry
envFrom:
- secretRef:
name: foundry-vtt-oauth2-proxy-secret
ports:
- containerPort: 4180

View file

@ -1,26 +0,0 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: foundry-vtt-oauth2-proxy-credentials
namespace: default
spec:
refreshInterval: "1h"
secretStoreRef:
name: vault-external-secrets-store
kind: ClusterSecretStore
target:
name: foundry-vtt-oauth2-proxy-secret
creationPolicy: Owner
data:
- secretKey: OAUTH2_PROXY_CLIENT_ID
remoteRef:
key: oauth2-proxy/foundry-vtt
property: client-id
- secretKey: OAUTH2_PROXY_CLIENT_SECRET
remoteRef:
key: oauth2-proxy/foundry-vtt
property: client-secret
- secretKey: OAUTH2_PROXY_COOKIE_SECRET
remoteRef:
key: oauth2-proxy/foundry-vtt
property: cookie-secret

View file

@ -1,11 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: foundry-vtt-oauth2-proxy
namespace: default
spec:
ports:
- port: 4180
targetPort: 4180
selector:
app: foundry-vtt-oauth2-proxy

View file

@ -0,0 +1,86 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: foundryvtt-proxy-foundryvtt
namespace: security
spec:
replicas: 1
selector:
matchLabels:
app: oauth2-proxy-foundryvtt
template:
metadata:
labels:
app: oauth2-proxy-foundryvtt
spec:
containers:
- name: oauth2-proxy
image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0
envFrom:
- secretRef:
name: foundry-oauth-secrets
args:
- "--provider=oidc"
- "--oidc-issuer-url=https://sso.mynest.love/realms/nest"
- "--oidc-groups-claim=groups"
- "--redirect-url=https://foundry.mynest.love/oauth2/callback"
- "--email-domain=*"
- "--allowed-group=foundryvtt"
- "--skip-provider-button=true"
- "--cookie-secure=true"
- "--cookie-domain=foundry.mynest.love"
- "--http-address=0.0.0.0:4180"
- "--reverse-proxy=true"
- "--upstream=static://200"
- "--whitelist-domain=foundry.mynest.love"
ports:
- containerPort: 4180
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: foundry-oauth-secrets
namespace: security
spec:
refreshInterval: "1h"
secretStoreRef:
name: vault-external-secrets-store
kind: ClusterSecretStore
target:
name: foundry-oauth-secrets
creationPolicy: Owner
data:
- secretKey: OAUTH2_PROXY_CLIENT_ID
remoteRef:
key: oauth2-proxy/foundryvtt
property: client-id
- secretKey: OAUTH2_PROXY_CLIENT_SECRET
remoteRef:
key: oauth2-proxy/foundryvtt
property: client-secret
- secretKey: OAUTH2_PROXY_COOKIE_SECRET
remoteRef:
key: oauth2-proxy/foundryvtt
property: cookie-secret
---
apiVersion: v1
kind: Service
metadata:
name: oauth2-proxy-foundryvtt
namespace: security
spec:
ports:
- port: 4180
targetPort: 4180
selector:
app: oauth2-proxy-foundryvtt
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: auth-foundryvtt
namespace: security
spec:
forwardAuth:
address: "http://oauth2-proxy-foundryvtt.security.svc.cluster.local:4180"
trustForwardHeader: true

View file

@ -15,7 +15,7 @@ spec:
spec: spec:
containers: containers:
- name: keycloak - name: keycloak
image: quay.io/keycloak/keycloak:24.0.0 image: quay.io/keycloak/keycloak:latest
command: ["/bin/sh", "-c", "/opt/keycloak/bin/kc.sh start"] command: ["/bin/sh", "-c", "/opt/keycloak/bin/kc.sh start"]
envFrom: envFrom:
- secretRef: - secretRef:

View file

@ -1,19 +0,0 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: navidrome-sa
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: navidrome-auth-delegator
subjects:
- kind: ServiceAccount
name: navidrome-sa
namespace: default
roleRef:
kind: ClusterRole
name: system:auth-delegator
apiGroup: rbac.authorization.k8s.io

View file

@ -26,6 +26,10 @@ spec:
- env: - env:
- name: TZ - name: TZ
value: America/New_York value: America/New_York
- name: ND_REVERSEPROXYUSERHEADER
value: "X-Auth-Request-Preferred-Username"
- name: ND_REVERSEPROXYWHITELIST
value: "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,10.42.0.0/16,10.43.0.0/16"
image: deluan/navidrome:latest image: deluan/navidrome:latest
name: navidrome name: navidrome
ports: ports:

View file

@ -1,23 +1,14 @@
apiVersion: traefik.io/v1alpha1 # 1. Main Web UI Ingress - Protected by SSO
kind: Middleware
metadata:
name: navidrome-proxy-headers
namespace: default
spec:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
---
apiVersion: networking.k8s.io/v1 apiVersion: networking.k8s.io/v1
kind: Ingress kind: Ingress
metadata: metadata:
name: navidrome-ingress name: navidrome-ingress-web
namespace: default namespace: default
annotations: annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod" cert-manager.io/cluster-issuer: "letsencrypt-prod"
traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true" traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.middlewares: default-navidrome-proxy-headers@kubernetescrd traefik.ingress.kubernetes.io/router.middlewares: default-navidrome-proxy-headers@kubernetescrd, security-auth-navidrome@kubernetescrd
spec: spec:
tls: tls:
- hosts: - hosts:
@ -34,3 +25,66 @@ spec:
name: navidrome name: navidrome
port: port:
name: http-web name: http-web
---
# 2. Subsonic API Ingress - Bypasses SSO Middleware for Mobile Clients
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: navidrome-ingress-api
namespace: default
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.middlewares: default-navidrome-proxy-headers@kubernetescrd
spec:
ingressClassName: traefik
tls:
- hosts:
- chirp.mynest.love
secretName: navidrome-tls
rules:
- host: chirp.mynest.love
http:
paths:
- path: /rest
pathType: Prefix
backend:
service:
name: navidrome
port:
name: http-web
- path: /share
pathType: Prefix
backend:
service:
name: navidrome
port:
name: http-web
---
# 3. Auth Callback Ingress - Bypasses SSO to deliver tokens directly to the proxy
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: navidrome-auth-ingress
namespace: security
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
ingressClassName: traefik
tls:
- hosts:
- chirp.mynest.love
secretName: navidrome-tls
rules:
- host: chirp.mynest.love
http:
paths:
- path: /oauth2
pathType: Prefix
backend:
service:
name: oauth2-proxy-navidrome
port:
number: 4180

View file

@ -0,0 +1,120 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: navidrome-oauth-secrets
namespace: security
spec:
refreshInterval: "1h"
secretStoreRef:
name: vault-external-secrets-store
kind: ClusterSecretStore
target:
name: navidrome-oauth-secrets
creationPolicy: Owner
data:
- secretKey: OAUTH2_PROXY_CLIENT_ID
remoteRef:
key: oauth2-proxy/navidrome
property: client-id
- secretKey: OAUTH2_PROXY_CLIENT_SECRET
remoteRef:
key: oauth2-proxy/navidrome
property: client-secret
- secretKey: OAUTH2_PROXY_COOKIE_SECRET
remoteRef:
key: oauth2-proxy/navidrome
property: cookie-secret
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: oauth2-proxy-navidrome
namespace: security
spec:
replicas: 1
selector:
matchLabels:
app: oauth2-proxy-navidrome
template:
metadata:
labels:
app: oauth2-proxy-navidrome
spec:
containers:
- name: oauth2-proxy
image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0
envFrom:
- secretRef:
name: navidrome-oauth-secrets
args:
- "--provider=oidc"
- "--user-id-claim=preferred_username"
- "--set-xauthrequest=true"
- "--oidc-issuer-url=https://sso.mynest.love/realms/nest"
- "--oidc-groups-claim=groups"
- "--redirect-url=https://chirp.mynest.love/oauth2/callback"
- "--email-domain=*"
- "--allowed-group=navidrome"
- "--skip-provider-button=true"
- "--cookie-secure=true"
- "--cookie-domain=chirp.mynest.love"
- "--http-address=0.0.0.0:4180"
- "--reverse-proxy=true"
- "--upstream=static://200"
- "--whitelist-domain=chirp.mynest.love"
- "--set-xauthrequest=true"
ports:
- containerPort: 4180
---
apiVersion: v1
kind: Service
metadata:
name: oauth2-proxy-navidrome
namespace: security
spec:
ports:
- port: 4180
targetPort: 4180
selector:
app: oauth2-proxy-navidrome
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: auth-navidrome
namespace: security
spec:
forwardAuth:
address: http://oauth2-proxy-navidrome.security.svc.cluster.local:4180
trustForwardHeader: true
authResponseHeaders:
- X-Auth-Request-User
- X-Auth-Request-Email
- X-Auth-Request-Preferred-Username
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: navidrome-auth-ingress
namespace: security
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
tls:
- hosts:
- chirp.mynest.love
secretName: navidrome-tls
rules:
- host: chirp.mynest.love
http:
paths:
- path: /oauth2
pathType: Prefix
backend:
service:
name: oauth2-proxy-navidrome
port:
number: 4180