You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: document the upstream s6 runtime, security/SCC tradeoff, provider config
- README: correct the now-false claims (read-only rootfs, uv-sync init container,
tini PID 1). Describe the FROM-upstream s6 image (gateway + OpenAI API server +
dashboard + Playwright browser + deps), the root-start→drop-to-1000 security
posture and its OpenShift SCC implication, the /opt/data state path, /health on
8443, and the spec.config.raw + spec.env provider-config pattern.
- docs/runtime.md (new): "Agent runtime" page covering the image, how the operator
runs it, the security/SCC tradeoff, and provider configuration. Linked from
docs/index.md and the mkdocs Operations nav.
- docs/api-reference-generated.md: regenerated for the ShareProcessNamespace
default/doc change (keeps the API Docs Sync check green).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
If you omit `spec.config.raw.model`, the operator injects a non-routable placeholder
73
+
so the gateway and API server still come up (and `/health` passes) without making
74
+
live LLM calls; inference then fails clearly until a real provider is set. Each
75
+
instance also gets an operator-managed random `api_server_key` (in its
76
+
`<name>-gateway-tokens` Secret) that authenticates the OpenAI-compatible
77
+
`/v1/...` API; `/health` is unauthenticated. See [Agent runtime](docs/runtime.md).
78
+
60
79
For more involved scenarios, see [`examples/`](examples/).
61
80
62
81
## Architecture
@@ -87,7 +106,7 @@ flowchart LR
87
106
STS[StatefulSet]
88
107
Svc[Service]
89
108
NetPol[NetworkPolicy default-deny]
90
-
PVC[PVC ~/.hermes]
109
+
PVC[PVC /opt/data]
91
110
Honcho[Honcho Deploy<br/>profile store]
92
111
CronJob[Backup CronJob]
93
112
end
@@ -132,7 +151,7 @@ fields only: explicit values on the instance always win.
132
151
|**Adaptive**|`HermesSelfConfig` for audited agent-initiated mutations | SSA under field manager `hermes.agent/selfconfig`. Policy-gated by `spec.selfConfigure.protectedKeys`. |
|**Secure**|Hardened container security context | The upstream s6 runtime starts as root so `/init` (PID 1) can remap the in-image user to uid/gid 1000 and chown `/opt/data`, then every service drops to uid 1000 via `s6-setuidgid`. `allowPrivilegeEscalation=false`, `fsGroup=1000`, and seccomp `RuntimeDefault` remain; `runAsNonRoot`/read-only rootfs/drop-ALL-caps are not set (s6 needs `CHOWN`/`SETUID`/`SETGID`/`DAC_OVERRIDE`/`FOWNER` and a writable `/run`). Requires an SCC that permits a root-start container (e.g. `anyuid`); incompatible with OpenShift `restricted`/`restricted-v2`. See [Agent runtime](docs/runtime.md). |
136
155
|**Secure**| Optional Tailscale Serve sidecar | Per-instance MagicDNS hostname + Tailscale TLS cert, no LoadBalancer/Ingress. See [Tailscale Serve](#tailscale-serve). |
137
156
|**Secure**| Per-CRD validating + defaulting webhooks | Plus warnings on unknown config keys and unresolvable gateway tokens. |
138
157
|**Secure**| RBAC aggregation labels |`kubectl auth can-i create hermesinstances --as=jane` works out of the box. |
@@ -141,13 +160,13 @@ fields only: explicit values on the instance always win.
141
160
|**Observable**|[Grafana dashboard](docs/grafana/)| Ships as JSON. Variables: `namespace`, `instance`. |
142
161
|**Observable**| Exhaustive [condition catalogue](docs/conditions.md)| Every condition × every reason code, documented and stable. |
|**Python runtime**|`uv`-installable agent runtime | Init container runs `uv sync`against a lockfile bundled in the agent image. |
145
-
|**Python runtime**| FFmpeg + ripgrepavailable out of the box |Hard dependencies of hermes-agent. |
163
+
|**Upstream runtime**|Ships the supported NousResearch/hermes-agent s6 image | The published `ghcr.io/paperclipinc/hermes-agent` is built `FROM` the upstream image (pinned by digest). It bundles the gateway, dashboard, OpenAI-compatible API server, a Playwright/Chromium browser, node, ffmpeg, and all Python deps. No init-container venv build — the old `uv sync`/ `init-apt`/`init-uv`/`init-pip` chain is gone. See [Agent runtime](docs/runtime.md). |
164
+
|**Upstream runtime**| FFmpeg, ripgrep, browser, node available out of the box |Bundled in the upstream hermes-agent image. |
146
165
|**Scalable**| Optional HPA via `spec.availability.hpa`| StatefulSet retained for identity through restarts. |
147
166
|**Scalable**| Optional `topologySpreadConstraints`| Sane defaults plus `spec.availability.topologySpreadConstraints` override. |
148
167
|**Resilient**| PodDisruptionBudget auto-managed when `replicas > 1`||
149
168
|**Resilient**| Finalizer-driven backup-on-delete |`r.Patch` (JSON patch) for finalizer mutations, never `r.Update`. |
150
-
|**Resilient**| Zombie-process reaper |`tini` as PID 1; `shareProcessNamespace: false` by default. |
169
+
|**Resilient**| Zombie-process reaper |s6-overlay `/init` as PID 1 reaps zombies; `shareProcessNamespace: false` by default (its `/init` must be PID 1). |
|`scheduling`_[SchedulingSpec](#schedulingspec)_| Scheduling targets the agent pod at specific nodes. || Optional: \{\} <br /> |
410
-
|`shareProcessNamespace`_boolean_| ShareProcessNamespace enables PID namespace sharing between all containers<br />in the pod. When true (the default), the infrastructure (pause) container<br />becomes PID 1 and reaps zombie processes, preventing accumulation of defunct<br />helper processes (git, plugins, shells) spawned under the agent entrypoint<br />when it does not call waitpid().<br />Security note: enabling this lets every container in the pod see and signal<br />every other container's processes. A compromised sidecar could send signals<br />to the agent and vice versa. Set to false to keep per-container PID isolation;<br />you are then responsible for reaping zombies (e.g. by baking tini or dumb-init<br />into the image). | true| Optional: \{\} <br /> |
410
+
|`shareProcessNamespace`_boolean_| ShareProcessNamespace enables PID namespace sharing between all containers<br />in the pod. Defaults to false: the upstream hermes-agent image runs under<br />s6-overlay, whose /init must be PID 1 (s6-overlay-suexec aborts otherwise),<br />and s6 already reaps zombies non-blocking on SIGCHLD — so sharing the process<br />namespace (which makes the pause container PID 1) is both incompatible and<br />unnecessary.<br />Security note: enabling this lets every container in the pod see and signal<br />every other container's processes. A compromised sidecar could send signals<br />to the agent and vice versa. Leave false to keep per-container PID isolation. | false| Optional: \{\} <br /> |
411
411
|`initContainers`_[Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#container-v1-core) array_| InitContainers is a user-supplied list of init containers appended after<br />any operator-managed init containers (e.g. runtime-init from Plan 3). || Optional: \{\} <br /> |
412
412
|`sidecars`_[Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#container-v1-core) array_| Sidecars is a user-supplied list of sidecars appended after operator-managed<br />sidecars (e.g. ollama / web-terminal / tailscale from Plan 3). || Optional: \{\} <br /> |
413
413
|`extraVolumes`_[Volume](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.31/#volume-v1-core) array_| ExtraVolumes is a user-supplied list of additional pod volumes. || Optional: \{\} <br /> |
Copy file name to clipboardExpand all lines: docs/index.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,6 +12,7 @@ This site is the rendered documentation for the operator. The source of truth fo
12
12
13
13
## Operations
14
14
15
+
-[Agent runtime](runtime.md) explains the upstream s6 image, how the operator runs it, the `/opt/data` state path, the security/SCC tradeoff, and LLM provider configuration.
15
16
-[Conditions](conditions.md) documents the status conditions the operator sets.
16
17
-[Backup and restore](backup-restore.md) and the [backup format](backup-format.md) cover data protection.
17
18
-[Auto-update](autoupdate.md) describes registry polling and rollback.
0 commit comments