Files
homelab/k8s/temporal/TEMPORAL_OAUTH2_SETUP.md
T
Story Crater Bot 69ad5c371c k8s/messaging: add kafka kmsvc and temporal workflows
- Kafka 3-broker cluster (RF=3, min-ISR=2)
- kmsvc SQS-like API on Kafka
- Redis dedup (standalone, can extend to HA)
- Temporal workflow orchestration (Cassandra backend)
2026-08-18 15:08:00 -07:00

5.3 KiB

Temporal OAuth2-Proxy Setup (Authentik OIDC)

Overview

Protects Temporal UI with Authentik OIDC authentication. Traffic flow:

Browser → Ingress (TLS) → oauth2-proxy (OIDC check) → temporal-web (internal)
                             ↓
                         Redirects to Authentik login
                             ↓
                         JWT cookie issued
                             ↓
                         Forwards to temporal-web

Prerequisites

Authentik OIDC provider temporal already exists with:

  • Client ID: temporal
  • Client Secret: stored in Kubernetes secret temporal-oidc (key: clientSecret)
  • Redirect URI: https://temporal.riotpiao.homelab.com/oauth2/callback

Secrets

The temporal-oidc secret must contain:

Key Value Source
clientSecret OAuth2 client secret from Authentik Authentik → Applications → temporal
cookieSecret Session encryption key (base64 32-byte) Generate: openssl rand -base64 32

Check existing secret:

kubectl get secret -n temporal temporal-oidc
kubectl describe secret -n temporal temporal-oidc

If missing, create it:

# Get client secret from Authentik UI
# Applications → temporal → copy "Client Secret"
CLIENT_SECRET="..."

# Generate cookie secret
COOKIE_SECRET=$(openssl rand -base64 32)

# Create secret
kubectl create secret generic temporal-oidc \
  -n temporal \
  --from-literal=clientSecret="${CLIENT_SECRET}" \
  --from-literal=cookieSecret="${COOKIE_SECRET}"

Deployment Steps

Step 1: Apply OAuth2-Proxy Manifests

kubectl apply -f k8s/temporal/oauth2-proxy.yaml

Verify:

kubectl get deploy -n temporal oauth2-proxy
kubectl logs -n temporal deploy/oauth2-proxy

Expected log:

[<timestamp>] [oauthproxy.go:...] Listening on 0.0.0.0:4180

Step 2: Apply OAuth2-Proxy Ingress

kubectl apply -f k8s/temporal/temporal-ingress-oauth2.yaml

Verify:

kubectl get ingress -n temporal

Expected:

NAME      CLASS   HOSTS                              ADDRESS   PORTS     AGE
temporal  nginx   temporal.riotpiao.homelab.com      ...       80, 443   10s

Step 3: Test Access

  1. Open Temporal UI (unauthenticated):

    open https://temporal.riotpiao.homelab.com
    

    Expected: Redirects to Authentik login page

  2. Login with Authentik credentials

    • Username/email
    • Password
    • Should redirect back to temporal.riotpiao.homelab.com and display UI
  3. Verify auth:

    # Check for oauth2_proxy cookie
    curl -v https://temporal.riotpiao.homelab.com 2>&1 | grep -i cookie
    
  4. Check oauth2-proxy logs:

    kubectl logs -n temporal deploy/oauth2-proxy -f
    

    Look for:

    [timestamp] [auth_test.go:...] Authentication successful
    

Troubleshooting

Redirect URI mismatch

Error in oauth2-proxy logs:

redirect_uri_mismatch: The redirect_uri does not match the one registered in Authentik

Fix:

  • Verify Authentik application (Applications → temporal) has redirect URI: https://temporal.riotpiao.homelab.com/oauth2/callback
  • Ensure HTTPS (not HTTP)

Missing secret

Error:

clientSecret: key not found in temporal-oidc secret

Fix:

kubectl get secret -n temporal temporal-oidc -o yaml
# If missing, create per "Secrets" section above

OAuth2-Proxy won't start if cookieSecret is empty or invalid.

Fix:

COOKIE_SECRET=$(openssl rand -base64 32)
kubectl patch secret temporal-oidc -n temporal \
  -p "{\"data\":{\"cookieSecret\":\"$(echo -n $COOKIE_SECRET | base64)\"}}}"
kubectl rollout restart deploy/oauth2-proxy -n temporal

oauth2-proxy crashes with "connection refused"

Error in logs:

upstream connect error or disconnect/reset before headers

Likely cause: temporal-web service not accessible.

Check:

kubectl get svc -n temporal temporal-web
kubectl exec -n temporal deploy/oauth2-proxy -- curl http://temporal-web:8080

File Structure

k8s/temporal/
├── oauth2-proxy.yaml              # oauth2-proxy Deployment + Service + SA
├── temporal-ingress-oauth2.yaml    # Ingress routing to oauth2-proxy
├── oauth2-proxy-values.yaml        # Helm values (reference only)
└── temporal-values.yaml            # Modified: ingress.enabled=false

Next: Add to Helmfile

If integrating with helmfile.yaml.gotmpl:

releases:
  - name: temporal
    # ... existing config ...
    hooks:
      postSync:
        - events: ["success"]
          showlogs: true
          command: "sh"
          args:
            - -c
            - |
              kubectl apply -f k8s/temporal/oauth2-proxy.yaml
              kubectl apply -f k8s/temporal/temporal-ingress-oauth2.yaml

Or add separate releases:

  - name: oauth2-proxy-temporal
    namespace: temporal
    chart: oauth2-proxy/oauth2-proxy
    version: "6.x.x"
    values:
      - k8s/temporal/oauth2-proxy-values.yaml
    set:
      - name: config.clientSecret
        value: "{{ (env "TEMPORAL_OIDC_CLIENT_SECRET") }}"
      - name: config.cookieSecret
        value: "{{ (env "TEMPORAL_OIDC_COOKIE_SECRET") }}"

Then add to .env:

TEMPORAL_OIDC_CLIENT_SECRET=<from Authentik>
TEMPORAL_OIDC_COOKIE_SECRET=$(openssl rand -base64 32)