Summary
hermes gateway install --system generates a unit file whose ExecStart points at the base uv-managed Python interpreter instead of the project's venv Python. Because all Hermes runtime dependencies (PyYAML, etc.) are installed into the venv's site-packages, the service crash-loops on startup with ModuleNotFoundError: No module named 'yaml'.
Environment
- Ubuntu 24.04
- Hermes Agent v0.8.0 (2026.4.8)
- Installed via the standard installer (uv-managed Python + project venv at
/root/.hermes/hermes-agent/venv)
- Running as root on a VPS (
--run-as-user root)
Repro
- Fresh install Hermes on Ubuntu 24.04 as root.
hermes gateway install --system --run-as-user root
hermes gateway start --system
journalctl -u hermes-gateway -f
Observed:
python3.11[...]: ModuleNotFoundError: No module named 'yaml'
systemd[1]: hermes-gateway.service: Main process exited, code=exited, status=1/FAILURE
Root cause
The generated unit file at /etc/systemd/system/hermes-gateway.service contains:
ExecStart=/root/.local/share/uv/python/cpython-3.11.15-linux-x86_64-gnu/bin/python3.11 -m hermes_cli.main gateway run --replace
Environment="VIRTUAL_ENV=/root/.hermes/hermes-agent/venv"
Environment="PATH=/root/.hermes/hermes-agent/venv/bin:..."
The unit correctly sets VIRTUAL_ENV and puts venv/bin on PATH, but ExecStart bypasses both by hard-coding an absolute path to the base uv interpreter. Invoking the base Python directly does not pick up the venv's site-packages, so none of the installed Hermes dependencies are importable.
For comparison, /root/.local/bin/hermes has the correct shebang:
#!/root/.hermes/hermes-agent/venv/bin/python3
…which is why running hermes manually works fine.
generate_systemd_unit() in hermes_cli/gateway.py appears to resolve the interpreter from sys.executable or similar at install time, which on a uv-managed install resolves to the base interpreter rather than the venv wrapper.
Workaround
Systemd drop-in override that replaces ExecStart with the venv Python:
mkdir -p /etc/systemd/system/hermes-gateway.service.d
cat > /etc/systemd/system/hermes-gateway.service.d/override.conf <<'OVERRIDE'
[Service]
ExecStart=
ExecStart=/root/.hermes/hermes-agent/venv/bin/python3 -m hermes_cli.main gateway run --replace
OVERRIDE
systemctl daemon-reload
systemctl reset-failed hermes-gateway.service
hermes gateway start --system
After this, the service starts cleanly and systemctl status shows the correct interpreter in Main PID.
Suggested fix
In generate_systemd_unit(), prefer $VIRTUAL_ENV/bin/python (or equivalently the shebang target of the installed hermes entrypoint) over sys.executable when generating ExecStart. Something like:
venv = os.environ.get("VIRTUAL_ENV")
python_exe = f"{venv}/bin/python" if venv and Path(f"{venv}/bin/python").exists() else sys.executable
This also makes the behavior consistent with the Environment="VIRTUAL_ENV=..." line the generator already emits.
Summary
hermes gateway install --systemgenerates a unit file whoseExecStartpoints at the base uv-managed Python interpreter instead of the project's venv Python. Because all Hermes runtime dependencies (PyYAML, etc.) are installed into the venv'ssite-packages, the service crash-loops on startup withModuleNotFoundError: No module named 'yaml'.Environment
/root/.hermes/hermes-agent/venv)--run-as-user root)Repro
hermes gateway install --system --run-as-user roothermes gateway start --systemjournalctl -u hermes-gateway -fObserved:
Root cause
The generated unit file at
/etc/systemd/system/hermes-gateway.servicecontains:The unit correctly sets
VIRTUAL_ENVand putsvenv/binonPATH, butExecStartbypasses both by hard-coding an absolute path to the base uv interpreter. Invoking the base Python directly does not pick up the venv'ssite-packages, so none of the installed Hermes dependencies are importable.For comparison,
/root/.local/bin/hermeshas the correct shebang:…which is why running
hermesmanually works fine.generate_systemd_unit()inhermes_cli/gateway.pyappears to resolve the interpreter fromsys.executableor similar at install time, which on a uv-managed install resolves to the base interpreter rather than the venv wrapper.Workaround
Systemd drop-in override that replaces
ExecStartwith the venv Python:After this, the service starts cleanly and
systemctl statusshows the correct interpreter inMain PID.Suggested fix
In
generate_systemd_unit(), prefer$VIRTUAL_ENV/bin/python(or equivalently the shebang target of the installedhermesentrypoint) oversys.executablewhen generatingExecStart. Something like:This also makes the behavior consistent with the
Environment="VIRTUAL_ENV=..."line the generator already emits.