# AIFRED stack: the agent, an OpenBao server that holds the key for stored secrets, and an # optional SearXNG (profile "search"). First run: scripts/setup.sh (see docs/deploy.md). name: aifred services: aifred: image: ${AIFRED_IMAGE:-aifred}:${AIFRED_VERSION:-0.10.0} # AIFRED_IMAGE=lordraw/aifred uses the published image (see docs/deploy.md) build: context: . args: VERSION: ${AIFRED_VERSION:-0.10.0} # no `init: true`: AIFRED itself is PID 1 so that /proc/1/environ (which holds the OpenBao # credentials) is protected by its hardening, and it reaps the orphans of terminal commands. restart: unless-stopped depends_on: - openbao ports: - "${AIFRED_BIND:-127.0.0.1}:${AIFRED_PORT:-8700}:8700" # Only these variables reach the container; anything else in .env stays on the host. environment: AIFRED_ADMIN_USER: ${AIFRED_ADMIN_USER:-} AIFRED_ADMIN_PASSWORD: ${AIFRED_ADMIN_PASSWORD:-} AIFRED_SECRETS_BACKEND: openbao AIFRED_OPENBAO_ADDR: ${AIFRED_OPENBAO_ADDR:-http://openbao:8200} AIFRED_OPENBAO_ROLE_ID: ${AIFRED_OPENBAO_ROLE_ID:-} AIFRED_OPENBAO_SECRET_ID: ${AIFRED_OPENBAO_SECRET_ID:-} AIFRED_OPENBAO_MOUNT: ${AIFRED_OPENBAO_MOUNT:-transit} AIFRED_OPENBAO_KEY: ${AIFRED_OPENBAO_KEY:-aifred} volumes: - aifred-data:/data read_only: true tmpfs: - /tmp:size=64m,mode=1777 cap_drop: [ALL] security_opt: ["no-new-privileges:true"] mem_limit: ${AIFRED_MEM_LIMIT:-1g} # the knowledge base keeps vectors in memory; see docs/deploy.md pids_limit: 256 # bounds a fork bomb started from the terminal tool extra_hosts: - "host.docker.internal:host-gateway" # reach Ollama/vLLM on the Docker host networks: [default, vault] openbao: image: openbao/openbao:${OPENBAO_VERSION:-2.7.1} command: server user: "100:1000" # the image's own openbao user; the entrypoint then needs no extra privileges restart: unless-stopped environment: BAO_ADDR: http://127.0.0.1:8200 volumes: - openbao-data:/openbao/file - openbao-logs:/openbao/logs - ./deploy/openbao/config.hcl:/openbao/config/config.hcl:ro read_only: true tmpfs: - /tmp:size=16m cap_drop: [ALL] security_opt: ["no-new-privileges:true"] mem_limit: 256m pids_limit: 128 networks: [vault] # no published port and no route to the outside healthcheck: # healthy when the server answers, sealed or not (bao status: 0 unsealed, 2 sealed, 1 error) test: ["CMD-SHELL", "bao status >/dev/null 2>&1; [ $$? -ne 1 ]"] interval: 15s timeout: 5s retries: 5 start_period: 5s searxng: profiles: [search] image: searxng/searxng:${SEARXNG_VERSION:-2026.10.24-ef0ec03da} restart: unless-stopped environment: SEARXNG_SECRET: ${SEARXNG_SECRET:-} # generated by scripts/setup.sh; SearXNG refuses to start without a real one volumes: - ./deploy/searxng/settings.yml:/etc/searxng/settings.yml:ro cap_drop: [ALL] cap_add: [CHOWN, SETGID, SETUID] security_opt: ["no-new-privileges:true"] mem_limit: 512m # reached by AIFRED at http://searxng:8080 (set SEARXNG_URL on the Config page) networks: vault: internal: true # OpenBao and AIFRED talk here; no egress, not reachable from the LAN volumes: aifred-data: openbao-data: openbao-logs: