# Investor Flow — production compose (local or Unraid). # # Unraid: copy deploy/unraid/.env.example to .env, set secrets, then: # docker compose --env-file .env up -d --build # Prefer a cache-only appdata path for SQLite (not /mnt/user FUSE). See docs/DEPLOY_UNRAID.md. services: backend: image: ${IFLOW_IMAGE_BACKEND:-investor-flow-backend:local} build: context: ./app/server dockerfile: Dockerfile restart: unless-stopped ports: - "${IFLOW_BACKEND_PORT:-3001}:3001" environment: NODE_ENV: production HOST: 0.0.0.0 PORT: 3001 IFLOW_DB_PATH: /app/data/investor-flow.db IFLOW_SESSION_SECRET: ${IFLOW_SESSION_SECRET:?set IFLOW_SESSION_SECRET} IFLOW_CRYPTO_KEY: ${IFLOW_CRYPTO_KEY:-} SEC_OPERATOR_EMAIL: ${SEC_OPERATOR_EMAIL:-operator@example.com} YF_OPERATOR_EMAIL: ${YF_OPERATOR_EMAIL:-${SEC_OPERATOR_EMAIL:-operator@example.com}} FRED_API_KEY: ${FRED_API_KEY:-} LLM_PROVIDER_URL: ${LLM_PROVIDER_URL:-} ORNITH_LLM_URL: ${ORNITH_LLM_URL:-${LLM_PROVIDER_URL:-}} GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID:-} GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET:-} GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-} GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-} volumes: - ${IFLOW_DATA_DIR:-./app/server/data}:/app/data healthcheck: test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3001/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"] interval: 30s timeout: 5s retries: 3 start_period: 40s frontend: image: ${IFLOW_IMAGE_FRONTEND:-investor-flow-frontend:local} build: context: ./app dockerfile: Dockerfile restart: unless-stopped depends_on: backend: condition: service_healthy ports: - "${IFLOW_WEB_PORT:-3000}:3000" environment: NODE_ENV: production HOSTNAME: 0.0.0.0 PORT: 3000 IFLOW_BACKEND_URL: http://backend:3001 healthcheck: test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3000/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"] interval: 30s timeout: 5s retries: 3 start_period: 40s