Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a525a52580 | ||
|
|
3e92f34153 | ||
|
|
549e0be502 |
@@ -9,12 +9,6 @@ metadata:
|
|||||||
# WebSocket support for Gotify client connections (/stream endpoint)
|
# WebSocket support for Gotify client connections (/stream endpoint)
|
||||||
# nginx-ingress handles Upgrade/Connection headers natively with http/1.1
|
# nginx-ingress handles Upgrade/Connection headers natively with http/1.1
|
||||||
nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
|
nginx.ingress.kubernetes.io/proxy-http-version: "1.1"
|
||||||
# Single sign-on. Gotify has no OIDC, so every request is handed to
|
|
||||||
# oauth2-proxy for an allow or deny decision. oauth2-proxy skips the token
|
|
||||||
# API paths itself, so /message keeps Gotify's own X-Gotify-Key check.
|
|
||||||
nginx.ingress.kubernetes.io/auth-url: "http://gotify-oauth2-proxy.notifications.svc.cluster.local:4180/oauth2/auth"
|
|
||||||
nginx.ingress.kubernetes.io/auth-signin: "https://gotify.riotpiao.com/oauth2/start?rd=$scheme://$host$request_uri"
|
|
||||||
nginx.ingress.kubernetes.io/auth-response-headers: "x-auth-request-user,x-auth-request-email"
|
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
ingressClassName: nginx
|
||||||
rules:
|
rules:
|
||||||
|
|||||||
@@ -5,9 +5,6 @@ resources:
|
|||||||
- db.yaml
|
- db.yaml
|
||||||
- deployment.yaml
|
- deployment.yaml
|
||||||
- service.yaml
|
- service.yaml
|
||||||
- oauth2-proxy-deployment.yaml
|
|
||||||
- oauth2-proxy-service.yaml
|
|
||||||
- oauth2-proxy-ingress.yaml
|
|
||||||
- ingress.yaml
|
- ingress.yaml
|
||||||
- igotify-pvc.yaml
|
- igotify-pvc.yaml
|
||||||
- igotify-deployment.yaml
|
- igotify-deployment.yaml
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
# oauth2-proxy in front of Gotify. Gotify has no OIDC support of its own, so it
|
|
||||||
# cannot validate a ZITADEL token. This proxy is the front door: nginx asks it
|
|
||||||
# for an auth decision on every request (auth_request), and it answers from a
|
|
||||||
# ZITADEL session cookie.
|
|
||||||
#
|
|
||||||
# The Gotify REST API keeps its own client-token auth (X-Gotify-Key) and must
|
|
||||||
# stay reachable without a browser session, or every push sender breaks:
|
|
||||||
# Forgejo webhooks, the harness, poimen-sender and the ntfy-style relays all post
|
|
||||||
# to /message. skip-auth-route leaves those paths to Gotify's own token check.
|
|
||||||
#
|
|
||||||
# Gotify's own login still exists behind the proxy. ZITADEL decides who may
|
|
||||||
# reach the service; Gotify decides what that person may do inside it.
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: gotify-oauth2-proxy
|
|
||||||
namespace: notifications
|
|
||||||
labels:
|
|
||||||
app: gotify-oauth2-proxy
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: gotify-oauth2-proxy
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: gotify-oauth2-proxy
|
|
||||||
spec:
|
|
||||||
securityContext:
|
|
||||||
runAsNonRoot: true
|
|
||||||
runAsUser: 65534
|
|
||||||
seccompProfile:
|
|
||||||
type: RuntimeDefault
|
|
||||||
containers:
|
|
||||||
- name: oauth2-proxy
|
|
||||||
image: quay.io/oauth2-proxy/oauth2-proxy:v7.7.1
|
|
||||||
args:
|
|
||||||
- --provider=oidc
|
|
||||||
- --oidc-issuer-url=https://zitadel.riotpiao.com
|
|
||||||
- --email-domain=*
|
|
||||||
- --upstream=static://202
|
|
||||||
- --reverse-proxy=true
|
|
||||||
- --set-xauthrequest=true
|
|
||||||
- --cookie-secure=true
|
|
||||||
- --cookie-expire=12h
|
|
||||||
- --cookie-refresh=1h
|
|
||||||
- --skip-provider-button=true
|
|
||||||
- --redirect-url=https://gotify.riotpiao.com/oauth2/callback
|
|
||||||
- --http-address=0.0.0.0:4180
|
|
||||||
# Browser paths keep SSO. API paths fall through to Gotify's own
|
|
||||||
# client-token check, so existing senders and the Android client
|
|
||||||
# keep working without a browser session.
|
|
||||||
- --skip-auth-route=^/(message|application|client|user|version|stream|health)(/.*)?$
|
|
||||||
env:
|
|
||||||
- name: OAUTH2_PROXY_CLIENT_ID
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef: {name: gotify-oauth2-proxy, key: client-id}
|
|
||||||
- name: OAUTH2_PROXY_CLIENT_SECRET
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef: {name: gotify-oauth2-proxy, key: client-secret}
|
|
||||||
- name: OAUTH2_PROXY_COOKIE_SECRET
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef: {name: gotify-oauth2-proxy, key: cookie-secret}
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
containerPort: 4180
|
|
||||||
readinessProbe:
|
|
||||||
httpGet: {path: /ping, port: http}
|
|
||||||
initialDelaySeconds: 5
|
|
||||||
periodSeconds: 10
|
|
||||||
livenessProbe:
|
|
||||||
httpGet: {path: /ping, port: http}
|
|
||||||
initialDelaySeconds: 15
|
|
||||||
periodSeconds: 20
|
|
||||||
securityContext:
|
|
||||||
allowPrivilegeEscalation: false
|
|
||||||
capabilities:
|
|
||||||
drop: ["ALL"]
|
|
||||||
resources:
|
|
||||||
requests: {cpu: 10m, memory: 32Mi}
|
|
||||||
limits: {cpu: 200m, memory: 128Mi}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
# The proxy needs its own ingress path. nginx auth_request also guards
|
|
||||||
# /oauth2/start and /oauth2/callback, which would loop: the login entry point
|
|
||||||
# would itself require a login. A longer path match sends /oauth2 to the proxy
|
|
||||||
# directly, and the prefix rule on the gotify ingress handles everything else.
|
|
||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: gotify-oauth2
|
|
||||||
namespace: notifications
|
|
||||||
spec:
|
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
|
||||||
- host: gotify.riotpiao.com
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /oauth2
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: gotify-oauth2-proxy
|
|
||||||
port:
|
|
||||||
number: 4180
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: gotify-oauth2-proxy
|
|
||||||
namespace: notifications
|
|
||||||
labels:
|
|
||||||
app: gotify-oauth2-proxy
|
|
||||||
spec:
|
|
||||||
type: ClusterIP
|
|
||||||
selector:
|
|
||||||
app: gotify-oauth2-proxy
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
port: 4180
|
|
||||||
targetPort: http
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
name: gotify-oauth2-proxy
|
|
||||||
namespace: notifications
|
|
||||||
type: Opaque
|
|
||||||
data:
|
|
||||||
client-id: ENC[AES256_GCM,data:Q+XQAR6cfHKoiuxhPZs6khTvqT0A/JG6,iv:LqhfuhXOYPVB6FQpPpERzWRQ+nxgxHZo4qdJO/g52y8=,tag:V2eK2fyscQKmM3/MmDnNtg==,type:str]
|
|
||||||
client-secret: ENC[AES256_GCM,data:P7F+83CLDhHnTN+Qx3SeCFbCjVH4JHb2rSteCr3Dywcb1ysMSNvC+3HyBXzsfJJ/EErUrCPWuwlRmV5ySts1oIrWhKyWMJxNrUTzv4eoclat4RyV6SaNDg==,iv:ESO1OUIqZbZPEVUuHrqjskA4tuTX/sc5m+K6Eo319kI=,tag:2isdxjFbtosov88FHZdeaQ==,type:str]
|
|
||||||
cookie-secret: ENC[AES256_GCM,data:WoWiANSdju+Ep5MuZQNeT0BQdKf5cFvrDUZpe+4B0VeUmQqnvblFi3dciJOeBFom9xYYzUCAI2tUSmX+a6tdAObyoGvjdFmLh+WTfw==,iv:41gYYRkyDIqC3GPuZkoob81Wl2njFTY07j4Puzaq0s4=,tag:x6z33zZnFwvmWUQIVPcxdQ==,type:str]
|
|
||||||
sops:
|
|
||||||
kms: []
|
|
||||||
gcp_kms: []
|
|
||||||
azure_kv: []
|
|
||||||
hc_vault: []
|
|
||||||
age:
|
|
||||||
- recipient: age1e5fq3hwxy78psus2nfvmtmua36g0u3suk78ephw6246l974d2utsvn0hla
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2UURWblY4aTBOQjFSNDRL
|
|
||||||
YkRXVjVHK1QvYW1iR2o0UWVmdE94c2lkWDJjCnlXK1k3cnZBNEExbDU3eDhQZ3FT
|
|
||||||
TVcyckFiWHdRSjZHQ201Nnl6UFdTN28KLS0tIExQeE90VnM1WHRCYkpycjJtR0ht
|
|
||||||
ZHFDNWhKeENSQzljZUNmdktDYWloUDQK/fOG8AjTb2TNqLbqNfArOs0mzInYNJVd
|
|
||||||
iaYxnjH6AjhbLKdnmCpecTQpgx8GeFGIkefV/x5pgrdSUwn0lcvpSQ==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
lastmodified: "2026-10-27T19:05:35Z"
|
|
||||||
mac: ENC[AES256_GCM,data:KZV3JNebQ+DbZZZ+e3fvtOGckwC9fmkIchh8DBJ0DMq9lbrPEhP4Juordmnrrs9vJvGxuFJ/KwUv9EELqBsuSy8c47+z7flEAXJiJCJkvVPL/jMidABsFqMALvNNrCqBPWvMHLZUj762DwxB2gKhSx3GLfRUXhm+ZiNcD+39EVw=,iv:ifUlEq/GhBc/QomJApkCaWc3f4ggXoLsvqjzZElO0fU=,tag:fMo+HBDUZdRXgfck+8AJbA==,type:str]
|
|
||||||
pgp: []
|
|
||||||
encrypted_regex: ^(data|stringData)$
|
|
||||||
version: 3.9.3
|
|
||||||
@@ -36,7 +36,6 @@ files:
|
|||||||
- etcd-defrag-creds.enc.yaml
|
- etcd-defrag-creds.enc.yaml
|
||||||
- zitadel-masterkey.enc.yaml
|
- zitadel-masterkey.enc.yaml
|
||||||
- smtp-gotify-secrets.enc.yaml
|
- smtp-gotify-secrets.enc.yaml
|
||||||
- gotify-oauth2-proxy-secrets.enc.yaml
|
|
||||||
# Login UI RSA keypair, adopted from the chart-generated Secret so ArgoCD
|
# Login UI RSA keypair, adopted from the chart-generated Secret so ArgoCD
|
||||||
# owns it. Without this, the chart re-generates the keypair on every render,
|
# owns it. Without this, the chart re-generates the keypair on every render,
|
||||||
# which changes checksum/secret-login-service-key and leaves both Zitadel
|
# which changes checksum/secret-login-service-key and leaves both Zitadel
|
||||||
|
|||||||
@@ -88,20 +88,6 @@ ROLES = {
|
|||||||
# permission string, so consumer manifests did not change.
|
# permission string, so consumer manifests did not change.
|
||||||
"llm:inference": "LLM inference access (api-gw)",
|
"llm:inference": "LLM inference access (api-gw)",
|
||||||
"llm-inference": "LLM inference access (dash alias)",
|
"llm-inference": "LLM inference access (dash alias)",
|
||||||
# Per-service capabilities. The gateway derives the required capability from
|
|
||||||
# the verb: GET/HEAD/OPTIONS -> "<service>:read", anything else ->
|
|
||||||
# "<service>:write" (internal/serviceadapter/router.go:142). The role key
|
|
||||||
# must match that string exactly, colon included.
|
|
||||||
"memory:read": "Poimen memory read (api-gw)",
|
|
||||||
"memory:write": "Poimen memory write (api-gw)",
|
|
||||||
"workflow:read": "Temporal workflow read (api-gw)",
|
|
||||||
"workflow:execute": "Temporal workflow execute (api-gw)",
|
|
||||||
"s3:read": "Object store read (api-gw)",
|
|
||||||
"s3:write": "Object store write (api-gw)",
|
|
||||||
"iam:read": "Identity read (api-gw)",
|
|
||||||
"iam:write": "Identity write (api-gw)",
|
|
||||||
"sqs:read": "Queue read (api-gw)",
|
|
||||||
"sqs:write": "Queue write (api-gw)",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_WEB = {"app_type_id": "OIDC_APP_TYPE_WEB", "auth_method_id": "OIDC_AUTH_METHOD_TYPE_BASIC"}
|
_WEB = {"app_type_id": "OIDC_APP_TYPE_WEB", "auth_method_id": "OIDC_AUTH_METHOD_TYPE_BASIC"}
|
||||||
@@ -122,11 +108,6 @@ OIDC_APPS = {
|
|||||||
"https://forgejo.riotpiao.com/user/oauth2/zitadel/callback",
|
"https://forgejo.riotpiao.com/user/oauth2/zitadel/callback",
|
||||||
"http://localhost:3000/user/oauth2/authentik/callback",
|
"http://localhost:3000/user/oauth2/authentik/callback",
|
||||||
"https://forgejo.riotpiao.com/user/oauth2/authentik/callback"]},
|
"https://forgejo.riotpiao.com/user/oauth2/authentik/callback"]},
|
||||||
# Gotify has no native OIDC, so oauth2-proxy sits in front of it and this app
|
|
||||||
# is the proxy's client. The callback path is the proxy's, not Gotify's.
|
|
||||||
"gotify": {**_WEB, "redirect_uris": [
|
|
||||||
"http://localhost:4180/oauth2/callback",
|
|
||||||
"https://gotify.riotpiao.com/oauth2/callback"]},
|
|
||||||
"grafana": {**_WEB, "redirect_uris": [
|
"grafana": {**_WEB, "redirect_uris": [
|
||||||
"http://localhost:3000/login/generic_oauth",
|
"http://localhost:3000/login/generic_oauth",
|
||||||
"https://grafana.riotpiao.com/login/generic_oauth"]},
|
"https://grafana.riotpiao.com/login/generic_oauth"]},
|
||||||
|
|||||||
Reference in New Issue
Block a user