After changing Gitea ROOT_URL to https://git.georgepet.duckdns.org,
the registry V2 auth challenge redirects to the external URL.
Kyverno needs to reach 185.47.204.231:443 for token exchange.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove components not needed for PaaS-focused infrastructure:
- argo-rollouts: only used by arch-docs canary, convert to plain Deployment
- oauth2-proxy: was for dev/staging auth (removed in Phase 18)
- nginx-test: test deployment, not needed
- kube-bench: CIS benchmark scanner, not needed for PaaS
- trivy-operator: vulnerability scanner, not needed for PaaS
- drift-check RBAC: drift-check service being removed
arch-docs-prod: rollout.enabled=false → Helm uses Deployment template
Use keycloak-config-cli env var substitution $(env:VAR_NAME) to inject
user passwords from K8s Secret instead of hardcoding them in ConfigMap.
- realm-configmap.yaml: passwords replaced with $(env:KC_INFRA_ADMIN_PASSWORD)
and $(env:KC_INFRA_CLAUDE_PASSWORD)
- keycloak ArgoCD app: added keycloakConfigCli.extraEnvVarsSecret
- Secrets sourced from OpenBao via create-keycloak-secrets.sh
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The kubernetes client (Phase 15) and direct-grant-no-otp auth flow were
created via API but missing from realm-configmap.yaml. A realm re-import
would lose these configurations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove MINIO_* env vars from dev/staging/prod values
- Remove minio-access-key and minio-secret-key from secrets
- Remove port 9000 from NetworkPolicy egress rules
- PDF stored in PostgreSQL BYTEA, MinIO no longer needed
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PG/MinIO removed from K8s, report-generator needs more CPU for
in-Go aggregation. Prod quota supports HPA up to 5 replicas.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Delete postgresql.yaml and minio.yaml (6 files) — stateful pods removed
- NetworkPolicy: replace podSelector with ipBlock 185.47.204.228/32
- Secrets: update credentials for VM PostgreSQL and MinIO
- Values: point DB_HOST/MINIO_ENDPOINT to VM, increase resources for CPU-intensive workload
- Seed jobs: v3 targeting VM databases (reports_dev/staging/prod)
- Prod: HPA 1-5 replicas, CPU req 1/lim 4, mem req 1Gi/lim 4Gi
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The $$ dollar-quoting in PL/pgSQL DO blocks gets expanded by bash
when passed via Kubernetes args to bash -c. Rewrites seed to use
individual psql -c calls and shell loop for batch inserts.
Also adds CREATE TABLE IF NOT EXISTS and idempotency check.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Root cause of recurring login failures:
- Password 'changeme' didn't meet realm password policy (12+ chars, digits, special)
- keycloak-config-cli failed HTTP 400 on every pod restart
- Failed state meant config-cli retried full import every restart
- requiredActions re-added CONFIGURE_TOTP on every restart
Fixes:
- Set proper passwords meeting password policy requirements
- Set temporary: false (no forced password change)
- Clear requiredActions on user level (realm defaultAction handles new users)
- Config-cli should now succeed and save state, preventing re-import loops
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add infra-operators group to Keycloak realm
- Add K8s RBAC: operators get full CRUD in dev/staging, readonly in prod,
cluster-level readonly for nodes/namespaces/storage, no infra ns access
- Update ArgoCD RBAC: operators → role:readonly
- Update oauth2-proxy: allow infra-operators group
- Add PostgreSQL NodePort (35432) for OpenBao Database engine access
- Update NetworkPolicy: allow NodePort traffic from node CIDR
- Extend keycloak-secrets-manager Role: statefulset get/patch for rotation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ingress controller needs to reach oauth2-proxy for auth_request
subrequests on dev/staging arch-docs. Port 4180 was missing from
the egress rules, causing timeout on all auth-protected routes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All current images in dev/staging/prod are signed with cosign.
CI pipeline signs new images automatically.
Enforce mode will block unsigned images from our registry.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Gitea registry (ROOT_URL=http://gitea:3000) redirects V2 token auth
to http://gitea:3000/v2/token. K8s pods can't resolve 'gitea' Docker
hostname. This Service+Endpoints maps gitea to 10.10.10.1 in kyverno ns.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Private infrastructure has no internet access from K8s nodes.
Kyverno was failing to verify signatures because it tried to
fetch Rekor TUF root from tuf-repo-cdn.sigstore.dev (timeout).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Create least-privilege ServiceAccounts for k8s-audit, drift-check,
and keycloak-secrets-manager instead of sharing admin kubeconfig.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
HmacSHA256 is not supported by Google Authenticator.
SHA1 is the standard TOTP algorithm per RFC 6238.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Configure OTP policy: TOTP, SHA256, 6 digits, 30s period
- Add CONFIGURE_TOTP as default required action for new users
- Force TOTP enrollment for existing users (admin, claude)
- Add password policy: min 12 chars, mixed case, digits, special chars
- Keycloak browser flow conditional OTP will enforce TOTP on every login
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
bitnami removed Docker Hub images (Aug 2025). The bitnami/kubectl:1.35 tag
does not exist, causing ImagePullBackOff. Switch to bitnamilegacy/kubectl:1.33
which is the latest available tag.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
In Keycloak 26, 'openid' is implicit in OIDC protocol and doesn't
exist as a named client scope. This caused config-cli import failure.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Match K8s cluster version (v1.35.1). The old bitnami/kubectl:1.31
image is no longer available in Docker Hub.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Helm chart: add allowVisualTest flag to enable ingress from visual-test pods
- Staging: enable allowVisualTest for arch-docs
- Namespaces: add visual-test-egress NetworkPolicy in staging
(allows egress to app pods on 8080 + external HTTPS for OpenRouter/Telegram)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Daily cleanup of completed/failed/evicted pods at 03:00 UTC.
Runs on master node with proper RBAC (ServiceAccount + ClusterRole).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Trivy Operator: continuous vulnerability scanning of running images
kube-bench: weekly CIS benchmark on control plane node
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>