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_URLrequiredBase URL consumers reach attachments through. Browsers load uploaded images from this URL, so it must be publicly routable.

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.

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 secretsopenssl 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