Skip to content

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/udp and 7868/tcp by default.

Quick start ​

Run everything from the docker/ directory.

  1. Copy the examples:

    sh
    cp .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.yaml
  2. Fill in .env. Replace every FILL_ME_IN, and set your domain:

    • BASE_DOMAIN=chat.example.com and BASE_URL=https://chat.example.com. BASE_DOMAIN can't change once the instance has data.
    • JWT_SECRET, DB_PASSWORD, DB_ROOT_PASSWORD and MEILI_MASTER_KEY (at least 16 characters): long random values, e.g. from openssl rand -hex 32.
    • LIVEKIT_PUBLIC_URL=wss://livekit.chat.example.com, plus the LiveKit secrets, which must match livekit-server.yaml (see Voice & LiveKit).
    • DOCKER_TAG: which release to run (see choosing an image).
  3. Edit the other files:

    • livekit-server.yaml: the two secrets under keys:, and rtc.node_ip (your server's public IP address).
    • app.config.yaml: registration and sign-in methods (see app.config.yaml). Keep media.local.dataDir: /data, so uploads land in data/refract/.
    • docker-compose.override.yaml: your host names in the Traefik labels, and remove the activity-chess example service.
  4. Create the proxy network, if your proxy doesn't already have it:

    sh
    docker network create traefik-net
  5. Create the database, then the first admin. The server won't start until the database is migrated and has at least one user:

    sh
    docker compose pull
    docker compose run --rm backend yarn migrate
    docker compose run --rm backend yarn cli --create-admin admin@example.org 'a-long-password'
  6. Start it:

    sh
    docker compose up -d
    docker compose ps

    docker compose ps shows 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 your BASE_URL and 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 ​

PathWhat it is
docker-compose.yamlThe services. Leave it as shipped, so upgrades stay simple
docker-compose.override.yamlYour changes: proxy labels, published ports, extra services
.envSecrets and settings (environment reference)
app.config.yamlInstance settings (app.config.yaml)
livekit-server.yamlLiveKit'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_TAGFollows
1.9.11Exactly that release. It never moves. Best for production
1.9The newest 1.9.x release
latestThe newest release
developThe newest development prerelease
1.9.12-develop.413Exactly 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 ​

  1. Back up (see below).

  2. Set the new DOCKER_TAG in .env, if you pin one.

  3. Pull the new image, migrate the database, then restart:

    sh
    docker 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.yaml and livekit-server.yaml;
  • data/, which holds MariaDB, the server's /data and, 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 seed

More 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/creds

Fill 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 down

Instances 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_UUID

deny_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.

Released under the GNU Affero General Public License v3.0.