# Back it up, and move it Two things are irreplaceable, and neither is the software. `somnia.db` holds where you are in every book, how far you have heard, and the index that makes semantic seek possible. The library holds hours of rendered audio that cost hours of CPU. Everything else — the virtual environment, the settings file, the catalog, and the joined-up copies under `streams` — can be rebuilt in ten minutes. ## Back up the database while it is running somnia runs in WAL mode, so copying the file with `cp` while the server is up can give you a torn database. sqlite's own backup does it safely, and the virtual environment already has everything needed: ```bash ~/somnia-venv/bin/python - <<'PY' import sqlite3 src = sqlite3.connect("/home/you/.local/share/somnia/somnia.db") dst = sqlite3.connect("/backup/somnia.db") with dst: src.backup(dst) PY ``` The library is ordinary files that are only ever appended to, so it needs nothing clever: ```bash rsync -a ~/library/audiobooks/ /backup/audiobooks/ ``` A render in progress means a partial chapter in the copy, which the next render overwrites. It is not a reason to stop the world. ## Move both to another machine Install somnia on the new box first — [Installation](../tutorials/installation.md) — then bring the data across, and set `SOMNIA_LIBRARY_DIR` to wherever the library has landed. Then there is one thing to fix, and it will not announce itself. ### The paths inside the database `chapters.audio_file` holds **absolute** paths, written when the chapter was rendered. Move the library to a different path — a different user, a different mount, `/srv` instead of `/home` — and every row points somewhere that does not exist. The server does not fall back to guessing: chapters are looked up in the database and never by path, and a row resolving outside `SOMNIA_LIBRARY_DIR` is refused even if the file is there, because a database carried from another machine can point anywhere. What you would see is a page that lists your books, answers questions, and plays nothing. Stop the server and rewrite the prefix: ```bash ~/somnia-venv/bin/python - <<'PY' import sqlite3 db = sqlite3.connect("/home/you/.local/share/somnia/somnia.db") with db: n = db.execute( "UPDATE chapters SET audio_file = replace(audio_file, ?, ?)", ("/home/old/library/audiobooks", "/srv/audiobooks"), ).rowcount print(f"{n} chapters repointed") PY ``` Then let `somnia-doctor.sh` (in the repo's `scripts/`, or curl it as [Installation](../tutorials/installation.md) does) confirm it, which is exactly what it is for: ```bash bash somnia-doctor.sh ``` It checks every chapter row for a file that exists and sits inside `SOMNIA_LIBRARY_DIR`, and names the first one that does not. ### What you do not need to move The catalog is a download: `somnia catalog-update` on the new box rebuilds it. The virtual environment should be built fresh rather than copied, since it holds absolute paths of its own. `SOMNIA_DATA_DIR/streams` is the other one, and it is the one that will tempt you, because it sits beside `somnia.db` and it is by far the largest thing in there — normally about the size of the library again, since it holds each book's chapters joined into the one file the page plays ([ADR 7](../explanations/decisions/0007-cross-a-chapter-without-letting-go.md)). Normally, not always. A join is written as `streams//.m4a`, where `n` is how many chapters it covers, so a book opened while it was still being rendered can leave earlier and shorter joins behind it — and nothing deletes them, which ADR 7 argues for deliberately rather than having overlooked. A book rendered before anybody listened to it has exactly one. So size this by looking rather than by multiplying: `du -sh` the directory says what is actually there. It is a cache either way. Every file in it is rebuilt from the library in a second or two of `ffmpeg -c copy` the first time somebody opens that book, so back it up and you are paying to store a copy of audio you already backed up, and leave it behind and you lose nothing at all — including the stale joins, which is the tidiest moment there is to be rid of them. If you rsync the data directory rather than copying `somnia.db` on its own, exclude it. ## Moving the renders somewhere faster This is not hypothetical — somnia's own renders moved to a home machine, which is where the 3.87× in [ADR 7](../explanations/decisions/0007-cross-a-chapter-without-letting-go.md) comes from, and the absolute-path catch below is the one thing that bit. Rendering and serving do not have to be the same machine, and the render host is the one that wants CPU ([#4](https://github.com/gilesknap/somnia/issues/4)). The catch is the same one as above: whichever box renders writes absolute paths into the database, so either both machines see the library at the same path — a shared mount, or the same directory name on both — or you rewrite the prefix each time you bring a book across. The same path on both is much the easier of the two.