# Hermes Agent (Nous Research) as a read-only "conversational analyst" for a
# Proxmox node, plus a small webhook receiver for Alertmanager. The scripts
# the agent runs (proxmox_review.py, guest_audit.py, alerts_report.py) are
# mounted read-only as tools and called from skills.
#
# The security boundary is NOT the list of allowed skills; it is what the
# container has: only an audit-only Proxmox token (Proxmox itself refuses
# changing calls), no docker.sock, no ssh keys, and terminal.backend=local,
# which means the model's commands run inside THIS container (it is the
# sandbox) and writes land in /opt/data only.
name: hermes

services:
  hermes:
    image: ${HERMES_IMAGE:-nousresearch/hermes-agent:latest}   # v0.20.1 on 2026-08-15
    container_name: hermes
    restart: unless-stopped
    command: ["gateway", "run"]
    environment:
      - HERMES_UID=10000
      - HERMES_GID=10000
      - TZ=${TZ:-Europe/Warsaw}
    volumes:
      # Hermes state: config.yaml, .env (secrets), SOUL.md, skills/, memory,
      # sessions, reports/ and alerts/alerts.db
      - ./data:/opt/data
      # our scripts, read-only; invoked from skills via /opt/data/bin/agent
      - ./agents:/opt/tools/agents:ro
    networks:
      agents:
        ipv4_address: 10.0.4.91
      litellm: {}
    security_opt: [no-new-privileges:true]
    mem_limit: 2g
    cpus: 1.5
    pids_limit: 512
    stop_grace_period: 30s
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  # --- Alertmanager webhook -> SQLite archive (stdlib only) ---
  # No separate image: reuse the Hermes image for its python 3.13.
  alert-sink:
    image: ${HERMES_IMAGE:-nousresearch/hermes-agent:latest}
    container_name: alert-sink
    restart: unless-stopped
    entrypoint: ["/opt/hermes/.venv/bin/python", "/opt/tools/agents/alert_sink.py"]
    environment:
      - ALERTS_DB=/opt/data/alerts/alerts.db
      - ALERT_SINK_ADDR=0.0.0.0:9099
      - ALERT_SINK_TOKEN=${ALERT_SINK_TOKEN:-}
      - ALERTS_KEEP_DAYS=${ALERTS_KEEP_DAYS:-120}
      - TZ=${TZ:-Europe/Warsaw}
    volumes:
      - ./agents:/opt/tools/agents:ro
      - ./data/alerts:/opt/data/alerts     # the same folder hermes sees as /opt/data/alerts
    networks:
      monitoring: {}                       # so alertmanager reaches it by name
    security_opt: [no-new-privileges:true]
    mem_limit: 256m
    cpus: 0.3
    pids_limit: 64
    healthcheck:
      test: ["CMD", "/opt/hermes/.venv/bin/python", "-c",
             "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:9099/health', timeout=5).status==200 else 1)"]
      interval: 60s
      timeout: 10s
      retries: 3
      start_period: 15s
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

networks:
  # Own network (a free /29 in the host's 10.0.4.0/24 plan): egress to the
  # internet (Telegram) and to the Proxmox API.
  agents:
    name: agents
    ipam:
      config:
        - subnet: 10.0.4.88/29
          gateway: 10.0.4.89
  # LiteLLM: http://litellm:4000
  litellm:
    name: litellm-internal
    external: true
  # the monitoring stack's network; only alert-sink needs it
  monitoring:
    name: monitoring
    external: true
