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:seedConfigure 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.localSet 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 devThe 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.