Files
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

229 lines
9.0 KiB
Bash

# Database Configuration
# PostgreSQL with pgvector is required; production rejects default passwords.
DATABASE_URL=postgres://raggr:replace-with-random-password@postgres:5432/raggr
# PostgreSQL credentials (if using docker-compose postgres service)
POSTGRES_USER=raggr
POSTGRES_PASSWORD=replace-with-random-password
POSTGRES_DB=raggr
# JWT Configuration
# Required: generate a random secret with openssl rand -hex 32
JWT_SECRET_KEY=
# Metrics Configuration
# Bearer token for the /metrics endpoint (Prometheus scrape + app token gate).
# Generate with: openssl rand -hex 32
# Leave empty to keep /metrics returning 403 (fail-closed).
METRICS_TOKEN=
# Paperless Configuration
PAPERLESS_TOKEN=
# Current Paperless clients prepend http://; use host[:port] without a scheme.
BASE_URL=
# llama-server Configuration (OpenAI-compatible API)
# If set, uses llama-server as the primary LLM backend with OpenAI as fallback
LLAMA_SERVER_URL=
LLAMA_MODEL_NAME=llama-3.1-8b-instruct
LLAMA_TIMEOUT_SECONDS=120
# Abandon a turn when an in-flight model call produces no output (prefill included)
# for this long. Thinking tokens count as output, so long reasoning is fine.
TTFT_TIMEOUT_SECONDS=30
# Context estimates include system instructions and tool definitions.
# Set the window to the smallest backend context; leave room for generation.
CONTEXT_WINDOW_TOKENS=32768
PROMPT_BUDGET_TOKENS=16000
RESPONSE_RESERVE_TOKENS=4096
# static: bind every role-appropriate tool on each call (stable, cacheable prompt
# prefix). dynamic: keyword-route tool groups per call with a discovery tool.
TOOL_ROUTING_MODE=static
# Optional durable summary sidecar; defaults to CHECKPOINT_DB_PATH + .summaries.db
# Store on the same persistent shared volume as the checkpoints.
# CONVERSATION_SUMMARY_DB_PATH=/app/checkpoints/conversation-summaries.db
# Durable chat runs (see docs/chat-runs.md). Lease = abandoned-worker timeout;
# max = whole generation; drain = shutdown wait for in-flight generations.
# scripts/deploy.sh gives the old container drain + 60s (override DEPLOY_STOP_SECONDS).
CHAT_RUN_LEASE_SECONDS=30
CHAT_RUN_MAX_SECONDS=1800
CHAT_RUN_DRAIN_SECONDS=1800
# Embedding Server Configuration
# If set, uses a custom OpenAI-compatible embedding server (e.g. llama-server)
# Falls back to OpenAI embeddings if not set
EMBEDDING_SERVER_URL=
EMBEDDING_MODEL_NAME=text-embedding-3-small
# OpenAI Configuration
# Required even with llama-server: the fallback client is always initialized.
OPENAI_API_KEY=
# Tavily Configuration (for web search)
# Legacy TAVILIY_API_KEY is accepted by Compose/startup; TAVILY_API_KEY wins.
# Current agent initialization needs this key even when web search is unused.
TAVILY_API_KEY=
# Immich Configuration
IMMICH_URL=http://192.168.1.5:2283
IMMICH_API_KEY=
SEARCH_QUERY="simba cat"
DOWNLOAD_DIR=./simba_photos
# Optional OIDC (Authelia): set all four fields together. Production requires HTTPS.
# Register the public callback URI: https://your-host/api/user/oidc/callback
OIDC_ISSUER=
OIDC_CLIENT_ID=
OIDC_CLIENT_SECRET=
OIDC_REDIRECT_URI=
OIDC_USE_DISCOVERY=true
# Optional: Manual OIDC endpoints (if discovery is disabled)
# OIDC_AUTHORIZATION_ENDPOINT=https://auth.example.com/api/oidc/authorization
# OIDC_TOKEN_ENDPOINT=https://auth.example.com/api/oidc/token
# OIDC_USERINFO_ENDPOINT=https://auth.example.com/api/oidc/userinfo
# OIDC_JWKS_URI=https://auth.example.com/api/oidc/jwks
# YNAB Configuration
# Get your Personal Access Token from https://app.ynab.com/settings/developer
YNAB_ACCESS_TOKEN=
# Optional: Specify a budget ID, or leave empty to use the default/first budget
YNAB_BUDGET_ID=
# Seconds between background YNAB delta syncs. Keep under the agent tools' 120s
# freshness window so tools rarely wait on an inline YNAB fetch.
YNAB_SYNC_INTERVAL=90
# Mealie Configuration
# Base URL for your Mealie instance (e.g., http://192.168.1.5:9000 or https://mealie.example.com)
MEALIE_BASE_URL=
# Get your API token from Mealie's user settings page
MEALIE_API_TOKEN=
# Group slug used in recipe page links (/g/<slug>/r/<recipe>); defaults to "home"
MEALIE_GROUP_SLUG=home
# Email Integration
# Required even without email: encrypted model fields initialize on startup.
# Email Encryption Key (32-byte URL-safe base64)
# Generate with: python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
FERNET_KEY=
# Twilio Configuration (WhatsApp)
TWILIO_ACCOUNT_SID=
TWILIO_AUTH_TOKEN=
TWILIO_WHATSAPP_NUMBER=
# Comma-separated list of WhatsApp numbers allowed to use the service (e.g., whatsapp:+1234567890)
# Use * to allow any number
ALLOWED_WHATSAPP_NUMBERS=
# Set to false to disable Twilio signature validation in development
TWILIO_SIGNATURE_VALIDATION=true
# If behind a reverse proxy, set this to your public webhook URL so signature validation works
# TWILIO_WEBHOOK_URL=https://your-domain.com/api/whatsapp/webhook
# Rate limiting: max messages per window (default: 10 messages per 60 seconds)
# WHATSAPP_RATE_LIMIT_MAX=10
# WHATSAPP_RATE_LIMIT_WINDOW=60
# Mailgun Configuration (Email channel)
MAILGUN_API_KEY=
MAILGUN_DOMAIN=
MAILGUN_WEBHOOK_SIGNING_KEY=
EMAIL_HMAC_SECRET=
# Rate limiting: max emails per window (default: 5 per 300 seconds)
# EMAIL_RATE_LIMIT_MAX=5
# EMAIL_RATE_LIMIT_WINDOW=300
# Set to false to disable Mailgun signature validation in development
MAILGUN_SIGNATURE_VALIDATION=true
# SendBlue Configuration (iMessage)
SENDBLUE_API_KEY=
SENDBLUE_API_SECRET=
SENDBLUE_FROM_NUMBER=
SENDBLUE_WEBHOOK_SECRET=
# Set to false to disable SendBlue signature validation in development
SENDBLUE_SIGNATURE_VALIDATION=true
# Comma-separated list of iMessage numbers allowed to use the service (E.164 format)
# Use * to allow any number
ALLOWED_IMESSAGE_NUMBERS=
# Rate limiting: max messages per window (default: 10 messages per 60 seconds)
# IMESSAGE_RATE_LIMIT_MAX=10
# IMESSAGE_RATE_LIMIT_WINDOW=60
# Google Calendar + Gmail Configuration (Python SDK)
# Run scripts/google_auth.py to generate token.json from your OAuth2 credentials:
# python scripts/google_auth.py --credentials credentials.json --token token.json
# Then mount token.json into the container (see docker-compose.yml).
# If GOOGLE_TOKEN_FILE points to a valid token, both Calendar and Gmail are enabled.
GOOGLE_TOKEN_FILE=/app/config/google-token.json
# Cronicle Integration
# Shared secret for Cronicle to authenticate cron job trigger requests.
# Generate with: openssl rand -hex 32
CRON_SECRET=
# Cronicle server URL and API key (from Cronicle Admin → API Keys)
# Used to auto-register scheduled jobs on startup.
CRONICLE_URL=
CRONICLE_API_KEY=
# SimbaKit / PetKit Configuration
# PetKit account credentials (used by SimbaKit to poll device data)
PETKIT_USERNAME=
PETKIT_PASSWORD=
PETKIT_REGION=US
PETKIT_TIMEZONE=America/New_York
# Internal URL for SimbaKit service (Docker network)
SIMBAKIT_URL=
# Homebox inventory (admin-only agent tools via homebox-mcp, needs Homebox >= 0.26)
# API key from Homebox Profile -> API Keys (starts with hb_). Leave empty to disable.
HOMEBOX_URL=
HOMEBOX_TOKEN=
# BookStack wiki (admin-only agent tools via bookstack-mcp: read, create, update; no deletes)
# API token from BookStack Profile -> API Tokens (user needs the "Access System API" permission).
# Leave empty to disable.
BOOKSTACK_BASE_URL=
BOOKSTACK_TOKEN_ID=
BOOKSTACK_TOKEN_SECRET=
# Obsidian Configuration (headless sync)
# Obsidian account credentials (used for `ob login` on container startup)
OBSIDIAN_EMAIL=
OBSIDIAN_PASSWORD=
# Vault ID to sync (found in Obsidian sync settings)
OBSIDIAN_VAULT_ID=
# End-to-end encryption password (if vault uses E2E encryption)
OBSIDIAN_E2E_PASSWORD=
# Device name shown in Obsidian sync activity
OBSIDIAN_DEVICE_NAME=simbarag
# Set to true to run continuous sync in the background
OBSIDIAN_CONTINUOUS_SYNC=false
# bidirectional: notes and journal tasks Simba writes sync back to your devices.
# pull-only: download only, Simba's writes stay in the container's copy.
# mirror-remote: download only and revert local changes.
OBSIDIAN_SYNC_MODE=bidirectional
OBSIDIAN_SYNC_INTERVAL=60
# Local path to Obsidian vault (where files are synced)
OBSIDIAN_VAULT_PATH=/app/data/obsidian
# Vault name for obsidian://open links in the artifact panel (optional; no link if unset)
OBSIDIAN_VAULT_NAME=
# LangGraph checkpoint store (SQLite). Must be on a persistent volume.
# Both blue and green containers share this volume via docker-compose.
CHECKPOINT_DB_PATH=/app/checkpoints/checkpoints.db
# Checkpoints keep a full message-list snapshot per turn; this bounds how many
# are kept per conversation thread (older ones are pruned after each turn).
CHECKPOINT_KEEP_PER_THREAD=20
# Beli restaurant recommendations
# Beli account credentials for each profile are stored encrypted in the database.
# No additional env vars needed — auth is done via the Beli API at login time.
# Optional S3 image storage (leave credentials empty to disable)
S3_ENDPOINT_URL=
S3_ACCESS_KEY_ID=
S3_SECRET_ACCESS_KEY=
S3_BUCKET_NAME=asksimba-images
S3_REGION=garage
# Ollama is used by image/PDF helper workflows, not the main chat agent.
OLLAMA_URL=http://localhost:11434
OLLAMA_HOST=http://localhost:11434