Sparround

Enterprise rollout: managed scope and hardening

The difference between personal use and an enterprise rollout is one question: which setting must a user not be able to change? Hermes answers it with a managed scope layer: a config.yaml and .env at system level (by default /etc/hermes) are controlled by the administrator and override the user's ~/.hermes/ settings.

Merging is leaf-level: only the keys you name are pinned. Pinning model.default does not freeze the rest of model.*.

The enforcement mechanism is not complicated: filesystem permissions. The managed files are root-owned and world-readable but writable only by an administrator. When a user tries to change a pinned value, Hermes refuses explicitly and names the file that governs it.

The limitations in the docs are stated plainly and are worth knowing: the managed .env is world-readable (so it is not suitable for sensitive secrets), the agent can change environment values within its own subprocess shell, tool and command allow-deny lists are not part of this layer, and native macOS/Windows support is out of scope for this version.

StepWhat you doWhy
1Set explicit allowlists; never use `GATEWAY_ALLOW_ALL_USERS`Stops the bot from being left open
2Choose `terminal.backend: docker`A mistake's damage stays in the container
3Set CPU, memory and disk limitsPrevents resource exhaustion
4Keep keys in `~/.hermes/.env` with `chmod 600`Stops secrets from being read
5Review `command_allowlist` periodicallyPermissions accumulate over time
6Set `terminal.cwd`; never run as rootConstrains the working area
7Monitor logs and update with `hermes update`Unauthorised attempts and security patches

Two more tools: hermes security audit checks supply-chain vulnerabilities against OSV.dev, and the built-in advisory scanner reports poisoned Python packages at CLI startup, in hermes doctor and at gateway startup (dismiss one permanently with hermes doctor --ack <id>).

There is also security.allow_lazy_installs: by default some optional dependencies are installed on first use. In a strict environment setting it to false — requiring that nothing installs at runtime — is the right call.

Practice. Prepare a managed configuration file for a pilot: pin the model provider, approvals.mode, terminal.backend and the website blocklist. Then, as an ordinary user, try to change one of them. Done means: you see the refusal message, and it names the file that governs the value.

📚 Sources and documentation