74 lines
2.5 KiB
Markdown
74 lines
2.5 KiB
Markdown
# Restore SQLite onto the live database path
|
|||
|
|
|
||
|
|
The restore script **refuses to write directly** to the path in `DB_PATH` while that variable still points at the live file. That avoids accidental overwrite with the service running.
|
||
|
|
|
||
|
|
`RESTORE_ACK_STOPPED=YES` is an **operator acknowledgment** only — the script does **not** detect whether the backend process is stopped. You must stop the service yourself before swapping files.
|
||
|
|
|
||
|
|
## Prerequisites
|
||
|
|
|
||
|
|
- Backend **stopped** (no open handles on `app.db`, `-wal`, `-shm`).
|
||
|
|
- A validated backup from `npm run backup:sqlite` (WAL-safe, schema-checked).
|
||
|
|
- Shell access to the data directory (host path or mounted volume).
|
||
|
|
|
||
|
|
## Recommended procedure (same logical database)
|
||
|
|
|
||
|
|
Replace `/app/data/app.db` with your paths.
|
||
|
|
|
||
|
|
1. **Stop backend**
|
||
|
|
|
||
|
|
```powershell
|
||
|
|
docker compose stop backend
|
||
|
|
# or: stop the Node process / systemd unit
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Optional safety backup of current file**
|
||
|
|
|
||
|
|
```powershell
|
||
|
|
$env:DB_PATH = "/app/data/app.db"
|
||
|
|
$env:BACKUP_DIR = "./backups"
|
||
|
|
npm run backup:sqlite
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Restore to a sibling file** (not the live `DB_PATH` target)
|
||
|
|
|
||
|
|
```powershell
|
||
|
|
npm run restore:sqlite -- ./backups/app-2026-01-01T12-00-00.db /app/data/app-restored.db
|
||
|
|
```
|
||
|
|
|
||
|
|
Use `RESTORE_ACK_STOPPED=YES` if `/app/data/app-restored.db` already exists from a prior attempt.
|
||
|
|
|
||
|
|
4. **Verify** (optional second check)
|
||
|
|
|
||
|
|
```powershell
|
||
|
|
node -e "import('./scripts/sqlite-app-schema.mjs').then(m=>console.log(m.validateAppSqliteFile('/app/data/app-restored.db')))"
|
||
|
|
```
|
||
|
|
|
||
|
|
5. **Swap files** (preserve previous DB on disk)
|
||
|
|
|
||
|
|
```powershell
|
||
|
|
mv /app/data/app.db /app/data/app.db.pre-restore-<timestamp>
|
||
|
|
rm -f /app/data/app.db-wal /app/data/app.db-shm
|
||
|
|
mv /app/data/app-restored.db /app/data/app.db
|
||
|
|
```
|
||
|
|
|
||
|
|
6. **Start backend** and check readiness
|
||
|
|
|
||
|
|
```powershell
|
||
|
|
docker compose start backend
|
||
|
|
curl http://127.0.0.1:<frontend-port>/health/ready
|
||
|
|
```
|
||
|
|
|
||
|
|
## What the script enforces
|
||
|
|
|
||
|
|
| Rule | Meaning |
|
||
|
|
|------|---------|
|
||
|
|
| No restore when `target === DB_PATH` | Use a sibling path, then rename after stop |
|
||
|
|
| `RESTORE_ACK_STOPPED=YES` if target exists | Confirms you intend to overwrite an existing file |
|
||
|
|
| Schema + `integrity_check` | Backup must match app migrations |
|
||
|
|
| Failed validation | Staging removed; live file unchanged |
|
||
|
|
| Existing target | Moved to `*.pre-restore-<timestamp>.bak` before replace |
|
||
|
|
|
||
|
|
## Development
|
||
|
|
|
||
|
|
Restoring to a **new temp path** does not require stopping production. See `npm run restore:sqlite -- backup.db ./tmp/restored.db`.
|