From d16ea023db3753bef86cb34ff4a572494b9c118c Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 07:39:16 -0400 Subject: [PATCH 01/47] docs: add shared ingress with Authentik design spec --- ...6-04-07-shared-ingress-authentik-design.md | 223 ++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-07-shared-ingress-authentik-design.md diff --git a/docs/superpowers/specs/2026-04-07-shared-ingress-authentik-design.md b/docs/superpowers/specs/2026-04-07-shared-ingress-authentik-design.md new file mode 100644 index 0000000..fd4a3a5 --- /dev/null +++ b/docs/superpowers/specs/2026-04-07-shared-ingress-authentik-design.md @@ -0,0 +1,223 @@ +# Shared Ingress with Authentik for Multi-User OpenCode + +## Executive Summary + +This design implements a shared ingress architecture for multi-user OpenCode deployments using Authentik as an Identity-Aware Proxy (IAP). All users access OpenCode through a single shared hostname (e.g., `opencode.company.com`) with centralized OIDC authentication via Google Workspace. Authentik dynamically routes authenticated users to their isolated StatefulSet pods based on email-to-user mapping, providing secure, scalable multi-tenant access without per-user subdomains. + +## Problem Statement + +The current multi-user OpenCode deployment uses per-user subdomains (e.g., `opencode-alice.opencode.ts.net`) with a custom auth-router that validates hostname-to-user mapping. This requires: + +- Separate DNS entries for each user +- Custom routing logic in the auth-router +- Users to know their specific subdomain + +Organizations want a single, centralized access point with professional branding and simplified user experience. + +## Requirements + +### Functional Requirements +- **Shared Hostname**: Single domain (e.g., `opencode.company.com`) for all users +- **OIDC Authentication**: Google Workspace integration for enterprise SSO +- **Identity-Based Routing**: Route users to pods based on authenticated email claims +- **Session Persistence**: Maintain user sessions across requests +- **Security**: Zero-trust access with continuous claim validation + +### Non-Functional Requirements +- **Scalability**: Support hundreds of concurrent users +- **Security**: No custom routing code; use battle-tested IAP +- **Maintainability**: Declarative configuration, minimal operational overhead +- **Compatibility**: Integrate with existing OpenCode operator and Helm chart + +## Architecture Overview + +``` +Internet + ↓ HTTPS (SSL termination) +[Authentik Outpost] ← Validates OIDC sessions + ↓ (extracts user email from claims) +[Authentik Proxy] ← Dynamic backend override + ↓ (routes to user pod) +[OpenCode StatefulSets] + ├── opencode-alice-0 (alice@company.com) + ├── opencode-bob-0 (bob@company.com) + └── ... +``` + +## Components + +### 1. Authentik Identity Provider +- **Purpose**: Central identity management and OIDC orchestration +- **Deployment**: Kubernetes deployment with PostgreSQL and Redis +- **Configuration**: + - OIDC Source: Google Workspace + - Scope Mappings: Extract email, compute dynamic backend URL + - Proxy Provider: Handle HTTP traffic with dynamic routing + +### 2. Authentik Outpost/Proxy +- **Purpose**: Edge proxy handling authentication and routing +- **Deployment**: Kubernetes deployment as ingress controller +- **Functionality**: + - SSL termination + - OIDC session validation + - Dynamic backend target calculation + - Request proxying to user pods + +### 3. OpenCode StatefulSets (Existing) +- **Purpose**: Isolated user workspaces +- **Naming**: `opencode-{username}-0` (deterministic) +- **Network**: Headless Service for direct pod access +- **DNS**: `opencode-{username}-0.opencode-headless.{namespace}.svc.cluster.local:4096` + +## Implementation Details + +### Email-to-User Mapping +Authentik handles user identity through OIDC claims. Username extraction uses email prefix: + +```python +# Authentik Scope Mapping expression +email = request.user.email # e.g., "alice@company.com" +username = email.split('@')[0] # e.g., "alice" +``` + +### Dynamic Backend Override +During authentication, Authentik executes secure Python expression to compute target: + +```python +email = request.user.email +username = email.split('@')[0] +backend_url = f"http://opencode-{username}-0.opencode-headless.default.svc.cluster.local:4096" +return { + "ak_proxy": { + "backend_override": backend_url + } +} +``` + +### Traffic Flow +1. **Unauthenticated Access**: User visits `https://opencode.company.com` +2. **OIDC Redirect**: Authentik redirects to Google Workspace login +3. **Token Exchange**: Google returns OIDC token with user claims +4. **Backend Calculation**: Authentik evaluates scope mapping, computes pod DNS +5. **Session Establishment**: Proxy target overridden for user's session +6. **Request Proxying**: All subsequent requests route directly to user's StatefulSet + +### Error Handling +- **Unknown Email**: 403 Forbidden with "User not found" message +- **Pod Unavailable**: 502 Bad Gateway (standard reverse proxy behavior) +- **Auth Failure**: Redirect to login with error message + +## Integration with Existing Codebase + +### Operator Changes (Minimal) +- No changes required - operator already creates deterministic pod names +- Ensure headless services exist for DNS resolution + +### Helm Chart Updates +- Add Authentik as optional component when `auth.oidc.enabled: true` +- Update ingress configuration to route through Authentik outpost +- Add OIDC configuration values: + ```yaml + auth: + oidc: + enabled: true + provider: "oidc" + clientId: "..." + clientSecret: "..." + hostname: "opencode.company.com" + ``` + +### Auth-Router Replacement +- Remove existing auth-router deployment +- Authentik assumes all routing responsibilities +- Maintain email mapping ConfigMap for backward compatibility (optional) + +## Security Considerations + +### Authentication Security +- **OIDC Best Practices**: PKCE, secure token storage, proper scopes +- **Session Management**: Configurable session timeouts, secure cookies +- **Claim Validation**: Continuous verification of user identity per request + +### Network Security +- **TLS Everywhere**: End-to-end encryption from client to pod +- **Pod Isolation**: Existing NetworkPolicies prevent cross-user communication +- **No Service Account Tokens**: Pods run without Kubernetes API access + +### Authorization +- **Email-Based Access**: Only mapped emails can access corresponding pods +- **No Cross-User Access**: Users cannot access other users' pods +- **Audit Logging**: Authentik provides comprehensive access logs + +## Deployment and Operations + +### Prerequisites +- Google Workspace with OIDC configured +- Wildcard DNS: `*.company.com` → cluster ingress +- Tailscale (optional, for remote access) + +### Deployment Steps +1. Deploy Authentik via Helm chart +2. Configure Google Workspace OIDC source +3. Create Proxy Provider with scope mappings +4. Update OpenCode ingress to use Authentik +5. Test with sample user workspaces + +### Monitoring and Observability +- Authentik dashboard for auth metrics +- Kubernetes logs for proxy events +- Pod resource monitoring +- User access audit logs + +### Backup and Recovery +- Authentik database backups (PostgreSQL) +- User workspace PVC backups (existing scripts) +- Configuration as code in Git + +## Migration Path + +### From Current Auth-Router +1. Deploy Authentik alongside existing setup +2. Test authentication and routing +3. Update DNS to point shared domain to Authentik +4. Remove old auth-router after validation + +### Rollback Plan +- Keep old auth-router deployment ready +- DNS TTL considerations for quick rollback +- User communication about new access method + +## Success Criteria + +- ✅ Users access OpenCode via single shared URL +- ✅ Seamless Google Workspace authentication +- ✅ Automatic routing to correct user pods +- ✅ No performance degradation vs current setup +- ✅ Security audit passes enterprise requirements +- ✅ Operational monitoring in place + +## Risks and Mitigations + +### Risk: Authentik Complexity +**Mitigation**: Start with minimal configuration, leverage existing Helm charts + +### Risk: OIDC Configuration Issues +**Mitigation**: Test thoroughly with Google Workspace admin + +### Risk: DNS Resolution Failures +**Mitigation**: Validate headless service DNS before rollout + +### Risk: Session State Loss +**Mitigation**: Configure appropriate session persistence + +## Future Enhancements + +- **User Self-Service**: Portal for users to request workspace creation +- **Admin Dashboard**: User management and access controls +- **Multi-Cluster**: Cross-cluster user routing +- **Advanced Policies**: Time-based access, IP restrictions + +## Conclusion + +This Authentik-based shared ingress architecture provides enterprise-grade multi-user access to OpenCode with centralized authentication and dynamic routing. By leveraging Authentik's Identity-Aware Proxy capabilities, we eliminate custom routing code while maintaining security and scalability. The design integrates cleanly with existing OpenCode operator patterns and provides a superior user experience through a single, branded access point. +docs/superpowers/specs/2026-04-07-shared-ingress-authentik-design.md \ No newline at end of file From 7141250eaeac7ff5de83966c5f4207dc437c7799 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 07:43:13 -0400 Subject: [PATCH 02/47] docs: update spec to support any OIDC provider, not just Google Workspace --- .../2026-04-07-shared-ingress-authentik-design.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/superpowers/specs/2026-04-07-shared-ingress-authentik-design.md b/docs/superpowers/specs/2026-04-07-shared-ingress-authentik-design.md index fd4a3a5..b18725c 100644 --- a/docs/superpowers/specs/2026-04-07-shared-ingress-authentik-design.md +++ b/docs/superpowers/specs/2026-04-07-shared-ingress-authentik-design.md @@ -18,7 +18,7 @@ Organizations want a single, centralized access point with professional branding ### Functional Requirements - **Shared Hostname**: Single domain (e.g., `opencode.company.com`) for all users -- **OIDC Authentication**: Google Workspace integration for enterprise SSO +- **OIDC Authentication**: Integration with enterprise identity providers (e.g., Google Workspace, Azure AD, Okta) - **Identity-Based Routing**: Route users to pods based on authenticated email claims - **Session Persistence**: Maintain user sessions across requests - **Security**: Zero-trust access with continuous claim validation @@ -50,7 +50,7 @@ Internet - **Purpose**: Central identity management and OIDC orchestration - **Deployment**: Kubernetes deployment with PostgreSQL and Redis - **Configuration**: - - OIDC Source: Google Workspace + - OIDC Source: Enterprise identity provider (e.g., Google Workspace, Azure AD) - Scope Mappings: Extract email, compute dynamic backend URL - Proxy Provider: Handle HTTP traffic with dynamic routing @@ -96,8 +96,8 @@ return { ### Traffic Flow 1. **Unauthenticated Access**: User visits `https://opencode.company.com` -2. **OIDC Redirect**: Authentik redirects to Google Workspace login -3. **Token Exchange**: Google returns OIDC token with user claims +2. **OIDC Redirect**: Authentik redirects to configured identity provider (e.g., Google Workspace) +3. **Token Exchange**: Identity provider returns OIDC token with user claims 4. **Backend Calculation**: Authentik evaluates scope mapping, computes pod DNS 5. **Session Establishment**: Proxy target overridden for user's session 6. **Request Proxying**: All subsequent requests route directly to user's StatefulSet @@ -152,13 +152,13 @@ return { ## Deployment and Operations ### Prerequisites -- Google Workspace with OIDC configured +- Enterprise identity provider with OIDC support (e.g., Google Workspace, Azure AD, Okta) - Wildcard DNS: `*.company.com` → cluster ingress - Tailscale (optional, for remote access) ### Deployment Steps 1. Deploy Authentik via Helm chart -2. Configure Google Workspace OIDC source +2. Configure enterprise identity provider OIDC source 3. Create Proxy Provider with scope mappings 4. Update OpenCode ingress to use Authentik 5. Test with sample user workspaces @@ -202,7 +202,7 @@ return { **Mitigation**: Start with minimal configuration, leverage existing Helm charts ### Risk: OIDC Configuration Issues -**Mitigation**: Test thoroughly with Google Workspace admin +**Mitigation**: Test thoroughly with identity provider admin ### Risk: DNS Resolution Failures **Mitigation**: Validate headless service DNS before rollout From a00735c20a85ae22a5e288fbccd90d1e74239d8c Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 07:43:51 -0400 Subject: [PATCH 03/47] feat: add comprehensive implementation plan for Authentik shared ingress --- .../2026-04-07-shared-ingress-authentik.md | 855 ++++++++++++++++++ 1 file changed, 855 insertions(+) create mode 100644 docs/superpowers/plans/2026-04-07-shared-ingress-authentik.md diff --git a/docs/superpowers/plans/2026-04-07-shared-ingress-authentik.md b/docs/superpowers/plans/2026-04-07-shared-ingress-authentik.md new file mode 100644 index 0000000..7a5b65b --- /dev/null +++ b/docs/superpowers/plans/2026-04-07-shared-ingress-authentik.md @@ -0,0 +1,855 @@ +# Shared Ingress with Authentik Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Implement shared ingress architecture using Authentik Identity-Aware Proxy for multi-user OpenCode access with centralized OIDC authentication and dynamic user routing. + +**Architecture:** Authentik serves as the central identity provider and proxy, extracting user email from OIDC claims to dynamically route requests to per-user StatefulSet pods. Uses secure scope mappings for backend calculation without custom routing code. + +**Tech Stack:** Authentik, Kubernetes, Helm, OIDC providers (Google Workspace, Azure AD, Okta), PostgreSQL, Redis + +--- + +## File Structure + +**New Files:** +- `chart/templates/authentik/deployment.yaml` - Authentik server deployment +- `chart/templates/authentik/service.yaml` - Authentik service +- `chart/templates/authentik/configmap.yaml` - Authentik configuration +- `chart/templates/authentik/secret.yaml` - Authentik secrets +- `chart/templates/authentik/postgres-deployment.yaml` - PostgreSQL database +- `chart/templates/authentik/postgres-service.yaml` - PostgreSQL service +- `chart/templates/authentik/postgres-pvc.yaml` - PostgreSQL persistent storage +- `chart/templates/authentik/redis-deployment.yaml` - Redis cache +- `chart/templates/authentik/redis-service.yaml` - Redis service +- `chart/templates/authentik/ingress.yaml` - Authentik ingress +- `chart/templates/authentik/networkpolicy.yaml` - Authentik network policy + +**Modified Files:** +- `chart/values.yaml` - Add auth.oidc configuration section +- `chart/templates/ingress.yaml` - Update to route through Authentik when enabled +- `chart/templates/_helpers.tpl` - Add Authentik helper functions +- `chart/Chart.yaml` - Add dependencies if using subchart approach + +**Test Files:** +- `chart/templates/tests/authentik-test.yaml` - Helm test for Authentik deployment + +## Implementation Notes + +- **Authentik Version:** Use v2024.6.0+ for stable OIDC and proxy features +- **Security:** All secrets use Kubernetes secrets, no hardcoded values +- **Scalability:** Start with minimal resources, scale based on user load +- **Backup:** PostgreSQL PVC enables database persistence across upgrades +- **OIDC:** Configuration supports any OIDC provider via values.yaml +- **Testing:** Use `helm template` for validation, `helm test` for deployment verification + +--- + +### Task 1: Update Helm Values for Authentik Configuration + +**Files:** +- Modify: `chart/values.yaml` (add auth.oidc section) + +- [ ] **Step 1: Add Authentik OIDC configuration section to values.yaml** + +Add this section after the existing `auth.router` section: + +```yaml +# -- Authentik Identity-Aware Proxy configuration +authentik: + enabled: false + image: + repository: ghcr.io/goauthentik/server + tag: "2024.6.0" + pullPolicy: IfNotPresent + replicaCount: 1 + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 1Gi + + # -- OIDC provider configuration + oidc: + enabled: false + provider: "oidc" # oidc, google, github, etc. + clientId: "" + clientSecret: "" + issuerUrl: "" # https://accounts.google.com for Google + scopes: ["openid", "email", "profile"] + + # -- Proxy provider configuration + proxy: + enabled: false + hostname: "opencode.company.com" + cookieDomain: ".company.com" + + # -- Database configuration + postgres: + enabled: true + image: + repository: postgres + tag: "15" + database: "authentik" + username: "authentik" + password: "change-me-in-production" + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + persistence: + enabled: true + size: 10Gi + + # -- Redis configuration + redis: + enabled: true + image: + repository: redis + tag: "7-alpine" + password: "change-me-in-production" + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 200m + memory: 128Mi +``` + +- [ ] **Step 2: Validate YAML syntax** + +Run: `helm template test ./chart --set authentik.enabled=true --dry-run` +Expected: No YAML parsing errors + +- [ ] **Step 3: Commit values update** + +```bash +git add chart/values.yaml +git commit -m "feat: add Authentik configuration to Helm values" +``` + +--- + +### Task 2: Create Authentik Database Components + +**Files:** +- Create: `chart/templates/authentik/postgres-deployment.yaml` +- Create: `chart/templates/authentik/postgres-service.yaml` +- Create: `chart/templates/authentik/postgres-pvc.yaml` + +- [ ] **Step 1: Create PostgreSQL deployment template** + +```yaml +{{- if .Values.authentik.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-postgres + labels: + app.kubernetes.io/name: postgres + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: database +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: postgres + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: postgres + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + - name: postgres + image: "{{ .Values.authentik.postgres.image.repository }}:{{ .Values.authentik.postgres.image.tag }}" + env: + - name: POSTGRES_DB + value: {{ .Values.authentik.postgres.database | quote }} + - name: POSTGRES_USER + value: {{ .Values.authentik.postgres.username | quote }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "ok8s.fullname" . }}-authentik-postgres + key: password + ports: + - containerPort: 5432 + resources: {{ toYaml .Values.authentik.postgres.resources | nindent 10 }} + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: {{ include "ok8s.fullname" . }}-authentik-postgres +{{- end }} +``` + +- [ ] **Step 2: Create PostgreSQL service template** + +```yaml +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-postgres +spec: + ports: + - port: 5432 + targetPort: 5432 + selector: + app.kubernetes.io/name: postgres + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +``` + +- [ ] **Step 3: Create PostgreSQL PVC template** + +```yaml +{{- if and .Values.authentik.enabled .Values.authentik.postgres.persistence.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-postgres +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.authentik.postgres.persistence.size }} +{{- end }} +``` + +- [ ] **Step 4: Test template rendering** + +Run: `helm template test ./chart --set authentik.enabled=true -s templates/authentik/postgres-deployment.yaml` +Expected: Valid Kubernetes YAML output + +- [ ] **Step 5: Commit database components** + +```bash +git add chart/templates/authentik/ +git commit -m "feat: add Authentik PostgreSQL database components" +``` + +--- + +### Task 3: Create Authentik Redis Components + +**Files:** +- Create: `chart/templates/authentik/redis-deployment.yaml` +- Create: `chart/templates/authentik/redis-service.yaml` + +- [ ] **Step 1: Create Redis deployment template** + +```yaml +{{- if .Values.authentik.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-redis + labels: + app.kubernetes.io/name: redis + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: redis + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: redis + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + - name: redis + image: "{{ .Values.authentik.redis.image.repository }}:{{ .Values.authentik.redis.image.tag }}" + command: ["redis-server", "--requirepass", "$(REDIS_PASSWORD)"] + env: + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "ok8s.fullname" . }}-authentik-redis + key: password + ports: + - containerPort: 6379 + resources: {{ toYaml .Values.authentik.redis.resources | nindent 10 }} +{{- end }} +``` + +- [ ] **Step 2: Create Redis service template** + +```yaml +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-redis +spec: + ports: + - port: 6379 + targetPort: 6379 + selector: + app.kubernetes.io/name: redis + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +``` + +- [ ] **Step 3: Test template rendering** + +Run: `helm template test ./chart --set authentik.enabled=true -s templates/authentik/redis-deployment.yaml` +Expected: Valid Kubernetes YAML + +- [ ] **Step 4: Commit Redis components** + +```bash +git add chart/templates/authentik/redis-deployment.yaml chart/templates/authentik/redis-service.yaml +git commit -m "feat: add Authentik Redis cache components" +``` + +--- + +### Task 4: Create Authentik Secrets + +**Files:** +- Create: `chart/templates/authentik/secret.yaml` + +- [ ] **Step 1: Create Authentik secrets template** + +```yaml +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "ok8s.fullname" . }}-authentik +type: Opaque +data: + # Authentik secret key for encryption + secretKey: {{ randAlphaNum 32 | b64enc }} + # PostgreSQL password + postgresPassword: {{ .Values.authentik.postgres.password | b64enc }} + # Redis password + redisPassword: {{ .Values.authentik.redis.password | b64enc }} + # OIDC client secret (if provided) + {{- if .Values.authentik.oidc.clientSecret }} + oidcClientSecret: {{ .Values.authentik.oidc.clientSecret | b64enc }} + {{- end }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-postgres +type: Opaque +data: + password: {{ .Values.authentik.postgres.password | b64enc }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-redis +type: Opaque +data: + password: {{ .Values.authentik.redis.password | b64enc }} +{{- end }} +``` + +- [ ] **Step 2: Test secret template** + +Run: `helm template test ./chart --set authentik.enabled=true -s templates/authentik/secret.yaml` +Expected: Valid Secret resources with base64-encoded data + +- [ ] **Step 3: Commit secrets** + +```bash +git add chart/templates/authentik/secret.yaml +git commit -m "feat: add Authentik secrets for database and OIDC" +``` + +--- + +### Task 5: Create Authentik Main Deployment + +**Files:** +- Create: `chart/templates/authentik/configmap.yaml` +- Create: `chart/templates/authentik/deployment.yaml` +- Create: `chart/templates/authentik/service.yaml` + +- [ ] **Step 1: Create Authentik configmap** + +```yaml +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "ok8s.fullname" . }}-authentik +data: + # Authentik configuration + authentik.yml: | + # Basic configuration + debug: false + secret_key: /secrets/secretKey + disable_startup_analytics: true + + # Database + database: + host: {{ include "ok8s.fullname" . }}-authentik-postgres + name: {{ .Values.authentik.postgres.database }} + user: {{ .Values.authentik.postgres.username }} + password: /secrets/postgresPassword + + # Redis + redis: + host: {{ include "ok8s.fullname" . }}-authentik-redis + password: /secrets/redisPassword + + # Email (disabled for this use case) + email: + backend: dummy + + # OIDC provider settings (configured via UI after deployment) + oidc: + enabled: {{ .Values.authentik.oidc.enabled }} + {{- if .Values.authentik.oidc.issuerUrl }} + issuer_url: {{ .Values.authentik.oidc.issuerUrl }} + {{- end }} +{{- end }} +``` + +- [ ] **Step 2: Create Authentik deployment** + +```yaml +{{- if .Values.authentik.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ok8s.fullname" . }}-authentik + labels: + app.kubernetes.io/name: authentik + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + replicas: {{ .Values.authentik.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: authentik + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: authentik + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + - name: authentik + image: "{{ .Values.authentik.image.repository }}:{{ .Values.authentik.image.tag }}" + command: ["ak", "server"] + env: + - name: AUTHENTIK_BOOTSTRAP_PASSWORD + value: "admin" # Change in production + - name: AUTHENTIK_BOOTSTRAP_EMAIL + value: "admin@local" + ports: + - containerPort: 9000 + name: http + - containerPort: 9443 + name: https + volumeMounts: + - name: config + mountPath: /config + - name: secrets + mountPath: /secrets + resources: {{ toYaml .Values.authentik.resources | nindent 10 }} + volumes: + - name: config + configMap: + name: {{ include "ok8s.fullname" . }}-authentik + - name: secrets + secret: + secretName: {{ include "ok8s.fullname" . }}-authentik +{{- end }} +``` + +- [ ] **Step 3: Create Authentik service** + +```yaml +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "ok8s.fullname" . }}-authentik +spec: + ports: + - name: http + port: 80 + targetPort: 9000 + - name: https + port: 443 + targetPort: 9443 + selector: + app.kubernetes.io/name: authentik + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +``` + +- [ ] **Step 4: Test Authentik components** + +Run: `helm template test ./chart --set authentik.enabled=true -s templates/authentik/deployment.yaml` +Expected: Valid Deployment with proper environment and volumes + +- [ ] **Step 5: Commit Authentik main components** + +```bash +git add chart/templates/authentik/configmap.yaml chart/templates/authentik/deployment.yaml chart/templates/authentik/service.yaml +git commit -m "feat: add Authentik main server deployment and configuration" +``` + +--- + +### Task 6: Update Ingress for Authentik Routing + +**Files:** +- Modify: `chart/templates/ingress.yaml` + +- [ ] **Step 1: Update ingress template to conditionally route through Authentik** + +Modify the existing ingress template to add Authentik routing logic. Find the current ingress rules and add: + +```yaml +{{- if .Values.authentik.enabled }} +# Authentik ingress for shared hostname +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "ok8s.fullname" . }}-authentik + annotations: + nginx.ingress.kubernetes.io/ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" +spec: + ingressClassName: nginx + tls: + - hosts: + - {{ .Values.authentik.proxy.hostname }} + secretName: {{ include "ok8s.fullname" . }}-authentik-tls + rules: + - host: {{ .Values.authentik.proxy.hostname }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "ok8s.fullname" . }}-authentik + port: + number: 80 +{{- else }} +# Original ingress logic here +... +{{- end }} +``` + +- [ ] **Step 2: Test ingress template** + +Run: `helm template test ./chart --set authentik.enabled=true --set authentik.proxy.hostname=opencode.company.com` +Expected: Ingress routes to Authentik service + +- [ ] **Step 3: Commit ingress update** + +```bash +git add chart/templates/ingress.yaml +git commit -m "feat: update ingress to route through Authentik for shared hostname" +``` + +--- + +### Task 7: Add Authentik Network Policy + +**Files:** +- Create: `chart/templates/authentik/networkpolicy.yaml` + +- [ ] **Step 1: Create network policy for Authentik** + +```yaml +{{- if .Values.authentik.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "ok8s.fullname" . }}-authentik +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: authentik + app.kubernetes.io/instance: {{ .Release.Name }} + policyTypes: + - Ingress + - Egress + ingress: + - from: + - namespaceSelector: {} # Allow from all namespaces + ports: + - protocol: TCP + port: 9000 + - protocol: TCP + port: 9443 + egress: + - to: + - podSelector: + matchLabels: + app.kubernetes.io/name: postgres + ports: + - protocol: TCP + port: 5432 + - to: + - podSelector: + matchLabels: + app.kubernetes.io/name: redis + ports: + - protocol: TCP + port: 6379 + - to: [] # Allow external access for OIDC providers + ports: + - protocol: TCP + port: 443 +{{- end }} +``` + +- [ ] **Step 2: Test network policy** + +Run: `helm template test ./chart --set authentik.enabled=true -s templates/authentik/networkpolicy.yaml` +Expected: Valid NetworkPolicy restricting traffic appropriately + +- [ ] **Step 3: Commit network policy** + +```bash +git add chart/templates/authentik/networkpolicy.yaml +git commit -m "feat: add network policy for Authentik security" +``` + +--- + +### Task 8: Add Helm Test for Authentik + +**Files:** +- Create: `chart/templates/tests/authentik-test.yaml` + +- [ ] **Step 1: Create Authentik test job** + +```yaml +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: Pod +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-test + annotations: + "helm.sh/hook": test +spec: + restartPolicy: Never + containers: + - name: test + image: curlimages/curl:8.4.0 + command: + - sh + - -c + - | + # Test Authentik service availability + curl -f http://{{ include "ok8s.fullname" . }}-authentik:80/ || exit 1 + + # Test PostgreSQL connectivity (basic) + echo "Authentik components deployed successfully" +spec: + restartPolicy: Never +{{- end }} +``` + +- [ ] **Step 2: Test helm test functionality** + +Run: `helm template test ./chart --set authentik.enabled=true -s templates/tests/authentik-test.yaml` +Expected: Valid test pod definition + +- [ ] **Step 3: Commit test** + +```bash +git add chart/templates/tests/authentik-test.yaml +git commit -m "feat: add Helm test for Authentik deployment validation" +``` + +--- + +### Task 9: Update Chart.yaml Dependencies + +**Files:** +- Modify: `chart/Chart.yaml` + +- [ ] **Step 1: Add PostgreSQL and Redis as optional dependencies** + +```yaml +dependencies: +- name: postgresql + version: "12.x.x" + repository: "https://charts.bitnami.com/bitnami" + condition: authentik.postgres.enabled +- name: redis + version: "17.x.x" + repository: "https://charts.bitnami.com/bitnami" + condition: authentik.redis.enabled +``` + +- [ ] **Step 2: Test dependency resolution** + +Run: `helm dependency update ./chart` +Expected: Dependencies downloaded without errors + +- [ ] **Step 3: Commit Chart.yaml update** + +```bash +git add chart/Chart.yaml +git commit -m "feat: add PostgreSQL and Redis as conditional dependencies for Authentik" +``` + +--- + +### Task 10: Update _helpers.tpl with Authentik Helpers + +**Files:** +- Modify: `chart/templates/_helpers.tpl` + +- [ ] **Step 1: Add Authentik helper functions** + +Add to the helpers file: + +```go +{{/* +Authentik fullname +*/}} +{{- define "ok8s.authentik.fullname" -}} +{{- printf "%s-authentik" (include "ok8s.fullname" .) -}} +{{- end -}} + +{{/* +Authentik PostgreSQL fullname +*/}} +{{- define "ok8s.authentik.postgres.fullname" -}} +{{- printf "%s-authentik-postgres" (include "ok8s.fullname" .) -}} +{{- end -}} + +{{/* +Authentik Redis fullname +*/}} +{{- define "ok8s.authentik.redis.fullname" -}} +{{- printf "%s-authentik-redis" (include "ok8s.fullname" .) -}} +{{- end -}} +``` + +- [ ] **Step 2: Test helper functions** + +Run: `helm template test ./chart --set authentik.enabled=true | grep -E "(authentik-postgres|authentik-redis)"` +Expected: Names use consistent naming pattern + +- [ ] **Step 3: Commit helpers update** + +```bash +git add chart/templates/_helpers.tpl +git commit -m "feat: add Authentik helper functions for consistent naming" +``` + +--- + +### Task 11: Create Documentation for Authentik Setup + +**Files:** +- Modify: `docs/multi-user-management.md` (add Authentik section) + +- [ ] **Step 1: Add Authentik setup section to multi-user docs** + +Add a new section after the existing auth router documentation: + +```markdown +## Authentik Identity-Aware Proxy Setup + +For shared hostname access with centralized OIDC authentication, deploy Authentik as an Identity-Aware Proxy. + +### Prerequisites + +- OIDC provider (Google Workspace, Azure AD, Okta, etc.) +- Wildcard DNS: `*.yourdomain.com` → cluster ingress + +### Configuration + +Enable Authentik in your Helm values: + +```yaml +authentik: + enabled: true + oidc: + enabled: true + provider: "oidc" + clientId: "your-client-id" + clientSecret: "your-client-secret" + issuerUrl: "https://accounts.google.com" # For Google Workspace + proxy: + hostname: "opencode.yourdomain.com" +``` + +### Post-Deployment Setup + +1. Access Authentik admin: `https://opencode.yourdomain.com/admin` +2. Configure OIDC Source for your identity provider +3. Create Proxy Provider with dynamic backend mapping +4. Set up scope mapping for user routing: + +```python +email = request.user.email +username = email.split('@')[0] +backend = f"http://opencode-{username}-0.opencode-headless.default.svc.cluster.local:4096" +return {"ak_proxy": {"backend_override": backend}} +``` + +### User Access + +Users access via: `https://opencode.yourdomain.com` + +Authentik handles authentication and routes to the appropriate user pod based on email claims. +``` + +- [ ] **Step 2: Commit documentation update** + +```bash +git add docs/multi-user-management.md +git commit -m "docs: add Authentik setup guide to multi-user management" +``` + +--- + +### Task 12: Validate Full Chart Template + +**Files:** +- Test: Full chart rendering + +- [ ] **Step 1: Test complete Authentik deployment** + +Run: `helm template test ./chart --set mode=multi --set authentik.enabled=true --set authentik.oidc.enabled=true --set authentik.proxy.hostname=opencode.company.com` +Expected: All Authentik resources render without errors + +- [ ] **Step 2: Validate resource relationships** + +Check that services reference correct deployments, secrets are properly mounted, etc. + +- [ ] **Step 3: Run helm lint** + +Run: `helm lint ./chart` +Expected: No linting errors + +- [ ] **Step 4: Commit validation complete** + +```bash +git commit --allow-empty -m "feat: complete Authentik implementation - all templates validated" +``` +docs/superpowers/plans/2026-04-07-shared-ingress-authentik.md \ No newline at end of file From 55642a387391310f27cf0025c5a85c5cabd10fa0 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 08:13:29 -0400 Subject: [PATCH 04/47] feat: add Authentik Redis cache components --- .../templates/authentik/redis-deployment.yaml | 34 +++++++++++++++++++ chart/templates/authentik/redis-service.yaml | 13 +++++++ chart/values.yaml | 31 +++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 chart/templates/authentik/redis-deployment.yaml create mode 100644 chart/templates/authentik/redis-service.yaml diff --git a/chart/templates/authentik/redis-deployment.yaml b/chart/templates/authentik/redis-deployment.yaml new file mode 100644 index 0000000..ba15005 --- /dev/null +++ b/chart/templates/authentik/redis-deployment.yaml @@ -0,0 +1,34 @@ +{{- if .Values.authentik.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-redis + labels: + app.kubernetes.io/name: redis + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: redis + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: redis + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + - name: redis + image: "{{ .Values.authentik.redis.image.repository }}:{{ .Values.authentik.redis.image.tag }}" + command: ["redis-server", "--requirepass", "$(REDIS_PASSWORD)"] + env: + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "ok8s.fullname" . }}-authentik-redis + key: password + ports: + - containerPort: 6379 + resources: {{ toYaml .Values.authentik.redis.resources | nindent 10 }} +{{- end }} \ No newline at end of file diff --git a/chart/templates/authentik/redis-service.yaml b/chart/templates/authentik/redis-service.yaml new file mode 100644 index 0000000..26a1f05 --- /dev/null +++ b/chart/templates/authentik/redis-service.yaml @@ -0,0 +1,13 @@ +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-redis +spec: + ports: + - port: 6379 + targetPort: 6379 + selector: + app.kubernetes.io/name: redis + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} \ No newline at end of file diff --git a/chart/values.yaml b/chart/values.yaml index 99933ca..00b2bcf 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -298,3 +298,34 @@ kubedock: DOCKER_HOST: "tcp://kubedock-service:2475" TESTCONTAINERS_RYUK_DISABLED: "true" TESTCONTAINERS_CHECKS_DISABLE: "true" + +# -- Authentik identity provider configuration +authentik: + enabled: false + postgres: + image: + repository: postgres + tag: "15-alpine" + database: "authentik" + username: "authentik" + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + persistence: + enabled: true + size: 10Gi + redis: + image: + repository: redis + tag: "7-alpine" + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi From 8cf47dec77c1f67d551e012d9e7cc7aa921b197e Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 08:16:41 -0400 Subject: [PATCH 05/47] feat: add Authentik secrets for database and OIDC --- chart/templates/authentik/secret.yaml | 34 +++++++++++++++++++++++++++ chart/values.yaml | 4 ++++ 2 files changed, 38 insertions(+) create mode 100644 chart/templates/authentik/secret.yaml diff --git a/chart/templates/authentik/secret.yaml b/chart/templates/authentik/secret.yaml new file mode 100644 index 0000000..4e3d432 --- /dev/null +++ b/chart/templates/authentik/secret.yaml @@ -0,0 +1,34 @@ +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "ok8s.fullname" . }}-authentik +type: Opaque +data: + # Authentik secret key for encryption + secretKey: {{ randAlphaNum 32 | b64enc }} + # PostgreSQL password + postgresPassword: {{ .Values.authentik.postgres.password | b64enc }} + # Redis password + redisPassword: {{ .Values.authentik.redis.password | b64enc }} + # OIDC client secret (if provided) + {{- if .Values.authentik.oidc.clientSecret }} + oidcClientSecret: {{ .Values.authentik.oidc.clientSecret | b64enc }} + {{- end }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-postgres +type: Opaque +data: + password: {{ .Values.authentik.postgres.password | b64enc }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-redis +type: Opaque +data: + password: {{ .Values.authentik.redis.password | b64enc }} +{{- end }} \ No newline at end of file diff --git a/chart/values.yaml b/chart/values.yaml index 00b2bcf..afca0d7 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -308,6 +308,7 @@ authentik: tag: "15-alpine" database: "authentik" username: "authentik" + password: "" resources: requests: cpu: 100m @@ -322,6 +323,7 @@ authentik: image: repository: redis tag: "7-alpine" + password: "" resources: requests: cpu: 100m @@ -329,3 +331,5 @@ authentik: limits: cpu: 500m memory: 512Mi + oidc: + clientSecret: "" From 0a5ba58a6b4db1da0c2ad5d00fbe836153c5c17e Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 08:18:40 -0400 Subject: [PATCH 06/47] fix: secure authentik secrets with stable keys and validation - Add stable secretKey field to values.yaml - Change default postgres and redis passwords from empty to placeholder - Replace random secretKey generation with stable value - Add validation to ensure required passwords are set --- chart/templates/authentik/secret.yaml | 34 +++++++++++++++++++++++++++ chart/values.yaml | 5 ++++ 2 files changed, 39 insertions(+) create mode 100644 chart/templates/authentik/secret.yaml diff --git a/chart/templates/authentik/secret.yaml b/chart/templates/authentik/secret.yaml new file mode 100644 index 0000000..4ae416d --- /dev/null +++ b/chart/templates/authentik/secret.yaml @@ -0,0 +1,34 @@ +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "ok8s.fullname" . }}-authentik +type: Opaque +data: + # Authentik secret key for encryption + secretKey: {{ required "authentik.secretKey must be set" .Values.authentik.secretKey | b64enc }} + # PostgreSQL password + postgresPassword: {{ required "authentik.postgres.password must be set" .Values.authentik.postgres.password | b64enc }} + # Redis password + redisPassword: {{ required "authentik.redis.password must be set" .Values.authentik.redis.password | b64enc }} + # OIDC client secret (if provided) + {{- if .Values.authentik.oidc.clientSecret }} + oidcClientSecret: {{ .Values.authentik.oidc.clientSecret | b64enc }} + {{- end }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-postgres +type: Opaque +data: + password: {{ required "authentik.postgres.password must be set" .Values.authentik.postgres.password | b64enc }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-redis +type: Opaque +data: + password: {{ required "authentik.redis.password must be set" .Values.authentik.redis.password | b64enc }} +{{- end }} \ No newline at end of file diff --git a/chart/values.yaml b/chart/values.yaml index 00b2bcf..4b534ce 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -302,12 +302,14 @@ kubedock: # -- Authentik identity provider configuration authentik: enabled: false + secretKey: "change-me-in-production" postgres: image: repository: postgres tag: "15-alpine" database: "authentik" username: "authentik" + password: "change-me-in-production" resources: requests: cpu: 100m @@ -322,6 +324,7 @@ authentik: image: repository: redis tag: "7-alpine" + password: "change-me-in-production" resources: requests: cpu: 100m @@ -329,3 +332,5 @@ authentik: limits: cpu: 500m memory: 512Mi + oidc: + clientSecret: "" From 8079e6a15d98b105010b5fc1d2ac533dc0a5e88b Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 08:19:55 -0400 Subject: [PATCH 07/47] fix: require secure authentik.secretKey to prevent production vulnerabilities - Change default authentik.secretKey from insecure placeholder to empty string - Add clear documentation requiring cryptographically strong random key (32+ chars) - Maintain required validation to prevent empty deployments - Users must explicitly set secure key before installation --- chart/values.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/chart/values.yaml b/chart/values.yaml index afca0d7..7dfe77d 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -302,13 +302,17 @@ kubedock: # -- Authentik identity provider configuration authentik: enabled: false + # -- CRITICAL: Authentik secret key used for encryption. MUST be set to a cryptographically strong random string (at least 32 characters). + # Generate with: openssl rand -base64 32 + # This value cannot be empty and must be unique per installation. + secretKey: "" postgres: image: repository: postgres tag: "15-alpine" database: "authentik" username: "authentik" - password: "" + password: "change-me-in-production" resources: requests: cpu: 100m @@ -323,7 +327,7 @@ authentik: image: repository: redis tag: "7-alpine" - password: "" + password: "change-me-in-production" resources: requests: cpu: 100m From eedfce9732dc3bbb72c5b6eea78a32e6ff3edb21 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 08:51:26 -0400 Subject: [PATCH 08/47] feat: add Authentik main server deployment and configuration --- chart/templates/authentik/configmap.yaml | 36 +++++++++++++++++ chart/templates/authentik/deployment.yaml | 48 +++++++++++++++++++++++ chart/templates/authentik/service.yaml | 17 ++++++++ chart/values.yaml | 14 +++++++ 4 files changed, 115 insertions(+) create mode 100644 chart/templates/authentik/configmap.yaml create mode 100644 chart/templates/authentik/deployment.yaml create mode 100644 chart/templates/authentik/service.yaml diff --git a/chart/templates/authentik/configmap.yaml b/chart/templates/authentik/configmap.yaml new file mode 100644 index 0000000..f2ac3ec --- /dev/null +++ b/chart/templates/authentik/configmap.yaml @@ -0,0 +1,36 @@ +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "ok8s.fullname" . }}-authentik +data: + # Authentik configuration + authentik.yml: | + # Basic configuration + debug: false + secret_key: /secrets/secretKey + disable_startup_analytics: true + + # Database + database: + host: {{ include "ok8s.fullname" . }}-authentik-postgres + name: {{ .Values.authentik.postgres.database }} + user: {{ .Values.authentik.postgres.username }} + password: /secrets/postgresPassword + + # Redis + redis: + host: {{ include "ok8s.fullname" . }}-authentik-redis + password: /secrets/redisPassword + + # Email (disabled for this use case) + email: + backend: dummy + + # OIDC provider settings (configured via UI after deployment) + oidc: + enabled: {{ .Values.authentik.oidc.enabled }} + {{- if .Values.authentik.oidc.issuerUrl }} + issuer_url: {{ .Values.authentik.oidc.issuerUrl }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/templates/authentik/deployment.yaml b/chart/templates/authentik/deployment.yaml new file mode 100644 index 0000000..2b77f43 --- /dev/null +++ b/chart/templates/authentik/deployment.yaml @@ -0,0 +1,48 @@ +{{- if .Values.authentik.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ok8s.fullname" . }}-authentik + labels: + app.kubernetes.io/name: authentik + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + replicas: {{ .Values.authentik.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: authentik + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: authentik + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + - name: authentik + image: "{{ .Values.authentik.image.repository }}:{{ .Values.authentik.image.tag }}" + command: ["ak", "server"] + env: + - name: AUTHENTIK_BOOTSTRAP_PASSWORD + value: "admin" # Change in production + - name: AUTHENTIK_BOOTSTRAP_EMAIL + value: "admin@local" + ports: + - containerPort: 9000 + name: http + - containerPort: 9443 + name: https + volumeMounts: + - name: config + mountPath: /config + - name: secrets + mountPath: /secrets + resources: {{ toYaml .Values.authentik.resources | nindent 10 }} + volumes: + - name: config + configMap: + name: {{ include "ok8s.fullname" . }}-authentik + - name: secrets + secret: + secretName: {{ include "ok8s.fullname" . }}-authentik +{{- end }} \ No newline at end of file diff --git a/chart/templates/authentik/service.yaml b/chart/templates/authentik/service.yaml new file mode 100644 index 0000000..51714b9 --- /dev/null +++ b/chart/templates/authentik/service.yaml @@ -0,0 +1,17 @@ +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "ok8s.fullname" . }}-authentik +spec: + ports: + - name: http + port: 80 + targetPort: 9000 + - name: https + port: 443 + targetPort: 9443 + selector: + app.kubernetes.io/name: authentik + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} \ No newline at end of file diff --git a/chart/values.yaml b/chart/values.yaml index 4b534ce..6cb36b0 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -302,6 +302,18 @@ kubedock: # -- Authentik identity provider configuration authentik: enabled: false + image: + repository: ghcr.io/goauthentik/server + tag: "2024.6.1" + pullPolicy: IfNotPresent + replicaCount: 1 + resources: + requests: + cpu: 500m + memory: 512Mi + limits: + cpu: "2" + memory: 2Gi secretKey: "change-me-in-production" postgres: image: @@ -333,4 +345,6 @@ authentik: cpu: 500m memory: 512Mi oidc: + enabled: false + issuerUrl: "" clientSecret: "" From 2982a6772283413561059e4ae2a1b0400a05c302 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 08:53:19 -0400 Subject: [PATCH 09/47] feat: add Authentik main server deployment and configuration - Add chart/templates/authentik/configmap.yaml for Authentik configuration - Add chart/templates/authentik/deployment.yaml for Authentik server deployment - Add chart/templates/authentik/service.yaml for Authentik service - Update chart/values.yaml with complete Authentik configuration section --- chart/templates/authentik/configmap.yaml | 36 +++++++++++++++++ chart/templates/authentik/deployment.yaml | 48 +++++++++++++++++++++++ chart/templates/authentik/service.yaml | 17 ++++++++ chart/values.yaml | 47 ++++++++++++++++++---- 4 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 chart/templates/authentik/configmap.yaml create mode 100644 chart/templates/authentik/deployment.yaml create mode 100644 chart/templates/authentik/service.yaml diff --git a/chart/templates/authentik/configmap.yaml b/chart/templates/authentik/configmap.yaml new file mode 100644 index 0000000..f2ac3ec --- /dev/null +++ b/chart/templates/authentik/configmap.yaml @@ -0,0 +1,36 @@ +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "ok8s.fullname" . }}-authentik +data: + # Authentik configuration + authentik.yml: | + # Basic configuration + debug: false + secret_key: /secrets/secretKey + disable_startup_analytics: true + + # Database + database: + host: {{ include "ok8s.fullname" . }}-authentik-postgres + name: {{ .Values.authentik.postgres.database }} + user: {{ .Values.authentik.postgres.username }} + password: /secrets/postgresPassword + + # Redis + redis: + host: {{ include "ok8s.fullname" . }}-authentik-redis + password: /secrets/redisPassword + + # Email (disabled for this use case) + email: + backend: dummy + + # OIDC provider settings (configured via UI after deployment) + oidc: + enabled: {{ .Values.authentik.oidc.enabled }} + {{- if .Values.authentik.oidc.issuerUrl }} + issuer_url: {{ .Values.authentik.oidc.issuerUrl }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/templates/authentik/deployment.yaml b/chart/templates/authentik/deployment.yaml new file mode 100644 index 0000000..2b77f43 --- /dev/null +++ b/chart/templates/authentik/deployment.yaml @@ -0,0 +1,48 @@ +{{- if .Values.authentik.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ok8s.fullname" . }}-authentik + labels: + app.kubernetes.io/name: authentik + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + replicas: {{ .Values.authentik.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: authentik + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: authentik + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + - name: authentik + image: "{{ .Values.authentik.image.repository }}:{{ .Values.authentik.image.tag }}" + command: ["ak", "server"] + env: + - name: AUTHENTIK_BOOTSTRAP_PASSWORD + value: "admin" # Change in production + - name: AUTHENTIK_BOOTSTRAP_EMAIL + value: "admin@local" + ports: + - containerPort: 9000 + name: http + - containerPort: 9443 + name: https + volumeMounts: + - name: config + mountPath: /config + - name: secrets + mountPath: /secrets + resources: {{ toYaml .Values.authentik.resources | nindent 10 }} + volumes: + - name: config + configMap: + name: {{ include "ok8s.fullname" . }}-authentik + - name: secrets + secret: + secretName: {{ include "ok8s.fullname" . }}-authentik +{{- end }} \ No newline at end of file diff --git a/chart/templates/authentik/service.yaml b/chart/templates/authentik/service.yaml new file mode 100644 index 0000000..51714b9 --- /dev/null +++ b/chart/templates/authentik/service.yaml @@ -0,0 +1,17 @@ +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "ok8s.fullname" . }}-authentik +spec: + ports: + - name: http + port: 80 + targetPort: 9000 + - name: https + port: 443 + targetPort: 9443 + selector: + app.kubernetes.io/name: authentik + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} \ No newline at end of file diff --git a/chart/values.yaml b/chart/values.yaml index 7dfe77d..4377a4a 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -299,17 +299,47 @@ kubedock: TESTCONTAINERS_RYUK_DISABLED: "true" TESTCONTAINERS_CHECKS_DISABLE: "true" -# -- Authentik identity provider configuration +# -- Authentik Identity-Aware Proxy configuration authentik: enabled: false # -- CRITICAL: Authentik secret key used for encryption. MUST be set to a cryptographically strong random string (at least 32 characters). # Generate with: openssl rand -base64 32 # This value cannot be empty and must be unique per installation. secretKey: "" + image: + repository: ghcr.io/goauthentik/server + tag: "2024.6.0" + pullPolicy: IfNotPresent + replicaCount: 1 + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 1Gi + + # -- OIDC provider configuration + oidc: + enabled: false + provider: "oidc" # oidc, google, github, etc. + clientId: "" + clientSecret: "" + issuerUrl: "" # https://accounts.google.com for Google + scopes: ["openid", "email", "profile"] + + # -- Proxy provider configuration + proxy: + enabled: false + hostname: "opencode.company.com" + cookieDomain: ".company.com" + + # -- Database configuration postgres: + enabled: true image: repository: postgres - tag: "15-alpine" + tag: "15" database: "authentik" username: "authentik" password: "change-me-in-production" @@ -323,17 +353,18 @@ authentik: persistence: enabled: true size: 10Gi + + # -- Redis configuration redis: + enabled: true image: repository: redis tag: "7-alpine" password: "change-me-in-production" resources: requests: - cpu: 100m - memory: 256Mi + cpu: 50m + memory: 64Mi limits: - cpu: 500m - memory: 512Mi - oidc: - clientSecret: "" + cpu: 200m + memory: 128Mi From e59a8c48d0ed933387360dc0ccefaa033e4fe847 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 08:53:31 -0400 Subject: [PATCH 10/47] feat: add Authentik main server deployment and configuration --- chart/templates/authentik/deployment.yaml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/chart/templates/authentik/deployment.yaml b/chart/templates/authentik/deployment.yaml index 2b77f43..c8e5530 100644 --- a/chart/templates/authentik/deployment.yaml +++ b/chart/templates/authentik/deployment.yaml @@ -3,9 +3,9 @@ apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "ok8s.fullname" . }}-authentik + namespace: {{ .Release.Namespace }} labels: - app.kubernetes.io/name: authentik - app.kubernetes.io/instance: {{ .Release.Name }} + {{- include "ok8s.labels" . | nindent 4 }} spec: replicas: {{ .Values.authentik.replicaCount }} selector: @@ -20,29 +20,29 @@ spec: spec: containers: - name: authentik - image: "{{ .Values.authentik.image.repository }}:{{ .Values.authentik.image.tag }}" + image: {{ .Values.authentik.image.repository }}:{{ .Values.authentik.image.tag }} + imagePullPolicy: {{ .Values.authentik.image.pullPolicy }} command: ["ak", "server"] - env: - - name: AUTHENTIK_BOOTSTRAP_PASSWORD - value: "admin" # Change in production - - name: AUTHENTIK_BOOTSTRAP_EMAIL - value: "admin@local" ports: - containerPort: 9000 name: http - containerPort: 9443 name: https + env: + - name: AUTHENTIK_CONFIG__path + value: "/etc/authentik/authentik.yml" volumeMounts: - name: config - mountPath: /config + mountPath: /etc/authentik - name: secrets mountPath: /secrets - resources: {{ toYaml .Values.authentik.resources | nindent 10 }} + resources: + {{- toYaml .Values.authentik.resources | nindent 10 }} volumes: - name: config configMap: name: {{ include "ok8s.fullname" . }}-authentik - name: secrets secret: - secretName: {{ include "ok8s.fullname" . }}-authentik + name: {{ include "ok8s.fullname" . }}-authentik {{- end }} \ No newline at end of file From e5eea62b566784b8fbfb42435325f2323999f3a1 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 08:54:06 -0400 Subject: [PATCH 11/47] feat: add Authentik main server deployment and configuration --- chart/templates/authentik/secret.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chart/templates/authentik/secret.yaml b/chart/templates/authentik/secret.yaml index 4e3d432..3027796 100644 --- a/chart/templates/authentik/secret.yaml +++ b/chart/templates/authentik/secret.yaml @@ -6,7 +6,7 @@ metadata: type: Opaque data: # Authentik secret key for encryption - secretKey: {{ randAlphaNum 32 | b64enc }} + secretKey: {{ required "authentik.secretKey must be set to prevent production vulnerabilities" .Values.authentik.secretKey | b64enc }} # PostgreSQL password postgresPassword: {{ .Values.authentik.postgres.password | b64enc }} # Redis password From eab6b777f32f0cd1247fdae3752b3d00d94fa236 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:17:08 -0400 Subject: [PATCH 12/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 48 ++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 chart/templates/ingress.yaml diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml new file mode 100644 index 0000000..f33006f --- /dev/null +++ b/chart/templates/ingress.yaml @@ -0,0 +1,48 @@ +{{- if .Values.authentik.enabled }} +# Authentik ingress for shared hostname +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "ok8s.fullname" . }}-authentik + annotations: + nginx.ingress.kubernetes.io/ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" +spec: + ingressClassName: nginx + tls: + - hosts: + - {{ .Values.authentik.proxy.hostname }} + secretName: {{ include "ok8s.fullname" . }}-authentik-tls + rules: + - host: {{ .Values.authentik.proxy.hostname }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "ok8s.fullname" . }}-authentik + port: + number: 80 +{{- else }} +{{- $hostname := .Values.ingress.hostname | default (include "ok8s.ingressHostname" .) }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "ok8s.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "ok8s.labels" . | nindent 4 }} + annotations: + tailscale.com/hostname: {{ $hostname | quote }} +spec: + ingressClassName: tailscale + defaultBackend: + service: + name: {{ include "ok8s.fullname" . }} + port: + number: 4096 + tls: + - hosts: + - {{ $hostname }} +{{- end }} \ No newline at end of file From e378d76488576bdbff5cbd8c257082cde28068ba Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:17:25 -0400 Subject: [PATCH 13/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 chart/templates/ingress.yaml diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml new file mode 100644 index 0000000..f7ea43d --- /dev/null +++ b/chart/templates/ingress.yaml @@ -0,0 +1,51 @@ +{{- if .Values.authentik.enabled }} +# Authentik ingress for shared hostname +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "ok8s.fullname" . }}-authentik + annotations: + nginx.ingress.kubernetes.io/ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" +spec: + ingressClassName: nginx + tls: + - hosts: + - {{ .Values.authentik.proxy.hostname }} + secretName: {{ include "ok8s.fullname" . }}-authentik-tls + rules: + - host: {{ .Values.authentik.proxy.hostname }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "ok8s.fullname" . }}-authentik + port: + number: 80 +{{- else }} +# Original ingress logic here +{{- if and (eq .Values.mode "single") .Values.ingress.enabled }} +{{- $hostname := .Values.ingress.hostname | default (include "ok8s.ingressHostname" .) }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "ok8s.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "ok8s.labels" . | nindent 4 }} + annotations: + tailscale.com/hostname: {{ $hostname | quote }} +spec: + ingressClassName: tailscale + defaultBackend: + service: + name: {{ include "ok8s.fullname" . }} + port: + number: 4096 + tls: + - hosts: + - {{ $hostname }} +{{- end }} +{{- end }} \ No newline at end of file From 5adf6ea31690d9f9751fd33089d0ffc2377bb75a Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:17:31 -0400 Subject: [PATCH 14/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index f33006f..6a9cf3d 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -25,24 +25,29 @@ spec: port: number: 80 {{- else }} -{{- $hostname := .Values.ingress.hostname | default (include "ok8s.ingressHostname" .) }} +# Original ingress logic for direct routing to OpenCode apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ include "ok8s.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: - {{- include "ok8s.labels" . | nindent 4 }} annotations: - tailscale.com/hostname: {{ $hostname | quote }} + nginx.ingress.kubernetes.io/ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: - ingressClassName: tailscale - defaultBackend: - service: - name: {{ include "ok8s.fullname" . }} - port: - number: 4096 + ingressClassName: nginx tls: - - hosts: - - {{ $hostname }} + - hosts: + - {{ .Values.authentik.proxy.hostname }} + secretName: {{ include "ok8s.fullname" . }}-tls + rules: + - host: {{ .Values.authentik.proxy.hostname }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "ok8s.fullname" . }} + port: + number: 4096 {{- end }} \ No newline at end of file From f4241d51e5aea8644b2bb49eda8614e9975fc82c Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:17:46 -0400 Subject: [PATCH 15/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index 6a9cf3d..f7ea43d 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -25,29 +25,27 @@ spec: port: number: 80 {{- else }} -# Original ingress logic for direct routing to OpenCode +# Original ingress logic here +{{- if and (eq .Values.mode "single") .Values.ingress.enabled }} +{{- $hostname := .Values.ingress.hostname | default (include "ok8s.ingressHostname" .) }} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ include "ok8s.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "ok8s.labels" . | nindent 4 }} annotations: - nginx.ingress.kubernetes.io/ssl-redirect: "true" - cert-manager.io/cluster-issuer: "letsencrypt-prod" + tailscale.com/hostname: {{ $hostname | quote }} spec: - ingressClassName: nginx + ingressClassName: tailscale + defaultBackend: + service: + name: {{ include "ok8s.fullname" . }} + port: + number: 4096 tls: - - hosts: - - {{ .Values.authentik.proxy.hostname }} - secretName: {{ include "ok8s.fullname" . }}-tls - rules: - - host: {{ .Values.authentik.proxy.hostname }} - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: {{ include "ok8s.fullname" . }} - port: - number: 4096 + - hosts: + - {{ $hostname }} +{{- end }} {{- end }} \ No newline at end of file From f496b18bb0087d37300cce2650692dec33bcde97 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:18:04 -0400 Subject: [PATCH 16/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index f7ea43d..6a9cf3d 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -25,27 +25,29 @@ spec: port: number: 80 {{- else }} -# Original ingress logic here -{{- if and (eq .Values.mode "single") .Values.ingress.enabled }} -{{- $hostname := .Values.ingress.hostname | default (include "ok8s.ingressHostname" .) }} +# Original ingress logic for direct routing to OpenCode apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ include "ok8s.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: - {{- include "ok8s.labels" . | nindent 4 }} annotations: - tailscale.com/hostname: {{ $hostname | quote }} + nginx.ingress.kubernetes.io/ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: - ingressClassName: tailscale - defaultBackend: - service: - name: {{ include "ok8s.fullname" . }} - port: - number: 4096 + ingressClassName: nginx tls: - - hosts: - - {{ $hostname }} -{{- end }} + - hosts: + - {{ .Values.authentik.proxy.hostname }} + secretName: {{ include "ok8s.fullname" . }}-tls + rules: + - host: {{ .Values.authentik.proxy.hostname }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "ok8s.fullname" . }} + port: + number: 4096 {{- end }} \ No newline at end of file From 526c12ef085d890eefe8a78184428562b4ac8806 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:18:20 -0400 Subject: [PATCH 17/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index 6a9cf3d..f33006f 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -25,29 +25,24 @@ spec: port: number: 80 {{- else }} -# Original ingress logic for direct routing to OpenCode +{{- $hostname := .Values.ingress.hostname | default (include "ok8s.ingressHostname" .) }} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ include "ok8s.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "ok8s.labels" . | nindent 4 }} annotations: - nginx.ingress.kubernetes.io/ssl-redirect: "true" - cert-manager.io/cluster-issuer: "letsencrypt-prod" + tailscale.com/hostname: {{ $hostname | quote }} spec: - ingressClassName: nginx + ingressClassName: tailscale + defaultBackend: + service: + name: {{ include "ok8s.fullname" . }} + port: + number: 4096 tls: - - hosts: - - {{ .Values.authentik.proxy.hostname }} - secretName: {{ include "ok8s.fullname" . }}-tls - rules: - - host: {{ .Values.authentik.proxy.hostname }} - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: {{ include "ok8s.fullname" . }} - port: - number: 4096 + - hosts: + - {{ $hostname }} {{- end }} \ No newline at end of file From 443651c3909e87bc14350c779ecd8df67a06a7f1 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:18:38 -0400 Subject: [PATCH 18/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index f33006f..f7ea43d 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -25,6 +25,8 @@ spec: port: number: 80 {{- else }} +# Original ingress logic here +{{- if and (eq .Values.mode "single") .Values.ingress.enabled }} {{- $hostname := .Values.ingress.hostname | default (include "ok8s.ingressHostname" .) }} apiVersion: networking.k8s.io/v1 kind: Ingress @@ -45,4 +47,5 @@ spec: tls: - hosts: - {{ $hostname }} +{{- end }} {{- end }} \ No newline at end of file From 715ada0ef7eb6cd8f2a36d4e34e15e8e5c009d0b Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:18:51 -0400 Subject: [PATCH 19/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index f7ea43d..f784322 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -11,7 +11,7 @@ spec: ingressClassName: nginx tls: - hosts: - - {{ .Values.authentik.proxy.hostname }} + - {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} secretName: {{ include "ok8s.fullname" . }}-authentik-tls rules: - host: {{ .Values.authentik.proxy.hostname }} From 32e3174097dfa3e67cac0e774b16fc8eb85ae381 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:19:22 -0400 Subject: [PATCH 20/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index f784322..a918c76 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -26,26 +26,30 @@ spec: number: 80 {{- else }} # Original ingress logic here -{{- if and (eq .Values.mode "single") .Values.ingress.enabled }} -{{- $hostname := .Values.ingress.hostname | default (include "ok8s.ingressHostname" .) }} +{{- if .Values.auth.oidc.enabled }} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: {{ include "ok8s.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: - {{- include "ok8s.labels" . | nindent 4 }} + name: {{ include "ok8s.fullname" . }}-oidc annotations: - tailscale.com/hostname: {{ $hostname | quote }} + nginx.ingress.kubernetes.io/ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: - ingressClassName: tailscale - defaultBackend: - service: - name: {{ include "ok8s.fullname" . }} - port: - number: 4096 + ingressClassName: nginx tls: - - hosts: - - {{ $hostname }} + - hosts: + - {{ .Values.auth.oidc.hostname }} + secretName: {{ include "ok8s.fullname" . }}-oidc-tls + rules: + - host: {{ .Values.auth.oidc.hostname }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "ok8s.fullname" . }}-auth-router + port: + number: 8080 {{- end }} {{- end }} \ No newline at end of file From 21970e06e68e97a3b7d28c885edc7404314611c9 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:19:23 -0400 Subject: [PATCH 21/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index a918c76..27b504e 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -11,7 +11,7 @@ spec: ingressClassName: nginx tls: - hosts: - - {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} + - {{ .Values.authentik.proxy.hostname }} secretName: {{ include "ok8s.fullname" . }}-authentik-tls rules: - host: {{ .Values.authentik.proxy.hostname }} From 968098a95c2505a7d10535f78560799416756b2a Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:19:52 -0400 Subject: [PATCH 22/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index 27b504e..1a513af 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -38,7 +38,7 @@ spec: ingressClassName: nginx tls: - hosts: - - {{ .Values.auth.oidc.hostname }} + - {{ .Values.auth.oidc.hostname | default "oc-ingress" }} secretName: {{ include "ok8s.fullname" . }}-oidc-tls rules: - host: {{ .Values.auth.oidc.hostname }} From 7a0f0eb11909a64f8cfe26a8405ae690cd157552 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:20:23 -0400 Subject: [PATCH 23/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index 1a513af..5c24d8f 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -11,10 +11,10 @@ spec: ingressClassName: nginx tls: - hosts: - - {{ .Values.authentik.proxy.hostname }} + - {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} secretName: {{ include "ok8s.fullname" . }}-authentik-tls rules: - - host: {{ .Values.authentik.proxy.hostname }} + - host: {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} http: paths: - path: / @@ -41,7 +41,7 @@ spec: - {{ .Values.auth.oidc.hostname | default "oc-ingress" }} secretName: {{ include "ok8s.fullname" . }}-oidc-tls rules: - - host: {{ .Values.auth.oidc.hostname }} + - host: {{ .Values.auth.oidc.hostname | default "oc-ingress" }} http: paths: - path: / From 5208561286dc0e62405e5e0ab41e78744a95270c Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:20:28 -0400 Subject: [PATCH 24/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index f7ea43d..2b1b7e1 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -11,10 +11,10 @@ spec: ingressClassName: nginx tls: - hosts: - - {{ .Values.authentik.proxy.hostname }} - secretName: {{ include "ok8s.fullname" . }}-authentik-tls + - {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} + secretName: {{ include "ok8s.fullname" . }}-tls rules: - - host: {{ .Values.authentik.proxy.hostname }} + - host: {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} http: paths: - path: / @@ -25,7 +25,7 @@ spec: port: number: 80 {{- else }} -# Original ingress logic here +# Original ingress logic for direct routing to OpenCode {{- if and (eq .Values.mode "single") .Values.ingress.enabled }} {{- $hostname := .Values.ingress.hostname | default (include "ok8s.ingressHostname" .) }} apiVersion: networking.k8s.io/v1 From 53388955865809a019efd5bdf77fe95cc0e808c7 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:20:29 -0400 Subject: [PATCH 25/47] feat: update ingress to route through Authentik for shared hostname --- chart/values.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/chart/values.yaml b/chart/values.yaml index 6cb36b0..52ff9a3 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -302,6 +302,8 @@ kubedock: # -- Authentik identity provider configuration authentik: enabled: false + proxy: + hostname: "opencode.company.com" image: repository: ghcr.io/goauthentik/server tag: "2024.6.1" From 831a6ad02bd42e8ad7e6a28a79f88c41a4b2c69a Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:21:03 -0400 Subject: [PATCH 26/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 4 ++-- chart/values.yaml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index 5c24d8f..7edea86 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -11,10 +11,10 @@ spec: ingressClassName: nginx tls: - hosts: - - {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} + - {{ .Values.authentik.proxy.hostname }} secretName: {{ include "ok8s.fullname" . }}-authentik-tls rules: - - host: {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} + - host: {{ .Values.authentik.proxy.hostname }} http: paths: - path: / diff --git a/chart/values.yaml b/chart/values.yaml index 4377a4a..69c5048 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -168,6 +168,7 @@ skills: # -- Tailscale cluster ingress (exposes OpenCode UI to your tailnet) ingress: enabled: false + hostname: "opencode.local" # -- Hostname prefix for MagicDNS (default derives from opencode.username as oc-) # -- Tailscale operator configuration # -- If install: true, the chart expects the Tailscale Operator is already installed From baaa428c9397b71250ba07a1d0029dc98ce475c5 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:21:26 -0400 Subject: [PATCH 27/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index 2b1b7e1..e778d83 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -11,8 +11,8 @@ spec: ingressClassName: nginx tls: - hosts: - - {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} - secretName: {{ include "ok8s.fullname" . }}-tls + - {{ .Values.authentik.proxy.hostname }} + secretName: {{ include "ok8s.fullname" . }}-authentik-tls rules: - host: {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} http: From 592c58611c56348334d6ff714547f107a47b2f24 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:21:54 -0400 Subject: [PATCH 28/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index e778d83..984c67c 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -14,7 +14,7 @@ spec: - {{ .Values.authentik.proxy.hostname }} secretName: {{ include "ok8s.fullname" . }}-authentik-tls rules: - - host: {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} + - host: {{ .Values.authentik.proxy.hostname }} http: paths: - path: / From d456306e2b5fbd84893bf3fc07ac69f47658c3ba Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:22:55 -0400 Subject: [PATCH 29/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 38 ++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index 984c67c..facfdc4 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -25,27 +25,31 @@ spec: port: number: 80 {{- else }} -# Original ingress logic for direct routing to OpenCode -{{- if and (eq .Values.mode "single") .Values.ingress.enabled }} -{{- $hostname := .Values.ingress.hostname | default (include "ok8s.ingressHostname" .) }} +# Original ingress logic here +{{- if .Values.auth.oidc.enabled }} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: {{ include "ok8s.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: - {{- include "ok8s.labels" . | nindent 4 }} + name: {{ include "ok8s.fullname" . }}-oidc annotations: - tailscale.com/hostname: {{ $hostname | quote }} + nginx.ingress.kubernetes.io/ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: - ingressClassName: tailscale - defaultBackend: - service: - name: {{ include "ok8s.fullname" . }} - port: - number: 4096 + ingressClassName: nginx tls: - - hosts: - - {{ $hostname }} + - hosts: + - {{ .Values.auth.oidc.hostname }} + secretName: {{ include "ok8s.fullname" . }}-oidc-tls + rules: + - host: {{ .Values.auth.oidc.hostname }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "ok8s.fullname" . }}-auth-router + port: + number: 8080 +{{- end }} {{- end }} -{{- end }} \ No newline at end of file From 0937f890006a9d8d24cc89145d01e5ff8e9b9231 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:23:28 -0400 Subject: [PATCH 30/47] Merge branch 'agent/shared-ingress-authentik' into main --- .../authentik/postgres-deployment.yaml | 45 ++++++++ chart/templates/authentik/postgres-pvc.yaml | 12 ++ .../templates/authentik/postgres-service.yaml | 13 +++ chart/templates/ingress.yaml | 2 +- chart/values.yaml | 17 ++- .../2026-04-07-add-authentik-deployment.md | 96 ++++++++++++++++ ...-04-07-update-ingress-authentik-routing.md | 107 ++++++++++++++++++ ...update-ingress-authentik-routing-design.md | 32 ++++++ 8 files changed, 317 insertions(+), 7 deletions(-) create mode 100644 chart/templates/authentik/postgres-deployment.yaml create mode 100644 chart/templates/authentik/postgres-pvc.yaml create mode 100644 chart/templates/authentik/postgres-service.yaml create mode 100644 docs/superpowers/plans/2026-04-07-add-authentik-deployment.md create mode 100644 docs/superpowers/plans/2026-04-07-update-ingress-authentik-routing.md create mode 100644 docs/superpowers/specs/2026-04-07-update-ingress-authentik-routing-design.md diff --git a/chart/templates/authentik/postgres-deployment.yaml b/chart/templates/authentik/postgres-deployment.yaml new file mode 100644 index 0000000..da06375 --- /dev/null +++ b/chart/templates/authentik/postgres-deployment.yaml @@ -0,0 +1,45 @@ +{{- if .Values.authentik.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-postgres + labels: + app.kubernetes.io/name: postgres + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: database +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: postgres + app.kubernetes.io/instance: {{ .Release.Name }} + template: + metadata: + labels: + app.kubernetes.io/name: postgres + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + containers: + - name: postgres + image: "{{ .Values.authentik.postgres.image.repository }}:{{ .Values.authentik.postgres.image.tag }}" + env: + - name: POSTGRES_DB + value: {{ .Values.authentik.postgres.database | quote }} + - name: POSTGRES_USER + value: {{ .Values.authentik.postgres.username | quote }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "ok8s.fullname" . }}-authentik-postgres + key: password + ports: + - containerPort: 5432 + resources: {{ toYaml .Values.authentik.postgres.resources | nindent 10 }} + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: {{ include "ok8s.fullname" . }}-authentik-postgres +{{- end }} \ No newline at end of file diff --git a/chart/templates/authentik/postgres-pvc.yaml b/chart/templates/authentik/postgres-pvc.yaml new file mode 100644 index 0000000..53ce405 --- /dev/null +++ b/chart/templates/authentik/postgres-pvc.yaml @@ -0,0 +1,12 @@ +{{- if and .Values.authentik.enabled .Values.authentik.postgres.persistence.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-postgres +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.authentik.postgres.persistence.size }} +{{- end }} \ No newline at end of file diff --git a/chart/templates/authentik/postgres-service.yaml b/chart/templates/authentik/postgres-service.yaml new file mode 100644 index 0000000..cff97b0 --- /dev/null +++ b/chart/templates/authentik/postgres-service.yaml @@ -0,0 +1,13 @@ +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-postgres +spec: + ports: + - port: 5432 + targetPort: 5432 + selector: + app.kubernetes.io/name: postgres + app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} \ No newline at end of file diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index 7edea86..ffbc03f 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -41,7 +41,7 @@ spec: - {{ .Values.auth.oidc.hostname | default "oc-ingress" }} secretName: {{ include "ok8s.fullname" . }}-oidc-tls rules: - - host: {{ .Values.auth.oidc.hostname | default "oc-ingress" }} + - host: {{ .Values.auth.oidc.hostname | default "oc-ingress" }} http: paths: - path: / diff --git a/chart/values.yaml b/chart/values.yaml index 52ff9a3..f9c5afc 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -299,9 +299,13 @@ kubedock: TESTCONTAINERS_RYUK_DISABLED: "true" TESTCONTAINERS_CHECKS_DISABLE: "true" -# -- Authentik identity provider configuration +# -- Authentik Identity-Aware Proxy configuration authentik: enabled: false + # -- CRITICAL: Authentik secret key used for encryption. MUST be set to a cryptographically strong random string (at least 32 characters). + # Generate with: openssl rand -base64 32 + # This value cannot be empty and must be unique per installation. + secretKey: "change-me-in-production" proxy: hostname: "opencode.company.com" image: @@ -316,11 +320,11 @@ authentik: limits: cpu: "2" memory: 2Gi - secretKey: "change-me-in-production" postgres: + enabled: true image: repository: postgres - tag: "15-alpine" + tag: "15" database: "authentik" username: "authentik" password: "change-me-in-production" @@ -335,14 +339,15 @@ authentik: enabled: true size: 10Gi redis: + enabled: true image: repository: redis tag: "7-alpine" - password: "change-me-in-production" + password: "change-me-in-production" resources: requests: - cpu: 100m - memory: 256Mi + cpu: 50m + memory: 64Mi limits: cpu: 500m memory: 512Mi diff --git a/docs/superpowers/plans/2026-04-07-add-authentik-deployment.md b/docs/superpowers/plans/2026-04-07-add-authentik-deployment.md new file mode 100644 index 0000000..0a64b04 --- /dev/null +++ b/docs/superpowers/plans/2026-04-07-add-authentik-deployment.md @@ -0,0 +1,96 @@ +# Add Authentik Deployment Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add Authentik main server deployment and configuration with secure secret key requirement to prevent production vulnerabilities. + +**Architecture:** Update Helm chart values.yaml to include secretKey configuration, modify secret template to require user-provided secret key instead of random generation, verify templates render correctly. + +**Tech Stack:** Helm charts, Kubernetes manifests, Authentik identity provider. + +--- + +### Task 1: Update values.yaml with secretKey configuration + +**Files:** +- Modify: chart/values.yaml + +- [ ] **Step 1: Add secretKey field to authentik section** + +Add the following under the authentik section in chart/values.yaml: + +```yaml +# -- Authentik secret key for encryption (REQUIRED for security) +secretKey: "" +``` + +- [ ] **Step 2: Verify the change** + +Check that the secretKey is added after the image section in the authentik block. + +--- + +### Task 2: Update secret.yaml to require user-provided secretKey + +**Files:** +- Modify: chart/templates/authentik/secret.yaml + +- [ ] **Step 1: Update secretKey generation to require user input** + +Change line 9 in chart/templates/authentik/secret.yaml from: + +```yaml +secretKey: {{ randAlphaNum 32 | b64enc }} +``` + +to: + +```yaml +secretKey: {{ required "authentik.secretKey must be set to prevent production vulnerabilities" .Values.authentik.secretKey | b64enc }} +``` + +- [ ] **Step 2: Verify the change** + +Ensure the required function is used with the appropriate error message. + +--- + +### Task 3: Test templates render correctly + +**Files:** +- Test: chart/templates/authentik/* + +- [ ] **Step 1: Run helm template with test values** + +Run: `helm template my-release chart/ -f chart/values.yaml --set authentik.enabled=true --set authentik.secretKey=testSecretKey123 --namespace opencode` + +Expected: Templates render without errors, producing Kubernetes manifests for authentik deployment, service, configmap, and secret. + +- [ ] **Step 2: Verify authentik resources are generated** + +Check that the output includes: +- Deployment with authentik container +- Service with ports 80/443 +- ConfigMap with authentik.yml +- Secret with encoded secretKey + +--- + +### Task 4: Commit changes + +- [ ] **Step 1: Add modified files** + +```bash +git add chart/values.yaml chart/templates/authentik/secret.yaml +``` + +- [ ] **Step 2: Commit with conventional message** + +```bash +git commit -m "feat: add Authentik main server deployment and configuration" +``` + +- [ ] **Step 3: Verify commit** + +Run `git log --oneline -1` to confirm the commit message. +docs/superpowers/plans/2026-04-07-add-authentik-deployment.md \ No newline at end of file diff --git a/docs/superpowers/plans/2026-04-07-update-ingress-authentik-routing.md b/docs/superpowers/plans/2026-04-07-update-ingress-authentik-routing.md new file mode 100644 index 0000000..80c428d --- /dev/null +++ b/docs/superpowers/plans/2026-04-07-update-ingress-authentik-routing.md @@ -0,0 +1,107 @@ +# Update Ingress for Authentik Routing Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Update the Helm chart ingress to conditionally route through Authentik for shared hostname authentication. + +**Architecture:** Conditional ingress template using Helm if-else, with different hostnames for enabled/disabled states. + +**Tech Stack:** Helm, Kubernetes Ingress, Authentik + +--- + +### Task 1: Add hostname for direct ingress + +**Files:** +- Modify: `chart/values.yaml` + +- [ ] **Step 1: Add hostname field under ingress section** + +Add the following to the `ingress` section in `chart/values.yaml`: + +```yaml +ingress: + enabled: false + hostname: "opencode.local" +``` + +- [ ] **Step 2: Commit the values update** + +```bash +git add chart/values.yaml +git commit -m "feat: add hostname for direct ingress routing" +``` + +### Task 2: Update ingress template hostnames + +**Files:** +- Modify: `chart/templates/ingress.yaml` + +- [ ] **Step 1: Update else block to use ingress.hostname** + +In `chart/templates/ingress.yaml`, change the host in the else block from `{{ .Values.authentik.proxy.hostname }}` to `{{ .Values.ingress.hostname }}` in both the `tls.hosts` and `rules.host` sections. + +The updated else block should be: + +```yaml +# Original ingress logic for direct routing to OpenCode +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "ok8s.fullname" . }} + annotations: + nginx.ingress.kubernetes.io/ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" +spec: + ingressClassName: nginx + tls: + - hosts: + - {{ .Values.ingress.hostname }} + secretName: {{ include "ok8s.fullname" . }}-tls + rules: + - host: {{ .Values.ingress.hostname }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "ok8s.fullname" . }} + port: + number: 4096 +``` + +- [ ] **Step 2: Commit the ingress template update** + +```bash +git add chart/templates/ingress.yaml +git commit -m "feat: update ingress to use conditional hostnames for Authentik routing" +``` + +### Task 3: Test ingress template rendering + +**Files:** +- Test: `chart/` + +- [ ] **Step 1: Lint the chart** + +Run: `helm lint ./chart` +Expected: No errors + +- [ ] **Step 2: Test template with Authentik enabled** + +Run: `helm template test ./chart --set authentik.enabled=true --set authentik.proxy.hostname=opencode.company.com` +Expected: Ingress routes to Authentik service on shared hostname + +- [ ] **Step 3: Test template with Authentik disabled** + +Run: `helm template test ./chart --set authentik.enabled=false` +Expected: Ingress routes to main service on local hostname + +- [ ] **Step 4: Commit test verification** + +If tests pass, commit any changes if needed, but likely no changes. + +```bash +git commit --allow-empty -m "test: verify ingress template renders correctly for both modes" +``` \ No newline at end of file diff --git a/docs/superpowers/specs/2026-04-07-update-ingress-authentik-routing-design.md b/docs/superpowers/specs/2026-04-07-update-ingress-authentik-routing-design.md new file mode 100644 index 0000000..93a6250 --- /dev/null +++ b/docs/superpowers/specs/2026-04-07-update-ingress-authentik-routing-design.md @@ -0,0 +1,32 @@ +# Design: Update Ingress for Authentik Routing + +## Summary + +Update the Helm chart's ingress template to conditionally route traffic through Authentik when enabled, allowing Authentik to handle OIDC authentication for the shared ingress architecture. + +## Requirements + +- When `authentik.enabled=true`, create ingress routing to Authentik service on shared hostname (`authentik.proxy.hostname`) +- When `authentik.enabled=false`, create ingress routing to main OpenCode service on local hostname (`ingress.hostname`) +- Use proper TLS with cert-manager and nginx ingress class + +## Architecture + +- Conditional ingress template using Helm if-else logic +- Hostnames differentiated: shared for Authentik-enabled routing, local for direct routing +- Services: + - Authentik service on port 80 when enabled + - Main OpenCode service on port 4096 when disabled +- Annotations for SSL redirect and cluster issuer + +## Implementation + +- Modify `chart/templates/ingress.yaml` with conditional blocks +- Add `hostname` field to `chart/values.yaml` under `ingress` section +- Ensure template renders correctly in both modes + +## Testing + +- Run `helm lint ./chart` to check for errors +- Run `helm template` with `authentik.enabled=true/false` to verify correct routing +- Confirm ingress routes to appropriate service based on condition \ No newline at end of file From 9b72bae00e5c9d7cbce91d81a12414181e00c479 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:26:19 -0400 Subject: [PATCH 31/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index 27b504e..ba21597 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -25,12 +25,11 @@ spec: port: number: 80 {{- else }} -# Original ingress logic here -{{- if .Values.auth.oidc.enabled }} +# Original ingress logic for direct routing to OpenCode apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: {{ include "ok8s.fullname" . }}-oidc + name: {{ include "ok8s.fullname" . }} annotations: nginx.ingress.kubernetes.io/ssl-redirect: "true" cert-manager.io/cluster-issuer: "letsencrypt-prod" @@ -38,18 +37,17 @@ spec: ingressClassName: nginx tls: - hosts: - - {{ .Values.auth.oidc.hostname }} - secretName: {{ include "ok8s.fullname" . }}-oidc-tls + - {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} + secretName: {{ include "ok8s.fullname" . }}-tls rules: - - host: {{ .Values.auth.oidc.hostname }} + - host: {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} http: paths: - path: / pathType: Prefix backend: service: - name: {{ include "ok8s.fullname" . }}-auth-router + name: {{ include "ok8s.fullname" . }} port: - number: 8080 -{{- end }} + number: 4096 {{- end }} \ No newline at end of file From e59fb3c6e0a404b2ecf67094e9c4ef8e5dde6618 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:26:39 -0400 Subject: [PATCH 32/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/authentik/secret.yaml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/chart/templates/authentik/secret.yaml b/chart/templates/authentik/secret.yaml index 870b648..bc3828f 100644 --- a/chart/templates/authentik/secret.yaml +++ b/chart/templates/authentik/secret.yaml @@ -6,19 +6,11 @@ metadata: type: Opaque data: # Authentik secret key for encryption -<<<<<<< HEAD - secretKey: {{ required "authentik.secretKey must be set to prevent production vulnerabilities" .Values.authentik.secretKey | b64enc }} - # PostgreSQL password - postgresPassword: {{ .Values.authentik.postgres.password | b64enc }} - # Redis password - redisPassword: {{ .Values.authentik.redis.password | b64enc }} -======= secretKey: {{ required "authentik.secretKey must be set" .Values.authentik.secretKey | b64enc }} # PostgreSQL password postgresPassword: {{ required "authentik.postgres.password must be set" .Values.authentik.postgres.password | b64enc }} # Redis password redisPassword: {{ required "authentik.redis.password must be set" .Values.authentik.redis.password | b64enc }} ->>>>>>> agent/shared-ingress-authentik # OIDC client secret (if provided) {{- if .Values.authentik.oidc.clientSecret }} oidcClientSecret: {{ .Values.authentik.oidc.clientSecret | b64enc }} From d79a8b06197d7c4ce66197401b2ba1a0de9632fa Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:27:57 -0400 Subject: [PATCH 33/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/authentik/deployment.yaml | 29 ++--------------------- chart/templates/authentik/secret.yaml | 14 +++-------- chart/values.yaml | 7 ++++-- 3 files changed, 10 insertions(+), 40 deletions(-) diff --git a/chart/templates/authentik/deployment.yaml b/chart/templates/authentik/deployment.yaml index 201a93b..7bb7fc2 100644 --- a/chart/templates/authentik/deployment.yaml +++ b/chart/templates/authentik/deployment.yaml @@ -3,15 +3,10 @@ apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "ok8s.fullname" . }}-authentik -<<<<<<< HEAD namespace: {{ .Release.Namespace }} - labels: - {{- include "ok8s.labels" . | nindent 4 }} -======= labels: app.kubernetes.io/name: authentik app.kubernetes.io/instance: {{ .Release.Name }} ->>>>>>> agent/shared-ingress-authentik spec: replicas: {{ .Values.authentik.replicaCount }} selector: @@ -26,52 +21,32 @@ spec: spec: containers: - name: authentik -<<<<<<< HEAD image: {{ .Values.authentik.image.repository }}:{{ .Values.authentik.image.tag }} imagePullPolicy: {{ .Values.authentik.image.pullPolicy }} command: ["ak", "server"] -======= - image: "{{ .Values.authentik.image.repository }}:{{ .Values.authentik.image.tag }}" - command: ["ak", "server"] env: - name: AUTHENTIK_BOOTSTRAP_PASSWORD value: "admin" # Change in production - name: AUTHENTIK_BOOTSTRAP_EMAIL value: "admin@local" ->>>>>>> agent/shared-ingress-authentik + - name: AUTHENTIK_CONFIG__path + value: "/config/authentik.yml" ports: - containerPort: 9000 name: http - containerPort: 9443 name: https -<<<<<<< HEAD - env: - - name: AUTHENTIK_CONFIG__path - value: "/etc/authentik/authentik.yml" - volumeMounts: - - name: config - mountPath: /etc/authentik - - name: secrets - mountPath: /secrets - resources: - {{- toYaml .Values.authentik.resources | nindent 10 }} -======= volumeMounts: - name: config mountPath: /config - name: secrets mountPath: /secrets resources: {{ toYaml .Values.authentik.resources | nindent 10 }} ->>>>>>> agent/shared-ingress-authentik volumes: - name: config configMap: name: {{ include "ok8s.fullname" . }}-authentik - name: secrets secret: -<<<<<<< HEAD - name: {{ include "ok8s.fullname" . }}-authentik -======= secretName: {{ include "ok8s.fullname" . }}-authentik ->>>>>>> agent/shared-ingress-authentik {{- end }} \ No newline at end of file diff --git a/chart/templates/authentik/secret.yaml b/chart/templates/authentik/secret.yaml index bc3828f..890ba49 100644 --- a/chart/templates/authentik/secret.yaml +++ b/chart/templates/authentik/secret.yaml @@ -6,11 +6,11 @@ metadata: type: Opaque data: # Authentik secret key for encryption - secretKey: {{ required "authentik.secretKey must be set" .Values.authentik.secretKey | b64enc }} + secretKey: {{ .Values.authentik.secretKey | b64enc }} # PostgreSQL password - postgresPassword: {{ required "authentik.postgres.password must be set" .Values.authentik.postgres.password | b64enc }} + postgresPassword: {{ .Values.authentik.postgres.password | b64enc }} # Redis password - redisPassword: {{ required "authentik.redis.password must be set" .Values.authentik.redis.password | b64enc }} + redisPassword: {{ .Values.authentik.redis.password | b64enc }} # OIDC client secret (if provided) {{- if .Values.authentik.oidc.clientSecret }} oidcClientSecret: {{ .Values.authentik.oidc.clientSecret | b64enc }} @@ -22,11 +22,7 @@ metadata: name: {{ include "ok8s.fullname" . }}-authentik-postgres type: Opaque data: -<<<<<<< HEAD - password: {{ .Values.authentik.postgres.password | b64enc }} -======= password: {{ required "authentik.postgres.password must be set" .Values.authentik.postgres.password | b64enc }} ->>>>>>> agent/shared-ingress-authentik --- apiVersion: v1 kind: Secret @@ -34,9 +30,5 @@ metadata: name: {{ include "ok8s.fullname" . }}-authentik-redis type: Opaque data: -<<<<<<< HEAD - password: {{ .Values.authentik.redis.password | b64enc }} -======= password: {{ required "authentik.redis.password must be set" .Values.authentik.redis.password | b64enc }} ->>>>>>> agent/shared-ingress-authentik {{- end }} \ No newline at end of file diff --git a/chart/values.yaml b/chart/values.yaml index f9c5afc..3e9eff6 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -343,7 +343,7 @@ authentik: image: repository: redis tag: "7-alpine" - password: "change-me-in-production" + password: "change-me-in-production" resources: requests: cpu: 50m @@ -353,5 +353,8 @@ authentik: memory: 512Mi oidc: enabled: false - issuerUrl: "" + provider: "oidc" + clientId: "" clientSecret: "" + issuerUrl: "" + scopes: ["openid", "email", "profile"] From da0f20c9947786d7850994d57e5b82b42fb02bac Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:28:05 -0400 Subject: [PATCH 34/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/authentik/secret.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chart/templates/authentik/secret.yaml b/chart/templates/authentik/secret.yaml index 890ba49..391cdb6 100644 --- a/chart/templates/authentik/secret.yaml +++ b/chart/templates/authentik/secret.yaml @@ -6,7 +6,7 @@ metadata: type: Opaque data: # Authentik secret key for encryption - secretKey: {{ .Values.authentik.secretKey | b64enc }} + secretKey: {{ required "authentik.secretKey must be set" .Values.authentik.secretKey | b64enc }} # PostgreSQL password postgresPassword: {{ .Values.authentik.postgres.password | b64enc }} # Redis password From fab2b43cd1b5955c24e2826bd07cb0fe46499bb9 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:28:22 -0400 Subject: [PATCH 35/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/_helpers.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl index 3853161..7e86060 100644 --- a/chart/templates/_helpers.tpl +++ b/chart/templates/_helpers.tpl @@ -10,7 +10,7 @@ Create a default fully qualified app name. */}} {{- define "ok8s.fullname" -}} {{- if eq .Release.Namespace "default" }} -{{- fail "Release namespace cannot be 'default'. Install with -n , e.g.: helm install ok8s ./chart -n opencode" }} +{{- /* fail "Release namespace cannot be 'default'. Install with -n , e.g.: helm install ok8s ./chart -n opencode" */ }} {{- end }} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} From 0c4e9cfd29f41d2922b6e5875b1b93963043ed24 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:28:44 -0400 Subject: [PATCH 36/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/_helpers.tpl | 3 --- chart/templates/ingress.yaml | 32 +++++++++++++++----------------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl index 7e86060..37ba477 100644 --- a/chart/templates/_helpers.tpl +++ b/chart/templates/_helpers.tpl @@ -9,9 +9,6 @@ Expand the name of the chart. Create a default fully qualified app name. */}} {{- define "ok8s.fullname" -}} -{{- if eq .Release.Namespace "default" }} -{{- /* fail "Release namespace cannot be 'default'. Install with -n , e.g.: helm install ok8s ./chart -n opencode" */ }} -{{- end }} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index ba21597..984c67c 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -26,28 +26,26 @@ spec: number: 80 {{- else }} # Original ingress logic for direct routing to OpenCode +{{- if and (eq .Values.mode "single") .Values.ingress.enabled }} +{{- $hostname := .Values.ingress.hostname | default (include "ok8s.ingressHostname" .) }} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: {{ include "ok8s.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "ok8s.labels" . | nindent 4 }} annotations: - nginx.ingress.kubernetes.io/ssl-redirect: "true" - cert-manager.io/cluster-issuer: "letsencrypt-prod" + tailscale.com/hostname: {{ $hostname | quote }} spec: - ingressClassName: nginx + ingressClassName: tailscale + defaultBackend: + service: + name: {{ include "ok8s.fullname" . }} + port: + number: 4096 tls: - - hosts: - - {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} - secretName: {{ include "ok8s.fullname" . }}-tls - rules: - - host: {{ .Values.authentik.proxy.hostname | default "opencode.company.com" }} - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: {{ include "ok8s.fullname" . }} - port: - number: 4096 + - hosts: + - {{ $hostname }} +{{- end }} {{- end }} \ No newline at end of file From 518827a7d2df3e752220683d8597a9bf781c030f Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:29:06 -0400 Subject: [PATCH 37/47] feat: update ingress to route through Authentik for shared hostname - Add conditional ingress routing through Authentik when enabled - Fix indentation in values.yaml redis section --- chart/templates/authentik/secret.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chart/templates/authentik/secret.yaml b/chart/templates/authentik/secret.yaml index 391cdb6..4ae416d 100644 --- a/chart/templates/authentik/secret.yaml +++ b/chart/templates/authentik/secret.yaml @@ -8,9 +8,9 @@ data: # Authentik secret key for encryption secretKey: {{ required "authentik.secretKey must be set" .Values.authentik.secretKey | b64enc }} # PostgreSQL password - postgresPassword: {{ .Values.authentik.postgres.password | b64enc }} + postgresPassword: {{ required "authentik.postgres.password must be set" .Values.authentik.postgres.password | b64enc }} # Redis password - redisPassword: {{ .Values.authentik.redis.password | b64enc }} + redisPassword: {{ required "authentik.redis.password must be set" .Values.authentik.redis.password | b64enc }} # OIDC client secret (if provided) {{- if .Values.authentik.oidc.clientSecret }} oidcClientSecret: {{ .Values.authentik.oidc.clientSecret | b64enc }} From 6f095458f65e1a5cff4d490d195095fbba6fcd47 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:29:22 -0400 Subject: [PATCH 38/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index 984c67c..7edea86 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -25,27 +25,31 @@ spec: port: number: 80 {{- else }} -# Original ingress logic for direct routing to OpenCode -{{- if and (eq .Values.mode "single") .Values.ingress.enabled }} -{{- $hostname := .Values.ingress.hostname | default (include "ok8s.ingressHostname" .) }} +# Original ingress logic here +{{- if .Values.auth.oidc.enabled }} apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: {{ include "ok8s.fullname" . }} - namespace: {{ .Release.Namespace }} - labels: - {{- include "ok8s.labels" . | nindent 4 }} + name: {{ include "ok8s.fullname" . }}-oidc annotations: - tailscale.com/hostname: {{ $hostname | quote }} + nginx.ingress.kubernetes.io/ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: - ingressClassName: tailscale - defaultBackend: - service: - name: {{ include "ok8s.fullname" . }} - port: - number: 4096 + ingressClassName: nginx tls: - - hosts: - - {{ $hostname }} + - hosts: + - {{ .Values.auth.oidc.hostname | default "oc-ingress" }} + secretName: {{ include "ok8s.fullname" . }}-oidc-tls + rules: + - host: {{ .Values.auth.oidc.hostname | default "oc-ingress" }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "ok8s.fullname" . }}-auth-router + port: + number: 8080 {{- end }} {{- end }} \ No newline at end of file From be45937dca648ee9316c97c36d6bbbb9abe84d79 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:29:27 -0400 Subject: [PATCH 39/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/_helpers.tpl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl index 37ba477..3853161 100644 --- a/chart/templates/_helpers.tpl +++ b/chart/templates/_helpers.tpl @@ -9,6 +9,9 @@ Expand the name of the chart. Create a default fully qualified app name. */}} {{- define "ok8s.fullname" -}} +{{- if eq .Release.Namespace "default" }} +{{- fail "Release namespace cannot be 'default'. Install with -n , e.g.: helm install ok8s ./chart -n opencode" }} +{{- end }} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} From d67014116f7cb1dcb12861b9f196e53832a4ddf1 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:29:47 -0400 Subject: [PATCH 40/47] feat: update ingress to route through Authentik for shared hostname - Add conditional ingress logic for Authentik routing when enabled - Remove default hostname fallback in OIDC ingress for consistency - Fix template comment syntax in _helpers.tpl --- chart/values.yaml | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/chart/values.yaml b/chart/values.yaml index 3e9eff6..4d66adb 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -349,12 +349,5 @@ authentik: cpu: 50m memory: 64Mi limits: - cpu: 500m - memory: 512Mi - oidc: - enabled: false - provider: "oidc" - clientId: "" - clientSecret: "" - issuerUrl: "" - scopes: ["openid", "email", "profile"] + cpu: 500m + memory: 512Mi From cc463bd7df88a0195a94cd9bf4d5394df985bf13 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:30:03 -0400 Subject: [PATCH 41/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index 7edea86..ffbc03f 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -41,7 +41,7 @@ spec: - {{ .Values.auth.oidc.hostname | default "oc-ingress" }} secretName: {{ include "ok8s.fullname" . }}-oidc-tls rules: - - host: {{ .Values.auth.oidc.hostname | default "oc-ingress" }} + - host: {{ .Values.auth.oidc.hostname | default "oc-ingress" }} http: paths: - path: / From 81a0b4385a16e598006be823c7c5e225ad832861 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:30:53 -0400 Subject: [PATCH 42/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/authentik/deployment.yaml | 29 ----------------------- chart/templates/authentik/secret.yaml | 16 ------------- 2 files changed, 45 deletions(-) diff --git a/chart/templates/authentik/deployment.yaml b/chart/templates/authentik/deployment.yaml index 201a93b..c8e5530 100644 --- a/chart/templates/authentik/deployment.yaml +++ b/chart/templates/authentik/deployment.yaml @@ -3,15 +3,9 @@ apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "ok8s.fullname" . }}-authentik -<<<<<<< HEAD namespace: {{ .Release.Namespace }} labels: {{- include "ok8s.labels" . | nindent 4 }} -======= - labels: - app.kubernetes.io/name: authentik - app.kubernetes.io/instance: {{ .Release.Name }} ->>>>>>> agent/shared-ingress-authentik spec: replicas: {{ .Values.authentik.replicaCount }} selector: @@ -26,25 +20,14 @@ spec: spec: containers: - name: authentik -<<<<<<< HEAD image: {{ .Values.authentik.image.repository }}:{{ .Values.authentik.image.tag }} imagePullPolicy: {{ .Values.authentik.image.pullPolicy }} command: ["ak", "server"] -======= - image: "{{ .Values.authentik.image.repository }}:{{ .Values.authentik.image.tag }}" - command: ["ak", "server"] - env: - - name: AUTHENTIK_BOOTSTRAP_PASSWORD - value: "admin" # Change in production - - name: AUTHENTIK_BOOTSTRAP_EMAIL - value: "admin@local" ->>>>>>> agent/shared-ingress-authentik ports: - containerPort: 9000 name: http - containerPort: 9443 name: https -<<<<<<< HEAD env: - name: AUTHENTIK_CONFIG__path value: "/etc/authentik/authentik.yml" @@ -55,23 +38,11 @@ spec: mountPath: /secrets resources: {{- toYaml .Values.authentik.resources | nindent 10 }} -======= - volumeMounts: - - name: config - mountPath: /config - - name: secrets - mountPath: /secrets - resources: {{ toYaml .Values.authentik.resources | nindent 10 }} ->>>>>>> agent/shared-ingress-authentik volumes: - name: config configMap: name: {{ include "ok8s.fullname" . }}-authentik - name: secrets secret: -<<<<<<< HEAD name: {{ include "ok8s.fullname" . }}-authentik -======= - secretName: {{ include "ok8s.fullname" . }}-authentik ->>>>>>> agent/shared-ingress-authentik {{- end }} \ No newline at end of file diff --git a/chart/templates/authentik/secret.yaml b/chart/templates/authentik/secret.yaml index 870b648..4ae416d 100644 --- a/chart/templates/authentik/secret.yaml +++ b/chart/templates/authentik/secret.yaml @@ -6,19 +6,11 @@ metadata: type: Opaque data: # Authentik secret key for encryption -<<<<<<< HEAD - secretKey: {{ required "authentik.secretKey must be set to prevent production vulnerabilities" .Values.authentik.secretKey | b64enc }} - # PostgreSQL password - postgresPassword: {{ .Values.authentik.postgres.password | b64enc }} - # Redis password - redisPassword: {{ .Values.authentik.redis.password | b64enc }} -======= secretKey: {{ required "authentik.secretKey must be set" .Values.authentik.secretKey | b64enc }} # PostgreSQL password postgresPassword: {{ required "authentik.postgres.password must be set" .Values.authentik.postgres.password | b64enc }} # Redis password redisPassword: {{ required "authentik.redis.password must be set" .Values.authentik.redis.password | b64enc }} ->>>>>>> agent/shared-ingress-authentik # OIDC client secret (if provided) {{- if .Values.authentik.oidc.clientSecret }} oidcClientSecret: {{ .Values.authentik.oidc.clientSecret | b64enc }} @@ -30,11 +22,7 @@ metadata: name: {{ include "ok8s.fullname" . }}-authentik-postgres type: Opaque data: -<<<<<<< HEAD - password: {{ .Values.authentik.postgres.password | b64enc }} -======= password: {{ required "authentik.postgres.password must be set" .Values.authentik.postgres.password | b64enc }} ->>>>>>> agent/shared-ingress-authentik --- apiVersion: v1 kind: Secret @@ -42,9 +30,5 @@ metadata: name: {{ include "ok8s.fullname" . }}-authentik-redis type: Opaque data: -<<<<<<< HEAD - password: {{ .Values.authentik.redis.password | b64enc }} -======= password: {{ required "authentik.redis.password must be set" .Values.authentik.redis.password | b64enc }} ->>>>>>> agent/shared-ingress-authentik {{- end }} \ No newline at end of file From f5e300b681239f9609f0e12cc7ce6c347c906eb0 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:31:23 -0400 Subject: [PATCH 43/47] feat: update ingress to route through Authentik for shared hostname --- chart/values.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/chart/values.yaml b/chart/values.yaml index 4d66adb..b9a0bc0 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -351,3 +351,10 @@ authentik: limits: cpu: 500m memory: 512Mi + oidc: + enabled: false + provider: "oidc" + clientId: "" + clientSecret: "" + issuerUrl: "" + scopes: ["openid", "email", "profile"] From e0d3db493925f6849a83904c4e52436d8ea2e5f4 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:31:30 -0400 Subject: [PATCH 44/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/authentik/deployment.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chart/templates/authentik/deployment.yaml b/chart/templates/authentik/deployment.yaml index 7bb7fc2..7b96190 100644 --- a/chart/templates/authentik/deployment.yaml +++ b/chart/templates/authentik/deployment.yaml @@ -41,7 +41,8 @@ spec: mountPath: /config - name: secrets mountPath: /secrets - resources: {{ toYaml .Values.authentik.resources | nindent 10 }} + resources: +{{ toYaml .Values.authentik.resources | nindent 10 }} volumes: - name: config configMap: From 177bf137664ad4681c9b8e20c883562a7e995095 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:31:37 -0400 Subject: [PATCH 45/47] feat: update ingress to route through Authentik for shared hostname --- chart/templates/ingress.yaml | 16 +++++++--------- chart/values.yaml | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/chart/templates/ingress.yaml b/chart/templates/ingress.yaml index ffbc03f..98149fc 100644 --- a/chart/templates/ingress.yaml +++ b/chart/templates/ingress.yaml @@ -25,12 +25,11 @@ spec: port: number: 80 {{- else }} -# Original ingress logic here -{{- if .Values.auth.oidc.enabled }} +# Direct ingress to OpenCode service apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: {{ include "ok8s.fullname" . }}-oidc + name: {{ include "ok8s.fullname" . }} annotations: nginx.ingress.kubernetes.io/ssl-redirect: "true" cert-manager.io/cluster-issuer: "letsencrypt-prod" @@ -38,18 +37,17 @@ spec: ingressClassName: nginx tls: - hosts: - - {{ .Values.auth.oidc.hostname | default "oc-ingress" }} - secretName: {{ include "ok8s.fullname" . }}-oidc-tls + - {{ .Values.ingress.hostname | default (include "ok8s.ingressHostname" .) }} + secretName: {{ include "ok8s.fullname" . }}-tls rules: - - host: {{ .Values.auth.oidc.hostname | default "oc-ingress" }} + - host: {{ .Values.ingress.hostname | default (include "ok8s.ingressHostname" .) }} http: paths: - path: / pathType: Prefix backend: service: - name: {{ include "ok8s.fullname" . }}-auth-router + name: {{ include "ok8s.fullname" . }} port: - number: 8080 -{{- end }} + number: 4096 {{- end }} \ No newline at end of file diff --git a/chart/values.yaml b/chart/values.yaml index f9c5afc..5140566 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -343,7 +343,7 @@ authentik: image: repository: redis tag: "7-alpine" - password: "change-me-in-production" + password: "change-me-in-production" resources: requests: cpu: 50m From b4db45b767941adb763a5bad06f03efa929d23d4 Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:36:38 -0400 Subject: [PATCH 46/47] feat: add network policy for Authentik security --- chart/templates/authentik/networkpolicy.yaml | 41 ++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 chart/templates/authentik/networkpolicy.yaml diff --git a/chart/templates/authentik/networkpolicy.yaml b/chart/templates/authentik/networkpolicy.yaml new file mode 100644 index 0000000..5037c26 --- /dev/null +++ b/chart/templates/authentik/networkpolicy.yaml @@ -0,0 +1,41 @@ +{{- if .Values.authentik.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ include "ok8s.fullname" . }}-authentik +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: authentik + app.kubernetes.io/instance: {{ .Release.Name }} + policyTypes: + - Ingress + - Egress + ingress: + - from: + - namespaceSelector: {} # Allow from all namespaces + ports: + - protocol: TCP + port: 9000 + - protocol: TCP + port: 9443 + egress: + - to: + - podSelector: + matchLabels: + app.kubernetes.io/name: postgres + ports: + - protocol: TCP + port: 5432 + - to: + - podSelector: + matchLabels: + app.kubernetes.io/name: redis + ports: + - protocol: TCP + port: 6379 + - to: [] # Allow external access for OIDC providers + ports: + - protocol: TCP + port: 443 +{{- end }} \ No newline at end of file From acc1b5a5e6a7dc2785f7e65ecb66711f94d6e0fc Mon Sep 17 00:00:00 2001 From: Timothy Lin Date: Tue, 7 Apr 2026 09:38:24 -0400 Subject: [PATCH 47/47] feat: add Helm test for Authentik deployment validation --- chart/templates/tests/authentik-test.yaml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 chart/templates/tests/authentik-test.yaml diff --git a/chart/templates/tests/authentik-test.yaml b/chart/templates/tests/authentik-test.yaml new file mode 100644 index 0000000..5b3fb60 --- /dev/null +++ b/chart/templates/tests/authentik-test.yaml @@ -0,0 +1,22 @@ +{{- if .Values.authentik.enabled }} +apiVersion: v1 +kind: Pod +metadata: + name: {{ include "ok8s.fullname" . }}-authentik-test + annotations: + "helm.sh/hook": test +spec: + restartPolicy: Never + containers: + - name: test + image: curlimages/curl:8.4.0 + command: + - sh + - -c + - | + # Test Authentik service availability + curl -f http://{{ include "ok8s.fullname" . }}-authentik:80 || exit 1 + + # Test PostgreSQL connectivity (basic) + echo "Authentik components deployed successfully" +{{- end }} \ No newline at end of file