Skip to main content

Configuration reference

Hermeum is configured entirely through HERMEUM_* environment variables. The Hermeum reads them once at startup via a Zod schema (apps/app/src/server/libs/config.ts); invalid or missing required values fail fast with a parse error before the server binds a port.

The Helm chart maps these to secrets.* (sensitive) and config.* (non-sensitive) values — see Installation. Every variable below is optional unless marked required.

Environment variables

Required variables must be set or the Hermeum pod refuses to start. All others fall back to the defaults listed here.

Core

VariableDefaultDescription
HERMEUM_DATABASE_URLConnection URL for the Hermeum database. For sqlite use file:/path/to/db.sqlite; for postgres use a postgres:// URL. See Database.
HERMEUM_DATABASE_DIALECTsqliteDatabase backend dialect. One of sqlite, postgres. Must match the scheme of HERMEUM_DATABASE_URL.
HERMEUM_KUBERNETES_NAMESPACEhermeumKubernetes namespace where HermesAgent custom resources are reconciled. Hermeum must have RBAC to read/write this namespace.
HERMEUM_CONFIG_PATH./config.yamlPath to the Hermeum instance config file. See Instance config for the schema.
HERMEUM_HERMES_DOCS_PATH./docs/hermes-configPath to the hermes-config docs directory used by the docs file adaptor.
HERMEUM_LOG_LEVELinfoLog verbosity. One of debug, info, warn, error.

Agent image

The container image emitted into every HermesAgent CR's spec.image.

VariableDefaultDescription
HERMEUM_HERMES_IMAGE_REPOSITORYnousresearch/hermes-agentContainer image repository for the Hermes agent. Omit the registry host for Docker Hub, or include it (e.g. ghcr.io/hermeum/hermes-agent) for other registries.
HERMEUM_HERMES_IMAGE_TAGv2026.7.7.2Container image tag for the Hermes agent. Pin to a specific release for reproducible agent pods.

Auth

Better Auth email/password, allowed email domains, and outgoing SMTP. Better Auth's own secret (BETTER_AUTH_SECRET) is provided via Helm secrets.* and is not a HERMEUM_* variable.

VariableDefaultDescription
HERMEUM_SMTP_URLSMTP server URL for outgoing email (e.g. smtps://user:pass@smtp.example.com:465). Optional.
HERMEUM_ALLOWED_EMAIL_DOMAINRestrict sign-ups to this email domain (e.g. example.com). Optional; when unset, any domain is accepted.

AI config generator

The AI config generator uses an OpenAI-compatible chat completion endpoint to draft agent config.yaml blocks from natural-language prompts.

VariableDefaultDescription
HERMEUM_OPENAI_MODELgpt-5.5Model id passed to the completion call. Must be a model the configured endpoint serves.
HERMEUM_OPENAI_BASE_URLOverride the OpenAI API base URL. Point this at any OpenAI-compatible gateway (vLLM, Ollama, Azure OpenAI, etc.). When unset, the OpenAI default is used.
HERMEUM_OPENAI_API_KEYAPI key for the OpenAI-compatible endpoint. Required when targeting the hosted OpenAI API; may be unused for local gateways.

Per-agent ingress

When HERMEUM_AGENT_INGRESS_BASE_HOSTNAME is set, Hermeum emits an Ingress per agent at <agent-id>.<base hostname>, routing to the agent's enabled HTTP platforms (api-server /v1, /api; webhook /webhooks; teams /api/messages). When it is unset, no ingress is generated.

VariableDefaultDescription
HERMEUM_AGENT_INGRESS_BASE_HOSTNAMEBase hostname for per-agent ingresses (<agent-id>.<base>). Unset = no ingress generated.
HERMEUM_AGENT_INGRESS_SCHEMEhttpPublic URL scheme advertised for agent ingresses. Display-only — it does not drive the emitted tls block; TLS is governed by HERMEUM_AGENT_INGRESS_TLS_SECRET_NAME.
HERMEUM_AGENT_INGRESS_CLASS_NAMEIngress controller class name set on generated ingresses (spec.ingressClassName). Omitted from the CR when unset.
HERMEUM_AGENT_INGRESS_TLS_SECRET_NAMETLS secret name for controller-terminated TLS. When set, the ingress emits a tls block with this secret; when unset, no tls block is emitted (covers plain HTTP and load-balancer-terminated TLS).

See Per-agent ingress and TLS for end-to-end TLS topologies.

Web server

Hermeum's own HTTP(S) listener.

VariableDefaultDescription
HERMEUM_PORT3000Port the web server listens on.
HERMEUM_HMR_PORT3001Port used by Vite's HMR websocket in dev. Ignored in production.
HERMEUM_TLS_CERT_FILEPath to the web TLS cert file (PEM). When set with HERMEUM_TLS_KEY_FILE, the web server serves HTTPS on HERMEUM_PORT.
HERMEUM_TLS_KEY_FILEPath to the web TLS key file (PEM). Pair with HERMEUM_TLS_CERT_FILE.

Webhook

The mutating admission webhook's HTTPS listener. It only starts when both HERMEUM_WEBHOOK_TLS_CERT_FILE and HERMEUM_WEBHOOK_TLS_KEY_FILE are set; otherwise the webhook is not served.

VariableDefaultDescription
HERMEUM_WEBHOOK_PORT8443HTTPS port for the mutating admission webhook. Only used when the webhook TLS cert and key are set.
HERMEUM_WEBHOOK_TLS_CERT_FILEPath to the mutating webhook TLS cert file (PEM). Pair with HERMEUM_WEBHOOK_TLS_KEY_FILE to start the webhook listener.
HERMEUM_WEBHOOK_TLS_KEY_FILEPath to the mutating webhook TLS key file (PEM). Pair with HERMEUM_WEBHOOK_TLS_CERT_FILE.

See Mutating webhook for how the webhook is wired into the cluster and how its caBundle gets populated.

RBAC notes

Hermeum runs as a Kubernetes controller for HermesAgent CRs inside HERMEUM_KUBERNETES_NAMESPACE. The chart's ServiceAccount grants the following scoped permissions:

  • hermesagents (custom resource): full CRUD within the configured namespace — Hermeum creates, patches, and finalizes agent CRs.
  • secrets: read/write within the namespace, used to materialize per-agent image-pull secrets and TLS material referenced by ingresses.
  • ingresses (networking.k8s.io): create/update/delete within the namespace when per-agent ingresses are enabled (HERMEUM_AGENT_INGRESS_BASE_HOSTNAME set).
  • pods / pods/log: read, for status display and log streaming from agent pods.

When per-agent ingress is disabled (no base hostname), the ingresses grant is unused in practice. If you deploy the chart into a namespace you do not own and instead grant a narrower Role manually, ensure the four resource groups above are still covered or the corresponding features will return RBAC forbidden errors at runtime.

The mutating admission webhook is served by the same pod but on a separate port (HERMEUM_WEBHOOK_PORT); it is authorized through the MutatingWebhookConfiguration's clientConfig.service path, not through the pod ServiceAccount.