feat(docker): add Docker container for the agent (salvage #1841) (#3668)
Adds a complete Docker packaging for Hermes Agent:
- Dockerfile based on debian:13.4 with all deps
- Entrypoint that bootstraps .env, config.yaml, SOUL.md on first run
- CI workflow to build, test, and push to DockerHub
- Documentation for interactive, gateway, and upgrade workflows
Closes #850, #913.
Changes vs original PR:
- Removed pre-created legacy cache/platform dirs from entrypoint
(image_cache, audio_cache, pairing, whatsapp/session) — these are
now created on demand by the application using the consolidated
layout from get_hermes_dir()
- Moved docs from docs/docker.md to website/docs/user-guide/docker.md
and added to Docusaurus sidebar
Co-authored-by: benbarclay <benbarclay@users.noreply.github.com>
2026-03-28 22:21:48 -07:00
|
|
|
#!/bin/bash
|
|
|
|
|
# Docker entrypoint: bootstrap config files into the mounted volume, then run hermes.
|
|
|
|
|
set -e
|
|
|
|
|
|
|
|
|
|
HERMES_HOME="/opt/data"
|
|
|
|
|
INSTALL_DIR="/opt/hermes"
|
|
|
|
|
|
2026-04-12 00:26:08 -07:00
|
|
|
# --- Privilege dropping via gosu ---
|
|
|
|
|
# When started as root (the default), optionally remap the hermes user/group
|
|
|
|
|
# to match host-side ownership, fix volume permissions, then re-exec as hermes.
|
|
|
|
|
if [ "$(id -u)" = "0" ]; then
|
|
|
|
|
if [ -n "$HERMES_UID" ] && [ "$HERMES_UID" != "$(id -u hermes)" ]; then
|
|
|
|
|
echo "Changing hermes UID to $HERMES_UID"
|
|
|
|
|
usermod -u "$HERMES_UID" hermes
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [ -n "$HERMES_GID" ] && [ "$HERMES_GID" != "$(id -g hermes)" ]; then
|
|
|
|
|
echo "Changing hermes GID to $HERMES_GID"
|
|
|
|
|
groupmod -g "$HERMES_GID" hermes
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
actual_hermes_uid=$(id -u hermes)
|
|
|
|
|
if [ "$(stat -c %u "$HERMES_HOME" 2>/dev/null)" != "$actual_hermes_uid" ]; then
|
|
|
|
|
echo "$HERMES_HOME is not owned by $actual_hermes_uid, fixing"
|
|
|
|
|
chown -R hermes:hermes "$HERMES_HOME"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo "Dropping root privileges"
|
|
|
|
|
exec gosu hermes "$0" "$@"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# --- Running as hermes from here ---
|
|
|
|
|
source "${INSTALL_DIR}/.venv/bin/activate"
|
|
|
|
|
|
feat(docker): add Docker container for the agent (salvage #1841) (#3668)
Adds a complete Docker packaging for Hermes Agent:
- Dockerfile based on debian:13.4 with all deps
- Entrypoint that bootstraps .env, config.yaml, SOUL.md on first run
- CI workflow to build, test, and push to DockerHub
- Documentation for interactive, gateway, and upgrade workflows
Closes #850, #913.
Changes vs original PR:
- Removed pre-created legacy cache/platform dirs from entrypoint
(image_cache, audio_cache, pairing, whatsapp/session) — these are
now created on demand by the application using the consolidated
layout from get_hermes_dir()
- Moved docs from docs/docker.md to website/docs/user-guide/docker.md
and added to Docusaurus sidebar
Co-authored-by: benbarclay <benbarclay@users.noreply.github.com>
2026-03-28 22:21:48 -07:00
|
|
|
# Create essential directory structure. Cache and platform directories
|
|
|
|
|
# (cache/images, cache/audio, platforms/whatsapp, etc.) are created on
|
|
|
|
|
# demand by the application — don't pre-create them here so new installs
|
|
|
|
|
# get the consolidated layout from get_hermes_dir().
|
2026-04-10 13:37:45 -07:00
|
|
|
# The "home/" subdirectory is a per-profile HOME for subprocesses (git,
|
|
|
|
|
# ssh, gh, npm …). Without it those tools write to /root which is
|
|
|
|
|
# ephemeral and shared across profiles. See issue #4426.
|
2026-04-10 15:11:20 -07:00
|
|
|
mkdir -p "$HERMES_HOME"/{cron,sessions,logs,hooks,memories,skills,skins,plans,workspace,home}
|
feat(docker): add Docker container for the agent (salvage #1841) (#3668)
Adds a complete Docker packaging for Hermes Agent:
- Dockerfile based on debian:13.4 with all deps
- Entrypoint that bootstraps .env, config.yaml, SOUL.md on first run
- CI workflow to build, test, and push to DockerHub
- Documentation for interactive, gateway, and upgrade workflows
Closes #850, #913.
Changes vs original PR:
- Removed pre-created legacy cache/platform dirs from entrypoint
(image_cache, audio_cache, pairing, whatsapp/session) — these are
now created on demand by the application using the consolidated
layout from get_hermes_dir()
- Moved docs from docs/docker.md to website/docs/user-guide/docker.md
and added to Docusaurus sidebar
Co-authored-by: benbarclay <benbarclay@users.noreply.github.com>
2026-03-28 22:21:48 -07:00
|
|
|
|
|
|
|
|
# .env
|
|
|
|
|
if [ ! -f "$HERMES_HOME/.env" ]; then
|
|
|
|
|
cp "$INSTALL_DIR/.env.example" "$HERMES_HOME/.env"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# config.yaml
|
|
|
|
|
if [ ! -f "$HERMES_HOME/config.yaml" ]; then
|
|
|
|
|
cp "$INSTALL_DIR/cli-config.yaml.example" "$HERMES_HOME/config.yaml"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# SOUL.md
|
|
|
|
|
if [ ! -f "$HERMES_HOME/SOUL.md" ]; then
|
|
|
|
|
cp "$INSTALL_DIR/docker/SOUL.md" "$HERMES_HOME/SOUL.md"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Sync bundled skills (manifest-based so user edits are preserved)
|
|
|
|
|
if [ -d "$INSTALL_DIR/skills" ]; then
|
|
|
|
|
python3 "$INSTALL_DIR/tools/skills_sync.py"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
exec hermes "$@"
|