| |
|
|
| ARG HERMES_AGENT_VERSION=latest |
| FROM nousresearch/hermes-agent:${HERMES_AGENT_VERSION} |
|
|
| USER root |
|
|
| RUN apt-get update && apt-get install -y --no-install-recommends \ |
| ca-certificates \ |
| curl \ |
| jq \ |
| sudo \ |
| python3 \ |
| python3-venv \ |
| python3-pip \ |
| chromium \ |
| dbus \ |
| dbus-x11 \ |
| libnss3 \ |
| libatk1.0-0 \ |
| libatk-bridge2.0-0 \ |
| libdrm2 \ |
| libgbm1 \ |
| libxcomposite1 \ |
| libxdamage1 \ |
| libxrandr2 \ |
| libxkbcommon0 \ |
| libx11-6 \ |
| libxext6 \ |
| libxfixes3 \ |
| fonts-dejavu-core \ |
| fonts-liberation \ |
| fonts-noto-color-emoji \ |
| && (apt-get install -y --no-install-recommends libasound2 2>/dev/null \ |
| || apt-get install -y --no-install-recommends libasound2t64 2>/dev/null \ |
| || true) \ |
| && rm -rf /var/lib/apt/lists/* \ |
| && uv pip install --python /opt/hermes/.venv/bin/python --no-cache-dir \ |
| huggingface_hub \ |
| hf_transfer \ |
| "jupyterlab>=4.0,<5" \ |
| "tornado>=6.4" \ |
| "ipywidgets>=8.1" \ |
| && printf 'hermes ALL=(ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/hermes \ |
| && chmod 0440 /etc/sudoers.d/hermes \ |
| && /usr/sbin/visudo -cf /etc/sudoers.d/hermes |
|
|
| COPY --chown=hermes:hermes start.sh /opt/huggingmes/start.sh |
| COPY --chown=hermes:hermes health-server.js /opt/huggingmes/health-server.js |
| COPY --chown=hermes:hermes hermes-sync.py /opt/huggingmes/hermes-sync.py |
| COPY --chown=hermes:hermes cloudflare-proxy-setup.py /opt/huggingmes/cloudflare-proxy-setup.py |
| COPY --chown=hermes:hermes cloudflare-keepalive-setup.py /opt/huggingmes/cloudflare-keepalive-setup.py |
| COPY --chown=hermes:hermes env-builder.html /opt/huggingmes/env-builder.html |
| COPY --chown=hermes:hermes env-builder.js /opt/huggingmes/env-builder.js |
|
|
| RUN chmod +x \ |
| /opt/huggingmes/start.sh \ |
| /opt/huggingmes/hermes-sync.py \ |
| /opt/huggingmes/cloudflare-proxy-setup.py \ |
| /opt/huggingmes/cloudflare-keepalive-setup.py |
|
|
| |
| |
| |
| |
| RUN python3 - <<'PY' |
| import sys |
| try: |
| from pathlib import Path |
|
|
| p = Path("/opt/hermes/hermes_cli/kanban_db.py") |
| if not p.exists(): |
| print("kanban patch: file not found, skipping") |
| sys.exit(0) |
|
|
| src = p.read_text(encoding="utf-8", errors="replace") |
| sentinel = "# huggingmes: idempotent-alter" |
| if sentinel in src: |
| print("kanban patch: already applied, skipping") |
| sys.exit(0) |
|
|
| old = ( |
| ' conn.execute(\n' |
| ' "ALTER TABLE tasks ADD COLUMN consecutive_failures "\n' |
| ' "INTEGER NOT NULL DEFAULT 0"\n' |
| ' )' |
| ) |
| new = ( |
| f' try: {sentinel}\n' |
| ' conn.execute(\n' |
| ' "ALTER TABLE tasks ADD COLUMN consecutive_failures "\n' |
| ' "INTEGER NOT NULL DEFAULT 0"\n' |
| ' )\n' |
| ' except Exception:\n' |
| ' pass' |
| ) |
|
|
| if old not in src: |
| print("kanban patch: pattern not found, may be fixed upstream, skipping") |
| sys.exit(0) |
|
|
| p.write_text(src.replace(old, new), encoding="utf-8") |
| print("kanban patch: applied") |
| except Exception as e: |
| print(f"kanban patch: error ({e}), skipping", file=sys.stderr) |
| PY |
|
|
| |
| |
| |
| RUN echo 'export PATH="/opt/hermes/.venv/bin:/opt/data/.local/bin:$PATH"' \ |
| > /etc/profile.d/hermes-venv.sh |
|
|
| ENV HERMES_HOME=/opt/data \ |
| HUGGINGMES_APP_DIR=/opt/huggingmes \ |
| HERMES_AGENT_VERSION=${HERMES_AGENT_VERSION} \ |
| PYTHONUNBUFFERED=1 \ |
| PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium |
|
|
| EXPOSE 7861 |
|
|
| HEALTHCHECK --interval=30s --timeout=5s --start-period=60s \ |
| CMD curl -fsS http://localhost:7861/health || exit 1 |
| |
| CMD ["/opt/huggingmes/start.sh"] |
| |