CVE-2026-109618 and CVE-2026-109619 (BSI BITS-H 2026-297981-1132) allow
unauthenticated RCE on every PHP before 8.5.12/8.4.27/8.3.36/8.2.35;
mod_php is the highest-risk variant. The running pod reports PHP 8.3.35
and www.renner.uno serves / to the internet without the Authentik gate.
Switch to the php8.5-apache variant of the same WordPress release,
pinned to the index digest rebuilt on 2026-10-22 after the PHP fix.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Flux source URL, flux-git rotator verify repo, review-bot REPOS, pipeline API,
clone and push URLs, the heating-can source label and the review-bot and
kuma-sync Go module paths. Merge right after the transfer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Homelab moves to konairius/homelab; after the Woodpecker move its pipelines
resolve org secrets in konairius. The k.renner containers stay until the move
is done.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Switches apps/hermes to gitea.renner.uno/gitea_admin/hermes, which
carries talosctl, kubectl, flux, bao, tea and jq in /usr/local/bin. The
image-automation policy now tracks its build.<unix-ts> tags instead of
upstream nousresearch/hermes-agent; .woodpecker/hermes-image.yml follows
upstream releases.
Drops the kubectl init container and its emptyDir: the binary sat in
/opt/data/.local/bin, which the agent's terminal does not have on PATH.
One group per own service with application-level checks (json-query on
health/API endpoints where ungated, keyword otherwise) and a Third-party
group with plain checks. Endpoints verified from the Kuma VPS.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The owner placed hermes-bot's API token at OpenBao apps/hermes/gitea
(api-token). ExternalSecret hermes-gitea mounts it as a file at
/var/run/secrets/gitea/api-token.
git is configured through GIT_CONFIG_* env on the container, so nothing
lives on the PVC: a credential helper for https://gitea.renner.uno that
answers with hermes-bot and the token read from the file, plus the
commit identity hermes-bot <hermes-bot@konstantin-renner.de>. Hermes'
subprocess env scrub only strips its own provider/messaging secrets, so
GIT_* reaches the terminal tool.
SOUL.md drops "no write access" and tells the agent how to use git and
the REST API (no tea in the image) without printing the token; the
existing feature-branch/PR/no-self-merge rules apply.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
apps/hermes sets namespaces per resource, not in the kustomization, so
configMapGenerator emitted hermes-soul and hermes-skills without one and
the Flux apply failed ("namespace not specified"). The earlier
server-side dry-run masked it by defaulting to the current namespace.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SOUL.md comes from git (ConfigMap hermes-soul, subPath over the PVC
copy): the stock persona plus the homelab's working rules distilled
from Claude Code's global CLAUDE.md and feedback memory — wiki first,
the verification ladder, the network/DNS/placement/secret design rules,
operational change discipline and how to work with the owner. Claude
Code harness specifics (Bash allowlisting, subagent sizing, worktrees,
claude-bot identities) are left out.
The homelab-wiki skill (ConfigMap hermes-skills, mounted at
/opt/hermes-skills and registered via skills.external_dirs) wraps the
wiki service API in a stdlib Python client, since the image has no
bash or jq. Hermes calls the in-cluster service directly with its own
API key, identity `hermes`:
- apps/hermes/wiki -> Secret hermes-wiki, mounted as a file (optional,
so the pod starts before it is seeded; reads are anonymous)
- apps/ai/wiki-api-key-hermes -> Auth__ApiKeys__hermes on the wiki. A
separate path rather than a field in apps/ai/wiki-api-keys, because
claude-bot's OpenBao policy is write-only and a put on the shared path
would drop the workstation key.
- CNPs: hermes egress to ai/wiki:8080, wiki ingress from hermes
- hermes added to the openbao ClusterSecretStore allowlist
The built-in memory store (2200/1375 chars, agent-rewritten) is left to
the agent.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kuma-setup.js now logs in after the admin setup and converges on every run:
- settings: Trust Proxy on, Primary Base URL https://kuma.renner.uno.
Read-modify-write; unset keys get the same defaults the Kuma settings page
applies before saving (a raw getSettings payload has nscd unset, which makes
setSettings stop nscd).
- notification "email" (SMTP, default enabled, applied to existing monitors):
created or updated in place by name, never duplicated. Credentials from
OpenBao homelab/infrastructure/uptime-kuma/smtp; recipient is the
Alertmanager receiver admin@renner.uno; 465 means implicit TLS, else STARTTLS.
- status page "renner" / "Renner" with custom domain uptime.renner.uno. Only
title and domain are enforced; saveStatusPage replaces all groups, so the
current publicGroupList from /api/status-page/<slug> is sent back unchanged.
Steady state does not call saveStatusPage at all.
- metrics API key "prometheus": Ansible checks the key stored at
homelab/infrastructure/uptime-kuma-metrics against /metrics; if it is
missing or rejected the script deletes all "prometheus" keys, creates a new
one and hands it over via a 0600 file in the data dir, which Ansible writes
to OpenBao (vault_kv2_write, community.hashi_vault 7.1.0 in the CI image)
and then removes. The key never reaches stdout/stderr or the Ansible log.
The script is restructured into small async steps with per-emit timeouts.
The uptime-kuma-vps policy gains read on the smtp path and
read/create/update on the metrics path (must be applied by hand).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nousresearch/hermes-agent still carries v2026.4.3..v2026.9.24 from the
old date-based scheme. As semver they sort above 0.x, so '>=0.22.2'
picked v2026.9.24 (2026-09-24) and rolled the pod back from v0.22.2.
Cap the range below 1.0.0 and pin the manifests back to v0.22.2.
Add a blackbox-http probe of kuma.renner.uno with a dedicated critical
UptimeKumaUnreachable rule (excluded from BlackboxProbeFailing), scrape
Kuma /metrics with the API key from OpenBao, and alert on sustained slow
monitor response times. No egress policy exists in the monitoring
namespace, so no CNP change is needed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hermes Agent as a pod in its own `hermes` namespace: gateway (messaging
platforms, cron, OpenAI-compatible API) and dashboard, supervised by the
image's s6-overlay, state on a 10Gi ceph-block PVC.
- hermes.renner.uno (LAN): dashboard and Hermes Desktop remote gateway.
Plain Traefik plus the dashboard's own Authentik OIDC login (public PKCE
client, Hermes Users group) — a forward-auth gate would break Desktop's
Bearer-token calls.
- hermes-api.renner.uno (LAN): API server, Bearer key generated in-cluster
by an ESO Password generator.
- Read-only kubectl via the built-in `view` ClusterRole.
- CNPs: world 443/80, kube-apiserver, Traefik for LAN hostnames, and
Prometheus/Alertmanager/Loki (with the matching monitoring-side grant).
- Image automation for nousresearch/hermes-agent v-tags.
After deploy: log in to Anthropic inside the pod
(`hermes auth add anthropic --type oauth --no-browser`, then `hermes model`);
platform and Home Assistant tokens go in via the dashboard.
Not yet covered: a Velero schedule for the PVC.
Last smoke-test step: Flux prunes the KumaMonitor and the controller's
finalizer deletes Kuma monitor 9.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keyword check on https://www.renner.uno/ (page title "Familie Renner")
with certificate-expiry notification. Exercises create, tagging,
restart adoption and deletion against the live Kuma; removed from git
again as the last smoke-test step.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Namespace, CRD (Flux prune disabled so a prune never cascades into
deleting every Kuma monitor via finalizers), cluster RBAC matching the
controller-gen role, Recreate Deployment of the first master build
(2026-10-19-0545) under image automation, and a default-deny
CiliumNetworkPolicy allowing only DNS, the kube-apiserver and
kuma.renner.uno:443 out, kubelet probes in.
The Kuma login comes from its own OpenBao path infrastructure/kuma-sync
(a copy of the single Kuma admin account) rather than reading
infrastructure/uptime-kuma.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AutoKuma 2.0.0 never applied its ownership tag against Uptime Kuma 2.5.6, so a pod restart with empty /data duplicated every managed monitor (pilot step 5). Replaced by an in-house controller under a separate plan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The flux-image-automation Alert forwarded every info event from
ImageUpdateAutomation (i.e. each successful bump commit) to Alertmanager,
which emailed it as FluxImageUpdateAutomationSucceeded. A success is not
a problem and must not be an alert; the commits are in git history.
Image-automation failures still alert: flux-failures covers
ImageUpdateAutomation at error severity. The Alertmanager source="flux"
route stays for those; its comment now says so.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace world:443 with toFQDNs kuma.renner.uno:443; the kube-dns rule gains
rules.dns so Cilium learns the name-to-IP mapping.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>