Infrastructure Migration Guide
This guide describes how to migrate the production deployment from one Raspberry Pi to another without corrupting the SQLite database.
The backend enables SQLite WAL mode in
backend-api/src/dicechess_trainer/database.py, so the database may span multiple files:
dicechess.dbdicechess.db-waldicechess.db-shm
When to use this guide
Section titled “When to use this guide”Use this procedure when moving production from one device to another, for example:
- Raspberry Pi 3 to Raspberry Pi 4
- SD card replacement with a fresh OS image
- Host replacement after hardware failure
GitHub Container Registry authentication
Section titled “GitHub Container Registry authentication”The Docker image is stored in GHCR (ghcr.io/rabestro/dicechess-lab). When the CD
workflow deploys automatically, it authenticates using a short-lived GITHUB_TOKEN issued by
GitHub Actions. That token is not available on a host shell, so any manual docker compose
command on a fresh device will fail with unauthorized unless you log in first.
The PAT required for GHCR access is saved in Vaultwarden under the entry
GitHub – read:packages PAT (dicechess RPi).
One-time login on a new device
Section titled “One-time login on a new device”Retrieve the PAT from Vaultwarden, then run:
echo "<PAT_FROM_VAULTWARDEN>" | docker login ghcr.io --username rabestro --password-stdinDocker saves the credential to ~/.docker/config.json; subsequent docker compose pull and
docker compose up commands will use it automatically.
Production data location
Section titled “Production data location”The deployed stack syncs docker-compose.yaml into ~/apps/dicechess-trainer/ and mounts:
./data:/app/dataThat means the production database files live on the host under:
~/apps/dicechess-trainer/data/Typical files are:
~/apps/dicechess-trainer/data/dicechess.db~/apps/dicechess-trainer/data/dicechess.db-wal~/apps/dicechess-trainer/data/dicechess.db-shmSafe migration procedure
Section titled “Safe migration procedure”-
Prepare the target device
- Install Docker and Docker Compose.
- Log in to GHCR using the PAT from Vaultwarden (see GHCR authentication above):
Terminal window echo "<PAT_FROM_VAULTWARDEN>" | docker login ghcr.io --username rabestro --password-stdin- Register the GitHub Actions runner with the
self-hostedandrpi4labels so that future CD deployments can target the new device automatically. - Create the deployment directory:
Terminal window mkdir -p ~/apps/dicechess-trainer -
Stop the application on the source device
Shut the stack down before copying any SQLite files:
Terminal window cd ~/apps/dicechess-trainerdocker compose downThis is the critical safety step for WAL databases. The application must not be writing while the copy is taken.
-
Copy the database files as one set
Copy
dicechess.dbtogether withdicechess.db-walanddicechess.db-shm.Terminal window rsync --archive --verbose ~/apps/dicechess-trainer/data/ pi4:~/apps/dicechess-trainer/data/If the source shutdown already checkpointed the WAL and removed the sidecar files, copy the whole
data/directory anyway. The important rule is: never copy onlydicechess.dbfrom a live WAL database. -
Back up any existing target data before overwriting
On the new device, if a previous deployment already created database files, back them up first:
Terminal window mv ~/apps/dicechess-trainer/data ~/apps/dicechess-trainer/data.backup.$(date +%Y%m%d-%H%M%S)mkdir -p ~/apps/dicechess-trainer/data -
Start the stack on the target device
After the copy completes, start the deployment:
Terminal window cd ~/apps/dicechess-trainerdocker compose up --detach
Optional integrity checks
Section titled “Optional integrity checks”After startup on the target host, verify that the container is running and the application logs look healthy.
cd ~/apps/dicechess-trainer
docker compose psdocker compose logs --tail 50 web | catIf you have SQLite CLI access, you can also inspect the migrated database directly:
sqlite3 ~/apps/dicechess-trainer/data/dicechess.db "PRAGMA journal_mode;"sqlite3 ~/apps/dicechess-trainer/data/dicechess.db "PRAGMA foreign_keys;"Expected values:
journal_mode->walforeign_keys->1
Recommended rollback plan
Section titled “Recommended rollback plan”Before switching traffic or disabling the old runner, keep:
- the old Raspberry Pi powered off but intact,
- a timestamped backup of the target
data/directory, - the copied
docker-compose.yamland.envfiles.
If anything looks wrong after migration, stop the new stack, restore the backup directory, and repeat the copy from the original source data.
Practical rules to remember
Section titled “Practical rules to remember”- Always stop the container before copying the database.
- Treat
dicechess.db,dicechess.db-wal, anddicechess.db-shmas one logical unit. - Copy the whole
data/directory instead of cherry-picking files. - Start the target container only after the copy has fully completed.