141 lines
5.0 KiB
YAML
141 lines
5.0 KiB
YAML
x-restart: &restart
|
||
restart: unless-stopped
|
||
|
||
services:
|
||
postgres:
|
||
image: postgres:16-alpine
|
||
profiles: [db]
|
||
<<: *restart
|
||
env_file: .env
|
||
volumes:
|
||
- postgres-data:/var/lib/postgresql/data
|
||
ports:
|
||
- "127.0.0.1:${PORT_POSTGRES:-5432}:5432"
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
||
interval: 5s
|
||
timeout: 3s
|
||
retries: 20
|
||
|
||
obsidian-headless:
|
||
container_name: beaver-obsidian
|
||
build:
|
||
context: .
|
||
dockerfile: obsidian.Dockerfile
|
||
profiles: [obsidian]
|
||
<<: *restart
|
||
volumes:
|
||
- vault:/vault
|
||
- obsidian-config:/root/.config
|
||
working_dir: /vault
|
||
|
||
gateway:
|
||
container_name: beaver-gateway
|
||
build:
|
||
context: https://git.kotikot.com/beaver/beaver-gateway.git#${GATEWAY_REF:-main}
|
||
profiles: [gateway]
|
||
<<: *restart
|
||
depends_on:
|
||
postgres:
|
||
condition: service_healthy
|
||
env_file: .env
|
||
environment:
|
||
CONFIG_PATH: /config/config.py
|
||
DATABASE_URL: postgresql+psycopg://${POSTGRES_USER:-beaver}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-beaver}
|
||
RAYCAST_CONFIG_PATH: /config/config.json
|
||
# Процесс модели: свой uid, свой HOME (там ~/.claude), белый список env
|
||
# собирает адаптер. В env модели нет DATABASE_URL, POSTGRES_*, *_PAT.
|
||
CLAUDE_RUNNER_USER: beaver-runner
|
||
CLAUDE_HOME: /home/beaver-runner
|
||
ports:
|
||
# один порт: /anthropic, /mcp, /admin, /api, /md, / -> админка
|
||
- "${PORT_GATEWAY:-62990}:62990"
|
||
volumes:
|
||
- ./config.py:/config/config.py:ro
|
||
- ./policy.py:/config/policy.py:ro
|
||
- ./mcps:/config/mcps:ro
|
||
- ./config.json:/config/config.json:ro
|
||
# §3.7: vault - дом диспетчера, rw целиком; границы (`.obsidian`,
|
||
# `мета` вне `бобер`, удаление чужого) держит policy.py (2026-08-30).
|
||
- vault:/vault
|
||
# клон репы комнаты вайбграма (сервис vibegram-repo), только читать
|
||
- vibegram:/vibegram:ro
|
||
- claude-home:/home/beaver-runner/.claude
|
||
extra_hosts:
|
||
# Home Assistant и прочее с network_mode: host
|
||
- "host.docker.internal:host-gateway"
|
||
healthcheck:
|
||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:62990/healthz', timeout=3)"]
|
||
interval: 30s
|
||
timeout: 5s
|
||
start_period: 60s
|
||
retries: 3
|
||
entrypoint:
|
||
- /bin/sh
|
||
- -c
|
||
- |
|
||
set -e
|
||
runner=beaver-runner
|
||
mkdir -p /home/$$runner/.claude
|
||
[ -e /home/$$runner/.claude/.claude.json ] || echo '{}' > /home/$$runner/.claude/.claude.json
|
||
chown -R $$runner /home/$$runner
|
||
# ACL, не chown: Obsidian Sync переписывает файлы под root, а default-ACL
|
||
# на папках даёт runner'у права и на то, что появится позже.
|
||
setfacl -R -m "u:$$runner:rwX" -m "d:u:$$runner:rwX" /vault \
|
||
|| echo "warning: cannot grant $$runner write access to /vault"
|
||
exec python -m beaver_gateway
|
||
|
||
t3code-mcp:
|
||
container_name: beaver-t3code-mcp
|
||
build:
|
||
context: https://git.kotikot.com/beaver/t3code-mcp.git#${T3CODE_MCP_REF:-main}
|
||
profiles: [t3]
|
||
<<: *restart
|
||
env_file: .env
|
||
environment:
|
||
# события тредов (завершён / упал / спрашивает) → инжект в мастер (§4.5)
|
||
T3CODE_MCP_HOOK_URL: http://gateway:62990/hooks/t3code
|
||
T3CODE_MCP_STATE: /data/t3code-mcp.json
|
||
volumes:
|
||
- ./t3code.toml:/config/t3code.toml:ro
|
||
- t3code-state:/data
|
||
|
||
vibegram-repo:
|
||
container_name: beaver-vibegram-repo
|
||
image: alpine/git:latest
|
||
profiles: [vibegram]
|
||
<<: *restart
|
||
env_file: .env
|
||
volumes:
|
||
- vibegram:/vibegram
|
||
# Клон репы комнаты и pull раз в 10 минут. Токен - только заголовком
|
||
# через GIT_CONFIG_*, в .git/config он не попадает: том читает модель.
|
||
entrypoint:
|
||
- /bin/sh
|
||
- -c
|
||
- |
|
||
repo="$${VIBEGRAM_REPO:?VIBEGRAM_REPO=org/repo}"
|
||
dir="/vibegram/$${repo##*/}"
|
||
if [ -n "$$VIBEGRAM_REPO_TOKEN" ]; then
|
||
export GIT_CONFIG_COUNT=1
|
||
export GIT_CONFIG_KEY_0="http.https://github.com/.extraheader"
|
||
export GIT_CONFIG_VALUE_0="AUTHORIZATION: basic $$(printf 'x-access-token:%s' "$$VIBEGRAM_REPO_TOKEN" | base64 | tr -d '\n')"
|
||
fi
|
||
while true; do
|
||
if [ -d "$$dir/.git" ]; then
|
||
git -C "$$dir" pull -q --ff-only || echo "vibegram-repo: pull failed"
|
||
else
|
||
git clone -q "https://github.com/$$repo.git" "$$dir" || echo "vibegram-repo: clone failed"
|
||
fi
|
||
chmod -R a+rX "$$dir" 2>/dev/null
|
||
sleep "$${VIBEGRAM_PULL_SECONDS:-600}"
|
||
done
|
||
|
||
volumes:
|
||
t3code-state:
|
||
postgres-data:
|
||
vault:
|
||
vibegram:
|
||
obsidian-config:
|
||
claude-home:
|