8.3 KiB
Operations And Configuration
Runtime Services
docker-compose.yml defines:
db(Postgres 16)redis(Redis 7)typesense(Typesense 29)api(FastAPI backend)worker(RQ worker viapython -m app.worker.run_worker)frontend(Vite React UI)
Persistent host bind mounts (default root ./data, overridable with DCM_DATA_DIR):
${DCM_DATA_DIR:-./data}/db-data${DCM_DATA_DIR:-./data}/redis-data${DCM_DATA_DIR:-./data}/storage${DCM_DATA_DIR:-./data}/typesense-data
Reset all persisted runtime data:
docker compose down
rm -rf ${DCM_DATA_DIR:-./data}
Core Commands
Start or rebuild:
docker compose up --build -d
Stop:
docker compose down
Tail logs:
docker compose logs -f
Host Bind Mounts
Compose is configured with host bind mounts for persistent data. Ensure host directories exist and are writable by the backend runtime user.
Backend and worker run as non-root user uid=10001 inside containers. For host-mounted storage paths:
mkdir -p ${DCM_DATA_DIR:-./data}/storage
sudo chown -R 10001:10001 ${DCM_DATA_DIR:-./data}/storage
sudo chmod -R u+rwX,g+rwX ${DCM_DATA_DIR:-./data}/storage
If permissions are incorrect, API startup fails with errors similar to:
PermissionError: [Errno 13] Permission denied: '/data/storage'FileNotFoundErrorfor/data/storage/originals
Frontend Build Baseline
The frontend Dockerfile uses node:22-slim with a standard npm ci --no-audit install step and no npm-specific build tuning flags.
Authentication Model
- Legacy shared build-time frontend token behavior was removed.
- API now uses server-issued sessions that are stored in HttpOnly cookies (
dcm_session) with a separate CSRF cookie (dcm_csrf). - Bootstrap users are provisioned from environment:
AUTH_BOOTSTRAP_ADMIN_USERNAMEAUTH_BOOTSTRAP_ADMIN_PASSWORD- optional
AUTH_BOOTSTRAP_USER_USERNAME - optional
AUTH_BOOTSTRAP_USER_PASSWORD
- Login brute-force protection is enabled by default and keyed by username and source IP:
AUTH_LOGIN_FAILURE_LIMITAUTH_LOGIN_FAILURE_WINDOW_SECONDSAUTH_LOGIN_LOCKOUT_BASE_SECONDSAUTH_LOGIN_LOCKOUT_MAX_SECONDS- Frontend signs in through
/api/v1/auth/loginand relies on browser session persistence for valid cookie-backed sessions.
DEV And LIVE Configuration Matrix
Use .env.example as baseline. The table below documents user-managed settings and recommended values.
| Variable | Local DEV (HTTP, docker-only) | LIVE (HTTPS behind reverse proxy) |
|---|---|---|
APP_ENV |
development |
production |
HOST_BIND_IP |
127.0.0.1 or local LAN bind if needed |
127.0.0.1 (publish behind proxy only) |
PUBLIC_BASE_URL |
http://localhost:8000 |
https://api.example.com |
VITE_API_BASE |
empty for host-derived http://<frontend-host>:8000/api/v1, or explicit local URL |
https://api.example.com/api/v1 (build-time value for production frontend image) |
VITE_ALLOWED_HOSTS |
optional comma-separated hostnames, for example localhost,docs.lan |
optional comma-separated public frontend hostnames, for example app.example.com |
CORS_ORIGINS |
["http://localhost:5173","http://localhost:3000"] |
exact frontend origins only, for example ["https://app.example.com"] |
REDIS_URL |
redis://:<password>@redis:6379/0 in isolated local network |
rediss://:<password>@redis.internal:6379/0 |
REDIS_SECURITY_MODE |
compat or auto |
strict |
REDIS_TLS_MODE |
allow_insecure or auto |
required |
AUTH_LOGIN_FAILURE_LIMIT |
default 5 |
tune to identity-protection policy and support requirements |
AUTH_LOGIN_FAILURE_WINDOW_SECONDS |
default 900 |
tune to identity-protection policy and support requirements |
AUTH_LOGIN_LOCKOUT_BASE_SECONDS |
default 30 |
tune to identity-protection policy and support requirements |
AUTH_LOGIN_LOCKOUT_MAX_SECONDS |
default 900 |
tune to identity-protection policy and support requirements |
AUTH_COOKIE_DOMAIN |
empty (host-only cookies) | parent frontend/API domain for split hosts, for example docs.lan |
AUTH_COOKIE_SAMESITE |
auto |
none for cross-origin frontend/API deployments, lax or strict for same-origin |
PROVIDER_BASE_URL_ALLOW_HTTP |
true only when intentionally testing local HTTP provider endpoints |
false |
PROVIDER_BASE_URL_ALLOW_PRIVATE_NETWORK |
true only for trusted local development targets |
false |
PROVIDER_BASE_URL_ALLOWLIST |
allow needed test hosts | explicit production allowlist, for example ["api.openai.com"] |
PROCESSING_LOG_STORE_MODEL_IO_TEXT |
false by default; temporary true only for controlled debugging |
false |
PROCESSING_LOG_STORE_PAYLOAD_TEXT |
false by default; temporary true only for controlled debugging |
false |
CONTENT_EXPORT_MAX_DOCUMENTS |
default 250 or lower based on host memory |
tuned to production capacity |
CONTENT_EXPORT_MAX_TOTAL_BYTES |
default 52428800 (50 MiB) or lower |
tuned to production capacity |
CONTENT_EXPORT_RATE_LIMIT_PER_MINUTE |
default 6 |
tuned to API throughput and abuse model |
PUBLIC_BASE_URL must point to the backend API public URL, not the frontend URL.
HTTPS Proxy Deployment Notes
This application supports both:
- local HTTP-only operation (no TLS termination in containers)
- HTTPS deployment behind a reverse proxy that handles TLS
Recommended LIVE pattern:
- Proxy terminates TLS and forwards to
apiandfrontendinternal HTTP endpoints. - Keep container published ports bound to localhost or internal network.
- Set
PUBLIC_BASE_URLandVITE_API_BASEto final HTTPS URLs. - Set
CORS_ORIGINSto exact HTTPS frontend origins. - Credentialed CORS is enabled and constrained for cookie-based sessions with strict origin allowlists.
Security Controls
- CORS uses explicit origin allowlist only; broad origin regex matching is removed.
- Worker Redis startup validates URL auth and TLS policy before consuming jobs.
- Provider API keys are encrypted at rest with standard AEAD (
cryptographyFernet).- legacy
enc-v1payloads are read for backward compatibility - new writes use
enc-v2
- legacy
- Processing logs default to metadata-only persistence.
- Login endpoint applies escalating temporary lockout on repeated failed credentials using Redis-backed subject keys for username and source IP.
- Markdown export enforces:
- max document count
- max total markdown bytes
- per-user Redis-backed rate limit
- spool-file streaming to avoid unbounded memory archives
- User-role document access is owner-scoped for non-admin accounts.
Frontend Runtime
- Frontend no longer consumes
VITE_API_TOKEN. - Frontend image target is environment-driven:
APP_ENV=developmentbuilds thedevelopmenttarget and runs Vite dev serverAPP_ENV=productionbuilds theproductiontarget and serves static assets through unprivileged Nginx
- Frontend Docker targets are selected from
APP_ENV, so usedevelopmentorproductionvalues. - Production frontend Nginx uses non-root runtime plus
/tmptemp-path configuration so it can run with container capability dropping enabled. - Vite dev server host allowlist uses the union of:
- hostnames extracted from
CORS_ORIGINS - optional explicit hostnames from
VITE_ALLOWED_HOSTS
- hostnames extracted from
VITE_ALLOWED_HOSTSonly affects development mode where Vite is running.- API auth cookies support optional domain and SameSite configuration through
AUTH_COOKIE_DOMAINandAUTH_COOKIE_SAMESITE. - HTTPS cookie security detection falls back to
PUBLIC_BASE_URLscheme when proxy headers are missing. - CSRF validation accepts header matches against any
dcm_csrfcookie value in the request, covering stale plus fresh duplicate-cookie transitions. - Session authentication is cookie-based; browser reloads and new tabs can reuse an active session until it expires or is revoked.
- Protected media and file download flows still use authenticated fetch plus blob/object URL handling.
Validation Checklist
After configuration changes:
GET /api/v1/healthreturns healthy response- login succeeds for bootstrap admin user
- admin can upload, search, open preview, download, and export markdown
- user account can only access its own documents
- admin-only settings and processing logs are not accessible by user role
docker compose logs -f api workershows no startup validation failures