Legacy Compose installs
A legacy Compose install is one started from deploy/docker-compose.yml and
deploy/.env. Postgres, the control plane, the node agent and quasar-updater
are services in your stack, and .env holds the secrets. New installs are owned
by Quasar instead: see Install with Docker.
What happens to a legacy install
Section titled “What happens to a legacy install”- It keeps running on its current release. Everything on this page keeps working.
- It gets no further releases. The console shows no new release (not an
error). The
edgechannel also stops. - Nothing converts it in place. To replace it, do a fresh install and bring your data across in a database dump: Move a Compose install.
The stack directory and .env
Section titled “The stack directory and .env”deploy/.env is the only copy of POSTGRES_PASSWORD, QUASAR_SECRET_KEY and any
static enrollment token. Nothing regenerates them. Keep a copy off the machine,
stored as a secret:
cp deploy/.env quasar-env-$(date +%Y%m%d).backupIf you lose QUASAR_SECRET_KEY, credentials saved in the admin area must be
entered again.
The stack directory must survive a reboot. On Unraid, /root is a ramdisk: a stack
there is lost at the next boot. Move it.
The updater service
Section titled “The updater service”quasar-updater recreates the control plane and agent when you apply an update
from the console. It holds the Docker socket, but:
- It pulls only digests inside
QUASAR_UPDATER_ALLOWED_NAMESPACES(default: the project’s own registry namespace). - It recreates only the two Quasar services in its own stack. It builds nothing, runs no arbitrary command, and never touches Postgres or other containers.
Set QUASAR_STACK_DIR in deploy/.env to the stack directory’s absolute host
path. If unset, the updater refuses to serve.
A stack without the updater also works: upgrade it by hand. Nothing ships the updater any more, so it can’t be added later.
Verify release signatures
Section titled “Verify release signatures”Optional, off by default. The installed digest is always the one the release
manifest pins. To also check the manifest’s signature, set these in that host’s
deploy/.env and recreate the updater:
QUASAR_UPDATER_SIGNATURE_MODE=verifyQUASAR_UPDATER_TRUSTED_KEYS=<key-id>:<base64 public key>docker compose -f deploy/docker-compose.yml up -d --no-deps quasar-updater| Mode | Bad signature | No signature |
|---|---|---|
verify |
Refused | Accepted |
require |
Refused | Refused, including every edge release and a revert to a build this instance can no longer name |
Either mode with no trusted keys refuses every update. Check a host’s
settings (signature_mode, trusted_key_ids, manifest_source):
docker compose -f deploy/docker-compose.yml exec quasar-updater \ curl -s --unix-socket /run/quasar-updater/updater.sock http://u/v1/selfUpgrade by hand
Section titled “Upgrade by hand”The Releases page shows these commands filled in. The digests are in the release’s
platform-release-manifest.json asset (control plane, then node agent).
-
Back up Postgres and
deploy/.env(below). Migrations only go forward. -
Pin the two digests in
deploy/.env:Terminal window QUASAR_CONTROL_IMAGE=ghcr.io/accreleus/quasar/quasar-control-plane@sha256:<control-plane digest>QUASAR_AGENT_IMAGE=ghcr.io/accreleus/quasar/quasar-node-agent@sha256:<node-agent digest> -
Pull and recreate those two services.
Terminal window docker compose -f deploy/docker-compose.yml pull quasar-control-plane quasar-node-agentdocker compose -f deploy/docker-compose.yml up -d --force-recreate --no-deps \quasar-control-plane quasar-node-agent -
Verify.
Terminal window docker compose -f deploy/docker-compose.yml pscurl http://localhost:8080/healthCheck the agent re-registered under Admin, Fleet, Hosts, then launch a real session.
- Repeat every
-fyou deploy with, for example-f deploy/docker-compose.nvidia.ymlon NVIDIA. Dropping an overlay recreates the containers without it. - Recreating the node agent ends every session on that host. Drain it first.
- Recreating the control plane runs migrations. From then on the hard rule applies: don’t pin back the old digest.
If your install ever ran a source build
Section titled “If your install ever ran a source build”The old source-built image ran as root, so its quasar-control-tls volume is
root-owned. Published images run as uid 1000 and crash-loop with:
fatal: tls: write TLS key /var/lib/quasar-control/tls/key.pem: permission deniedNothing is damaged. Fix it once:
docker volume ls --format '{{.Name}}' | grep quasar-control-tlsdocker run --rm -v <that name>:/t alpine chown -R 1000:1000 /tdocker compose -f deploy/docker-compose.yml up -d --no-deps quasar-control-planeBack up and restore
Section titled “Back up and restore”Take a dump before every upgrade:
docker compose -f deploy/docker-compose.yml exec -T quasar-postgres \ pg_dump -U quasar -Fc quasar > quasar-$(date +%Y%m%d-%H%M).dumpThe same dump is how you move to an owned install.
To restore into this stack:
-
Stop the control plane. Never restore over a live database.
Terminal window docker compose -f deploy/docker-compose.yml stop quasar-control-plane -
Restore the dump.
Terminal window docker compose -f deploy/docker-compose.yml exec -T quasar-postgres \pg_restore -U quasar -d quasar --clean --if-exists --no-owner --no-privileges \--exit-on-error < quasar-20260810-1430.dump -
Restore
deploy/.env, especiallyQUASAR_SECRET_KEY. With a different key, saved credentials can’t be decrypted. -
Start the control plane. It applies any migrations.
Terminal window docker compose -f deploy/docker-compose.yml start quasar-control-plane
The updater leaves .env.prev beside deploy/.env: the file as it was before the
last apply, showing which digests were replaced.
Moving an existing stack
Section titled “Moving an existing stack”For a stack directory that won’t survive a reboot (on Unraid, anything under
/root). Move it; don’t reinstall, since the .env credentials are irreplaceable.
cp=$(docker ps -q --filter 'label=com.docker.compose.service=quasar-control-plane')old=$(docker inspect "$cp" --format '{{ index .Config.Labels "com.docker.compose.project.working_dir" }}')new=/mnt/user/appdata/quasar/deploy # persistent storage on this host
docker compose -f "$old/docker-compose.yml" downinstall -d -m 0700 "$(dirname "$new")"mv "$old" "$new"sed -i "s|^QUASAR_STACK_DIR=.*|QUASAR_STACK_DIR=$new|" "$new/.env"docker compose -f "$new/docker-compose.yml" up -dKeep the directory named deploy: Compose takes the project name from it.
down without -v keeps the database and saves.
Recovering a stack written to a ramdisk
Section titled “Recovering a stack written to a ramdisk”If the directory is already gone, the containers usually keep running, so it only
shows at the next docker compose command or upgrade.
Recover the credentials before stopping anything. They now exist only in the running containers:
cp=$(docker ps -q --filter 'label=com.docker.compose.service=quasar-control-plane')docker inspect "$cp" --format '{{ range .Config.Env }}{{ println . }}{{ end }}' \ | grep -E '^(QUASAR_SECRET_KEY|ENROLLMENT_TOKEN)='
pg=$(docker ps -q --filter 'label=com.docker.compose.service=quasar-postgres')docker inspect "$pg" --format '{{ range .Config.Env }}{{ println . }}{{ end }}' \ | grep -E '^POSTGRES_PASSWORD='Then rebuild the stack directory on persistent storage with those values. Don’t generate new credentials: the database expects the old password.
install -d -m 0700 /mnt/user/appdata/quasar/deploy(keep the namedeploy).- Save
deploy/docker-compose.ymlfrom your release’s tag into it. - Write
.envwith the recovered values andQUASAR_STACK_DIRset to the new path. docker compose -f /mnt/user/appdata/quasar/deploy/docker-compose.yml up -d.
Adding a GPU host
Section titled “Adding a GPU host”Add hosts the current way: Fleet ▸ Hosts ▸ Add host. It mints a single-use
enrollment token and prints a one-line installer to run as root on the new
machine, plus the same seed as a one-service Compose stack on its Dockge or
Arcane tab. The installer checks the host and, when you accept, applies a fix
before it starts the seed. The stack carries only the enrollment string, so
preparing the host, including NVIDIA, stays the one-line command’s job
(sh enroll-host.sh --fix-only prepares it and stops). See Upgrading, backing
up, and rolling back, “Coming from a Compose
install”.
Health and logs
Section titled “Health and logs”docker compose -f deploy/docker-compose.yml psdocker compose -f deploy/docker-compose.yml logs -f quasar-control-planedocker compose -f deploy/docker-compose.yml logs -f quasar-node-agentStop, and uninstall
Section titled “Stop, and uninstall”Stop, keeping everything:
docker compose -f deploy/docker-compose.yml downStop and delete the database, the agent’s enrollment secret, the TLS certificate and the artwork cache:
docker compose -f deploy/docker-compose.yml down -v