v0.50.260: Docker reliability batch - PR #1428 + broader UX/docs improvements + Opus advisor fixes
Combines PR #1428 (UID/GID alignment) with a broader Docker reliability pass
that addresses recurring user reports about compose files not working.
Constituent PR:
- #1428 sunnysktsang - Align agent UID/GID with webui (fixes #1399).
Two- and three-container compose files had agent at UID 10000 (image
default) and webui at UID 1000 (WANTED_UID default), causing permission
denied on shared hermes-home volume. All services now use ${UID:-1000}.
Plus broader Docker UX overhaul:
- All 3 compose files document HERMES_SKIP_CHMOD/HERMES_HOME_MODE escape
hatches inline (the v0.50.254 fix wasn't surfaced for Docker users).
- New .env.docker.example template covering UID/GID, paths, password,
permission handling. UID/GID are uncommented with placeholder values
per Opus advisor (so macOS users don't skim past).
- New docs/docker.md - comprehensive guide: 5-min quickstart, failure
mode table with one-line fixes, bind-mount migration, multi-container
architecture diagram, macOS Docker Desktop VirtioFS note, link to
community sunnysktsang/hermes-suite all-in-one image.
- README Docker section rewritten - clearer quickstart, failure-mode
table, link to docs/docker.md. Stale /root/.hermes references removed.
Plus Opus pre-release advisor MUST-FIX:
- HERMES_HOME_MODE has DIFFERENT semantics in the WebUI vs the agent
image. WebUI: credential-file mode threshold (0640 allows group bits).
Agent: HERMES_HOME directory mode (default 0700). 0640 on a directory
has no owner-execute bit, so the agent can't traverse its own home and
bricks. My initial draft recommended HERMES_HOME_MODE=0640 in agent
service blocks - corrected to 0750 across all 4 surfaces (compose
files, .env.docker.example, docs/docker.md). 3 regression tests pin
the asymmetry.
12 regression tests total in test_v050260_docker_invariants.py.
Full suite: 3627 passed, 0 failed.
Nathan explicitly authorized merge with my own review + Opus only, no
independent review needed.
2026-05-01 23:09:50 +00:00
|
|
|
# Hermes Web UI — Docker Compose configuration template
|
|
|
|
|
#
|
|
|
|
|
# Copy this file to `.env` next to your docker-compose.yml.
|
|
|
|
|
# All variables are optional — Docker Compose substitutes defaults if unset.
|
|
|
|
|
#
|
|
|
|
|
# cp .env.docker.example .env
|
|
|
|
|
# # edit values you care about, then:
|
|
|
|
|
# docker compose up -d
|
|
|
|
|
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
|
# UID / GID — host user mapping
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
|
# Critical when bind-mounting an EXISTING host directory (e.g. ~/.hermes).
|
|
|
|
|
# The container runs as UID/GID and must match your host file ownership,
|
|
|
|
|
# otherwise the container can't read your config.yaml or write sessions.
|
|
|
|
|
#
|
|
|
|
|
# Find yours: id -u (UID) | id -g (GID)
|
|
|
|
|
#
|
|
|
|
|
# On macOS, UIDs start at 501 (not 1000), so you MUST set these.
|
|
|
|
|
# On Linux, the default of 1000 usually matches the first interactive user.
|
|
|
|
|
#
|
|
|
|
|
# REPLACE THESE WITH YOUR ACTUAL VALUES (run `id -u` and `id -g`):
|
|
|
|
|
UID=1000
|
|
|
|
|
GID=1000
|
|
|
|
|
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
|
# Hermes home directory — single-container compose only
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
|
# Where on the host your config, sessions, skills, and state live.
|
|
|
|
|
# Default: ~/.hermes (works for everyone with a standard install)
|
|
|
|
|
# Override if your .hermes is elsewhere:
|
|
|
|
|
# HERMES_HOME=/opt/hermes-data
|
|
|
|
|
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
|
# Workspace directory — single-container compose
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
|
# Path to your code/project directory. The WebUI's file browser shows
|
|
|
|
|
# this at /workspace inside the container.
|
|
|
|
|
# Default: ~/workspace
|
|
|
|
|
# HERMES_WORKSPACE=/home/me/dev
|
|
|
|
|
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
|
# Password — protect remote access
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
|
# REQUIRED if you expose the container on anything other than 127.0.0.1.
|
|
|
|
|
# Without a password, anyone who can reach the port can run commands as
|
|
|
|
|
# the agent.
|
|
|
|
|
# HERMES_WEBUI_PASSWORD=change-me-to-something-strong
|
|
|
|
|
|
docs(env): document the HERMES_WEBUI_* vars the code reads but no template listed
.env.example listed 8 basic vars; the server reads ~30. Add the
operator-facing ones with defaults from the code, grouped into Security,
Reverse-proxy header trust, Uploads & limits, Onboarding, and Advanced
integrations: PASSWORD, PASSKEY, SESSION_TTL, SECURE, COOKIE_NAME,
ALLOWED_ORIGINS, TLS_CERT/KEY, CSP_CONNECT_EXTRA/FRAME_EXTRA,
TRUST_FORWARDED_HOST/FOR/PROTO, ATTACHMENT_DIR, MAX_EXTRACTED_MB,
FOLDER_ZIP_MAX_*, SLOW_REQUEST_SECONDS, SKIP_ONBOARDING, PREFILL_* hooks,
EXTERNAL_NOTES_SOURCES, PLUGINS_DIR, GATEWAY_API_KEY, CLAUDE_PROJECTS_DIR,
CODEX_HOME, WIKI_PATH. The Docker template notes each needs a compose
environment: passthrough to take effect.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 01:13:29 +00:00
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
|
# Additional security / networking / limit knobs — advanced
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
|
# The WebUI process reads more HERMES_WEBUI_* variables than the compose
|
|
|
|
|
# files forward by default. To use any of these in Docker, uncomment it here
|
|
|
|
|
# AND add a matching passthrough line under `environment:` in your compose
|
|
|
|
|
# file (e.g. `- HERMES_WEBUI_SESSION_TTL=${HERMES_WEBUI_SESSION_TTL:-}`).
|
|
|
|
|
# Full descriptions live in .env.example.
|
|
|
|
|
#
|
|
|
|
|
# Auth cookie lifetime in seconds (default 2592000 = 30 days):
|
|
|
|
|
# HERMES_WEBUI_SESSION_TTL=2592000
|
|
|
|
|
#
|
|
|
|
|
# Force the Secure cookie flag when serving HTTPS via a reverse proxy:
|
|
|
|
|
# HERMES_WEBUI_SECURE=1
|
|
|
|
|
#
|
|
|
|
|
# Allowed public origins (scheme required) when behind a reverse proxy:
|
|
|
|
|
# HERMES_WEBUI_ALLOWED_ORIGINS=https://myapp.example.com
|
|
|
|
|
#
|
|
|
|
|
# Trust reverse-proxy forwarded headers (only enable behind a proxy YOU run):
|
|
|
|
|
# HERMES_WEBUI_TRUST_FORWARDED_HOST=1
|
|
|
|
|
# HERMES_WEBUI_TRUST_FORWARDED_FOR=1
|
|
|
|
|
# HERMES_WEBUI_TRUST_FORWARDED_PROTO=1
|
|
|
|
|
#
|
|
|
|
|
# Enable the passkey/WebAuthn login surface (default off):
|
|
|
|
|
# HERMES_WEBUI_PASSKEY=1
|
|
|
|
|
#
|
|
|
|
|
# Archive extraction cap (MB) and "download folder as ZIP" caps:
|
|
|
|
|
# HERMES_WEBUI_MAX_EXTRACTED_MB=2048
|
|
|
|
|
# HERMES_WEBUI_FOLDER_ZIP_MAX_MB=1024
|
|
|
|
|
# HERMES_WEBUI_FOLDER_ZIP_MAX_FILES=50000
|
|
|
|
|
|
v0.50.260: Docker reliability batch - PR #1428 + broader UX/docs improvements + Opus advisor fixes
Combines PR #1428 (UID/GID alignment) with a broader Docker reliability pass
that addresses recurring user reports about compose files not working.
Constituent PR:
- #1428 sunnysktsang - Align agent UID/GID with webui (fixes #1399).
Two- and three-container compose files had agent at UID 10000 (image
default) and webui at UID 1000 (WANTED_UID default), causing permission
denied on shared hermes-home volume. All services now use ${UID:-1000}.
Plus broader Docker UX overhaul:
- All 3 compose files document HERMES_SKIP_CHMOD/HERMES_HOME_MODE escape
hatches inline (the v0.50.254 fix wasn't surfaced for Docker users).
- New .env.docker.example template covering UID/GID, paths, password,
permission handling. UID/GID are uncommented with placeholder values
per Opus advisor (so macOS users don't skim past).
- New docs/docker.md - comprehensive guide: 5-min quickstart, failure
mode table with one-line fixes, bind-mount migration, multi-container
architecture diagram, macOS Docker Desktop VirtioFS note, link to
community sunnysktsang/hermes-suite all-in-one image.
- README Docker section rewritten - clearer quickstart, failure-mode
table, link to docs/docker.md. Stale /root/.hermes references removed.
Plus Opus pre-release advisor MUST-FIX:
- HERMES_HOME_MODE has DIFFERENT semantics in the WebUI vs the agent
image. WebUI: credential-file mode threshold (0640 allows group bits).
Agent: HERMES_HOME directory mode (default 0700). 0640 on a directory
has no owner-execute bit, so the agent can't traverse its own home and
bricks. My initial draft recommended HERMES_HOME_MODE=0640 in agent
service blocks - corrected to 0750 across all 4 surfaces (compose
files, .env.docker.example, docs/docker.md). 3 regression tests pin
the asymmetry.
12 regression tests total in test_v050260_docker_invariants.py.
Full suite: 3627 passed, 0 failed.
Nathan explicitly authorized merge with my own review + Opus only, no
independent review needed.
2026-05-01 23:09:50 +00:00
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
|
# Permission handling for bind-mounted .hermes — advanced
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
|
# By default, the WebUI's startup credential-permission fixer enforces
|
|
|
|
|
# 0600 mode on .env, auth.json, and similar credential files in HERMES_HOME.
|
|
|
|
|
# This is the right behavior on a clean install, but it can clash with:
|
|
|
|
|
#
|
|
|
|
|
# - Bind-mounting an EXISTING ~/.hermes whose .env is intentionally 0640
|
|
|
|
|
# (e.g. group-readable for a Docker user group)
|
|
|
|
|
# - HERMES_HOME_MODE configured at the agent level for a multi-user setup
|
|
|
|
|
#
|
|
|
|
|
# To bypass the WebUI's fixer entirely:
|
|
|
|
|
# HERMES_SKIP_CHMOD=1
|
|
|
|
|
#
|
|
|
|
|
# OR to allow group bits while still stripping world-readable:
|
|
|
|
|
# HERMES_HOME_MODE=0640
|
|
|
|
|
#
|
|
|
|
|
# ⚠️ MULTI-CONTAINER WARNING: HERMES_HOME_MODE has DIFFERENT semantics in
|
|
|
|
|
# the WebUI vs. the agent image:
|
|
|
|
|
# - WebUI: credential FILE mode threshold (0640 = allow group bits)
|
|
|
|
|
# - Agent: HERMES_HOME *directory* mode (default 0700)
|
|
|
|
|
# 0640 on a directory has NO execute bit, so the agent can't enter its own
|
|
|
|
|
# home → broken. If you set HERMES_HOME_MODE for a multi-container setup,
|
|
|
|
|
# use 0750 (group-traversable) or 0701 (x-only for non-owner traversal).
|
|
|
|
|
# The compose files document both correctly per-service.
|
|
|
|
|
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
|
# Multi-container only — used by docker-compose.two-container.yml and
|
|
|
|
|
# docker-compose.three-container.yml
|
|
|
|
|
# ──────────────────────────────────────────────────────────────────────────
|
|
|
|
|
# These compose files use named Docker volumes by default (recommended).
|
|
|
|
|
# Set the variables above to your host UID/GID — both the agent container
|
|
|
|
|
# (HERMES_UID/HERMES_GID) and the webui container (WANTED_UID/WANTED_GID)
|
|
|
|
|
# are derived from $UID/$GID so files written by one are readable by the
|
|
|
|
|
# other.
|
|
|
|
|
#
|
|
|
|
|
# If you switch to bind mounts (replacing `hermes-home: {}` with a `device:`
|
|
|
|
|
# bind), ALL THREE containers must mount the SAME host path and run as the
|
|
|
|
|
# SAME UID/GID. Mismatched UIDs → "Permission denied" → the WebUI crashes
|
|
|
|
|
# on every HTTP request because it can't read its own auth signing key.
|