hermes - ✅(Solved) Fix hermes login writes auth.json owned by root when run via 'docker exec'; gateway running as non-root user can't read it [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#15718Fetched 2026-04-26 05:25:34
View on GitHub
Comments
0
Participants
1
Timeline
6
Reactions
0
Author
Participants
Timeline (top)
labeled ×5cross-referenced ×1

When Hermes is deployed in a container where the gateway process runs as a non-root user (e.g. hermes UID 10000), running hermes login --provider openai-codex interactively via docker exec -it <container> hermes login ... writes $HERMES_HOME/auth.json as root:root mode 600. The TUI started the same way works (root can read its own file), but the gateway process — and therefore the Telegram/Discord/etc. channel — fails on every request with:

Provider authentication failed: no Codex credentials stored.
Run 'hermes auth' to authenticate. Run 'hermes model' to reauthenticate.

Logs show:

WARNING agent.auxiliary_client: resolve_provider_client: openai-codex requested but no Codex OAuth token found (run: hermes model)

The error message is misleading — credentials are stored, they're just unreadable by the gateway's UID.

Error Message

The error message is misleading — credentials are stored, they're just unreadable by the gateway's UID. 4. Send a message via the Telegram channel → fails with the error above. 2. When the gateway hits a "no credentials" path while auth.json exists on disk but is unreadable, raise a clearer error (auth.json exists but is not readable by uid=N instead of the generic "no credentials stored").

Root Cause

When Hermes is deployed in a container where the gateway process runs as a non-root user (e.g. hermes UID 10000), running hermes login --provider openai-codex interactively via docker exec -it <container> hermes login ... writes $HERMES_HOME/auth.json as root:root mode 600. The TUI started the same way works (root can read its own file), but the gateway process — and therefore the Telegram/Discord/etc. channel — fails on every request with:

Provider authentication failed: no Codex credentials stored.
Run 'hermes auth' to authenticate. Run 'hermes model' to reauthenticate.

Logs show:

WARNING agent.auxiliary_client: resolve_provider_client: openai-codex requested but no Codex OAuth token found (run: hermes model)

The error message is misleading — credentials are stored, they're just unreadable by the gateway's UID.

Fix Action

Workaround

docker exec hermes-gateway chown <uid>:<gid> /opt/data/auth.json
docker compose restart hermes-gateway

Or run the login as the container user from the start:

docker exec -u <uid> -it hermes-gateway /opt/hermes/.venv/bin/hermes login --provider openai-codex

PR fix notes

PR #15861: fix(auth): hand auth.json to the data-dir owner when login runs as root

Description (problem / solution / changelog)

Summary

When `hermes login` runs via `docker exec -it` against a container whose data dir is owned by the gateway user (UID 10000 by default), the resulting `auth.json` is written `root:root 0600`. The gateway process — running as the non-root user — silently can't read its own credentials and surfaces the misleading "no Codex credentials stored" error, while the TUI (also launched as root) shows a fully working login (#15718).

This is the user's suggested fix #1 (chown on save) plus #2 (clearer error on load):

  • New `_align_owner_to_parent()` helper: when running as root and the parent dir is owned by a non-root UID, chown the file to match. Best-effort, swallows `OSError`s. No-op on Windows or when not running as root.
  • `_save_auth_store` calls it after the atomic replace, so the fix applies to every credential write.
  • `_load_auth_store` now distinguishes `PermissionError` from a parse failure. Previously both fell into the "corrupt" branch, leaving a stray `auth.json.corrupt` copy and an opaque warning. The new path names the file's owner/mode and surfaces the chown command to recover already-broken installations.

Test plan

  • `pytest tests/hermes_cli/test_auth_store_ownership.py` — 7 passed (new file)
  • `pytest tests/hermes_cli/test_auth_commands.py tests/hermes_cli/test_auth_codex_provider.py tests/hermes_cli/test_auth_nous_provider.py` — 88 passed (existing auth tests unaffected)

Closes #15718

🤖 Generated with Claude Code

Changed files

  • hermes_cli/auth.py (modified, +64/-0)
  • scripts/release.py (modified, +1/-0)
  • tests/hermes_cli/test_auth_store_ownership.py (added, +125/-0)

Code Example

Provider authentication failed: no Codex credentials stored.
Run 'hermes auth' to authenticate. Run 'hermes model' to reauthenticate.

---

WARNING agent.auxiliary_client: resolve_provider_client: openai-codex requested but no Codex OAuth token found (run: hermes model)

---

docker exec hermes-gateway chown <uid>:<gid> /opt/data/auth.json
docker compose restart hermes-gateway

---

docker exec -u <uid> -it hermes-gateway /opt/hermes/.venv/bin/hermes login --provider openai-codex
RAW_BUFFERClick to expand / collapse

Summary

When Hermes is deployed in a container where the gateway process runs as a non-root user (e.g. hermes UID 10000), running hermes login --provider openai-codex interactively via docker exec -it <container> hermes login ... writes $HERMES_HOME/auth.json as root:root mode 600. The TUI started the same way works (root can read its own file), but the gateway process — and therefore the Telegram/Discord/etc. channel — fails on every request with:

Provider authentication failed: no Codex credentials stored.
Run 'hermes auth' to authenticate. Run 'hermes model' to reauthenticate.

Logs show:

WARNING agent.auxiliary_client: resolve_provider_client: openai-codex requested but no Codex OAuth token found (run: hermes model)

The error message is misleading — credentials are stored, they're just unreadable by the gateway's UID.

Reproduction

  1. Build/run Hermes in a container whose entrypoint runs the gateway as a non-root user (in our case the official Dockerfile pattern with USER hermes UID 10000, HOME=/opt/data).
  2. From the host, log in interactively as root: docker exec -it hermes-gateway hermes login --provider openai-codex and complete the OAuth device flow.
  3. Verify in TUI (also via docker exec -it hermes-gateway hermes): chat works, hermes status shows OpenAI Codex ✓ logged in, hermes auth list shows openai-codex (1 credentials).
  4. Send a message via the Telegram channel → fails with the error above.

ls -la /opt/data/auth.json shows -rw------- 1 root root while the rest of /opt/data/ is owned by hermes:hermes.

Workaround

docker exec hermes-gateway chown <uid>:<gid> /opt/data/auth.json
docker compose restart hermes-gateway

Or run the login as the container user from the start:

docker exec -u <uid> -it hermes-gateway /opt/hermes/.venv/bin/hermes login --provider openai-codex

Suggested fix

One or more of:

  1. When hermes login writes auth.json, chown the file to the parent directory's owner (i.e. match $HERMES_HOME ownership). Most robust — works regardless of who launched hermes login.
  2. When the gateway hits a "no credentials" path while auth.json exists on disk but is unreadable, raise a clearer error (auth.json exists but is not readable by uid=N instead of the generic "no credentials stored").
  3. Document the docker exec -u <uid> pattern in the Docker/deployment docs.

Happy to PR (1) or (2) if you'd like.

Environment

  • Hermes: main branch (rreben/hermes-agent fork, last sync April 2026)
  • Container user: hermes UID 10000, HERMES_HOME=/opt/data
  • Provider: openai-codex (also affects any OAuth-based provider that writes auth.json — likely nous too)
  • Channel: Telegram (but applies to any gateway channel, since they share the gateway process)

extent analysis

TL;DR

Change the ownership of the auth.json file to the container user to resolve the authentication issue.

Guidance

  • Run the hermes login command as the container user using docker exec -u <uid> -it hermes-gateway /opt/hermes/.venv/bin/hermes login --provider openai-codex to ensure the auth.json file is written with the correct ownership.
  • Alternatively, use chown to change the ownership of the auth.json file to the container user after running hermes login as root.
  • Consider implementing a fix in the hermes login command to automatically set the correct ownership of the auth.json file.
  • Verify the ownership of the auth.json file using ls -la /opt/data/auth.json to ensure it matches the container user.

Example

docker exec -u 10000 -it hermes-gateway /opt/hermes/.venv/bin/hermes login --provider openai-codex

Notes

The issue is specific to running the hermes login command as root in a container where the gateway process runs as a non-root user. The suggested fixes and workarounds should resolve the issue, but it's recommended to implement a permanent fix in the hermes login command to set the correct ownership of the auth.json file.

Recommendation

Apply the workaround by running the hermes login command as the container user using docker exec -u <uid> -it hermes-gateway /opt/hermes/.venv/bin/hermes login --provider openai-codex to ensure the auth.json file is written with the correct ownership. This will resolve the authentication issue until a permanent fix is implemented.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix hermes login writes auth.json owned by root when run via 'docker exec'; gateway running as non-root user can't read it [1 pull requests, 1 participants]