Files
simbarag/docker-compose.yml
T
ryan b02bf0a6df
CI / backend (pull_request) Successful in 42s
CI / frontend (pull_request) Failing after 6s
CI / backend (push) Successful in 41s
CI / frontend (push) Failing after 7s
Sync Obsidian both ways so notes Simba writes reach your devices
The container ran Obsidian Sync in pull-only mode, so notes, tasks and journal
entries the agent wrote stayed in its local copy. OBSIDIAN_SYNC_MODE now
defaults to bidirectional (merge on conflict); pull-only and mirror-remote
remain available.

Blue and green share the vault volume, and two sync clients writing one vault
and its sync state would race during a deploy. Setup and sync now run under a
flock on a file in the vault, so a new container starts syncing only after the
old container's sync process exits. Clearing Obsidian's stale sync lock is safe
inside that lock. Setup runs in the background, so startup no longer waits for
Obsidian login.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 08:10:48 -04:00

161 lines
6.5 KiB
YAML

x-raggr-common: &raggr-common
build:
context: .
dockerfile: Dockerfile
image: torrtle/simbarag:latest
environment:
- METRICS_TOKEN=${METRICS_TOKEN:-}
- TTFT_TIMEOUT_SECONDS=${TTFT_TIMEOUT_SECONDS:-30}
- LLAMA_TIMEOUT_SECONDS=${LLAMA_TIMEOUT_SECONDS:-120}
- CONTEXT_WINDOW_TOKENS=${CONTEXT_WINDOW_TOKENS:-32768}
- PROMPT_BUDGET_TOKENS=${PROMPT_BUDGET_TOKENS:-16000}
- RESPONSE_RESERVE_TOKENS=${RESPONSE_RESERVE_TOKENS:-4096}
- CHECKPOINT_DB_PATH=${CHECKPOINT_DB_PATH:-/app/checkpoints/checkpoints.db}
- CHECKPOINT_KEEP_PER_THREAD=${CHECKPOINT_KEEP_PER_THREAD:-20}
- CONVERSATION_SUMMARY_DB_PATH=${CONVERSATION_SUMMARY_DB_PATH:-${CHECKPOINT_DB_PATH:-/app/checkpoints/checkpoints.db}.summaries.db}
- CHAT_RUN_LEASE_SECONDS=${CHAT_RUN_LEASE_SECONDS:-30}
- CHAT_RUN_MAX_SECONDS=${CHAT_RUN_MAX_SECONDS:-1800}
- CHAT_RUN_DRAIN_SECONDS=${CHAT_RUN_DRAIN_SECONDS:-1800}
- OBSIDIAN_SYNC_INTERVAL=${OBSIDIAN_SYNC_INTERVAL:-60}
- OIDC_AUTHORIZATION_ENDPOINT=${OIDC_AUTHORIZATION_ENDPOINT:-}
- OIDC_TOKEN_ENDPOINT=${OIDC_TOKEN_ENDPOINT:-}
- OIDC_USERINFO_ENDPOINT=${OIDC_USERINFO_ENDPOINT:-}
- OIDC_JWKS_URI=${OIDC_JWKS_URI:-}
- EMAIL_HMAC_SECRET=${EMAIL_HMAC_SECRET:-}
- WHATSAPP_RATE_LIMIT_MAX=${WHATSAPP_RATE_LIMIT_MAX:-10}
- WHATSAPP_RATE_LIMIT_WINDOW=${WHATSAPP_RATE_LIMIT_WINDOW:-60}
- IMESSAGE_RATE_LIMIT_MAX=${IMESSAGE_RATE_LIMIT_MAX:-10}
- IMESSAGE_RATE_LIMIT_WINDOW=${IMESSAGE_RATE_LIMIT_WINDOW:-60}
- PAPERLESS_TOKEN=${PAPERLESS_TOKEN}
- BASE_URL=${BASE_URL}
- OLLAMA_URL=${OLLAMA_URL:-http://localhost:11434}
- OPENAI_API_KEY=${OPENAI_API_KEY}
- EMBEDDING_SERVER_URL=${EMBEDDING_SERVER_URL}
- EMBEDDING_MODEL_NAME=${EMBEDDING_MODEL_NAME:-text-embedding-3-small}
- JWT_SECRET_KEY=${JWT_SECRET_KEY}
- LLAMA_SERVER_URL=${LLAMA_SERVER_URL}
- LLAMA_MODEL_NAME=${LLAMA_MODEL_NAME:-llama-3.1-8b-instruct}
- TOOL_ROUTING_MODE=${TOOL_ROUTING_MODE:-static}
- OIDC_ISSUER=${OIDC_ISSUER}
- OIDC_CLIENT_ID=${OIDC_CLIENT_ID}
- OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET}
- OIDC_REDIRECT_URI=${OIDC_REDIRECT_URI}
- OIDC_USE_DISCOVERY=${OIDC_USE_DISCOVERY:-true}
- DATABASE_URL=${DATABASE_URL:-postgres://raggr:changeme@postgres:5432/raggr}
- TAVILY_API_KEY=${TAVILY_API_KEY:-${TAVILIY_API_KEY:-}}
- YNAB_ACCESS_TOKEN=${YNAB_ACCESS_TOKEN}
- YNAB_BUDGET_ID=${YNAB_BUDGET_ID}
- YNAB_SYNC_INTERVAL=${YNAB_SYNC_INTERVAL:-90}
- MEALIE_BASE_URL=${MEALIE_BASE_URL}
- MEALIE_API_TOKEN=${MEALIE_API_TOKEN}
- MEALIE_GROUP_SLUG=${MEALIE_GROUP_SLUG:-home}
- TWILIO_ACCOUNT_SID=${TWILIO_ACCOUNT_SID}
- TWILIO_AUTH_TOKEN=${TWILIO_AUTH_TOKEN}
- TWILIO_WHATSAPP_NUMBER=${TWILIO_WHATSAPP_NUMBER}
- ALLOWED_WHATSAPP_NUMBERS=${ALLOWED_WHATSAPP_NUMBERS}
- TWILIO_SIGNATURE_VALIDATION=${TWILIO_SIGNATURE_VALIDATION:-true}
- TWILIO_WEBHOOK_URL=${TWILIO_WEBHOOK_URL:-}
- OBSIDIAN_EMAIL=${OBSIDIAN_EMAIL}
- OBSIDIAN_PASSWORD=${OBSIDIAN_PASSWORD}
- OBSIDIAN_VAULT_ID=${OBSIDIAN_VAULT_ID}
- OBSIDIAN_E2E_PASSWORD=${OBSIDIAN_E2E_PASSWORD}
- OBSIDIAN_DEVICE_NAME=${OBSIDIAN_DEVICE_NAME}
- OBSIDIAN_CONTINUOUS_SYNC=${OBSIDIAN_CONTINUOUS_SYNC:-false}
- OBSIDIAN_SYNC_MODE=${OBSIDIAN_SYNC_MODE:-bidirectional}
- OBSIDIAN_VAULT_PATH=${OBSIDIAN_VAULT_PATH:-/app/data/obsidian}
- OBSIDIAN_VAULT_NAME=${OBSIDIAN_VAULT_NAME:-}
- S3_ENDPOINT_URL=${S3_ENDPOINT_URL}
- S3_ACCESS_KEY_ID=${S3_ACCESS_KEY_ID}
- S3_SECRET_ACCESS_KEY=${S3_SECRET_ACCESS_KEY}
- S3_BUCKET_NAME=${S3_BUCKET_NAME:-asksimba-images}
- S3_REGION=${S3_REGION:-garage}
- OLLAMA_HOST=${OLLAMA_HOST:-http://localhost:11434}
- FERNET_KEY=${FERNET_KEY}
- GOOGLE_TOKEN_FILE=${GOOGLE_TOKEN_FILE:-/app/config/google-token.json}
- MAILGUN_API_KEY=${MAILGUN_API_KEY}
- MAILGUN_DOMAIN=${MAILGUN_DOMAIN}
- MAILGUN_WEBHOOK_SIGNING_KEY=${MAILGUN_WEBHOOK_SIGNING_KEY}
- MAILGUN_SIGNATURE_VALIDATION=${MAILGUN_SIGNATURE_VALIDATION:-true}
- EMAIL_RATE_LIMIT_MAX=${EMAIL_RATE_LIMIT_MAX:-5}
- EMAIL_RATE_LIMIT_WINDOW=${EMAIL_RATE_LIMIT_WINDOW:-300}
- SENDBLUE_API_KEY=${SENDBLUE_API_KEY}
- SENDBLUE_API_SECRET=${SENDBLUE_API_SECRET}
- SENDBLUE_FROM_NUMBER=${SENDBLUE_FROM_NUMBER}
- SENDBLUE_WEBHOOK_SECRET=${SENDBLUE_WEBHOOK_SECRET}
- SENDBLUE_SIGNATURE_VALIDATION=${SENDBLUE_SIGNATURE_VALIDATION:-true}
- ALLOWED_IMESSAGE_NUMBERS=${ALLOWED_IMESSAGE_NUMBERS}
- SIMBAKIT_URL=${SIMBAKIT_URL:-http://simbakit:8585}
- CRON_SECRET=${CRON_SECRET}
- CRONICLE_URL=${CRONICLE_URL:-http://cronicle:3012}
- CRONICLE_API_KEY=${CRONICLE_API_KEY}
- HOMEBOX_URL=${HOMEBOX_URL}
- HOMEBOX_TOKEN=${HOMEBOX_TOKEN}
- BOOKSTACK_BASE_URL=${BOOKSTACK_BASE_URL}
- BOOKSTACK_TOKEN_ID=${BOOKSTACK_TOKEN_ID}
- BOOKSTACK_TOKEN_SECRET=${BOOKSTACK_TOKEN_SECRET}
depends_on:
postgres:
condition: service_healthy
volumes:
- ./obvault:/app/data/obsidian
- ./token.json:/app/config/google-token.json:ro
- raggr-checkpoints:/app/checkpoints
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/api/health"]
interval: 5s
timeout: 5s
retries: 3
start_period: 60s
restart: unless-stopped
services:
postgres:
image: pgvector/pgvector:pg16
ports:
- "5432:5432"
environment:
- POSTGRES_USER=${POSTGRES_USER:-raggr}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-changeme}
- POSTGRES_DB=${POSTGRES_DB:-raggr}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./docker/init-pgvector.sql:/docker-entrypoint-initdb.d/init-pgvector.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-raggr}"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
# Blue-green deployment: exactly one of raggr-blue/raggr-green serves at a
# time; Caddy health-checks both ports and routes to the healthy one.
# Use scripts/deploy.sh (make redeploy) to swap colors with zero downtime.
raggr-blue:
<<: *raggr-common
profiles: ["blue"]
ports:
- "8080:8080"
raggr-green:
<<: *raggr-common
profiles: ["green"]
ports:
- "8081:8080"
simbakit:
build:
context: ./simbakit
restart: unless-stopped
volumes:
- simbakit-data:/app/data
environment:
- PETKIT_USERNAME=${PETKIT_USERNAME}
- PETKIT_PASSWORD=${PETKIT_PASSWORD}
- PETKIT_REGION=${PETKIT_REGION:-US}
- PETKIT_TIMEZONE=${PETKIT_TIMEZONE:-America/New_York}
volumes:
postgres_data:
simbakit-data:
raggr-checkpoints: