Environment variables
Every CARIOS_* variable Cariosan understands, organised by area.
Every runtime knob is a CARIOS_* environment variable. The server reads them at startup; there is no YAML config file. See .env.example for a complete template with secret-generation commands.
Required vs optional — required variables have no default and cause startup to fail with a clear error. Optional variables show their default value in the table below.
Server
| Variable | Default | Purpose |
|---|---|---|
CARIOS_ENV | dev | One of dev, prod, test. Affects log verbosity and safety checks. |
CARIOS_HTTP_PORT | 8080 | HTTP and WebSocket listen port (same server). |
CARIOS_LOG_LEVEL | info | debug, info, warn, error. |
CARIOS_CORS_ALLOWED_ORIGINS | (empty) | Comma-separated list of origins allowed on the WebSocket upgrade (and HTTP CORS). Empty = same-origin only. * allows any origin. |
Mobile / native clients must be allowed
The WebSocket upgrade enforces an origin check. A browser on a different host — and React Native / mobile clients, which send an Origin header — will have their handshake rejected (the SDK reports as disconnected) unless their origin is listed here. For local device testing set CARIOS_CORS_ALLOWED_ORIGINS=*; in production list your real app origins. REST works without this (no upgrade), which is why a misconfigured origin looks like "messages send but never arrive live".
Database
| Variable | Default | Purpose |
|---|---|---|
CARIOS_DATABASE_URL | required | Postgres connection URL. |
Redis
| Variable | Default | Purpose |
|---|---|---|
CARIOS_REDIS_URL | required | Redis URL (e.g. redis://redis:6379/0). |
JWT
| Variable | Default | Purpose |
|---|---|---|
CARIOS_JWT_SECRET | required, ≥ 32 bytes | HMAC signing key for client SDK JWTs. Rotate by restarting with a new value — invalidates all outstanding tokens. |
CARIOS_JWT_ISSUER | cariosan | iss claim on minted tokens. |
CARIOS_JWT_TTL_HOURS | 24 | Default TTL for tokens issued via IssueUserToken. Callers can override per-call. |
Object storage
| Variable | Default | Purpose |
|---|---|---|
CARIOS_S3_ENDPOINT | required | S3 API endpoint (MinIO URL for self-host, empty or https://s3.REGION.amazonaws.com for AWS). |
CARIOS_S3_REGION | us-east-1 | AWS region. Ignored by MinIO but still required for request signing. |
CARIOS_S3_BUCKET | required | Bucket name. Created automatically against MinIO; must exist pre-deploy for AWS. |
CARIOS_S3_ACCESS_KEY | required | S3 access key. |
CARIOS_S3_SECRET_KEY | required | S3 secret key. |
CARIOS_S3_USE_SSL | false | Only relevant if you override the SDK's default client. |
CARIOS_S3_PUBLIC_URL | required | Base URL consumers reach attachments through. Browsers load uploaded images from this URL, so it must be publicly routable. |
Limits
| Variable | Default | Purpose |
|---|---|---|
CARIOS_MAX_MESSAGE_SIZE_BYTES | 8192 | Max content length on REST message sends. |
CARIOS_MAX_ATTACHMENT_SIZE_BYTES | 10485760 (10 MiB) | Max upload size. Enforced by the presigned URL's content-length binding — clients can't lie. |
CARIOS_RATE_LIMIT_MESSAGES_PER_MINUTE | 60 | Per-user send rate. Over-limit returns 429 with Retry-After. |
CARIOS_PRESENCE_TTL_SECONDS | 60 | How long a "user online" marker stays alive between heartbeats. |
CARIOS_TYPING_TTL_SECONDS | 3 | How long a typing indicator persists without refresh. |
Push notifications (FCM) — optional, BYO Firebase
| Variable | Default | Purpose |
|---|---|---|
CARIOS_FCM_SERVICE_ACCOUNT_FILE | (empty) | Path to a Firebase service-account JSON key. Empty = push disabled (device registration still works; nothing is delivered). |
CARIOS_FCM_PROJECT_ID | (empty) | GCP project id. Optional — falls back to the project_id in the service-account JSON. |
Push is bring-your-own Firebase: create a Firebase project, download a service-account key, and mount it into the container. FCM is free (no per-push charge); covers Android, iOS (via APNs — upload an APNs auth key to the Firebase project, no server-side APNs code), and Web. Payloads are minimal by design — a title only, no message body — so content never transits the push network. See Push notifications.
Runtime behaviours worth knowing
JWT secret minimum — startup fails if CARIOS_JWT_SECRET is shorter than 32 bytes. A short HMAC key is trivial to brute-force given a handful of issued tokens.
- Secrets in logs. The server's startup log echoes the full config with credential-bearing URLs (Postgres / Redis) redacted — the username stays, the password is replaced with
REDACTED. - Auto-migrate on boot. The server runs every outstanding migration on startup. MVP migrations are additive only, so this is safe for rollbacks.
Generating secrets — openssl rand -base64 48 produces a 64-character string suitable for CARIOS_JWT_SECRET. Re-run for every environment so a leak in staging doesn't compromise prod.
Was this page helpful?