Every release is tested this way before it is published. An install of the previous release, filled with data shaped like real use of everything that release can hold (for example imported tickets, attachments, tags, contacts, saved replies, several agents, a locked workspace, three workspaces), is upgraded to the new release. The release is refused if any row, column or file is lost or changed, if a row ends up linked to another workspace, or if the upgraded server does not serve each inbox. The backup and both restores below are part of the same test. Details: upgrade testing.
Releases are tested from the release just before them. If you are several releases behind, upgrade one release at a time.
The commands below are for an install made with the installer: run them in its
directory (./colliedesk by default), where compose.yaml and .env are.
1. Back up
Note the release you run now; you need it to roll back:
docker compose run --rm --no-deps -T server '/app/collie version'
grep COLLIE_DESK_IMAGE .env
Stop the server, so nothing changes during the backup, then save the database and the attachment files:
docker compose stop server
stamp=$(date -u +%Y%m%dT%H%M%SZ)
docker compose exec -T postgres sh -c 'pg_dump -U "$POSTGRES_USER" --format=custom colliedesk' >"colliedesk-$stamp.dump"
docker compose run --rm --no-deps -T server 'tar -C /data/attachments -cf - .' >"attachments-$stamp.tar"
Check that both files are complete before you go on. Both commands end without an error (echo $?
prints 0) when they are:
docker compose exec -T postgres pg_restore --list <"colliedesk-$stamp.dump" >/dev/null
tar -tf "attachments-$stamp.tar" >/dev/null
Keep the two files somewhere other than this machine. pg_dump runs as the PostgreSQL superuser
(POSTGRES_USER in .env), because row-level security hides other workspaces' rows from every
other user.
2. Pull the new release
If .env has COLLIE_DESK_IMAGE=ghcr.io/colliedesk/colliedesk:latest, pulling is enough. If it
pins a version (...:0.0.1), change it to the new one first. Then:
docker compose pull server
Read the release notes of the new release.
3. Migrate
docker compose run --rm --no-deps -T server '/app/collie migrate'
It prints migrations applied. If it prints an error instead, do not start the server: roll back
(below) and report the error. Each migration runs in its own transaction, so a failed upgrade can
leave the database between two releases, and only the backup brings it back.
4. Start and check
docker compose up -d
docker compose ps
docker compose exec -T server /app/collie version
docker compose ps shows the server healthy within a minute, and collie version prints the new
release. If it prints the old one, COLLIE_DESK_IMAGE is set in your shell and wins over .env:
unset COLLIE_DESK_IMAGE and start again from step 3. Sign in, open the inbox, and open a
conversation that has an attachment. If your session has ended, print a sign-in link:
docker compose exec -T server /app/collie pair --workspace <slug> --email <your email>
Every exec and run here has -T (no terminal), so the commands also work from a script.
Roll back
Roll back when the migration fails or the new release does not work for you. The install goes back to the moment of the backup: anything written since then (new conversations, replies, received mail, changes) is gone. If you keep the new release running for a while before you decide, export what you need first (Export all your data).
- Stop the server and put the release you noted back in
.env(here0.0.1; edit the file by hand if you prefer):docker compose stop server sed -i.bak 's#^COLLIE_DESK_IMAGE=.*#COLLIE_DESK_IMAGE=ghcr.io/colliedesk/colliedesk:0.0.1#' .env grep COLLIE_DESK_IMAGE .env - Replace the database with the backup. Use the file names of your backup:
In installs older than the request user,docker compose exec -T postgres sh -c 'dropdb -U "$POSTGRES_USER" colliedesk && createdb -U "$POSTGRES_USER" -O colliedesk colliedesk' docker compose exec -T postgres sh -c 'pg_restore -U "$POSTGRES_USER" -d colliedesk --exit-on-error' <colliedesk-20261020T090000Z.dumpDATABASE_URLconnects as the superuser and the database owner is that user: use it after-O. - Replace the attachment files with the backup:
docker compose run --rm --no-deps -T server 'find /data/attachments -mindepth 1 -delete && tar -C /data/attachments -xf -' <attachments-20261020T090000Z.tar - Check the previous release takes the database as it is, then start it:
docker compose run --rm --no-deps -T server '/app/collie migrate' docker compose up -d .env.bakis a copy of.envwith its passwords: delete it once the install works.rm .env.bak
Sessions come back as they were at the backup. If you revoked a session or an agent token after the
backup, revoke it again (Sessions and devices). An install rolled back to v0.0.1
cannot restore one workspace (below), only the whole install as above.
Restore one workspace
To bring back one workspace and leave the others as they are (for example after a bad import or a
mistaken bulk change), use restore-workspace.sh of the release you are running, with a backup made
as in step 1. The script ships with every release after v0.0.1; on v0.0.1, upgrade first.
Replace <tag> with your release (collie version prints it, for example v0.0.2):
curl -fsSLO https://raw.githubusercontent.com/colliedesk/colliedesk/<tag>/restore-workspace.sh
docker compose stop server
sh restore-workspace.sh --workspace acme --database colliedesk-20261020T090000Z.dump \
--attachments attachments-20261020T090000Z.tar --replace
docker compose up -d
Replace acme with the workspace slug. Each release tests its
script on its own schema and on a backup of the release before. It:
- loads the backup into a scratch database beside yours and brings it to the schema of the release you run, so the backup may come from an older release;
- copies every row of that workspace in one transaction, and commits only when each table matches the backup row for row and every link points at a row that exists;
- replaces the workspace's attachment files with the backup's and checks each one against its checksum;
- touches no other workspace, and removes the scratch database at the end.
Without --replace it refuses to overwrite a workspace that still exists. Running it again gives
the same result. The workspace's sessions, agent tokens and unused invite links come back revoked:
everyone in it signs in again (an admin prints a link with collie pair), and AI agents need new
tokens. Anything that workspace wrote after the backup is gone.
From a clone
The repository's compose.yaml runs the binary directly instead of a shell. Put
--entrypoint sh before server and -c after it in the docker compose run commands above.
restore-workspace.sh needs the installer's layout.
This page is rendered from the repository. Spot a mistake? Open an issue or a pull request.