Cariosan

Environment variables

Every CARIOS_* variable Cariosan understands, organised by area.

7 min readUpdated Mar 12, 2026

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

VariableDefaultPurpose
CARIOS_ENVdevOne of dev, prod, test. Affects log verbosity and safety checks.
CARIOS_HTTP_PORT8080HTTP and WebSocket listen port (same server).
CARIOS_LOG_LEVELinfodebug, 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

VariableDefaultPurpose
CARIOS_DATABASE_URLrequiredPostgres connection URL.

Redis

VariableDefaultPurpose
CARIOS_REDIS_URLrequiredRedis URL (e.g. redis://redis:6379/0).

JWT

VariableDefaultPurpose
CARIOS_JWT_SECRETrequired, ≥ 32 bytesHMAC signing key for client SDK JWTs. Rotate by restarting with a new value — invalidates all outstanding tokens.
CARIOS_JWT_ISSUERcariosaniss claim on minted tokens.
CARIOS_JWT_TTL_HOURS24Default TTL for tokens issued via IssueUserToken. Callers can override per-call.

Object storage

VariableDefaultPurpose
CARIOS_S3_ENDPOINTrequiredS3 API endpoint (MinIO URL for self-host, empty or https://s3.REGION.amazonaws.com for AWS).
CARIOS_S3_REGIONus-east-1AWS region. Ignored by MinIO but still required for request signing.
CARIOS_S3_BUCKETrequiredBucket name. Created automatically against MinIO; must exist pre-deploy for AWS.
CARIOS_S3_ACCESS_KEYrequiredS3 access key.
CARIOS_S3_SECRET_KEYrequiredS3 secret key.
CARIOS_S3_USE_SSLfalseOnly relevant if you override the SDK's default client.
CARIOS_S3_PUBLIC_URLrequiredExternally reachable S3 endpoint used to sign uploads and downloads. It must preserve the signed host and path through your proxy. The legacy variable name does not enable anonymous access.

Limits

VariableDefaultPurpose
CARIOS_MAX_MESSAGE_SIZE_BYTES8192Max content length on REST message sends.
CARIOS_MAX_ATTACHMENT_SIZE_BYTES10485760 (10 MiB)Max upload size. Enforced by the presigned URL's content-length binding — clients can't lie.
CARIOS_RATE_LIMIT_MESSAGES_PER_MINUTE60Per-user send rate. Over-limit returns 429 with Retry-After.
CARIOS_PRESENCE_TTL_SECONDS60How long a "user online" marker stays alive between heartbeats.
CARIOS_TYPING_TTL_SECONDS3How long a typing indicator persists without refresh.
CARIOS_RECEIPT_COALESCE_MS1000Per-process delivery/read receipt coalescing window in milliseconds, from 0 to 60000. First report runs immediately; bursts merge into a trailing update. 0 disables. Restart to apply.

Delivery cursor persistence and receipt broadcasts can lag by the window plus processing time. Read cursors still persist on every request; only their broadcasts are coalesced. Pending updates are in memory, not durable across process exit; clients can report again. Each server instance coalesces independently.

Push notifications (FCM) — optional, BYO Firebase

VariableDefaultPurpose
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?

On this page