-
Notifications
You must be signed in to change notification settings - Fork 57
Expand file tree
/
Copy pathDockerfile
More file actions
135 lines (118 loc) · 4.71 KB
/
Copy pathDockerfile
File metadata and controls
135 lines (118 loc) · 4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# HuggingMes - Hermes Agent Gateway for Hugging Face Spaces
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
# Patch kanban migration: wrap ALTER TABLE ADD COLUMN in try/except so a
# persisted DB with the column already present doesn't crash the gateway.
# Entire block wrapped in try/except — skips silently if Hermes fixes this
# upstream or the file structure changes.
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
# hermes v0.17+ self-patches its own Python files at container startup
# (workspace/startup.sh), but ships them read-only in the image.
# Make all subdirs traversable first so find reaches every .py file; dirs
# without execute permission cause find to silently skip them.
# Use a+w (not u+w): this RUN executes as root during build, but HF Spaces
# runs the container as an arbitrary non-root UID at runtime — u+w only
# grants write to the file's owner (root), which the runtime UID isn't.
RUN find /opt/hermes -type d -exec chmod a+rwx {} + 2>/dev/null || true \
&& find /opt/hermes -name "*.py" -exec chmod a+w {} + 2>/dev/null || true
# Ensure hermes CLI is discoverable in ALL shell types (login, interactive,
# non-interactive). /etc/profile.d/ is sourced by login shells after /etc/profile
# resets PATH, so this survives even full environment resets.
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"]