Manual Update & Rollback
SeqDesk does not keep a .update-backup/ directory. Every release lives in its
own directory and the live application is whichever release the current/
symlink points at. Rolling back means pointing current/ at a previous release —
there is no file restoration step.
The thing an operator actually needs to know before rolling back is what happens to the database. The short answer is nothing: a rollback moves a symlink. The long answer is below.
Release layout
A release-layout install is organised under a single root directory:
<root>/
current -> releases/1.1.125 # atomic symlink to the live release
releases/
1.1.124/ # previous release (kept for rollback)
1.1.125/ # active release
settings.json # shared config, symlinked into each release
data/ # shared, symlinked into each release
pipelines/ # shared
pipeline_runs/ # shared
backups/ # pre-update pg_dump files
start.sh # wrapper -> current/start.sh
.update-state.json # phase, previous/target/active release
.update-status.json # last reported progress
.update-lock # present while an update is running
.seqdesk-bind-host # persisted SEQDESK_BIND_HOST, mode 600data/, pipelines/, pipeline_runs/ and settings.json live at the root and
are symlinked into each release, so they are shared across versions and survive
updates and rollbacks. Inside a release, settings.json is a relative symlink
(../../settings.json).
Never replace releases/<version>/settings.json with a real file. The
application writes configuration through that symlink, so a real file
silently splits the live config in two and is discarded at the next update.
Edit <root>/settings.json instead.
Installs that predate the canonical filename keep using seqdesk.config.json
instead; the installer deliberately reuses whichever of the two names already
exists, so an upgrade never ends up with both.
The root start.sh is a thin wrapper that cds into current/ and runs that
release’s start.sh, which ends in exec node server.js. Because it resolves
current/ at launch, restarting after a symlink swap is all that is needed to
change versions.
Run seqdesk doctor to diagnose a broken install
— it reports on the layout, the current/ symlink target, database
connectivity, and the HTTP endpoint.
Rollback
One-click (recommended)
From Settings → Info → Software Updates, use Roll back release. This
calls POST /api/admin/updates/rollback, which re-points current/ at the
release recorded as previousRelease in .update-state.json and restarts the
application. The button appears whenever a previous release is recorded — in
practice, after a failed update.
Rollback goes one step back, to the release that was active before the last
update. It is not a version picker: .update-state.json records a single
previous release, and each rollback overwrites it with the release you are
leaving. To reach an older version than that, use the manual swap below.
The route refuses, with the reason shown in the panel, when:
| Message | Cause |
|---|---|
Rollback is only available for release-layout installations. | There is no current/ symlink — this is a flat install |
No previous release is recorded for rollback (409) | .update-state.json has no previousRelease, usually because no update has ever run here |
Previous release is missing: <path> | The recorded directory was deleted |
SeqDesk is already running the recorded previous release. | Nothing to do |
Update already in progress (409) | The update lock is held |
Manual fallback (symlink swap)
If the in-app action is unavailable — the app will not start, or you need to go back further than one release — re-point the symlink by hand.
Stop the server
# pm2
pm2 stop seqdesk
# user systemd service
systemctl --user stop seqdesk
# system systemd service
sudo systemctl stop seqdeskRe-point the current symlink
From the install root, point current at the prior release directory:
cd /opt/seqdesk
ls releases/ # e.g. 1.1.123 1.1.124 1.1.125
ln -sfn releases/1.1.124 current # atomic replace of the symlinkln -sfn replaces the link atomically. Do not rm current first — that leaves a
window in which the wrapper script has nothing to cd into.
Restart the server
./start.shOr via your process manager (pm2 restart seqdesk,
systemctl --user restart seqdesk, or sudo systemctl restart seqdesk).
Confirm
readlink current
npx -y seqdesk@latest doctor --dir /opt/seqdeskWhat a rollback does to the database
Nothing. A rollback moves a symlink and restarts the process. It does not run migrations, does not drop tables, and does not restore data.
That is usually what you want, and occasionally exactly the problem:
- Migrations run with
prisma migrate deployand are forward-only. If the release you are rolling away from applied new migrations, the schema is already migrated and stays migrated. - An older application version then runs against a newer schema. Prisma tolerates additive migrations (new tables, new nullable columns) well, and does not tolerate destructive ones (dropped or renamed columns the old client still selects) at all.
- So: rolling back across an additive migration is normally safe. Rolling back across a destructive one requires restoring the database as well.
If you do not know which kind you crossed, compare the prisma/migrations/
directories of the two releases:
diff <(ls /opt/seqdesk/releases/1.1.124/prisma/migrations) \
<(ls /opt/seqdesk/releases/1.1.125/prisma/migrations)Migrations present only in the newer release are the ones the older code has never seen.
Restoring the pre-update database dump
Before every migration — during both an update and a Retry update repair — the updater writes a best-effort custom-format dump:
<root>/backups/pre-update-<ISO-timestamp>.dumpTo restore it, stop SeqDesk first so nothing writes during the restore:
pm2 stop seqdesk # or your service manager
pg_restore \
--clean --if-exists \
--dbname "$DATABASE_URL" \
/opt/seqdesk/backups/pre-update-2026-07-27T09-14-02-118Z.dump
pm2 start seqdesk--clean --if-exists drops and recreates the objects in the dump, so the
database returns to its pre-migration schema and contents. Everything written
since the dump was taken is lost — that is the trade, and it is why the dump is a
restore point rather than a backup strategy.
The dump is best-effort. If pg_dump was not available on the server, no dump
was written and the update said so in its failure message. ls <root>/backups/ before you rely on one existing.
Manual update
To start an update, use Settings → Info → Software Updates: Check now, review the release, then Install update. That flow downloads, verifies, stages, activates and migrates the new release. It is the only supported update path — see Automatic Updates.
There is no seqdesk update command. Upgrading the npm launcher
(npx seqdesk@latest) upgrades the launcher, not an already-installed
application.
The following command is configuration-only and deliberately skips the release download:
npx seqdesk@latest -y --reconfigure --dir /opt/seqdeskUse it to re-apply configuration to an existing install. It leaves the database
alone unless you add --reseed-db, which runs prisma migrate deploy and then
the seed.
Do not hand-extract tarballs over a live release, and do not use
--overwrite-existing as an update substitute — it backs up the whole install
directory and replaces it, which is a reinstall, not an upgrade. If the
application cannot start, use the manual rollback above to restore the previous
release, then retry the built-in update.
Disk usage over time
Old release directories are never pruned automatically. Each one is a full
application tree with its own node_modules, so a long-lived install accumulates
hundreds of megabytes per release, and the update itself needs 150 MB free before
it will start.
Prune by hand, keeping at least the active release and the one before it:
cd /opt/seqdesk
readlink current # confirm what is live, e.g. releases/1.1.125
cat .update-state.json # confirm previousRelease
rm -rf releases/1.1.120 releases/1.1.121Deleting the directory named in previousRelease disables one-click rollback:
the route then fails with Previous release is missing.
Pre-update dumps in backups/ also accumulate, one per update and per repair.
They are the only automatic restore point you have, so prune them on a schedule
rather than opportunistically — keep the last few, and rely on your own backup
system for anything older.
Backup strategy
The release directories cover application code only, and the pre-update dumps cover only the moment just before a migration. For real disaster recovery:
- Database — back up PostgreSQL on your own schedule with
pg_dumpor a snapshot. This is the only copy of orders, samples, studies, users and settings. - Configuration — keep a sanitised copy of
<root>/settings.jsonunder version control, and the secrets in your secret manager. See Config File Reference. - Sequencing data — the shared
data/directory is not managed by SeqDesk; use your own backup system. - Pipeline outputs — back up
pipeline_runs/if the results matter; they can be large and are usually reproducible from the inputs.
The Software Updates panel states this plainly: database backups stay operator-managed. SeqDesk applies migrations; it does not own your backups.
Related
- Automatic Updates — the flow, the safeguards, and the errors each step produces
seqdesk doctor— diagnose layout, database and HTTP problems- Config File Reference — why
settings.jsonsurvives updates and where it really lives