760b4a7c6c
#321 — `minstrel admin reset-password [-user admin] [-password X]`: loads config, updates BOTH password_hash (bcrypt) and subsonic_password (plaintext, for Subsonic t+s) so neither auth path is left stale; generates+prints a strong password when -password is omitted. Recovers a locked-out operator without DB surgery. Subcommand dispatch added to main.go (os.Args switch before flag-parse; server path untouched) plus a `minstrel migrate` subcommand exposing db.Migrate standalone. #339 — integration tests no longer truncate the dev DB: - deploy/initdb creates minstrel_test on a fresh compose volume; `make test-integration` ensures it idempotently and points MINSTREL_TEST_DATABASE_URL at minstrel_test. - docker-compose.yml + README updated. CI integration job (test-go.yml): the prior workflow only ran `go test -short -race` with no DB, so the entire integration suite silently t.Skip'd — "CI green" never covered API/db/scanner. New `integration` job runs the full `go test -race` against an ephemeral Postgres service, using the act_runner shared-daemon pattern: no published ports, discover the service container by job-name filter via the docker socket, reach it by bridge IP, hard exactly-one assertion + dev-compose-name reject (a wrong target would truncate real data), TCP-wait, `minstrel migrate`, then test. Fast `test` job kept as the quick gate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
111 lines
5.1 KiB
Markdown
111 lines
5.1 KiB
Markdown
# Minstrel
|
|
|
|
A self-hosted music server that thinks for you. Smart shuffle, contextual likes, ListenBrainz-aware radio, and Lidarr automation — server-side, so every client (web, mobile, Subsonic third-party) gets the same intelligence.
|
|
|
|
> State and intelligence belong on the server, not the client.
|
|
|
|
<!-- TODO: screenshot of the home page -->
|
|
|
|
## Highlights
|
|
|
|
- **OpenSubsonic-compatible.** Existing Subsonic clients (DSub, Symfonium, play:Sub, etc.) connect with no special configuration.
|
|
- **Server-side smart shuffle.** Track-similarity vectors, dual-like model (general + contextual), and session memory keep mixes coherent across devices.
|
|
- **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.
|
|
- **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).
|
|
|
|
## Quickstart
|
|
|
|
```yaml
|
|
# compose.yaml
|
|
services:
|
|
minstrel:
|
|
image: git.fabledsword.com/bvandeusen/minstrel:latest
|
|
ports: ['4533:4533']
|
|
volumes:
|
|
- ./music:/music:ro
|
|
- minstrel-data:/data
|
|
environment:
|
|
MINSTREL_DATABASE_URL: postgres://minstrel:minstrel@db:5432/minstrel?sslmode=disable
|
|
MINSTREL_LIBRARY_SCAN_PATHS: /music
|
|
depends_on: [db]
|
|
|
|
db:
|
|
image: postgres:17
|
|
environment:
|
|
POSTGRES_USER: minstrel
|
|
POSTGRES_PASSWORD: minstrel
|
|
POSTGRES_DB: minstrel
|
|
volumes: [pgdata:/var/lib/postgresql/data]
|
|
|
|
volumes:
|
|
minstrel-data:
|
|
pgdata:
|
|
```
|
|
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
After the stack is up, visit `http://localhost:4533/register` and create your admin account. The first user to register on a fresh instance is automatically marked as the administrator; subsequent users can register through the same form (or via invite tokens generated from the admin Users panel, depending on how you configure registration).
|
|
|
|
For the full configuration surface, see [`config.example.yaml`](./config.example.yaml).
|
|
|
|
## Configuration
|
|
|
|
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_STORAGE_DATA_DIR` — defaults to `./data`. Holds playlist cover collages and other generated artefacts.
|
|
- `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.
|
|
|
|
Most operational keys have a `MINSTREL_<SECTION>_<FIELD>` env override. Recommendation and events tuning are yaml-only. See [`config.example.yaml`](./config.example.yaml) for the authoritative surface.
|
|
|
|
## Updating
|
|
|
|
- `:main` — rolling, follows the dev branch's tested tip. Recommended only for the operator who's running an upstream-watching deployment.
|
|
- `:v1.0.x` — pinned releases. Recommended default. Database migrations run automatically at startup; rollbacks require restoring a Postgres dump.
|
|
|
|
## Specs
|
|
|
|
Authoritative scope lives under [`docs/`](./docs):
|
|
|
|
- [Server spec](./docs/smart-music-server-spec.md) — current implementation focus.
|
|
- [Client spec](./docs/smart-music-client-spec.md) — Flutter companion app.
|
|
|
|
## Development
|
|
|
|
Two concurrent dev processes:
|
|
|
|
1. **Backend:** `docker compose up` — Postgres + Minstrel on `:4533`.
|
|
2. **Frontend:** `cd web && npm install && npm run dev` — Vite dev server on `:5173` with HMR. The Vite server proxies `/api/*` and `/rest/*` to `:4533` so session cookies work.
|
|
|
|
### Testing
|
|
|
|
- Unit + race (no DB): `make test-short`.
|
|
- Full suite incl. integration tests: `make test-integration`. This runs
|
|
against a dedicated `minstrel_test` database so a test run never
|
|
truncates your dev `minstrel` data (admin user, library, likes). It
|
|
brings up the compose Postgres and creates the test DB if missing.
|
|
- CI runs both: a fast `go test -short -race` gate plus an integration
|
|
job with its own ephemeral Postgres (`.forgejo/workflows/test-go.yml`).
|
|
|
|
### Production build
|
|
|
|
`docker build -t minstrel .` runs the SvelteKit build inside a `node` stage, copies the output into the `golang` stage, and `//go:embed`s it into the final binary. The container serves the SPA from `/` alongside the API surfaces; no separate static-file server is required.
|
|
|
|
### Branches
|
|
|
|
- Day-to-day work happens on `dev` (or feature branches merged into `dev`).
|
|
- `main` is **protected** — changes land via PR from `dev`.
|
|
- Releases are cut by tagging `v*` off `main`; the release workflow builds and pushes the container image to the Forgejo registry.
|
|
|
|
Task and milestone tracking: Fable (`Minstrel` project, id 12).
|
|
|
|
## License
|
|
|
|
See [LICENSE](./LICENSE).
|