Run with Docker ​
The supported way to run Refract.Chat is the Docker Compose setup in the repository's docker/ directory. It runs the server image with MariaDB, Redis, Meilisearch and LiveKit, and keeps everything that matters in that one directory.
Refract.Chat is a work in progress. Back up before every upgrade, and expect data loss while this warning is here.
Before you start ​
- A Linux host with Docker and the Compose plugin.
- Two DNS names pointing at it: one for the app (e.g.
chat.example.com) and one for LiveKit (e.g.livekit.chat.example.com). - A reverse proxy that terminates TLS for both. The examples use Traefik on an external Docker network named
traefik-net; see Reverse proxy & TLS. - Firewall openings for LiveKit's media ports,
7867/udpand7868/tcpby default.
Quick start ​
Run everything from the docker/ directory.
Copy the examples:
shcp .env.example .env cp app.config.example.yaml app.config.yaml cp livekit-server.example.yaml livekit-server.yaml cp docker-compose.override.example.yaml docker-compose.override.yamlFill in
.env. Replace everyFILL_ME_IN, and set your domain:BASE_DOMAIN=chat.example.comandBASE_URL=https://chat.example.com.BASE_DOMAINcan't change once the instance has data.JWT_SECRET,DB_PASSWORD,DB_ROOT_PASSWORDandMEILI_MASTER_KEY(at least 16 characters): long random values, e.g. fromopenssl rand -hex 32.LIVEKIT_PUBLIC_URL=wss://livekit.chat.example.com, plus the LiveKit secrets, which must matchlivekit-server.yaml(see Voice & LiveKit).DOCKER_TAG: which release to run (see choosing an image).
Edit the other files:
livekit-server.yaml: the two secrets underkeys:, andrtc.node_ip(your server's public IP address).app.config.yaml: registration and sign-in methods (see app.config.yaml). Keepmedia.local.dataDir: /data, so uploads land indata/refract/.docker-compose.override.yaml: your host names in the Traefik labels, and remove theactivity-chessexample service.
Create the proxy network, if your proxy doesn't already have it:
shdocker network create traefik-netCreate the database, then the first admin. The server won't start until the database is migrated and has at least one user:
shdocker compose pull docker compose run --rm backend yarn migrate docker compose run --rm backend yarn cli --create-admin admin@example.org 'a-long-password'Start it:
shdocker compose up -d docker compose psdocker compose psshows each service's health. The server waits for MariaDB, Redis and search to be healthy, then for its own checks, so give it a minute. Then open yourBASE_URLand sign in.
To fill a test instance with demo people and data instead of creating an admin, run docker compose run --rm backend yarn seed. The seeded accounts use the password password, so never seed an instance people can reach.
What's in the directory ​
| Path | What it is |
|---|---|
docker-compose.yaml | The services. Leave it as shipped, so upgrades stay simple |
docker-compose.override.yaml | Your changes: proxy labels, published ports, extra services |
.env | Secrets and settings (environment reference) |
app.config.yaml | Instance settings (app.config.yaml) |
livekit-server.yaml | LiveKit's own configuration (Voice & LiveKit) |
data/mariadb/ | The database |
data/refract/ | The server's /data: uploaded media, the federation key, push relay state |
data/search/ | The search index. Safe to delete: it's rebuilt from the database on start |
Choosing an image ​
DOCKER_TAG in .env picks which build of the server to run:
DOCKER_TAG | Follows |
|---|---|
1.9.11 | Exactly that release. It never moves. Best for production |
1.9 | The newest 1.9.x release |
latest | The newest release |
develop | The newest development prerelease |
1.9.12-develop.413 | Exactly that build |
Pin an exact release in production, so a restart never moves you to a new version unexpectedly. Settings in the app shows the running version and commit.
Upgrading ​
Back up (see below).
Set the new
DOCKER_TAGin.env, if you pin one.Pull the new image, migrate the database, then restart:
shdocker compose pull docker compose run --rm backend yarn migrate docker compose up -d
The server checks for pending migrations every time it starts. If it finds any, it stops with "There are pending migrations, please run these manually!" instead of running on an old schema, so always run yarn migrate after pulling a new image. Read the release notes before upgrading too: some releases need a step of their own.
Backups ​
Everything is in the docker/ directory, so a backup is a copy of it:
- the compose files,
.env,app.config.yamlandlivekit-server.yaml; data/, which holds MariaDB, the server's/dataand, if you run one, the push relay's data.
data/search/ can be skipped, as the index is rebuilt from the database. For a consistent copy of the database, stop the stack first (docker compose stop), or dump MariaDB while it runs. Keep the federation key in data/refract/federation/ safe in particular: other instances remember it.
Copy it somewhere off the host, by hand or with any backup tool or script you like.
Users and admin commands ​
Run the server's admin commands in a one-off container:
sh
# create an admin account
docker compose run --rm backend yarn cli --create-admin admin@example.org 'a-long-password'
# fill a test instance with demo data (password: password)
docker compose run --rm backend yarn seedMore commands are listed in Administration.
Building the image yourself ​
From the docker/ directory, docker compose up -d --build builds the image from your checkout instead of pulling it. A local build has no release version, so Settings shows 1.0.0.
Running a push relay ​
Mobile push notifications go through a push relay, which holds the Firebase and Apple credentials for the mobile app. Instances use the public relay at https://relay.refract.chat by default, and register with it from the admin settings (see Email, search & push). You only need your own relay if you build and distribute your own mobile app.
The relay is a separate Compose stack, independent of the server and its Redis. From the docker/ directory:
sh
cp .env.relay.example .env.relay
cp docker-compose.relay.override.example.yaml docker-compose.relay.override.yaml
# put the Firebase service-account JSON (and APNs .p8 key) here
mkdir -p data/relay/credsFill in .env.relay (JWT_SECRET from openssl rand -hex 32, the provider settings), and your relay's host name in the override's Traefik labels. Then:
sh
docker compose --env-file .env.relay -f docker-compose.relay.yaml -f docker-compose.relay.override.yaml up -d
# stop it
docker compose --env-file .env.relay -f docker-compose.relay.yaml -f docker-compose.relay.override.yaml downInstances ask the relay for access from their admin settings. Review and approve those requests on the relay:
sh
docker compose --env-file .env.relay -f docker-compose.relay.yaml -f docker-compose.relay.override.yaml \
exec relay yarn list_requests
docker compose --env-file .env.relay -f docker-compose.relay.yaml -f docker-compose.relay.override.yaml \
exec relay yarn approve_request REQUEST_UUIDdeny_request, list_tokens and revoke_token run the same way. Keep JWT_SECRET and data/relay/redis/ across upgrades: changing either cuts off every instance using the relay.