Moving an install
Neither move happens in place. You do a fresh install and load a dump of the old database before the new install first starts.
| From | To | Follow |
|---|---|---|
| A legacy Compose install | An owned install | Move a Compose install |
| A rootful owned install | Rootless Docker or Podman | Move to rootless |
Either way:
- The database comes with you: accounts, app library, profiles and settings.
- Hosts are added again, under their old node names, which keeps their history and homes.
- Stored credentials are entered again. The new install has a new
QUASAR_SECRET_KEY.
Before you start
Section titled “Before you start”- From Admin, Fleet, note each host’s node name and every machine’s home root (and template root).
- Install the same release as the old one, or newer. A dump from a newer release is refused.
- Plan a window with no one playing.
- Read Install with Docker or Install with Podman once.
Move a Compose install
Section titled “Move a Compose install”- The old install keeps working meanwhile and gets no updates. No rush.
- Homes stay where they are. Give the new install the same home root.
- Keep the old
deploy/.env.
-
Stop the old control plane and every agent, but not the database. On the first machine, from its stack directory:
Terminal window docker compose -f deploy/docker-compose.yml stop quasar-control-plane quasar-node-agent quasar-updaterOn each other GPU host:
Terminal window docker compose --project-directory /opt/quasar-agent down -
Dump the old database in custom format (
-Fc):Terminal window docker compose -f deploy/docker-compose.yml exec -T quasar-postgres \pg_dump -Fc -U quasar quasar > quasar-move.dumphead -c 5 quasar-move.dump; echo # prints PGDMPIf
deploy/.envsetsPOSTGRES_USER, use that instead ofquasar. A dump withoutPGDMPwill be refused. -
Remove the old stack on the first machine, without
-v:Terminal window docker compose -f deploy/docker-compose.yml downThis keeps the old volumes so you can go back. The old containers must be removed, not just stopped: the new install refuses to work around them, and they hold ports 8080 and 8443.
-
Install the first machine, held for the restore. Follow Install the first machine with three changes:
- add
QUASAR_AWAIT_RESTORE=1(-e QUASAR_AWAIT_RESTORE=1withdocker run, orQUASAR_AWAIT_RESTORE: "1"in the stack’senvironment); - use the same home root as the old
QUASAR_HOME_ROOT; - on a combined machine, set
QUASAR_NODE_NAMEto the oldNODE_NAME.
The seed installs Postgres and waits; the console isn’t up yet.
docker logs quasar-recoveryshows the next command. Restore only works into Quasar’s own database. If you use your own (QUASAR_DATABASE_HOST), restore it with your own tools before installing. - add
-
Load the dump, on the machine holding
quasar-move.dump:Terminal window docker exec -i quasar-recovery quasar-recovery restore --dump - < quasar-move.dumpKeep
-i: the dump comes from standard input. The restore checks the file, loads it, creates the control plane and waits until it’s healthy. If it fails before creating the control plane, nothing is kept: fix the named problem and rerun. If the command stops without a message, see If the restore stops without a message. -
Sign in with your old admin account. Every host shows Offline, except a combined machine’s own.
-
Add each GPU host again (Add a GPU host) with its old node name and the same home root. A new name makes a new host; the old one stays offline until you remove it.
-
Enter stored credentials again, such as the SteamGridDB key (Admin, Library, Sources) and Admin, Settings, Secrets. They were encrypted with the old
QUASAR_SECRET_KEYand show as not readable. -
Verify as in Check your install: hosts online and a real session plays. Players stay signed in.
After the install, you can remove QUASAR_AWAIT_RESTORE from the seed.
What does not come across
Section titled “What does not come across”- Stored credentials (step 8).
- The old hosts’ agents (step 7).
- The old stack’s files. Most
deploy/.envsettings don’t apply; see the environment reference. - Portainer isn’t supported. Plain Docker (including a
docker runseed on Unraid), Dockge and Arcane are.
Move to rootless
Section titled “Move to rootless”An install can’t be switched from rootful to rootless in place.
- Homes are copied into a new root owned by the
quasaraccount, never re-owned in place (why). - Same machine or a different one. Either way, fully uninstall the old install before starting the new one.
- These steps show rootless Podman. For rootless Docker, use
dockerin place ofpodman.
-
Stop the old seed (
docker rm -f quasar-seed,systemctl stop quasar-seedfor a Podman seed, with--userwhen rootless, or remove it in your stack manager). The next step refuses while a seed exists. -
Take a final dump and remove the old install, on the old machine:
Terminal window img=$(docker inspect -f '{{.Config.Image}}' quasar-recovery)docker run --rm -it --security-opt label=disable \-v /var/run/docker.sock:/var/run/docker.sock \-v quasar-machine:/var/lib/quasar-machine "$img" uninstall --purge \--confirm <old node name> --dump-to /var/lib/quasar/moveIt runs in its own container because it stops the recovery actor. (Running
uninstallthroughdocker exec(podman execon Podman) is refused and prints this command for your engine.) This writes/var/lib/quasar/move/quasar-final-<timestamp>.dumpon the host, then removes the old containers, volumes and network. Homes and templates are kept. If the dump fails, nothing is deleted. Copy the dump off if you’re changing machines, then:Terminal window docker volume rm quasar-machineYour own database (
QUASAR_DATABASE_HOST) is not dumped. Restore it with your own tools before the new install first starts. -
Prepare the new host for rootless, following Prepare the host, once, as root with new homes and templates paths:
/var/lib/quasar/homes-rootlessand/var/lib/quasar/templates-rootlesshere. On the same machine, do this after step 2. -
Copy homes and templates, setting the owner during the copy:
Terminal window sudo rsync -a --chown=quasar:quasar /var/lib/quasar/homes/ /var/lib/quasar/homes-rootless/sudo rsync -a --chown=quasar:quasar /var/lib/quasar/templates/ /var/lib/quasar/templates-rootless/Don’t
chown -Ror delete the old roots until the new install has played a real session. -
Install fresh, held for the restore, as in Install, as
quasar, with the old install’s role (combined or control-only) and the new homes and templates roots. Before starting the seed, add to the Quadlet unit:Terminal window Environment=QUASAR_AWAIT_RESTORE="1"Environment=QUASAR_NODE_NAME="<old node name>"(
QUASAR_NODE_NAMEon a combined machine only. Withpodman run, use-e.) The seed installs Postgres and waits. As thequasaraccount,podman logs quasar-seedshows the restore command (no session yet? see getting a rootless session). -
Restore the dump, on the new machine:
Terminal window podman exec -i quasar-recovery quasar-recovery restore --dump - < quasar-final-<timestamp>.dumpKeep
-i: the dump comes from standard input. If it fails before the control plane is created, nothing is kept: fix the named problem and rerun. If the command stops without a message, see If the restore stops without a message. -
Sign in with the old admin account and add each GPU host again (Add a GPU host) with its old node name and the new homes root. On rootless, run the command as the
quasaraccount. -
Enter stored credentials again (the SteamGridDB key and Admin, Settings secrets).
-
Verify as in Check your install: hosts online and a real session that saves into the copied homes. Then remove the old homes and template roots.
uninstall --purge also refuses while a seed exists (step 1) or when run inside
the recovery actor’s own container.
If the restore says no
Section titled “If the restore says no”| Message | Fix |
|---|---|
| Dump is newer than this install’s control plane | Take the new install apart with uninstall --purge and install that release or newer. |
Not a custom-format archive, or pg_restore can’t read it |
Dump again with -Fc. Check it starts with PGDMP and matches the size on the old machine. |
| This machine’s control plane has already been created | The install wasn’t held, or has booted since. The message prints the command that takes it apart, filled in for your engine (it runs in its own container, as in Move to rootless, step 2). Then remove the quasar-machine volume and install again with QUASAR_AWAIT_RESTORE=1. |
| Control plane did not report healthy | Check docker logs quasar-control-plane. To start over, take the new install apart as above. |
If the restore stops without a message
Section titled “If the restore stops without a message”The restore runs in the recovery actor, so if the actor restarts or is killed, the command ends (exit code 137) with nothing printed. The restore itself carries on or stops by itself. Don’t run it again yet. Read:
docker exec quasar-recovery quasar-recovery status(podman exec on Podman.)
status shows |
Meaning | Do |
|---|---|---|
| The control plane running and healthy | The restore finished. | Nothing. Running it again is refused. |
An attempt still open (in_flight set) |
It resumed after the restart. | Wait, then read status again. |
| A failed result whose output says “nothing was changed. Run the command again.” | It stopped before touching anything. | Run the same restore command again. |
| A failed result, control plane not created | The file was not kept. | Fix what the output names, then run the restore again with the file. |
| A failed result, control plane created | The dump loaded, then the first boot or the health check failed. | Don’t run it again (it is refused). Follow the start-over command the output prints, as in If the restore says no. |
Staying on Compose
Section titled “Staying on Compose”A legacy install keeps working on its release, without updates. See Legacy Compose installs. Building from source with Compose is for contributors only: Set up a checkout.