Bug Description
When running the nousresearch/hermes-agent Docker image with -v ~/.hermes:/opt/data, the gateway process starts without HERMES_HOME in its environment. This causes get_hermes_home() to fall back to ~/.hermes (resolved as /opt/data/.hermes for the hermes user), creating a nested .hermes/ directory inside the mounted volume. User configuration placed in the top-level .env and config.yaml is silently ignored by the gateway.
Steps to Reproduce
- Start the container with a mounted volume:
docker run -d --name hermes \
-v ~/.hermes:/opt/data \
nousresearch/hermes-agent gateway run
- Set
GATEWAY_ALLOW_ALL_USERS=true in the host's ~/.hermes/.env
- Check the gateway log:
docker exec hermes grep "No user allowlists" /opt/data/.hermes/logs/gateway.log
- Note the warning persists despite the env var being set
Expected Behavior
- Gateway should load config from
/opt/data/.env and /opt/data/config.yaml
GATEWAY_ALLOW_ALL_USERS=true in ~/.hermes/.env should be respected
- Logs should go to
/opt/data/logs/gateway.log
- No duplicate
.hermes/ directory should be created inside the mounted volume
Actual Behavior
- Gateway writes logs to
/opt/data/.hermes/logs/gateway.log instead of /opt/data/logs/gateway.log
- Environment variables in
/opt/data/.env (e.g., GATEWAY_ALLOW_ALL_USERS=true) are not seen by the gateway
- A duplicate
.hermes/ data directory is silently created inside the mounted volume
- The warning "No user allowlists configured" appears despite
GATEWAY_ALLOW_ALL_USERS=true being set
docker exec CLI sessions correctly inherit HERMES_HOME=/opt/data, but the gateway (Docker CMD) does not
- The two data directories diverge independently, making diagnosis extremely difficult
Affected Component
- Configuration (config.yaml, .env, hermes setup)
- Gateway (Telegram/Discord/Slack/WhatsApp)
Messaging Platform
Operating System
Docker container (windows)
Hermes Version
Latest (nousresearch/hermes-agent with s6-overlay)
Additional Logs / Traceback
- Gateway logs appear at
/opt/data/.hermes/logs/gateway.log (wrong path)
docker exec <container> cat /proc/<gateway_pid>/environ | tr '\0' '\n' | grep HERMES_HOME returns nothing
Root Cause Analysis
The container uses s6-overlay for process supervision. The Docker CMD runs as the "main program" (not an s6-supervised service), so it does NOT go through the with-contenv mechanism that loads container environment variables into service processes.
The startup chain is:
rc.init → main-wrapper.sh → exec s6-setuidgid hermes → hermes gateway run
main-wrapper.sh sources the venv activate script (/opt/hermes/.venv/bin/activate), which sets PATH and VIRTUAL_ENV but does not set HERMES_HOME. When exec s6-setuidgid hermes performs the privilege drop to the hermes user, the HERMES_HOME variable from the container environment (/run/s6/container_environment/HERMES_HOME) is not propagated.
Docker's -e HERMES_HOME=/opt/data writes to /run/s6/container_environment/, which is only loaded by s6-supervised services via with-contenv. The main program (Docker CMD) does not pick them up.
Proposed Fix
In /opt/hermes/docker/main-wrapper.sh, explicitly export HERMES_HOME before the exec s6-setuidgid call:
cd /opt/data
. /opt/hermes/.venv/bin/activate
+# Explicitly propagate container environment variables through s6-setuidgid.
+# In s6-overlay, the Docker CMD runs outside the with-contenv mechanism, so
+# container env vars from /run/s6/container_environment/ are NOT inherited.
+_HERMES_HOME="${HERMES_HOME:-/opt/data}"
+export HERMES_HOME="$_HERMES_HOME"
+export PATH VIRTUAL_ENV
+
if [ $# -eq 0 ]; then
exec s6-setuidgid hermes hermes
fi
This ensures the gateway process inherits HERMES_HOME regardless of how it was launched.
Bug Description
When running the
nousresearch/hermes-agentDocker image with-v ~/.hermes:/opt/data, the gateway process starts withoutHERMES_HOMEin its environment. This causesget_hermes_home()to fall back to~/.hermes(resolved as/opt/data/.hermesfor thehermesuser), creating a nested.hermes/directory inside the mounted volume. User configuration placed in the top-level.envandconfig.yamlis silently ignored by the gateway.Steps to Reproduce
docker run -d --name hermes \ -v ~/.hermes:/opt/data \ nousresearch/hermes-agent gateway runGATEWAY_ALLOW_ALL_USERS=truein the host's~/.hermes/.envExpected Behavior
/opt/data/.envand/opt/data/config.yamlGATEWAY_ALLOW_ALL_USERS=truein~/.hermes/.envshould be respected/opt/data/logs/gateway.log.hermes/directory should be created inside the mounted volumeActual Behavior
/opt/data/.hermes/logs/gateway.loginstead of/opt/data/logs/gateway.log/opt/data/.env(e.g.,GATEWAY_ALLOW_ALL_USERS=true) are not seen by the gateway.hermes/data directory is silently created inside the mounted volumeGATEWAY_ALLOW_ALL_USERS=truebeing setdocker execCLI sessions correctly inheritHERMES_HOME=/opt/data, but the gateway (Docker CMD) does notAffected Component
Messaging Platform
Operating System
Docker container (windows)
Hermes Version
Latest (
nousresearch/hermes-agentwith s6-overlay)Additional Logs / Traceback
/opt/data/.hermes/logs/gateway.log(wrong path)docker exec <container> cat /proc/<gateway_pid>/environ | tr '\0' '\n' | grep HERMES_HOMEreturns nothingRoot Cause Analysis
The container uses s6-overlay for process supervision. The Docker CMD runs as the "main program" (not an s6-supervised service), so it does NOT go through the
with-contenvmechanism that loads container environment variables into service processes.The startup chain is:
main-wrapper.shsources the venv activate script (/opt/hermes/.venv/bin/activate), which setsPATHandVIRTUAL_ENVbut does not setHERMES_HOME. Whenexec s6-setuidgid hermesperforms the privilege drop to thehermesuser, theHERMES_HOMEvariable from the container environment (/run/s6/container_environment/HERMES_HOME) is not propagated.Docker's
-e HERMES_HOME=/opt/datawrites to/run/s6/container_environment/, which is only loaded by s6-supervised services viawith-contenv. The main program (Docker CMD) does not pick them up.Proposed Fix
In
/opt/hermes/docker/main-wrapper.sh, explicitly exportHERMES_HOMEbefore theexec s6-setuidgidcall:This ensures the gateway process inherits
HERMES_HOMEregardless of how it was launched.