Environment reference ​
The server reads these from docker/.env. docker-compose.yaml sets a few itself (DATABASE_URL, MEILI_URL, APP_CONFIG_PATH, NODE_ENV), so you don't need to.
Core ​
| Variable | Default | What it is |
|---|---|---|
BASE_DOMAIN | none (required) | The instance's domain, e.g. chat.example.com. Every ID it creates contains it, so it can't change once there's data |
BASE_URL | none | The address people open, e.g. https://chat.example.com |
SERVER_PORT | 8778 | The API's port |
SERVER_HOST | all interfaces | The address the API and webhook listener bind to |
LOG_LEVEL | warn | error, warn, info or debug |
NODE_ENV | development | production in the Docker setup |
DATABASE_URL | set by Compose | The MariaDB connection, mariadb://user:password@host:3306/database, built from the DB_* variables |
APP_CONFIG_PATH | set by Compose | Where app.config.yaml is. Compose mounts it at /config/app.config.yaml |
The Compose file also reads DOCKER_TAG (which image) and DB_USER, DB_PASSWORD, DB_DATABASE and DB_ROOT_PASSWORD for MariaDB.
Security ​
| Variable | Default | What it is |
|---|---|---|
JWT_SECRET | none (required) | Signs sign-in tokens. A long random string; changing it signs everyone out |
INSTANCE_SETTINGS_SECRET | JWT_SECRET | Encrypts secrets saved in the admin settings, such as a GIF API key |
CORS_ORIGIN_VALUE | https://${BASE_DOMAIN} | Comma-separated web origins allowed to call the API and Socket.IO; refract://app is also allowed for the desktop app |
TRUST_PROXY | false | true behind a reverse proxy, so client IPs come from its forwarded header |
TRUST_PROXY_IPS | 127.0.0.1,::1 | The proxies to trust: addresses or CIDR ranges, comma-separated |
TRUST_PROXY_HEADER | X-Forwarded-For | The header to read the client IP from first |
SECURITY_HEADERS_ENABLED | true | Security headers. Always on in production |
CSP_DIRECTIVES | built in | Replaces the whole Content-Security-Policy: keep the frame, media and voice sources it needs |
REFERRER_POLICY | strict-origin-when-cross-origin | The Referrer-Policy header |
ACTIVITY_BASE_URL | BASE_URL | Origin packaged activities are served from; set a separate host for Watch Together |
See Reverse proxy & TLS for the proxy settings.
For multiple web clients, set CORS_ORIGIN_VALUE=https://chat.example.com,https://other.example.com. The desktop origin is included automatically, so the default supports both the web and desktop apps. A * entry allows every origin and is intended for development. Restart the backend after changing this setting.
Redis and search ​
| Variable | Default | What it is |
|---|---|---|
REDIS_URL | none (required) | redis://redis:6379 in the Docker setup |
MEILI_URL | set by Compose | Meilisearch's address. The server won't start without it |
MEILI_MASTER_KEY | none (required) | Shared by the search container and the server. At least 16 characters |
MEILI_INDEX_PREFIX | refract_ | Prefix for index names, so several instances can share one Meilisearch |
LiveKit ​
| Variable | Default | What it is |
|---|---|---|
LIVEKIT_PUBLIC_URL | wss://livekit.${BASE_DOMAIN} | Where people's apps connect for calls |
LIVEKIT_API_URL | LIVEKIT_PUBLIC_URL | Where the server calls LiveKit's API. Use the internal address, http://livekit:7866 |
LIVEKIT_API_KEY | none (required) | A key name from keys: in livekit-server.yaml |
LIVEKIT_API_SECRET | none (required) | That key's secret |
LIVEKIT_WEBHOOK_PORT | 8779 | The webhook listener. Never publish it |
LIVEKIT_WEBHOOK_API_KEY | none (required) | The key LiveKit signs webhooks with: webhook.api_key in livekit-server.yaml |
LIVEKIT_WEBHOOK_API_SECRET | none (required) | That key's secret |
LIVEKIT_ENABLE_ENCRYPTION | true | End-to-end encrypted call media. Only false turns it off |
See Voice & LiveKit for how these fit together.
Email ​
| Variable | Default | What it is |
|---|---|---|
EMAIL_PROVIDER | smtp | smtp, or ses for Amazon SES |
SMTP_FROM | none | The sender, e.g. "Refract.Chat <noreply@example.com>" |
SMTP_HOST, SMTP_PORT | none | The SMTP server |
SMTP_USER, SMTP_PASSWORD | none | SMTP credentials, if it needs them |
AWS_SES_ACCESS_KEY_ID | AWS_ACCESS_KEY_ID | SES credentials |
AWS_SES_SECRET_ACCESS_KEY | AWS_SECRET_ACCESS_KEY | SES credentials |
AWS_SES_REGION | us-east-1 | The SES region |
See Email, search & push.
Media ​
| Variable | Default | What it is |
|---|---|---|
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN | none | S3 credentials, when media is stored in S3 and the host has no IAM role |
MEDIA_ATTACHMENT_EXTENSIONS | from the config | Accepted attachment types, e.g. png,jpg,pdf. Wins over app.config.yaml |
MEDIA_IMAGE_EXTENSIONS | from the config | Accepted avatar, icon and banner types |
MEDIA_MAX_ATTACHMENTS_PER_MESSAGE | from the config | Attachments per message |
FFMPEG_PATH, FFPROBE_PATH | ffmpeg, ffprobe | For re-encoding video avatars. The Docker image includes both |
See Media storage.
Features ​
| Variable | Default | What it is |
|---|---|---|
KLIPY_API_KEY | none | Turns on GIF search, from KLIPY. Wins over the config file and admin settings |
GIFGOODER_URL | none | The address of a gifgooder server, such as https://gif.example.com, with no path. Needed with GIFGOODER_TOKEN |
GIFGOODER_TOKEN | none | Adds gifgooder to GIF search, with GIFGOODER_URL. With both providers set up, the picker has a tab for each |
BUZZ_COOLDOWN_SECONDS | from the config | Seconds between one person's /buzz nudges in a conversation. Wins over app.config.yaml |
PUSH_RELAY_URL | https://relay.refract.chat | The push relay for mobile notifications |
PUSH_RELAY_STATE_FILE | beside the federation key | Where the relay credentials are saved. Keep it on /data |