# services/hermes-chat/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: hermes-chat namespace: hermes-chat labels: app: hermes-chat spec: replicas: 1 revisionHistoryLimit: 2 progressDeadlineSeconds: 1800 strategy: type: Recreate selector: matchLabels: app: hermes-chat template: metadata: labels: app: hermes-chat annotations: ai.bstein.dev/model: openai-codex/gpt-5.6-terra with local gpt-oss:20b fallback ai.bstein.dev/role: personal-chat-research ai.bstein.dev/isolation: observer-only Kubernetes RBAC, private-service egress denied ai.bstein.dev/session-reset: "20260802-consumer-pty-recovery" ai.bstein.dev/frontend-fix: scope PTY attachment by selected conversation ai.bstein.dev/user-boundary: one OIDC subject with an isolated PVC subdirectory spec: serviceAccountName: hermes-chat automountServiceAccountToken: true securityContext: fsGroup: 10000 fsGroupChangePolicy: OnRootMismatch seccompProfile: type: RuntimeDefault affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/arch operator: In values: - arm64 - key: node-role.kubernetes.io/worker operator: In values: - "true" - key: kubernetes.io/hostname operator: NotIn values: - titan-13 - titan-15 - titan-17 - titan-18 - titan-19 preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 preference: matchExpressions: - key: atlas.bstein.dev/spillover operator: DoesNotExist - weight: 90 preference: matchExpressions: - key: hardware operator: In values: - rpi5 - weight: 50 preference: matchExpressions: - key: hardware operator: In values: - rpi4 initContainers: - name: migrate-user-sessions image: registry.bstein.dev/bstein/hermes-agent@sha256:15c5c538c0b58686af2e54e10bc870b23284789d485a609349df24ed3053622f imagePullPolicy: IfNotPresent command: - /opt/hermes/bin/hermes-session-migrate env: - name: HERMES_HOME value: /storage/users/4794ab8284a14d421eaeea3e - name: HERMES_MIGRATE_SOURCE_HOME value: /storage - name: HERMES_MIGRATE_USER_ID value: 26b56113-0ec5-40b0-be7d-c2cd862f9bbc - name: HERMES_MIGRATE_SESSION_IDS value: 20260802_182723_9f53f1,20260802_173527_9dc51b securityContext: allowPrivilegeEscalation: false runAsUser: 10000 runAsGroup: 10000 seccompProfile: type: RuntimeDefault volumeMounts: - name: home mountPath: /storage resources: requests: cpu: 25m memory: 64Mi limits: cpu: 250m memory: 256Mi - name: init-config image: busybox:1.37 imagePullPolicy: IfNotPresent command: - sh - -c - | set -eu user_home=/storage/users/4794ab8284a14d421eaeea3e mkdir -p "${user_home}/workspace/skills" "${user_home}/home/.local/bin" "${user_home}/logs" cp /config/config.yaml "${user_home}/config.yaml" cp /config/SOUL.md "${user_home}/SOUL.md" cp /config/AGENTS.md "${user_home}/workspace/AGENTS.md" touch "${user_home}/.env" if ! grep -q '^API_SERVER_KEY=' "${user_home}/.env"; then api_key="$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | od -An -tx1 | tr -d ' \n')" printf '\nAPI_SERVER_KEY=%s\n' "${api_key}" >> "${user_home}/.env" fi chmod 0600 "${user_home}/.env" chown -R 10000:10000 "${user_home}" securityContext: allowPrivilegeEscalation: false runAsUser: 0 runAsGroup: 0 seccompProfile: type: RuntimeDefault volumeMounts: - name: home mountPath: /storage - name: config mountPath: /config readOnly: true resources: requests: cpu: 25m memory: 32Mi limits: cpu: 100m memory: 64Mi - name: install-kubectl image: bitnami/kubectl@sha256:554ab88b1858e8424c55de37ad417b16f2a0e65d1607aa0f3fe3ce9b9f10b131 imagePullPolicy: IfNotPresent command: - /bin/sh - -c - | set -eu cp "$(command -v kubectl)" /tools/kubectl chmod 0755 /tools/kubectl chown 10000:10000 /tools/kubectl securityContext: allowPrivilegeEscalation: false runAsUser: 0 runAsGroup: 0 seccompProfile: type: RuntimeDefault volumeMounts: - name: tools mountPath: /tools resources: requests: cpu: 25m memory: 32Mi limits: cpu: 100m memory: 64Mi containers: - name: hermes-chat image: registry.bstein.dev/bstein/hermes-agent@sha256:15c5c538c0b58686af2e54e10bc870b23284789d485a609349df24ed3053622f imagePullPolicy: IfNotPresent args: - gateway - run ports: - name: dashboard containerPort: 9119 protocol: TCP env: - name: HERMES_HOME value: /opt/data - name: HOME value: /opt/data/home - name: PATH value: /opt/data/home/.local/bin:/opt/hermes/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - name: HERMES_DASHBOARD value: "1" - name: HERMES_DASHBOARD_HOST value: 0.0.0.0 - name: HERMES_DASHBOARD_PORT value: "9119" - name: HERMES_DASHBOARD_PUBLIC_URL value: https://chat.bstein.dev - name: HERMES_DASHBOARD_OIDC_ISSUER value: https://sso.bstein.dev/realms/atlas - name: HERMES_DASHBOARD_OIDC_CLIENT_ID value: hermes-chat-dashboard - name: HERMES_DASHBOARD_OIDC_SCOPES value: openid profile email groups - name: HERMES_DASHBOARD_OIDC_ALLOWED_USER_IDS value: 26b56113-0ec5-40b0-be7d-c2cd862f9bbc - name: API_SERVER_ENABLED value: "true" - name: API_SERVER_HOST value: 0.0.0.0 - name: API_SERVER_PORT value: "8642" - name: API_SERVER_CORS_ORIGINS value: https://chat.bstein.dev volumeMounts: - name: home mountPath: /opt/data subPath: users/4794ab8284a14d421eaeea3e - name: tools mountPath: /usr/local/bin/kubectl subPath: kubectl readinessProbe: httpGet: path: /api/status port: dashboard initialDelaySeconds: 30 periodSeconds: 10 timeoutSeconds: 5 livenessProbe: httpGet: path: /api/status port: dashboard initialDelaySeconds: 90 periodSeconds: 30 timeoutSeconds: 10 securityContext: allowPrivilegeEscalation: false seccompProfile: type: RuntimeDefault resources: requests: cpu: 100m memory: 768Mi ephemeral-storage: 256Mi limits: cpu: "1" memory: 2Gi ephemeral-storage: 1Gi volumes: - name: home persistentVolumeClaim: claimName: hermes-chat-home - name: config configMap: name: hermes-chat-config - name: tools emptyDir: {}