docs: correct README setup/OOBE + fix data-volume mount
Bring the README and client/README in line with the current product and release pipeline ahead of making the repo public-facing: - Highlights: replace the retired "Flutter client in flight" bullet with the native-Android-APK-bundled-in-the-image story. - Quickstart: document the purpose of each compose volume mount, and fix the minstrel-data mount (/data -> /app/data) so it matches the image's MINSTREL_STORAGE_DATA_DIR and generated artefacts actually persist. - Configuration: tie MINSTREL_STORAGE_DATA_DIR to the /app/data mount. - Updating: replace the bogus :v1.0.x scheme with the real tag model (:latest, immutable :vYYYY.MM.DD, :main) and note the bundled APK. - client/README: rewrite the Production section to match release.yml (android-release + needs: ordering, non-tag :latest bundle path). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,7 +13,7 @@ A self-hosted music server that thinks for you. Smart shuffle, contextual likes,
|
|||||||
- **ListenBrainz radio.** Session-aware "more like this" pulls from ListenBrainz similarity data, not a static genre tag.
|
- **ListenBrainz radio.** Session-aware "more like this" pulls from ListenBrainz similarity data, not a static genre tag.
|
||||||
- **Lidarr integration.** Triggered scans, request-driven album imports, and a quarantine flow when something doesn't fit.
|
- **Lidarr integration.** Triggered scans, request-driven album imports, and a quarantine flow when something doesn't fit.
|
||||||
- **Built-in web SPA.** Full-feature library, search, queue, playlists, and admin — no separate frontend container to deploy.
|
- **Built-in web SPA.** Full-feature library, search, queue, playlists, and admin — no separate frontend container to deploy.
|
||||||
- **Flutter mobile client in flight.** Tracking issue [#356](https://git.fabledsword.com/bvandeusen/minstrel/issues/356).
|
- **Native Android client, shipped with the server.** The signed APK is bundled into every image and attached to each [release](https://git.fabledsword.com/bvandeusen/minstrel/releases) — sideload it once, then the app self-updates straight from your own server (no app store, no separate download to track).
|
||||||
|
|
||||||
## Quickstart
|
## Quickstart
|
||||||
|
|
||||||
@@ -24,10 +24,18 @@ services:
|
|||||||
image: git.fabledsword.com/bvandeusen/minstrel:latest
|
image: git.fabledsword.com/bvandeusen/minstrel:latest
|
||||||
ports: ['4533:4533']
|
ports: ['4533:4533']
|
||||||
volumes:
|
volumes:
|
||||||
|
# Your music library. Point ./music at wherever your audio files
|
||||||
|
# live. Mounted read-only — Minstrel never writes to your library.
|
||||||
- ./music:/music:ro
|
- ./music:/music:ro
|
||||||
- minstrel-data:/data
|
# Generated data: playlist cover collages, artist art, caches.
|
||||||
|
# The path must match MINSTREL_STORAGE_DATA_DIR, which the image
|
||||||
|
# sets to /app/data — keep this mount on /app/data or your cache
|
||||||
|
# won't survive a container recreate.
|
||||||
|
- minstrel-data:/app/data
|
||||||
environment:
|
environment:
|
||||||
MINSTREL_DATABASE_URL: postgres://minstrel:minstrel@db:5432/minstrel?sslmode=disable
|
MINSTREL_DATABASE_URL: postgres://minstrel:minstrel@db:5432/minstrel?sslmode=disable
|
||||||
|
# Colon-separated library roots to scan; must match the container
|
||||||
|
# path of the read-only music mount above (/music here).
|
||||||
MINSTREL_LIBRARY_SCAN_PATHS: /music
|
MINSTREL_LIBRARY_SCAN_PATHS: /music
|
||||||
depends_on: [db]
|
depends_on: [db]
|
||||||
|
|
||||||
@@ -37,6 +45,8 @@ services:
|
|||||||
POSTGRES_USER: minstrel
|
POSTGRES_USER: minstrel
|
||||||
POSTGRES_PASSWORD: minstrel
|
POSTGRES_PASSWORD: minstrel
|
||||||
POSTGRES_DB: minstrel
|
POSTGRES_DB: minstrel
|
||||||
|
# Postgres data dir — users, likes, play history, sessions, settings.
|
||||||
|
# The one volume you must never lose; back it up with pg_dump.
|
||||||
volumes: [pgdata:/var/lib/postgresql/data]
|
volumes: [pgdata:/var/lib/postgresql/data]
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
@@ -57,7 +67,7 @@ For the full configuration surface, see [`config.example.yaml`](./config.example
|
|||||||
Most operators only need the env vars in the quickstart above. A few extras worth knowing:
|
Most operators only need the env vars in the quickstart above. A few extras worth knowing:
|
||||||
|
|
||||||
- `MINSTREL_BRANDING_APP_NAME` — rename the instance ("Family Jukebox", "Office Music"). Surfaces in the header, browser tab, and OG share previews.
|
- `MINSTREL_BRANDING_APP_NAME` — rename the instance ("Family Jukebox", "Office Music"). Surfaces in the header, browser tab, and OG share previews.
|
||||||
- `MINSTREL_STORAGE_DATA_DIR` — defaults to `./data`. Holds playlist cover collages and other generated artefacts.
|
- `MINSTREL_STORAGE_DATA_DIR` — where generated artefacts (playlist cover collages, artist art, caches) are written. The container image sets this to `/app/data`, which is why the quickstart mounts the `minstrel-data` volume there.
|
||||||
- `MINSTREL_LIBRARY_SCAN_PATHS` — colon-separated list of music library roots to scan. Supports multiple roots (`/music:/podcasts`).
|
- `MINSTREL_LIBRARY_SCAN_PATHS` — colon-separated list of music library roots to scan. Supports multiple roots (`/music:/podcasts`).
|
||||||
|
|
||||||
ListenBrainz integration (per-user scrobble + similarity tokens) and Lidarr integration (URL + API key) are configured through the admin Settings UI rather than env vars or yaml — per Minstrel's "config in UI" rule, integration settings live where operators can edit them without restarting.
|
ListenBrainz integration (per-user scrobble + similarity tokens) and Lidarr integration (URL + API key) are configured through the admin Settings UI rather than env vars or yaml — per Minstrel's "config in UI" rule, integration settings live where operators can edit them without restarting.
|
||||||
@@ -66,8 +76,13 @@ Most operational keys have a `MINSTREL_<SECTION>_<FIELD>` env override. Recommen
|
|||||||
|
|
||||||
## Updating
|
## Updating
|
||||||
|
|
||||||
- `:main` — rolling, follows the dev branch's tested tip. Recommended only for the operator who's running an upstream-watching deployment.
|
Image tags (`git.fabledsword.com/bvandeusen/minstrel:<tag>`):
|
||||||
- `:v1.0.x` — pinned releases. Recommended default. Database migrations run automatically at startup; rollbacks require restoring a Postgres dump.
|
|
||||||
|
- `:latest` — the newest blessed image. Moves on every `main` push **and** every release. Recommended for most operators.
|
||||||
|
- `:vYYYY.MM.DD` — immutable per-day release tags. Pin one of these for a deployment you don't want moving under you. (Per-day CalVer — no trailing patch digit; a same-day re-cut moves the tag forward.)
|
||||||
|
- `:main` — the rolling post-merge tip. Same image as `:latest` at push time; choose it if you want to track `main` explicitly rather than the release line.
|
||||||
|
|
||||||
|
Every `:latest` and every `:vYYYY.MM.DD` bundles the current signed Android APK, so the in-app update channel is always live. Database migrations run automatically at startup; rollbacks require restoring a Postgres dump.
|
||||||
|
|
||||||
## Specs
|
## Specs
|
||||||
|
|
||||||
|
|||||||
+18
-8
@@ -6,17 +6,27 @@ in-app update flow (#397).
|
|||||||
|
|
||||||
## Production
|
## Production
|
||||||
|
|
||||||
CI populates this directory on tag releases:
|
CI populates this directory in `release.yml` (no Flutter — the client is
|
||||||
1. `flutter.yml` builds `app-release.apk` and attaches it to the
|
native Android, built by the `android-release` job):
|
||||||
Gitea release as `minstrel-<TAG>.apk`.
|
|
||||||
2. `release.yml` waits for that asset to appear, downloads it into
|
- **Tag release (`v*`):** the `android-release` job builds + signs the
|
||||||
this directory as `minstrel.apk`, writes the tag string to
|
APK, uploads it as a workflow artifact, and attaches it to the Gitea
|
||||||
`minstrel.apk.version`, and `docker buildx build` includes both
|
release as `minstrel-<TAG>.apk`. The `image-release` job
|
||||||
via `COPY client/ /app/client/`.
|
(`needs: android-release`) downloads that artifact into this directory
|
||||||
|
as `minstrel.apk` and writes the computed versionName to
|
||||||
|
`minstrel.apk.version`.
|
||||||
|
- **Main push (non-tag `:latest` / `:main`):** no APK is built, but the
|
||||||
|
image still moves `:latest`, so `image-release` pulls the most-recent
|
||||||
|
release's signed APK from the Gitea API and reconstructs its exact
|
||||||
|
versionName — keeping the in-app update channel alive on `:latest`
|
||||||
|
instead of stripping it until the next tag.
|
||||||
|
|
||||||
|
Either way, `docker buildx build` bakes both files into the image via
|
||||||
|
`COPY client/ /app/client/`.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
Empty directory works fine — the endpoints return 404 and the Flutter
|
Empty directory works fine — the endpoints return 404 and the Android
|
||||||
update banner stays hidden ("no update channel" graceful degradation).
|
update banner stays hidden ("no update channel" graceful degradation).
|
||||||
|
|
||||||
To smoke-test the update flow locally, drop a real APK + a version
|
To smoke-test the update flow locally, drop a real APK + a version
|
||||||
|
|||||||
Reference in New Issue
Block a user