Bug Description
Running the official gateway + dashboard stack on a shared data volume (necessary to keep SQLite state databases, dynamic skills, and config in sync) triggers an endless, sub-second s6-log lock crash loop in the dashboard sidecar container under v0.15.0 and v0.15.1.
Steps to Reproduce
- Set up a standard multi-container Docker Compose stack containing both
gateway and dashboard services.
- Bind-mount the same host data folder to both containers:
- /volume1/docker/hermes/data:/opt/data
- Launch the stack:
docker compose up -d
- The gateway container boots first and claims the shared logs lock.
- The dashboard container boots second, fails to lock the shared path, and crashes
s6-log.
- Inspect the dashboard logs:
docker logs hermes-dashboard
Expected Behavior
Both containers should boot and execute their respective services (gateway and web dashboard) peacefully while sharing the same underlying data directory without locking conflicts or crash-loops.
Actual Behavior
The dashboard container is trapped in an endless, rapid log-supervisor crash loop because it cannot acquire the lock on /opt/data/logs/gateways/default/lock (which is already held by the gateway container).
This loop creates a continuous, high-frequency stream of disk writes on the host (rattling mechanical hard drives on Btrfs/ext4 systems continuously).
Affected Component
Other
Messaging Platform (if gateway-related)
No response
Debug Report
Host Environment: Synology DS224+ (Intel Celeron J4125, 10GB RAM)
Orchestration: Docker Compose
Mount Type: Shared Btrfs host volume bind-mount
Operating System
Synology DSM 7.2+ (Linux Kernel 5.10.x)
Python Version
3.11.9
Hermes Version
0.15.1 (v2026.5.29)
Additional Logs / Traceback (optional)
s6-log: fatal: unable to lock /opt/data/logs/gateways/default/lock: Resource busy
s6-log: fatal: unable to lock /opt/data/logs/gateways/default/lock: Resource busy
s6-log: fatal: unable to lock /opt/data/logs/gateways/default/lock: Resource busy
s6-log: fatal: unable to lock /opt/data/logs/gateways/default/lock: Resource busy
Root Cause Analysis (optional)
In Hermes v0.15.0, process supervision via s6-overlay was introduced. Inside the base image, s6-log is hardcoded to acquire a file-level lock on /opt/data/logs/gateways/default/lock on startup.
Because both the gateway and dashboard containers share the /opt/data mount (to access the same SQLite database and user profiles/skills), they both execute s6-log targeting the exact same lock path. The first container locks the file successfully; the second container is immediately blocked with a Resource busy error, causing its s6-log service to crash and be continuously restarted by the container supervisor in a tight loop.
Proposed Fix (optional)
Decouple the s6-log locking path from the shared user data directory, or make the lock file path container-specific or configurable via an environment variable.
For example, s6-log could lock /opt/data/logs/gateways/default/lock-<hostname> or use a local container path like /var/log that is not bound to a shared host volume.
For end-users facing this, the immediate workaround is to map the logging directory of the sidecar container to an in-memory tmpfs volume in docker-compose.yml:
tmpfs:
- /opt/data/logs:uid=1026,gid=100,mode=1777
Bug Description
Running the official gateway + dashboard stack on a shared data volume (necessary to keep SQLite state databases, dynamic skills, and config in sync) triggers an endless, sub-second
s6-loglock crash loop in the dashboard sidecar container under v0.15.0 and v0.15.1.Steps to Reproduce
gatewayanddashboardservices.- /volume1/docker/hermes/data:/opt/datadocker compose up -ds6-log.docker logs hermes-dashboardExpected Behavior
Both containers should boot and execute their respective services (gateway and web dashboard) peacefully while sharing the same underlying data directory without locking conflicts or crash-loops.
Actual Behavior
The dashboard container is trapped in an endless, rapid log-supervisor crash loop because it cannot acquire the lock on
/opt/data/logs/gateways/default/lock(which is already held by the gateway container).This loop creates a continuous, high-frequency stream of disk writes on the host (rattling mechanical hard drives on Btrfs/ext4 systems continuously).
Affected Component
Other
Messaging Platform (if gateway-related)
No response
Debug Report
Operating System
Synology DSM 7.2+ (Linux Kernel 5.10.x)
Python Version
3.11.9
Hermes Version
0.15.1 (v2026.5.29)
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
In Hermes v0.15.0, process supervision via
s6-overlaywas introduced. Inside the base image,s6-logis hardcoded to acquire a file-level lock on/opt/data/logs/gateways/default/lockon startup.Because both the
gatewayanddashboardcontainers share the/opt/datamount (to access the same SQLite database and user profiles/skills), they both executes6-logtargeting the exact same lock path. The first container locks the file successfully; the second container is immediately blocked with aResource busyerror, causing itss6-logservice to crash and be continuously restarted by the container supervisor in a tight loop.Proposed Fix (optional)
Decouple the
s6-loglocking path from the shared user data directory, or make the lock file path container-specific or configurable via an environment variable.For example,
s6-logcould lock/opt/data/logs/gateways/default/lock-<hostname>or use a local container path like/var/logthat is not bound to a shared host volume.For end-users facing this, the immediate workaround is to map the logging directory of the sidecar container to an in-memory
tmpfsvolume indocker-compose.yml: