Upgrading¶
Schema migrations run automatically on startup, in order, and are recorded in
SQLite's user_version. There is no separate migrate command to remember.
Before you start¶
Back up the data directory. The database runs in WAL mode, so copy all three files together, or stop the service first:
sudo systemctl stop longbox # or: docker compose stop
cp -a /var/lib/longbox /var/lib/longbox.backup-$(date +%F)
Check where you are starting from. A minimal Debian install has no sqlite3
command, so either works:
sqlite3 /var/lib/longbox/longbox.db 'PRAGMA user_version;'
python3 -c "import sqlite3;print(sqlite3.connect('/var/lib/longbox/longbox.db').execute('PRAGMA user_version').fetchone()[0])"
| Version | Shipped |
|---|---|
| 1 | Single-user catalogue |
| 2 | Multi-user accounts, OAuth identity model |
| 3 | Password reset, admin audit log |
| 4 | Full ComicInfo coverage, portable ids, integrity hashes |
| 5 | A second metadata source — Metron ids alongside the Comic Vine ones |
| 6 | Skins, with Newsprint and Midnight seeded as real rows |
Docker¶
cd longbox
git pull
docker compose up -d --build
docker compose logs -f longbox # watch it come up
systemd¶
Re-run the installer. It replaces the application and the unit file, refreshes dependencies, and leaves your data and configuration alone:
cd longbox
git pull
sudo ./deploy/install.sh
journalctl -u longbox -f
/var/lib/longbox is never touched, and /etc/longbox.env keeps every value
you have set — which is why host-specific settings belong in the env file and
not in the unit, since anything you put in the unit is overwritten on the next
upgrade. The installer will append a setting the file is missing entirely,
so that longbox-cli reads the same paths the service does, and tells you when
it does.
Upgrading onto the /var/cache layout. Extracted pages used to live in
/var/lib/longbox/pages and now use /var/cache/longbox, so a backup of the
library no longer sweeps them up. They rebuild themselves on demand, so there
is nothing to migrate — the installer points out the old directory and you can
remove it whenever it suits you.
What each upgrade does to your data¶
1 → 2 (single-user to multi-user). comic, library_folder and setting
are rebuilt, because they need constraints SQLite cannot add to an existing
table. Your library is parked on an inactive placeholder account, and the
first account you create adopts all of it — comics, reading state,
favourites, watched folders and your Comic Vine key. So after this upgrade,
open the web UI and register before anyone else does; whoever registers first
becomes the administrator and inherits the library.
2 → 3 (password reset and audit log). Purely additive: two new tables and one column. Nothing moves, nobody needs to re-register.
3 → 4 (metadata coverage and identity). Seventeen nullable columns, then a
backfill that gives every existing comic a portable id. Nothing is re-read from
disk, so the new ComicInfo fields stay empty on comics already imported until
you re-read them — python -m app.cli verify will not do it, but "Re-read file"
on a comic, or a rescan with Re-read files already imported, will.
4 → 5 (a second metadata source). Nullable columns only. Metron ids sit alongside the Comic Vine ones rather than replacing them, so a book tagged from either source carries both and stays cross-referenced.
5 → 6 (skins). A new table and its two seed rows, both created by the schema script that runs after every migration. Nothing existing is altered, and the active skin is a setting rather than a row — selecting "Default" clears it.
Afterwards¶
Confirm the service actually restarted, before anything else. Copying files over a running process does not change what it serves, and every other check on this page can pass while the previous release keeps answering.
systemctl show longbox -p ActiveEnterTimestamp
That timestamp should be from the upgrade, not from whenever the service last
came up. install.sh now runs systemctl restart rather than relying on
enable --now, which starts a stopped unit and does nothing at all to a
running one — so on any release before that fix, re-running the installer left
the old process in place. It looked like a successful upgrade in every respect
the log could show.
Then:
GET /healthzreports the version and the number of accounts.- Check
PRAGMA user_versionagain to confirm it advanced. - Open the library and confirm your comics are there. Covers are cached in
data/covers/and are not touched by migrations. - If something looks wrong, stop the service and restore the backup. Migrations are one-way — a newer database will not run on an older release, so rolling back means restoring the copy you took.
If you are locked out after upgrading¶
The account recovery CLI needs no web UI and no third-party packages:
sudo longbox-cli list-users
sudo longbox-cli reset-password <username>
Use the wrapper rather than calling the interpreter yourself. Invoking
/opt/longbox/.venv/bin/python -m app.cli by hand picks up neither
/etc/longbox.env — systemd loads it only for the units it starts — nor the
working directory the package needs, so it would look for a database in the
wrong place entirely.