Set up Keycloak and oauth2 with foundry as first conversion

This commit is contained in:
Astra Logical 2026-04-12 18:25:16 -04:00
parent d2852ab9c5
commit 186221bc6d
11 changed files with 261 additions and 42 deletions

View file

@ -1,8 +1,6 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
io.kompose.service: foundry-vtt
name: foundry-vtt
annotations:
reloader.stakater.com/auto: "true"
@ -10,13 +8,13 @@ spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: foundry-vtt
app: foundry-vtt
strategy:
type: Recreate
template:
metadata:
labels:
io.kompose.service: foundry-vtt
app: foundry-vtt
spec:
containers:
- name: foundry-vtt

View file

@ -1,30 +0,0 @@
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

View file

@ -8,6 +8,20 @@ spec:
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
kind: Ingress
metadata:
@ -15,10 +29,11 @@ metadata:
namespace: default
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
traefik.ingress.kubernetes.io/router.entrypoints: web
traefik.ingress.kubernetes.io/router.entrypoints: web, websecure
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.middlewares: default-foundry-proxy-headers@kubernetescrd
traefik.ingress.kubernetes.io/router.middlewares: default-foundry-proxy-headers@kubernetescrd, default-foundry-vtt-oauth-auth@kubernetescrd
spec:
ingressClassName: traefik
tls:
- hosts:
- foundry.mynest.love
@ -34,3 +49,31 @@ spec:
name: foundry-vtt
port:
name: http-web
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: foundry-oauth-ingress
namespace: default
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
traefik.ingress.kubernetes.io/router.entrypoints: web, websecure
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.middlewares: default-foundry-proxy-headers@kubernetescrd
spec:
ingressClassName: traefik
tls:
- hosts:
- foundry.mynest.love
secretName: foundry-vtt-tls
rules:
- host: foundry.mynest.love
http:
paths:
- path: /oauth2
pathType: Prefix
backend:
service:
name: foundry-vtt-oauth2-proxy
port:
number: 4180

View file

@ -0,0 +1,39 @@
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

@ -0,0 +1,26 @@
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

@ -0,0 +1,11 @@
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

@ -1,11 +1,6 @@
apiVersion: v1
kind: Service
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
spec:
type: ClusterIP
@ -14,4 +9,4 @@ spec:
port: 80
targetPort: web-ui
selector:
io.kompose.service: foundry-vtt
app: foundry-vtt

View file

@ -0,0 +1,40 @@
apiVersion: k8s.keycloak.org/v2alpha1
kind: Keycloak
metadata:
name: keycloak
namespace: default
spec:
instances: 1
image: quay.io/keycloak/keycloak:latest
startOptimized: false
db:
vendor: postgres
host: birdfeeder2.home.nest
port: 5432
database: keycloak
usernameSecret:
name: keycloak-db-secret
key: username
passwordSecret:
name: keycloak-db-secret
key: password
http:
httpEnabled: true
hostname:
hostname: sso.mynest.love
strict: true
additionalOptions:
- name: proxy-headers
value: xforwarded
- name: hostname-strict-https
value: "true"
- name: bootstrap-admin-username
secret:
name: keycloak-admin-login
key: username
- name: bootstrap-admin-password
secret:
name: keycloak-admin-login
key: password
ingress:
enabled: false

View file

@ -0,0 +1,45 @@
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: keycloak-db-credentials
namespace: default
spec:
refreshInterval: "1h"
secretStoreRef:
name: vault-external-secrets-store
kind: ClusterSecretStore
target:
name: keycloak-db-secret
creationPolicy: Owner
data:
- secretKey: username
remoteRef:
key: keycloak/database
property: username
- secretKey: password
remoteRef:
key: keycloak/database
property: password
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: keycloak-admin-credentials
namespace: default
spec:
refreshInterval: "1h"
secretStoreRef:
name: vault-external-secrets-store
kind: ClusterSecretStore
target:
name: keycloak-admin-login
creationPolicy: Owner
data:
- secretKey: username
remoteRef:
key: keycloak/admin
property: username
- secretKey: password
remoteRef:
key: keycloak/admin
property: password

View file

@ -0,0 +1,37 @@
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: keycloak-proxy-headers
namespace: default
spec:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: keycloak-ingress
namespace: default
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
traefik.ingress.kubernetes.io/router.entrypoints: websecure, web
traefik.ingress.kubernetes.io/router.tls: "true"
traefik.ingress.kubernetes.io/router.middlewares: default-keycloak-proxy-headers@kubernetescrd
spec:
ingressClassName: traefik
tls:
- hosts:
- sso.mynest.love
secretName: keycloak-tls
rules:
- host: sso.mynest.love
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: keycloak-service
port:
number: 8080

View file

@ -0,0 +1,15 @@
apiVersion: k8s.keycloak.org/v2alpha1
kind: KeycloakRealmImport
metadata:
name: keycloak-realm
namespace: default
spec:
keycloakCRName: keycloak
realm:
id: nest
realm: nest
enabled: true
displayName: "Nest SSO"
# You will eventually dump your full JSON realm export here
# clients: [...]
# users: [...]