Files
poimen-memory/k8s/app/CONFIG.md
T
rock 985bb7ff46
CI / CI (pull_request) Successful in 32m52s
config: env-based service URIs via ConfigMap (prod: SOPS-encrypted)
- config.yaml: prod config with cluster-internal DNS (LLM, OpenSearch, Authentik, Temporal, API-GW)
- config.local.yaml: dev config with external URLs via ingress
- deployment.yaml: remove hardcoded URIs, read all from ConfigMap envFrom
- All downstream service URIs now configurable per environment
- Production config encrypted with SOPS (Age-based)
- Application code reads LLM_ENDPOINT, OPENSEARCH_HOST, AUTHENTIK_ISSUER, etc. from ENV
- Simplifies prod/dev switching: just swap ConfigMap, no code changes
2026-09-13 11:12:53 +09:00

4.5 KiB

Poimen Memory - Environment Configuration Guide

All downstream service URIs are read from environment variables, sourced from ConfigMap.

How It Works

  1. ConfigMap provides URIs: k8s/app/config.yaml (production, SOPS-encrypted)
  2. Deployment injects via envFrom: envFrom: configMapRef: poimen-memory-config
  3. Application reads from ENV: Code parses LLM_ENDPOINT, OPENSEARCH_HOST, AUTHENTIK_ISSUER, etc.
# deployment.yaml
envFrom:
  - configMapRef:
      name: poimen-memory-config  # All vars injected as ENV

Environment Variables

LLM Service (Entity & Fact Extraction)

  • LLM_ENDPOINT — full URL to chat/completions endpoint
  • LLM_API_BASE — base API URL (used for client initialization)
  • LLM_MODEL — model identifier (ornith:35b, qwen:7b, etc.)
  • LLM_TIMEOUT_SECS — timeout for LLM requests
  • ENABLE_LLM_EXTRACTION — enable/disable LLM extraction (true/false)

OpenSearch (Vector Store, BM25)

  • OPENSEARCH_HOST — hostname:port
  • OPENSEARCH_SCHEME — http or https
  • OPENSEARCH_VERIFY_CERTS — SSL certificate verification (true/false)

Authentik (OIDC)

  • AUTHENTIK_ISSUER — OIDC issuer URL
  • AUTHENTIK_VERIFY_SSL — SSL certificate verification (true/false)
  • MEM_AUTH_MODE — auth mode: jwt | apikey | none

Temporal (Workflow Orchestration - Future)

  • TEMPORAL_ENDPOINT — temporal frontend hostname:port
  • TEMPORAL_NAMESPACE — temporal namespace

API Gateway (Route Optimization - Future)

  • GATEWAY_URL — gateway base URL

Memory Service Config

  • MEM_AUTH_MODE — jwt | apikey | none
  • MEM_RATE_LIMIT_INGEST — ingest requests per second
  • MEM_RATE_LIMIT_QUERY — query requests per second
  • MEM_EMBEDDING_BATCH_SIZE — batch size for embeddings

Deployment Scenarios

Production (SOPS-Encrypted ConfigMap)

File: k8s/app/config.yaml

Services use cluster-internal DNS:

LLM_ENDPOINT: http://reasoning-predictor.llm-serving.svc.cluster.local:8000/v1/chat/completions
OPENSEARCH_HOST: opensearch.poimen.svc.cluster.local:9200
AUTHENTIK_ISSUER: https://authentik.auth.svc.cluster.local:9443/application/o/poimen/
TEMPORAL_ENDPOINT: temporal-frontend.temporal.svc.cluster.local:7233
GATEWAY_URL: http://api-gw.poimen.svc.cluster.local:8080
MEM_AUTH_MODE: jwt

Deploy:

# SOPS auto-decrypts based on .sops.yaml age key
kubectl apply -f k8s/app/config.yaml -k k8s/app/

Local/Development (Plaintext ConfigMap)

File: k8s/app/config.local.yaml

Services via external URLs (ingress):

LLM_ENDPOINT: https://api.riotpiao.com/v1/chat/completions
OPENSEARCH_HOST: opensearch.riotpiao.com:443
AUTHENTIK_ISSUER: https://authentik.riotpiao.com/application/o/poimen/
TEMPORAL_ENDPOINT: temporal.riotpiao.com:443
GATEWAY_URL: https://api.riotpiao.com
MEM_AUTH_MODE: none

Deploy (override production config):

# Delete prod config, apply local
kubectl delete configmap poimen-memory-config -n poimen
kubectl apply -f k8s/app/config.local.yaml

Encrypting with SOPS

Production config.yaml is encrypted with SOPS (Age-based).

Encrypt:

sops -e k8s/app/config.yaml > k8s/app/config.yaml.enc
mv k8s/app/config.yaml.enc k8s/app/config.yaml

Decrypt for editing (SOPS auto-handles with $EDITOR):

sops k8s/app/config.yaml

View decrypted (without editing):

sops -d k8s/app/config.yaml

.sops.yaml defines encryption key:

creation_rules:
  - path_regex: k8s/app/config.yaml
    key_groups:
      - age:
          - <age-public-key>

Application Code Pattern

Example: Application should read URIs from ENV at startup.

// Pseudocode
let llm_endpoint = env::var("LLM_ENDPOINT")
    .unwrap_or("http://localhost:11434/v1/chat/completions".to_string());
let opensearch_host = env::var("OPENSEARCH_HOST")
    .unwrap_or("localhost:9200".to_string());
let auth_mode = env::var("MEM_AUTH_MODE")
    .unwrap_or("none".to_string());

// Initialize clients with these URIs
let llm_client = LlmClient::new(llm_endpoint)?;
let search_client = OpenSearchClient::new(opensearch_host)?;

Summary

Aspect Production Local
Config File config.yaml config.local.yaml
Encryption SOPS (Age) Plaintext
Service URIs Cluster-internal DNS External HTTPS
Auth Mode JWT (Authentik) None (disabled)
Rate Limits 100/1000 1000/10000
Deploy kubectl apply -k k8s/app/ kubectl apply -f config.local.yaml