feat: Minstrel backs itself up nightly to a folder or an S3 bucket, off until an admin switches it on (#6773)
release / web (push) Failing after 15s
release / govulncheck (push) Successful in 16s
release / go (push) Failing after 41s
release / integration (push) Failing after 3m29s
release / android (push) Successful in 4m7s
release / Attach APK to the Release (tag releases only) (push) Canceled after 0s
release / Build + push container image (push) Canceled after 0s
release / Verify release artifacts (tag releases only) (push) Canceled after 0s
release / Build signed APK (push) Canceled after 5m34s

Admin › Backups shows a verdict first (off, not set up, waiting, backed up,
overdue, failing since when), Back up now, Test destination and the latest
runs, with the settings beside them.

- backup.Service: one run at a time, bounded at 30 minutes; the schedule
  ticks every 5 minutes, catches up a slot missed while the server was down,
  and retries a failure after an hour and then after as long as it has been
  failing. Runs are recorded in backup_runs, pruned after 90 days; a run cut
  off by a shutdown is marked failed at the next start.
- A folder destination writes database/minstrel-<UTC stamp>.tar and refuses
  a folder that isn't there. An S3 destination stages the file, hashes it,
  and uploads it under database/ through a throttled reader (4 MiB/s by
  default, 0 for no limit).
- Test destination checks the form as typed and only lists.
- The bucket secret is sealed like every stored credential; backup_settings
  and backup_runs are left out of the backup itself.
- The panel polls only while a run is going, capped at the run limit plus
  five minutes.

The music switch named in the task is left to #6774, so no control ships
that does nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-02 14:50:55 -05:00
co-authored by Claude Opus 5.5
parent faf19ef67b
commit 9d324ab2d0
29 changed files with 2384 additions and 4 deletions
+19
View File
@@ -83,6 +83,25 @@ Creating the first account (which becomes the admin) requires that token, so
whoever reaches a newly exposed server first can't claim it. The token
changes on every restart until an account exists.
## Backups
Minstrel can back itself up once a night: accounts, likes, playlists,
listening history, requests and settings, in one file. It is off until an
admin switches it on under **Admin › Backups**. Anything Minstrel can fetch
or work out again (artwork, fingerprints, MusicBrainz data) is left out, and
so are the keys and passwords Minstrel keeps for other services, which are
entered again on a restored server. Sign-in passwords are kept.
A backup goes to one of:
- **an S3 bucket**, path-style (MinIO, Garage, or any S3-compatible store).
The key only needs to add and list objects. Files land under `database/`.
- **a folder** on the server, under `database/` inside it. Mount a volume
there; Minstrel refuses to write into a folder that isn't there.
Minstrel only adds files, named by date, and never deletes one. Keep as many
as you like with the destination's own retention. **Test destination** lists
what is there without writing anything.
## Android app
The app connects over whatever URL you give it, HTTP or HTTPS. Once the