snapshot of 82e970afb581494c2d30c99b177f854ed4a00f96 Annotations recorded against the manifests that run this cluster. https://github.com/janpuc/home-ops

kubernetes/apps/ai/hermes/app/helmrelease.yaml

1 ---
2 # yaml-language-server: $schema=https://raw.githubusercontent.com/bjw-s-labs/helm-charts/main/charts/other/app-template/schemas/helmrelease-helm-v2.schema.json
3 apiVersion: helm.toolkit.fluxcd.io/v2
4 kind: HelmRelease
5 metadata:
6 name: hermes
7 spec:
8 chartRef:
9 kind: OCIRepository
10 name: hermes
11 interval: 15m
12 timeout: 20m
13 values:
14 defaultPodOptions:
15 automountServiceAccountToken: true
16 terminationGracePeriodSeconds: 120
17 securityContext:
18 fsGroup: 1000
19 fsGroupChangePolicy: OnRootMismatch
20 runAsGroup: 1000
21 runAsUser: 1000
22 seccompProfile:
23 type: RuntimeDefault
24 controllers:
25 hermes:
26 annotations:
27 reloader.stakater.com/auto: "true"
28 strategy: Recreate
29 type: deployment
30 initContainers:
31 copy-agent-source:
32 image:
33 repository: nousresearch/hermes-agent
34 tag: v2026.8.16.2@sha256:a39fc11620213e3669a327aff5c6cb1eb2b8a238c6044e33e7ef8885833d89a7
35 command:
36 - /bin/sh
37 - -c
38 - |
39 set -e
40 cp -r /opt/hermes/. /agent-src/ 2>/tmp/cp.err || true
41 if grep -v 'Permission denied' /tmp/cp.err; then exit 1; fi
42 test -e /agent-src/.venv
43 securityContext:
44 allowPrivilegeEscalation: false
45 capabilities:
46 drop:
47 - ALL
48 runAsGroup: 1000
49 runAsUser: 1000
50 init:
51 image:
52 repository: docker.io/library/alpine
53 tag: "3.24"
54 command:
55 - sh
56 - -c
57 - |
58 set -euo pipefail
59 mkdir -p /opt/data
60 cp /run/config/config.yaml /opt/data/config.yaml
61 chmod 600 /opt/data/config.yaml
62 mkdir -p /opt/data/hook-scripts
63 cp /run/config/home-ops-guard.py /opt/data/hook-scripts/home-ops-guard.py
64 chmod 644 /opt/data/hook-scripts/home-ops-guard.py
65 mkdir -p /opt/data/.local/bin
66 cp /run/config/matrix-post.py /opt/data/.local/bin/matrix-post
67 chmod 755 /opt/data/.local/bin/matrix-post
68 cp /run/config/weekly-digest.py /opt/data/.local/bin/weekly-digest
69 chmod 755 /opt/data/.local/bin/weekly-digest
70 mkdir -p /opt/data/scripts
71 cp /run/config/weekly-digest-run.sh /opt/data/scripts/weekly-digest-run.sh
72 chmod 755 /opt/data/scripts/weekly-digest-run.sh
73 securityContext:
74 allowPrivilegeEscalation: false
75 capabilities:
76 drop:
77 - ALL
78 runAsGroup: 1000
79 runAsUser: 1000
80 install-tools:
81 image:
82 repository: nousresearch/hermes-agent
83 tag: v2026.8.16.2@sha256:a39fc11620213e3669a327aff5c6cb1eb2b8a238c6044e33e7ef8885833d89a7
84 command:
85 - /bin/sh
86 - -c
87 - |
88 set -e
89 mkdir -p /opt/data/.local/bin /opt/data/.local/go
90
91 rm -f /opt/data/.local/bin/hermes /opt/data/.local/bin/docker
92
93 if [ ! -f /opt/data/.local/bin/gh ]; then
94 cd /tmp
95 curl -fsSL https://github.com/cli/cli/releases/download/v2.61.0/gh_2.61.0_linux_amd64.tar.gz -o gh.tar.gz
96 tar xzf gh.tar.gz
97 cp gh_2.61.0_linux_amd64/bin/gh /opt/data/.local/bin/
98 rm -rf gh.tar.gz gh_2.61.0_linux_amd64
99 fi
100
101 if [ ! -f /opt/data/.local/go/bin/go ]; then
102 cd /tmp
103 curl -fsSL https://go.dev/dl/go1.23.5.linux-amd64.tar.gz -o go.tar.gz
104 tar xzf go.tar.gz
105 mv go /opt/data/.local/
106 rm -rf go.tar.gz
107 fi
108
109 if [ ! -f /opt/data/.local/homebrew/bin/brew ]; then
110 export HOMEBREW_PREFIX=/opt/data/.local/homebrew
111 mkdir -p $HOMEBREW_PREFIX
112 git clone --depth 1 https://github.com/Homebrew/brew $HOMEBREW_PREFIX
113 fi
114
115 if [ ! -f /opt/data/plugins/memini/plugin.yaml ]; then
116 mkdir -p /opt/data/plugins
117 cd /tmp
118 rm -rf memini-src
119 git clone --depth 1 --branch v0.7.14 https://github.com/eleboucher/memini memini-src
120 mv memini-src/integrations/hermes/plugin/memini /opt/data/plugins/memini
121 rm -rf memini-src
122 fi
123
124 if [ ! -f /opt/data/.local/bin/shellcheck ]; then
125 cd /tmp
126 curl -fsSL https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.linux.x86_64.tar.xz -o sc.tar.xz
127 tar xJf sc.tar.xz
128 cp shellcheck-v0.10.0/shellcheck /opt/data/.local/bin/
129 rm -rf sc.tar.xz shellcheck-v0.10.0
130 fi
131
132 if [ ! -f /opt/data/.local/bin/typescript-language-server ]; then
133 npm install -g --prefix /opt/data/.local \
134 typescript@5.7.2 typescript-language-server@4.3.3
135 fi
136
137 if [ ! -f /opt/data/.local/bin/yaml-language-server ]; then
138 npm install -g --prefix /opt/data/.local \
139 yaml-language-server@1.15.0
140 fi
141
142 if [ ! -f /opt/data/.local/bin/gopls ]; then
143 GOBIN=/opt/data/.local/bin \
144 GOPATH=/opt/data/go \
145 GOCACHE=/opt/data/.cache/go-build \
146 /opt/data/.local/go/bin/go install golang.org/x/tools/gopls@v0.17.1
147 fi
148
149 export HOME=/opt/data
150 export HERMES_HOME=/opt/data
151 HERMES=/opt/hermes/.venv/bin/hermes
152
153 $HERMES kanban init >/dev/null 2>&1 || true
154
155 if ! $HERMES kanban boards list 2>/dev/null | grep -qw home-ops; then
156 $HERMES kanban boards create home-ops --name "home-ops" || true
157 fi
158
159 if ! $HERMES project list 2>/dev/null | grep -qw home-ops; then
160 $HERMES project create "home-ops" \
161 /opt/data/workspace/home-ops \
162 /opt/data/workspace/home-ops-sync \
163 --slug home-ops \
164 --board home-ops \
165 --description "Flux-managed homelab cluster. Primary checkout plus the fork-sync clone." || true
166 fi
167
168 $HERMES bundles create briefing --force \
169 -s morning-briefing -s weather-forecast -s news-curated \
170 -s file-delivery-to-chat \
171 -d "Daily brief: weather, curated news, delivered to chat" || true
172
173 $HERMES bundles create cluster --force \
174 -s cluster-resource-pressure-investigation \
175 -s homelab-mcp-debugging -s home-ops-flux-app-template \
176 -s flux-operator-stack-debugging -s hermes-cron-debugging \
177 -d "Homelab cluster debugging: resource pressure, Flux, MCP, cron" || true
178
179 if ! $HERMES cron list 2>/dev/null | grep -q "weekly-digest"; then
180 $HERMES cron create "0 8 * * 1" \
181 --name weekly-digest \
182 --script weekly-digest-run.sh \
183 --no-agent \
184 --deliver local || true
185 fi
186 securityContext:
187 allowPrivilegeEscalation: false
188 capabilities:
189 drop:
190 - ALL
191 runAsGroup: 1000
192 runAsUser: 1000
193 containers:
194 app:
195 image:
196 repository: nousresearch/hermes-agent
197 tag: v2026.8.16.2@sha256:a39fc11620213e3669a327aff5c6cb1eb2b8a238c6044e33e7ef8885833d89a7
198 args:
199 - gateway
200 - run
201 - --no-supervise
202 env:
203 API_SERVER_ENABLED: "true"
204 API_SERVER_HOST: 0.0.0.0
205 API_SERVER_KEY:
206 valueFrom:
207 secretKeyRef:
208 name: hermes-config
209 key: API_SERVER_KEY
210 GOPATH: /opt/data/go
211 HERMES_GID: "1000"
212 HERMES_HOME: /opt/data
213 HERMES_UID: "1000"
214 HERMES_CRON_TIMEOUT: 0
215 HOME: /opt/data
216 HOMEBREW_CELLAR: /opt/data/.local/homebrew/Cellar
217 HOMEBREW_PREFIX: /opt/data/.local/homebrew
218 HOMEBREW_REPOSITORY: /opt/data/.local/homebrew
219 LITELLM_API_KEY:
220 valueFrom:
221 secretKeyRef:
222 name: hermes-config
223 key: LITELLM_API_KEY
224 MEMINI_BASE_URL: http://memini.ai.svc.cluster.local:8080
225 MEMINI_NAMESPACE: homelab
226 MEMINI_HOME: personal/jan
227 MEMINI_API_KEY:
228 valueFrom:
229 secretKeyRef:
230 name: hermes-config
231 key: MEMINI_API_KEY
232 HOMELAB_GH_TOKEN:
233 valueFrom:
234 secretKeyRef:
235 name: hermes-config
236 key: GH_TOKEN
237 PATH: /opt/hermes/.venv/bin:/opt/data/.local/bin:/opt/data/.local/go/bin:/opt/data/.local/homebrew/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
238 PIP_BREAK_SYSTEM_PACKAGES: "1"
239 SEARXNG_URL: http://searxng.selfhosted.svc.cluster.local:8080
240 SUMMARY_LLM_API_KEY:
241 valueFrom:
242 secretKeyRef:
243 name: hermes-config
244 key: LITELLM_API_KEY
245 SUMMARY_LLM_MODEL: opencode-go/hy3
246 SUMMARY_LLM_URL: http://litellm.ai:4000/v1
247 TERM: xterm-256color
248 TERMINAL_MAX_FOREGROUND_TIMEOUT: "1800"
249 HERMES_DASHBOARD: "1"
250 HERMES_DASHBOARD_PUBLIC_URL: https://hermes.janpuc.com
251 HERMES_DASHBOARD_OIDC_ISSUER: https://id.janpuc.com
252 envFrom:
253 - secretRef:
254 name: "{{ .Release.Name }}-oidc-credentials"
255 - secretRef:
256 name: hermes-matrix-access
257 resources:
258 requests:
259 cpu: 500m
260 memory: 1Gi
261 limits:
262 memory: 4Gi
263 securityContext:
264 allowPrivilegeEscalation: false
265 capabilities:
266 add:
267 - CHOWN
268 - DAC_OVERRIDE
269 - FOWNER
270 - FSETID
271 - SETGID
272 - SETUID
273 drop:
274 - ALL
275 readOnlyRootFilesystem: false
276 runAsGroup: 0
277 runAsNonRoot: false
278 runAsUser: 0
279 codeserver:
280 image:
281 repository: ghcr.io/coder/code-server
282 tag: 4.135.0@sha256:ccd326184d71efc5ebb94155eda7bb30153902342a35dbc8525450d81aa55012
283 args:
284 - --auth
285 - none
286 - --user-data-dir
287 - /opt/data/.vscode
288 - --extensions-dir
289 - /opt/data/.vscode
290 - --port
291 - "12321"
292 - /opt/data
293 env:
294 GH_TOKEN:
295 valueFrom:
296 secretKeyRef:
297 name: hermes-config
298 key: GH_TOKEN
299 resources:
300 requests:
301 cpu: 10m
302 limits:
303 memory: 1Gi
304 securityContext:
305 allowPrivilegeEscalation: false
306 capabilities:
307 drop:
308 - ALL
309 service:
310 app:
311 controller: hermes
312 ipFamilies:
313 - IPv4
314 ports:
315 codeserver:
316 port: 12321
317 gateway:
318 port: 8642
319 dashboard:
320 port: 9119
321 route:
322 app:
323 hostnames:
324 - hermes.janpuc.com
325 parentRefs:
326 - name: envoy-internal
327 namespace: network
328 rules:
329 - backendRefs:
330 - identifier: app
331 port: 9119
332 codeserver:
333 hostnames:
334 - hermes-code.janpuc.com
335 parentRefs:
336 - name: envoy-internal
337 namespace: network
338 rules:
339 - backendRefs:
340 - identifier: app
341 port: 12321
342 persistence:
343 agent-source:
344 type: emptyDir
345 advancedMounts:
346 hermes:
347 copy-agent-source:
348 - path: /agent-src
349 install-tools:
350 - path: /opt/hermes
351 app:
352 - path: /opt/hermes
353 data:
354 existingClaim: hermes
355 advancedMounts:
356 hermes:
357 init:
358 - path: /opt/data
359 install-tools:
360 - path: /opt/data
361 app:
362 - path: /opt/data
363 codeserver:
364 - path: /opt/data
365 config-yaml:
366 type: configMap
367 name: hermes-configmap
368 defaultMode: 0o755
369 advancedMounts:
370 hermes:
371 init:
372 - path: /run/config/config.yaml
373 subPath: config.yaml
374 - path: /run/config/home-ops-guard.py
375 subPath: home-ops-guard.py
376 - path: /run/config/matrix-post.py
377 subPath: matrix-post.py
378 - path: /run/config/weekly-digest.py
379 subPath: weekly-digest.py
380 - path: /run/config/weekly-digest-run.sh
381 subPath: weekly-digest-run.sh
382 config:
383 type: secret
384 name: hermes-config
385 defaultMode: 0o400
386 advancedMounts:
387 hermes:
388 init:
389 - path: /run/config/env
390 subPath: env
391 run:
392 type: emptyDir
393 advancedMounts:
394 hermes:
395 app:
396 - path: /run
397 tmp:
398 type: emptyDir
399 globalMounts:
400 - path: /tmp
401 rbac:
402 roles:
403 hermes-read-all:
404 type: ClusterRole
405 rules:
406 - apiGroups:
407 - ""
408 resources:
409 - pods
410 - pods/log
411 - nodes
412 - services
413 - namespaces
414 - configmaps
415 - persistentvolumes
416 - persistentvolumeclaims
417 - endpoints
418 - resourcequotas
419 - limitranges
420 - serviceaccounts
421 - events
422 verbs:
423 - "get"
424 - "list"
425 - "watch"
426 - apiGroups:
427 - "apps"
428 resources:
429 - deployments
430 - daemonsets
431 - statefulsets
432 - replicasets
433 - controllerrevisions
434 verbs:
435 - "get"
436 - "list"
437 - "watch"
438 - apiGroups:
439 - "batch"
440 resources:
441 - "jobs"
442 - "cronjobs"
443 verbs:
444 - "get"
445 - "list"
446 - "watch"
447 - apiGroups:
448 - "networking.k8s.io"
449 resources:
450 - "ingresses"
451 - "ingressclasses"
452 - "networkpolicies"
453 verbs:
454 - "get"
455 - "list"
456 - "watch"
457 - apiGroups:
458 - "storage.k8s.io"
459 resources:
460 - storageclasses
461 - csinodes
462 - csidrivers
463 - volumeattachments
464 verbs:
465 - "get"
466 - "list"
467 - "watch"
468 - apiGroups:
469 - "helm.toolkit.fluxcd.io"
470 resources:
471 - "helmreleases"
472 verbs:
473 - "get"
474 - "list"
475 - "watch"
476 - apiGroups:
477 - "kustomize.toolkit.fluxcd.io"
478 resources:
479 - "kustomizations"
480 verbs:
481 - "get"
482 - "list"
483 - "watch"
484 - apiGroups:
485 - "source.toolkit.fluxcd.io"
486 resources:
487 - gitrepositories
488 - helmrepositories
489 - ocirepositories
490 - buckets
491 - helmcharts
492 verbs:
493 - "get"
494 - "list"
495 - "watch"
496 - apiGroups:
497 - "external-secrets.io"
498 resources:
499 - externalsecrets
500 - secretstores
501 - clustersecretstores
502 verbs:
503 - "get"
504 - "list"
505 - "watch"
506 - apiGroups:
507 - "miroir.home-operations.com"
508 resources:
509 - miroirvolumes
510 - miroirnodes
511 - miroirnodegroups
512 - miroirsnapshots
513 - miroirsnapshotgroups
514 verbs:
515 - "get"
516 - "list"
517 - "watch"
518 - apiGroups:
519 - "kopiur.home-operations.com"
520 resources:
521 - snapshots
522 - snapshotpolicies
523 - snapshotschedules
524 - restores
525 - repositories
526 - clusterrepositories
527 verbs:
528 - "get"
529 - "list"
530 - "watch"
531 - apiGroups:
532 - "cert-manager.io"
533 resources:
534 - certificates
535 - certificaterequests
536 - issuers
537 - clusterissuers
538 verbs:
539 - "get"
540 - "list"
541 - "watch"
542 - apiGroups:
543 - "metrics.k8s.io"
544 resources:
545 - nodes
546 - pods
547 verbs:
548 - "get"
549 - "list"
550 hermes-pod-delete:
551 type: ClusterRole
552 rules:
553 - apiGroups:
554 - ""
555 resources:
556 - "pods"
557 verbs:
558 - "delete"
559 hermes-exec-deploy:
560 type: Role
561 rules:
562 - apiGroups:
563 - ""
564 resources:
565 - "pods/exec"
566 verbs:
567 - "create"
568 - apiGroups:
569 - "apps"
570 resources:
571 - "deployments"
572 verbs:
573 - "patch"
574 - "update"
575 bindings:
576 hermes-read-all:
577 type: ClusterRoleBinding
578 roleRef:
579 identifier: hermes-read-all
580 subjects:
581 - identifier: hermes
582 serviceAccount: hermes
583 hermes-pod-delete:
584 type: ClusterRoleBinding
585 roleRef:
586 identifier: hermes-pod-delete
587 subjects:
588 - identifier: hermes
589 serviceAccount: hermes
590 hermes-exec-deploy:
591 type: RoleBinding
592 roleRef:
593 identifier: hermes-exec-deploy
594 subjects:
595 - identifier: hermes
596 serviceAccount: hermes
597 namespace: ai
598 serviceAccount:
599 hermes: {}

Find an annotation

Search file paths, rationale, kinds, and authors.

↑↓ moveEnter openEsc close