Compare commits

..
Author SHA1 Message Date
hermes-bot 69915ce0dd fix(wiki): the service reads the wiki-index BasicAuth users
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
#1383 + konairius/Wiki#14 put the wiki's read API behind an OIDC session
or an API key. External agents only have the wiki-index.renner.uno
BasicAuth credentials and got 401 since.

konairius/Wiki (feat/basic-auth-machines) checks `Authorization: Basic`
in the service against the htpasswd lines Traefik uses. This mounts the
existing Secret wiki-api-basic-auth (OpenBao apps/ai/wiki-index-basic-auth,
already the wiki's own) read-only at /var/run/secrets/wiki-basic-auth.
Auth__Basic__UsersPath points at the directory, because the service reads
every key there, as Traefik does. A rotated Secret now also rolls the pod
(reloader annotation).

Order does not matter: the current image ignores the setting, and the new
image without it authenticates nobody over BasicAuth. Traefik's middleware
on wiki-index stays.
2026-10-19 14:07:11 +00:00
k.renner 4a05b82fe8 Merge pull request 'test(hermes): raise dashboard WS ping interval to 60s' (#1385) from fix/hermes-dashboard-ws-ping-interval into main
ci/woodpecker/cron/e2e Pipeline failed
ci/woodpecker/cron/security-scan Pipeline was successful
ci/woodpecker/cron/issue-fix Pipeline was successful
ci/woodpecker/cron/alert-monitor Pipeline was successful
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/review-bot-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was canceled
Reviewed-on: #1385
2026-10-19 11:30:20 +00:00
hermes-bot 538a968edb test(hermes): raise dashboard WS ping interval to 60s
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
The dashboard console's /api/pty and /api/events WebSockets close
together every ~12-23 s (Traefik durations 18.9/21.8/22.7/22.8 s on
2026-10-19 11:14-11:19Z), the browser reports code 1006 and shows
"Please wait while the conversation loads…". The TUI process and
/api/status stay healthy meanwhile. The only ~20 s server timer found is
uvicorn's WS keepalive (dashboard.ws_ping_interval, default 20 s).

Diagnostic change: if socket lifetimes move to ~60 s the keepalive is
implicated; if they stay at ~20 s it is ruled out. Set via init container
like dashboard.trusted_proxies since there is no env equivalent.
2026-10-19 11:27:25 +00:00
k.renner 47592bd308 Merge pull request 'fix(hermes): request offline_access so the dashboard session refreshes' (#1384) from fix/hermes-dashboard-refresh-token into main
ci/woodpecker/cron/alert-monitor Pipeline was successful
Reviewed-on: #1384
2026-10-19 10:47:07 +00:00
hermes-bot 2d2959f32a fix(hermes): request offline_access so the dashboard session refreshes
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
The dashboard logged out exactly ~60 min after every login
(dashboard-auth.log: session_rejected reason=no_cookie at login+60m).
Hermes' self-hosted OIDC provider defaults to "openid profile email" and
the Authentik hermes-provider mapped only those scopes. Since authentik
2024.2 a refresh token is issued only when the client requests
offline_access and the provider has the offline_access scope mapping, so
Hermes never got one and could not rotate the session when the ID-token
cookie expired.

- authentik blueprint: add the managed scope-offline_access mapping to
  hermes-provider (refresh_token grant was already enabled).
- hermes: HERMES_DASHBOARD_OIDC_SCOPES adds offline_access.
2026-10-19 10:46:02 +00:00
k.renner d153d3e62e Merge pull request 'feat(wiki): wiki.renner.uno on plain Traefik, gate and header trust go (3/3)' (#1383) from feat/wiki-drop-gate into main
ci/woodpecker/cron/issue-fix Pipeline was successful
ci/woodpecker/cron/alert-monitor Pipeline was successful
Reviewed-on: #1383
2026-10-19 10:33:16 +00:00
security-bot de570ddf7c chore(image-automation): bump gitea.renner.uno/konairius/wiki:build.1792404861
ci/woodpecker/cron/alert-monitor Pipeline was successful
Updates managed by image-automation-controller.
2026-10-19 10:20:54 +00:00
k.renner 5a81930991 Merge pull request 'fix: [alert] FluxImageAutomationNotReady (cluster) (#1363)' (#1371) from alert-fix/issue-1363 into main
ci/woodpecker/cron/alert-monitor Pipeline was successful
Reviewed-on: #1371
2026-10-19 10:14:12 +00:00
k.renner 7f4ab6fc21 Merge pull request 'feat(wiki): Authentik OIDC application for the wiki's own login (1/3)' (#1382) from feat/wiki-oidc-provider into main
Reviewed-on: #1382
Reviewed-by: Review Bot <review-bot@renner.uno>
2026-10-19 10:07:25 +00:00
hermes-bot c659cc2bd6 feat(wiki): wiki.renner.uno on plain Traefik, the gate and header trust go
review-bot reviewed: comment
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
Stage 3 of 3. Merge only after konairius/Wiki feat/oidc-login is running
(Deployment image newer than build.1790322994 and `wiki-79948db4c6` gone):
the current image has no login of its own, so on plain Traefik its UI
would be open to the LAN.

- Ingress `wiki`: ingressClassName traefik instead of authentik-gate.
  authentik-gate-sync's sweep then deletes what it generated for the gate
  (Ingress/Service/CNP wiki-gate in ai, CNP gate-ai-wiki-c9ba6b in
  authentik, the ai-wiki-c9ba6b outpost, application and provider). One
  proxy layer fewer: Traefik -> wiki.
- Deployment: the Auth__ReverseProxy__TrustedProxies entries go. They were
  a hand copy of the Talos podSubnets, and the OIDC image no longer reads
  them.
- Middleware wiki-api-strip-identity goes. No header names a user any
  more; wiki-index.renner.uno keeps BasicAuth.
- Comments in ai-ns.yaml and the Authentik blueprint follow.

The `wiki` CNP already admits Traefik on 8080, and the ai namespace egress
already reaches Traefik, so auth.renner.uno (OIDC discovery, JWKS, token)
needs no new rule.
2026-10-19 09:47:23 +00:00
issue-fix-bot 853d2ba803 fix: [alert] FluxImageAutomationNotReady (cluster) (#1363)
review-bot reviewed: comment
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
2026-10-19 08:43:38 +00:00
7 changed files with 52 additions and 33 deletions
@@ -295,8 +295,8 @@ data:
name: llama-gate
state: absent
# Retired: wiki-gate. wiki.renner.uno is gated by authentik-gate-sync
# (kubernetes/apps/wiki/ingress.yaml).
# Retired: wiki-gate. The wiki signs humans in itself (application
# `wiki` in passkey-stepup.yaml).
- model: authentik_outposts.outpost
identifiers:
name: wiki-gate
@@ -1011,6 +1011,7 @@ data:
- !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-openid]]
- !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-profile]]
- !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-email]]
- !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-offline_access]]
redirect_uris:
- url: https://hermes.renner.uno/auth/callback
matching_mode: strict
+27
View File
@@ -71,6 +71,30 @@ spec:
volumeMounts:
- name: data
mountPath: /opt/data
# WebSocket keepalive ping interval in seconds (default 20).
- name: config-ws-ping
image: gitea.renner.uno/konairius/hermes:build.1792397861 # {"$imagepolicy": "flux-system:hermes"}
command:
- /opt/hermes/.venv/bin/hermes
- config
- set
- dashboard.ws_ping_interval
- "60"
env:
- name: HERMES_HOME
value: /opt/data
- name: HOME
value: /opt/data
securityContext:
runAsUser: 10000
runAsGroup: 10000
runAsNonRoot: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
volumeMounts:
- name: data
mountPath: /opt/data
# Skills from git (ConfigMap hermes-skills) beside the PVC's skills/.
- name: skills-config
image: gitea.renner.uno/konairius/hermes:build.1792397861 # {"$imagepolicy": "flux-system:hermes"}
@@ -140,6 +164,9 @@ spec:
value: https://auth.renner.uno/application/o/hermes/
- name: HERMES_DASHBOARD_OIDC_CLIENT_ID
value: hermes-dashboard
# offline_access: Authentik issues a refresh token only when requested.
- name: HERMES_DASHBOARD_OIDC_SCOPES
value: openid profile email offline_access
- name: API_SERVER_ENABLED
value: "true"
- name: API_SERVER_HOST
+11 -7
View File
@@ -24,7 +24,7 @@ metadata:
namespace: ai
annotations:
# Keys, tokens and the Anthropic key arrive via envFrom; a rotated Secret rolls the pod.
secret.reloader.stakater.com/reload: wiki-gitea,wiki-api-keys,wiki-typesafe,wiki-anthropic
secret.reloader.stakater.com/reload: wiki-gitea,wiki-api-keys,wiki-typesafe,wiki-anthropic,wiki-api-basic-auth
labels:
app.kubernetes.io/name: wiki
spec:
@@ -53,7 +53,7 @@ spec:
type: RuntimeDefault
containers:
- name: wiki
image: gitea.renner.uno/konairius/wiki:build.1790322994 # {"$imagepolicy": "flux-system:wiki"}
image: gitea.renner.uno/konairius/wiki:build.1792404861 # {"$imagepolicy": "flux-system:wiki"}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
@@ -77,11 +77,9 @@ spec:
value: https://auth.renner.uno/application/o/wiki/
- name: Auth__Oidc__ClientId
value: wiki
# Pod networks: the CNPs admit only the gate outpost and Gitea.
- name: Auth__ReverseProxy__TrustedProxies__0
value: fd10:244::/48
- name: Auth__ReverseProxy__TrustedProxies__1
value: 10.244.0.0/16
# wiki-index BasicAuth users (htpasswd), checked by the service for the read API.
- name: Auth__Basic__UsersPath
value: /var/run/secrets/wiki-basic-auth
envFrom:
- secretRef:
name: wiki-gitea
@@ -127,12 +125,18 @@ spec:
mountPath: /data
- name: tmp
mountPath: /tmp
- name: basic-auth
mountPath: /var/run/secrets/wiki-basic-auth
readOnly: true
volumes:
- name: data
persistentVolumeClaim:
claimName: wiki-data
- name: tmp
emptyDir: {}
- name: basic-auth
secret:
secretName: wiki-api-basic-auth
---
apiVersion: v1
kind: Service
+1 -1
View File
@@ -87,7 +87,7 @@ spec:
key: apps/ai/wiki-anthropic
property: api_key
---
# BasicAuth users for the machine door; same OpenBao key as the Python service used.
# BasicAuth users for the machine door, read by Traefik and by the service; same OpenBao key as the Python service used.
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
+6 -18
View File
@@ -1,7 +1,6 @@
# wiki.renner.uno — LAN-only (no dns.renner.uno/public label). Gated by
# authentik-gate-sync (ingress class authentik-gate); the service trusts
# X-Authentik-Username only from pod addresses, and the generated CNP admits
# only the gate outpost.
# wiki.renner.uno — LAN-only (no dns.renner.uno/public label). Plain Traefik:
# the service signs humans in itself with OIDC (application `wiki` in
# apps/authentik/blueprints-configmap.yaml).
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
@@ -10,7 +9,7 @@ metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-cluster
spec:
ingressClassName: authentik-gate
ingressClassName: traefik
tls:
- hosts:
- wiki.renner.uno
@@ -28,8 +27,7 @@ spec:
number: 8080
---
# wiki-index.renner.uno — the machine door (bin/wiki_rank.py, wiki_ask.py):
# Traefik BasicAuth, and the identity header stripped so only the outpost path
# can carry X-Authentik-Username to the service.
# Traefik BasicAuth; the service checks the same credentials itself.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
@@ -40,16 +38,6 @@ spec:
secret: wiki-api-basic-auth
realm: wiki
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: wiki-api-strip-identity
namespace: ai
spec:
headers:
customRequestHeaders:
X-Authentik-Username: ""
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
@@ -57,7 +45,7 @@ metadata:
namespace: ai
annotations:
cert-manager.io/cluster-issuer: letsencrypt-cluster
traefik.ingress.kubernetes.io/router.middlewares: ai-wiki-api-strip-identity@kubernetescrd,ai-wiki-api-basic-auth@kubernetescrd
traefik.ingress.kubernetes.io/router.middlewares: ai-wiki-api-basic-auth@kubernetescrd
spec:
ingressClassName: traefik
tls:
@@ -4,7 +4,7 @@ metadata:
name: gitea-mcp
namespace: flux-system
spec:
image: docker.gitea.com/gitea-mcp-server@sha256:20701c3dcf3b71df384417d04f9f6382205b7f362380b258fb8e4dcf9599091f
image: docker.gitea.com/gitea-mcp-server
interval: 1h
---
apiVersion: image.toolkit.fluxcd.io/v1
@@ -140,10 +140,9 @@ spec:
- port: "8080"
protocol: TCP
---
# wiki: Traefik (the machine door wiki-index.renner.uno, BasicAuth with
# X-Authentik-Username stripped), Gitea (push webhook) and Hermes Agent (API
# key) may reach it; the gate outpost (humans, after Authentik) is admitted
# by the CNP wiki-gate that authentik-gate-sync generates. Gitea and wiki-embed
# wiki: Traefik (wiki.renner.uno, OIDC login in the service, and the machine
# door wiki-index.renner.uno, BasicAuth), Gitea (push webhook) and Hermes Agent
# (API key) may reach it. Gitea, wiki-embed and auth.renner.uno (via Traefik)
# are reached through the namespace egress above; no OpenBao access.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy