MyanLex

Self-hosting

Operator setup, separate from API-consumer integration.

This section is for deployment operators. API consumers using an existing deployment do not need these steps.

Local development deployment

Clone the repository, use its .nvmrc Node version and pinned pnpm version, then run pnpm install. Copy the checked-in API and web .env.example templates to their local environment files and set DATABASE_URL to your local PostgreSQL database. Do not commit secrets.

docker compose --profile auth up -d
pnpm db:deploy
pnpm db:seed

Configure apps/api/.env:

PORT=3001
AUTH_ENABLED=true
AUTH_PUBLIC_URL=http://localhost:3000
# Generate AUTH_SECRET using: openssl rand -base64 48
SMTP_HOST=localhost
SMTP_PORT=1025
SMTP_SECURE=false
SMTP_FROM=auth@myanlex.local

Set AUTH_SECRET to the generated secret. In apps/web/.env.local, set API_INTERNAL_URL=http://localhost:3001, NEXT_PUBLIC_API_DOCS_URL=http://localhost:3001/docs, and NEXT_PUBLIC_DOCS_URL=http://localhost:3002.

Run each application in its own terminal:

pnpm --filter @myanlex/api start:dev
pnpm --filter @myanlex/web dev
pnpm --filter @myanlex/docs dev

The console is at localhost:3000, the API at localhost:3001, this documentation site at localhost:3002, and Mailpit at localhost:8025. Register and follow the verification link in Mailpit. Do not manually modify verification database fields.

Distributed limits and quotas

Start Redis with docker compose --profile redis up -d and set REDIS_URL. Use one prefix and consistent limit settings across replicas. Redis failures fail closed rather than granting a fresh local allowance.

Monthly quotas are opt-in: set MYANLEX_QUOTAS_ENABLED=true consistently across replicas after migrations and seeding. Enforcement uses PostgreSQL, not Redis. Bootstrap keys and sessions bypass monthly quotas; remove a bootstrap key in production if that bypass is inappropriate. Historical traffic is not backfilled on enablement, and disabling enforcement stops counting.

Readiness and metrics

Keep GET /v1/health as the liveness probe. Use GET /v1/health/ready for traffic readiness: it returns 200 with {"status":"ready"} or 503 with {"status":"not_ready"}. It checks configured PostgreSQL and Redis connectivity, caches results for one second, and does not consume quotas. It does not verify schema migrations, SMTP or OAuth setup.

Metrics are disabled by default. Generate a separate operator token with openssl rand -hex 32, set MYANLEX_METRICS_TOKEN in apps/api/.env or the process environment, and restart the API. Prometheus can then scrape GET /internal/metrics with Authorization: Bearer <operator-token>. Never reuse an NLP key or put this secret in a NEXT_PUBLIC_* variable. Restrict metrics to private ingress and TLS; scrape each API replica separately.

Metrics cover completed request counts, latency histograms, observed aborted bodies, process memory and uptime. Labels use registered route templates and never submitted text or tenant identifiers. Operational probes are excluded. These counters reset on restart and are not billing records. A Prometheus/Grafana deployment and alerts still need to be configured by the operator.

Production checklist

The repository includes an optional local monitoring stack: compose.monitoring.yaml. Set MYANLEX_METRICS_TOKEN_FILE to an absolute path containing only the operator token, then run docker compose -f compose.monitoring.yaml up -d. Prometheus is on localhost:9090 and Alertmanager on localhost:9093. The default receiver is UI-only: no email, chat or paging notifications are sent until you configure a destination.

Run pnpm monitoring:check to validate configuration and alert rules, and pnpm operations:rehearsal for a disposable local load/outage exercise. The rehearsal never targets existing services. Follow docs/staging-validation.md for target configuration, approved staging load, notification verification and release evidence. Local rehearsal timings are not production capacity results.

Local Compose is not a complete production deployment. Before launch, configure HTTPS, private database/Redis access, secret management, real SMTP, backups, monitoring and recovery procedures. Configure optional Google/GitHub OAuth callbacks on the console origin. Never store submitted text in usage logs.

Set the docs app's NEXT_PUBLIC_CONSOLE_URL and the console's NEXT_PUBLIC_DOCS_URL to their deployed origins, then rebuild. The docs app requires no database or authentication secrets. Build it with the repository root available so it can read the single OpenAPI contract.

On this page