6.1 KiB
6.1 KiB
title, created, updated, type, namespace, tags, related
| title | created | updated | type | namespace | tags | related | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Hermes Docker on Kraken | 2026-05-23 | 2026-06-04 | tech | personal |
|
|
Hermes Docker on Kraken
Key Rule
Hermes runs via docker compose from the hermes-build/ directory.
Directory Layout (on Kraken)
/srv/.../docker/
├── hermes-build/ ← build + run from here
│ ├── Dockerfile ← clones upstream NousResearch/hermes-agent
│ ├── docker-compose.yml ← canonical compose file
│ ├── config.yaml ← unused at build time (runtime config is in hermes/config/)
│ └── .env ← all secrets/API keys (sourced by compose)
└── hermes/
└── config/ ← mounted as /opt/data (HERMES_HOME) inside container
Compose File (hermes-build/docker-compose.yml)
services:
kraken:
build:
context: .
dockerfile: Dockerfile
image: hermes-kraken:latest
container_name: hermes-kraken
stdin_open: true
tty: true
restart: unless-stopped
volumes:
- /srv/.../docker/hermes/config:/opt/data
- /home/kraken/obsidian:/vault:rw
environment:
- HERMES_ALLOW_ROOT_GATEWAY=1
env_file:
- .env
command: gateway
network_mode: host
Managing the Container
cd /srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/docker/hermes-build
docker compose up -d # start
docker compose down # stop
docker compose pull # pull new image (if from registry)
docker compose build # rebuild image from Dockerfile
docker compose restart # restart
docker compose logs -f # follow logs
Image
Built locally from Dockerfile — clones upstream NousResearch/hermes-agent
(--depth=1 from main). Not a custom fork. To update Hermes:
cd /srv/.../docker/hermes-build
docker compose build --no-cache
docker compose up -d
Volumes
| Host path | Container path | Purpose |
|---|---|---|
hermes/config/ |
/opt/data |
HERMES_HOME — config, sessions, skills, memory |
/home/kraken/obsidian |
/vault |
Obsidian vault read/write access |
SSH из контейнера → хост (диагностика и фиксы)
Перенесено из удалённого скилла
kraken-omv-maintenance/kraken-docker-ssh. Актуальные пути и фиксы для случая, когдаssh kraken-hostизнутри контейнераhermes-krakenне работает.
Архитектура
Container (hermes-kraken)
uid=10000 (dropped from root by entrypoint)
HOME=/opt/data
~/.ssh/config = /opt/data/.ssh/config (bind mount from host)
/etc/ssh/ssh_config — bind mount (полный /etc/ssh/)
Host (Kraken RPi5)
User kraken (uid=1000) owns /home/kraken/.ssh/
/home/kraken/.ssh/id_ed25519 — закрытый ключ (обязательно 600)
/home/kraken/.ssh/authorized_keys — должен содержать публичный ключ
Fixed points (НЕ менять)
- В compose не задавать
user:,entrypoint:,HERMES_UID/GID— entrypoint сам сбрасывает uid (image defaults). - Публичный ключ на хост один раз:
ssh-copy-id kraken@<host>. - Закрытый ключ на хосте обязан быть 600:
ssh kraken@<host> "chmod 600 /home/kraken/.ssh/id_ed25519"— OpenSSH 10.x (Bookworm) отвергает 644. - В
/etc/passwdконтейнера должен бытьkraken:x:1000— не выставлятьuser:в compose. - SSH config обязан лежать в
$HOME/.ssh/config($HOME=/opt/data→/opt/data/.ssh/config).
Диагностика по порядку
ssh kraken@<host> "echo OK && hostname" # доступен ли хост
ssh kraken@<host> "sudo docker ps --filter name=hermes-kraken --format '{{.Names}} {{.Status}}'"
# изнутри контейнера на хост (loopback алиас kraken-host)
ssh kraken@<host> "sudo docker exec hermes-kraken ssh -o ConnectTimeout=5 kraken-host 'echo HELLO'"
# verbose — какие конфиги читает SSH
ssh kraken@<host> "sudo docker exec hermes-kraken ssh -v kraken-host 'echo HELLO' 2>&1 | grep -E 'config|debug1.*/ssh|Host|connect|Permission|authenticate|bad|owner' | head -15"
ssh kraken@<host> "sudo docker exec hermes-kraken getent passwd 1000" # uid 1000 в passwd?
ssh kraken@<host> "sudo docker exec hermes-kraken ls -la /opt/data/.ssh/id_ed25519"
ssh kraken@<host> "sudo docker exec hermes-kraken cat /opt/data/.ssh/config"
ssh kraken@<host> "sudo docker exec hermes-kraken sh -c 'echo HOME=\$HOME; ls -la \"\$HOME/.ssh/config\"'"
Pitfalls
- Не менять
user:в compose — entrypoint должен стартовать как root, чтобы сделать chown. - Не chown'ить
/opt/dataна1000:1000— entrypoint делаетchown -R hermes:hermes(uid 10000). - Не ставить 644 на закрытый ключ.
- НЕ использовать
Include ~/.ssh/configв системном/etc/ssh/ssh_config— OpenSSH не резолвит~в системных Include. - Если
$HOME=/opt/data, а конфиг живёт в/opt/data/home/.ssh/— SSH его не прочитает (путь не совпадает). - Может быть несколько пар ключей: bind mount приносит хост-ключ, а агент может иметь свой в
/opt/data/home/.ssh/. - passwd сбрасывается при пересоздании контейнера.
- Полный mount
/etc/ssh/перезаписывает и host keys тоже.
Notes
network_mode: host— port 8642 is directly on the Kraken host, no port mapping neededHERMES_ALLOW_ROOT_GATEWAY=1— required since container runs as root- All secrets in
hermes-build/.env(not committed)