# Local stack. MinIO stands in for Cloudflare R2 (same S3 API); in prod drop minio and set R2_* vars. services: postgres: image: pgvector/pgvector:pg16 environment: POSTGRES_USER: notestack POSTGRES_PASSWORD: notestack POSTGRES_DB: notestack ports: ["5432:5432"] volumes: [pgdata:/var/lib/postgresql/data] healthcheck: test: ["CMD-SHELL", "pg_isready -U notestack"] interval: 5s retries: 10 redis: image: redis:7-alpine ports: ["6379:6379"] minio: image: minio/minio:latest command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: minioadmin ports: ["9000:9000", "9001:9001"] volumes: [miniodata:/data] api: build: ./backend env_file: .env environment: DATABASE_URL: postgresql+psycopg://notestack:notestack@postgres:5432/notestack REDIS_URL: redis://redis:6379/0 R2_ENDPOINT_URL: ${R2_ENDPOINT_URL:-http://minio:9000} RENDERER_URL: http://renderer:3100 API_URL: http://api:8000 ports: ["8000:8000"] depends_on: postgres: { condition: service_healthy } redis: { condition: service_started } worker: build: ./backend command: arq app.worker.WorkerSettings env_file: .env environment: DATABASE_URL: postgresql+psycopg://notestack:notestack@postgres:5432/notestack REDIS_URL: redis://redis:6379/0 R2_ENDPOINT_URL: ${R2_ENDPOINT_URL:-http://minio:9000} RENDERER_URL: http://renderer:3100 API_URL: http://api:8000 depends_on: [api] renderer: build: ./renderer environment: INTERNAL_TOKEN: ${INTERNAL_TOKEN:-internal-change-me} ports: ["3100:3100"] frontend: image: node:22-alpine working_dir: /app command: sh -c "npm install && npx vite --host 0.0.0.0" environment: VITE_API_PROXY: http://api:8000 VITE_GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-} volumes: ["./frontend:/app", "/app/node_modules"] ports: ["5173:5173"] depends_on: [api] volumes: pgdata: miniodata: