CI / CI (pull_request) Successful in 3m40s
SECURITY: - Add authentik_jwt.rs: OAuth2 client credentials flow with caching - SOPS encrypt secrets with age key (SOPS_AGE_KEY_FILE) - JWT tokens for LLM gateway, S3, and API gateway access - Token auto-refresh when expired (60s before expiry) - No hardcoded credentials in code or config ENTITY EXTRACTION: - LlmEntityExtractor now uses Authentik JWT instead of mock - Fallback to env var if Authentik not configured - Reflection verification still enabled - WikiLink extraction as Stage 0 (always active) DEPLOYMENT: - ConfigMap: LLM_ENDPOINT, LLM_MODEL, timeouts - Secret: AUTHENTIK_ISSUER, CLIENT_ID, CLIENT_SECRET, S3 keys - envFrom mounts both ConfigMap and Secret - KSOPS plugin for ArgoCD auto-decryption DOCUMENTATION: - docs/AUTHENTIK_SOPS_SETUP.md: Complete integration guide - Service account creation in Authentik - SOPS encryption/decryption workflow - JWT token exchange flow - Troubleshooting guide FILES: - crates/mem-ingest/src/authentik_jwt.rs (new, 180 LOC) - crates/mem-ingest/src/entity_extractor.rs (updated, JWT auth) - crates/mem-ingest/Cargo.toml (add reqwest) - k8s/app/poimen-memory-secrets.yaml (new, unencrypted template) - k8s/app/deployment.yaml (add secrets envFrom) - k8s/app/config.yaml (add LLM config) - k8s/.sops.yaml (encryption rules) - docs/AUTHENTIK_SOPS_SETUP.md (new, 350 LOC) NEXT: 1. Create Authentik service account (manual) 2. Encrypt secrets with SOPS 3. Deploy to poimen namespace 4. Test JWT token exchange with LLM endpoint
118 lines
3.4 KiB
YAML
118 lines
3.4 KiB
YAML
# Poimen Memory API Server
|
|
# Serves 7 HTTP endpoints for memory ingest, query, and management.
|
|
# Connects to memory-db (pgvector) for persistent storage.
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: poimen-memory
|
|
namespace: poimen
|
|
labels:
|
|
app.kubernetes.io/name: poimen-memory
|
|
app.kubernetes.io/component: api-server
|
|
spec:
|
|
replicas: 2
|
|
selector:
|
|
matchLabels:
|
|
app.kubernetes.io/name: poimen-memory
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app.kubernetes.io/name: poimen-memory
|
|
spec:
|
|
serviceAccountName: poimen-memory
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 1000
|
|
runAsGroup: 999
|
|
fsGroup: 999
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
containers:
|
|
- name: memory
|
|
image: forgejo.riotpiao.com/riotpiao-poimen/poimen-memory:latest
|
|
securityContext:
|
|
allowPrivilegeEscalation: false
|
|
readOnlyRootFilesystem: true
|
|
capabilities:
|
|
drop:
|
|
- ALL
|
|
imagePullPolicy: Always
|
|
ports:
|
|
- containerPort: 8080
|
|
name: http
|
|
env:
|
|
# Database connection (from CNPG auto-generated secret)
|
|
- name: DATABASE_HOST
|
|
value: "memory-db-rw.poimen.svc.cluster.local"
|
|
- name: DATABASE_PORT
|
|
value: "5432"
|
|
- name: DATABASE_NAME
|
|
value: "memory"
|
|
- name: DATABASE_USER
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: memory-db-app
|
|
key: username
|
|
- name: DATABASE_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: memory-db-app
|
|
key: password
|
|
- name: DATABASE_URL
|
|
value: "postgresql://$(DATABASE_USER):$(DATABASE_PASSWORD)@$(DATABASE_HOST):$(DATABASE_PORT)/$(DATABASE_NAME)?sslmode=disable"
|
|
# LLM Gateway API key
|
|
- name: MEM_API_KEY
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: poimen-memory-secrets
|
|
key: llm-api-key
|
|
# Server config (from ConfigMap)
|
|
- name: MEM_PORT
|
|
value: "8080"
|
|
- name: MEM_HOME
|
|
value: "/tmp"
|
|
envFrom:
|
|
- configMapRef:
|
|
name: poimen-memory-config
|
|
- secretRef:
|
|
name: poimen-memory-auth
|
|
- secretRef:
|
|
name: poimen-memory-secrets
|
|
args:
|
|
- serve
|
|
- --port
|
|
- "8080"
|
|
- --api-key
|
|
- "$(MEM_API_KEY)"
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 128Mi
|
|
limits:
|
|
cpu: 500m
|
|
memory: 512Mi
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: http
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 30
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: http
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 10
|
|
volumeMounts:
|
|
- name: tmp
|
|
mountPath: /tmp
|
|
volumes:
|
|
- name: tmp
|
|
emptyDir:
|
|
sizeLimit: 64Mi
|
|
# Tolerate control-plane nodes
|
|
tolerations:
|
|
- key: node-role.kubernetes.io/control-plane
|
|
operator: Exists
|
|
effect: NoSchedule
|