# Deployment Guide ## Requirements - Docker and Docker Compose - PostgreSQL 16 with pgvector extension (included in pgvector/pgvector:pg16 image) - Reverse proxy (Nginx, Caddy, or Traefik) for HTTPS termination - At least one AI provider configured ## Docker Deployment ### 1. Configure Environment ```bash cp .env.example .env ``` Required settings: ```env AI_PROVIDER=litellm # or bedrock, azure, vertex, openrouter JWT_SECRET=<64-char random> # openssl rand -hex 32 DB_PASSWORD= APP_URL=https://your-domain.com # used for CORS, emails, verification links ``` ### 2. Build and Start ```bash docker compose up -d --build ``` This starts two containers: - `pediatric-ai-scribe` -- Node.js app on port 3552 (mapped to container port 3000) - `pedscribe-db` -- PostgreSQL 16 with pgvector ### 3. Verify ```bash docker compose ps curl http://localhost:3552/api/health ``` ### 4. First User Navigate to `https://your-domain.com` and register. The first user is automatically promoted to admin. ## Reverse Proxy The app binds to `127.0.0.1:3552` by default. You need a reverse proxy for HTTPS. ### Nginx ```nginx server { listen 443 ssl http2; server_name scribe.example.com; ssl_certificate /etc/ssl/certs/scribe.example.com.pem; ssl_certificate_key /etc/ssl/private/scribe.example.com.key; client_max_body_size 100M; location / { proxy_pass http://127.0.0.1:3552; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } ``` ### Caddy ``` scribe.example.com { reverse_proxy localhost:3552 } ``` ### Trust Proxy If you see `X-Forwarded-For` warnings in logs, add `trust proxy` to Express. The app currently runs behind a local reverse proxy, so rate limiting uses the direct connection IP. ## Volumes | Volume | Purpose | Backup Priority | |--------|---------|----------------| | `pgdata` | PostgreSQL data (all user data, settings, content) | Critical | | `scribe-logs` | Application log files (YYYY-MM-DD.log) | Low | ### Backup PostgreSQL ```bash docker exec pedscribe-db pg_dump -U pedscribe pedscribe > backup.sql ``` ### Restore ```bash cat backup.sql | docker exec -i pedscribe-db psql -U pedscribe pedscribe ``` ## Updating ```bash git pull docker compose build --no-cache docker compose up -d ``` Database migrations run automatically on startup (CREATE TABLE IF NOT EXISTS, ALTER TABLE ADD COLUMN IF NOT EXISTS patterns). ## Health Check The container includes a built-in health check: ``` wget --spider -q http://localhost:3000/api/health ``` Runs every 30 seconds with a 20-second start period. Docker marks the container as healthy/unhealthy automatically. ## Resource Requirements - Memory: 256MB minimum, 512MB recommended - Disk: ~200MB for Docker image (includes self-hosted Whisper WASM models) - PostgreSQL: depends on usage (audio backups use BYTEA storage, auto-deleted after 24h) ## Environment-Specific Notes ### Production Checklist - Set a strong `JWT_SECRET` (64+ characters) - Set a strong `DB_PASSWORD` - Set `APP_URL` to your actual domain (required for CORS, email links) - Configure SMTP for email verification and password reset - Use a HIPAA-eligible AI provider if handling PHI (Bedrock, Azure, Vertex) - Enable Cloudflare Turnstile for bot protection - Set up regular PostgreSQL backups - Configure OIDC/SSO for enterprise environments ### Development ```bash npm install cp .env.example .env # Start PostgreSQL separately or use docker compose for just the DB: docker compose up -d postgres node server.js ``` The app runs on port 3000 by default. Without `APP_URL` set, CORS allows all origins. ## Ports | Service | Internal | External (default) | |---------|----------|--------------------| | Node.js app | 3000 | 127.0.0.1:3552 | | PostgreSQL | 5432 | Not exposed | To change the external port, edit `docker-compose.yml`: ```yaml ports: - "127.0.0.1:YOUR_PORT:3000" ``` ## Logs Application logs are written to: - Console (visible via `docker compose logs`) - `/app/data/logs/YYYY-MM-DD.log` inside the container (mapped to `scribe-logs` volume) - Database tables: `audit_log`, `api_log`, `access_log` View logs: ```bash docker compose logs -f pediatric-scribe docker compose logs --since=1h pediatric-scribe ``` ## Auto-Cleanup The application automatically cleans up expired data: - Saved encounters: deleted after 7 days (configurable via `site.auto_delete_days`) - Audio backups: deleted after 24 hours - Cleanup runs hourly and 10 seconds after startup