Wiki
Deploy with Docker
The uVersion server + PostgreSQL as containers, turnkey: download the image, load it, configure .env, start. Data and database location configurable.
An alternative to the .deb package: the uVersion server and its
PostgreSQL database run as containers, brought up by a single docker compose up.
Ideal if you prefer a containerized deployment, or to test quickly.
Prerequisites: Docker Engine 20.10+ with the Compose v2 plugin
(docker compose version), and a uVersion licence key. The server refuses
to start without a valid, signed key: get it from
your account (or obtain one from
the signup page).
docker with podman in every command on this page:
podman compose pull, podman load -i,
podman compose up -d. The docker-compose.yml provided already
labels its mounts for SELinux (the access control enabled by default on Red Hat, Rocky,
Alma and Fedora), with the :z suffix. Without this label, the container is
denied access to the mounted directories, and the message looks like a corrupt database
rather than a permissions problem.
Install
1. Fetch the compose file and the environment template
Two files, in a fresh folder that will become the stack's: the
docker-compose.yml and the .env template.
mkdir uversion && cd uversion
wget -N -O docker-compose.yml https://uversion.io/downloads/server/docker/docker-compose.yml
wget -N -O .env https://uversion.io/downloads/server/docker/env.example
2. Fetch the image
Online, the registry is enough:
docker compose pull
With no Internet access (isolated network), download the archive and load it instead: it carries the same image name as the compose, so startup finds it without downloading anything.
wget -N https://uversion.io/downloads/server/docker/uversion-server_latest_docker.tar.gz
docker load -i uversion-server_latest_docker.tar.gz
3. Fill in .env
Two values are required: UVERSION_LICENCE__KEY (your licence key, the
long signed string received by email) and POSTGRES_PASSWORD (a strong
password for the bundled database).
nano .env
The secret that signs sessions is generated on first start and kept
in the data directory. You have nothing to enter. It is part of the backup: if it
disappears, everyone will have to sign in once again, nothing is lost. If you prefer to
set your own (32 characters minimum), fill in
UVERSION_SECURITY__JWT_SECRET in .env: it is indeed passed to
the container, which then uses it instead of generating one.
POSTGRES_PASSWORD is only applied when the database is created, while its
directory is empty. Changing it afterwards in .env changes nothing on the
PostgreSQL side, which keeps the old one, while the server presents the new one: the
connection breaks without the message explaining it. To change it for real, change it
on both sides:
# Changer reellement le mot de passe de la base
docker compose exec db psql -U uversion -c "ALTER USER uversion PASSWORD 'nouveau-mot-de-passe'"
# Puis reporter la MEME valeur dans POSTGRES_PASSWORD (.env) et relancer
docker compose up -d
.env along with your data
It contains the licence key and the database password, and it lives next to the
docker-compose.yml, not in the volumes. Losing the machine while keeping the
data disks leaves a database nobody can address and a licence to request again: the
activation code received at signup is single-use and already consumed, only the
licence key it produced is reusable, and that is the one that is here. Treat
this file as a secret: chmod 600, and in the same backup as the database and
the chunks (the pieces of files, which take up the space).
4. Start the stack
docker compose up -d
The server is then reachable at https://YOUR-HOST:8443. No domain or
Let’s Encrypt certificate is required: the TOFU model handles it, that is, trust on first
contact, like SSH when it asks you to confirm a machine's fingerprint the first time.
5. Read the server fingerprint
It is rewritten in the logs at every start:
# L'empreinte du serveur, reecrite dans les journaux a chaque demarrage
docker compose logs server | grep -i "TLS fingerprint"
This is the server fingerprint (SHA-256 of its certificate): the server serves self-signed HTTPS on port 8443, and each client confirms it on the first connection. Share it with your team (see TLS fingerprint). Do not confuse it with a checksum, which is used to verify a downloaded file: this one identifies your server.
6. Read the initial admin password
Log in as admin with this password, then change it. The file is deleted as
soon as you change it.
# Le mot de passe admin initial (le fichier disparait des que vous le changez)
docker compose exec server cat /data/initial-admin-password
To follow the startup live, docker compose logs -f server works, but do
not put it in the middle of a sequence of commands: the -f follows the logs
indefinitely and never returns (Ctrl + C to exit).
Data and database
All the server's state (chunk store, TLS certificate and therefore the fingerprint,
server identity) lives in one host directory, and the PostgreSQL database in another. Both
are set in .env:
# Dans .env : placer les donnees et la base sur un disque large et sauvegarde
UVERSION_DATA_DIR=/srv/uversion/data # chunks, cert TLS, identite serveur
UVERSION_DB_DIR=/srv/uversion/db # PostgreSQL fourni
For a real deployment, point UVERSION_DATA_DIR at a large, backed-up
disk: the binary chunks of an Unreal project can be sizeable. The container adjusts the
permissions of the mounted directory on its own (it starts as root just long enough to fix
ownership, then drops to an unprivileged user), so you have nothing to chown
beforehand.
To use an external PostgreSQL already in place, set
UVERSION_DATABASE__URL in .env, then remove the
db service and the depends_on block in
docker-compose.yml.
# Dans .env : brancher un PostgreSQL existant
UVERSION_DATABASE__URL=postgres://user:motdepasse@db.interne:5432/uversion
Move the data and database
The simplest case is to set both variables before the first
up: nothing exists yet, there is nothing to copy. If the stack is
already running, you have to stop it and copy the directories by hand, preserving
ownership.
1. Stop the stack
Nothing must write during the copy:
docker compose down
2. Copy the two directories
It is the -a that preserves ownership and permissions:
sudo rsync -a ./data/server/ /srv/uversion/data/
sudo rsync -a ./data/db/ /srv/uversion/db/
3. Point .env at the new location
# Dans .env, LES DEUX lignes, pas une seule
UVERSION_DATA_DIR=/srv/uversion/data
UVERSION_DB_DIR=/srv/uversion/db
4. Restart
docker compose up -d
UVERSION_DB_DIR pointing at an empty directory gives a
blank database: PostgreSQL initializes it without flinching, and you end up with a full
chunk store paired with a database that has no metadata at all.
Three path pitfalls, all encountered:
- A relative path is resolved relative to the compose file, not
relative to the directory from which you run the command.
./data/serveralways designates the neighbour of thedocker-compose.yml. - A network share (NFS, CIFS, a Windows share) generally refuses the
chownthat the container performs at startup. The container then exits immediately, on a permissions error that mentions neither uVersion nor storage. Use a local disk or a block volume. rsync -ais what preserves ownership and permissions. A copy made withcpwithout options, or from a file explorer, resets everything to the current account, and PostgreSQL then refuses to start on its own directory.
Operations
Back up: the database
It carries the metadata: files, revisions, users, locks.
docker compose exec db pg_dump -U uversion uversion > uversion-db.sql
Back up: the server data
This is the host directory designated by UVERSION_DATA_DIR. Both backups
count: one without the other restores nothing.
# .env n'est pas charge dans votre shell, chargez-le pour reutiliser la variable
set -a; . ./.env; set +a
DATA_DIR="$UVERSION_DATA_DIR"
[ -n "$DATA_DIR" ] || DATA_DIR=./data/server # valeur par defaut
tar czf uversion-data.tar.gz -C "$DATA_DIR" .
Update
The data and the database are not touched, the migrations apply at startup.
docker compose pull
docker compose up -d # les migrations s'appliquent au demarrage
On an isolated network, load a newer archive instead:
wget -N https://uversion.io/downloads/server/docker/uversion-server_latest_docker.tar.gz
docker load -i uversion-server_latest_docker.tar.gz
docker compose up -d
Stop
docker compose stop stops the containers, docker compose down
removes them. In both cases your data stays in place.
down -v erases nothing here
The published compose uses no named volume: your data and your database are in the two
host directories designated by .env. Neither down nor
down -v touches them. To really start from scratch, you have to delete these
directories yourself. This is important to know: the reflex, after an authentication
failure, is to run down -v then up, and that loops back onto
exactly the same error, with the same database and the same password.