docs: README in the standard order; setup files say what works today (#6277)
release / govulncheck (push) Successful in 17s
release / web (push) Successful in 1m25s
release / go (push) Successful in 1m40s
release / integration (push) Successful in 5m19s
release / android (push) Successful in 5m32s
release / Build signed APK (releases and dev) (push) Successful in 5m51s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 15s
release / Verify release artifacts (tag releases only) (push) Skipped

README: logo header, short summary, a compose quick start with one-line
comments, first-run steps, a configuration table, setup pitfalls,
updating and backups, then features grouped by what you do. The Specs
section (it called the Android client the "Flutter companion app"), the
dated tag-history sentence and the Fable pointer are gone. Feature lines
were checked against the code: radio seeds from a track only, and the
Android app plays from its cache rather than offering downloads.

.env.example used the SMARTMUSIC_ prefix, which the config loader has not
read for a long time, so copying it set nothing. It now uses MINSTREL_.

config.example.yaml is also the config the image bakes in at
/etc/smartmusic/config.yaml. It listed five recommendation weights
(base_weight, like_boost, recency_weight, skip_penalty, jitter_magnitude)
that moved to Admin > Tuning; yaml.Unmarshal ignored them silently. They
are removed, and the file parses to exactly Default(), so the running
server is unchanged. coverart_from_mbcaa is not listed: nothing reads it.

docker-compose.yml, the Makefile and the spec banners lose their task and
milestone ids.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-23 12:02:25 -04:00
co-authored by Claude Opus 5.5
parent eac320c8d7
commit 9f9609591d
7 changed files with 128 additions and 214 deletions
+30 -58
View File
@@ -1,82 +1,54 @@
# Minstrel example configuration.
# Every field is optional; defaults shown below match Default() in internal/config.
# Each setting can be overridden at runtime via MINSTREL_* environment variables
# (see internal/config/config.go for the full list).
# Minstrel example configuration. In the container image, mount it at
# /etc/smartmusic/config.yaml. Every field is optional; the values below are
# the defaults. Each MINSTREL_* variable named here overrides its field.
server:
address: ":4533"
address: ":4533" # MINSTREL_SERVER_ADDRESS
storage:
# On-disk root for cached runtime artifacts (currently playlist cover
# collages under <data_dir>/playlist_covers/). Default: "./data" relative
# to the working directory. Production deployments should set an absolute
# path on persistent storage.
# Env: MINSTREL_STORAGE_DATA_DIR
data_dir: "./data"
# Artwork, caches and the stream-signing key. Use persistent storage.
data_dir: "./data" # MINSTREL_STORAGE_DATA_DIR (the image sets /app/data)
database:
# Postgres connection string, e.g. postgres://minstrel:minstrel@localhost:5432/minstrel?sslmode=disable
url: ""
# e.g. postgres://minstrel:minstrel@localhost:5432/minstrel?sslmode=disable
url: "" # MINSTREL_DATABASE_URL
log:
level: "info" # debug | info | warn | error
format: "text" # text | json
level: "info" # debug | info | warn | error. MINSTREL_LOG_LEVEL
format: "text" # text | json. MINSTREL_LOG_FORMAT
library:
# Filesystem roots to scan for music. Each path is walked recursively.
# These are the starting folders only: once they are changed in
# Admin › Library, the saved ones are used and this value is ignored.
# Changing a folder there moves its tracks with it, so moving the library
# to a new mount keeps every play, like and playlist.
# Env: MINSTREL_LIBRARY_SCAN_PATHS (colon-separated, PATH-style)
scan_paths: []
# Kick off a scan on server startup. On by default so a fresh install
# populates its library on first boot with no manual step. Scans are
# incremental (unchanged files are skipped by mtime), so the cost on
# every later restart is just a directory walk, not a full re-index.
# Set false if you'd rather scan only on a schedule / via the admin UI.
# Env: MINSTREL_LIBRARY_SCAN_ON_STARTUP
scan_on_startup: true
# Library folders, walked recursively. Used on first start only: once they
# are changed in Admin › Library, the saved ones win. Changing a folder there
# moves its tracks with it, so plays, likes and playlists survive a new mount.
scan_paths: [] # MINSTREL_LIBRARY_SCAN_PATHS (colon-separated)
# Scan on startup. Scans are incremental, so a restart only walks the folders.
scan_on_startup: true # MINSTREL_LIBRARY_SCAN_ON_STARTUP
# Contact sent to the Cover Art Archive in the User-Agent. Empty sends
# the project's URL.
contact_email: "" # MINSTREL_CONTACT_EMAIL
# Per-instance branding. Operators can rename their instance ("Family
# Jukebox", "Office Music", etc.) and override the OG share-preview
# description. Both fields default to sensible Minstrel values when
# unset; you only need this section to override.
# Env: MINSTREL_BRANDING_APP_NAME, MINSTREL_BRANDING_DESCRIPTION
branding:
app_name: "Minstrel"
description: "Self-hosted music server with Subsonic compatibility, smart shuffle, and music acquisition."
app_name: "Minstrel" # MINSTREL_BRANDING_APP_NAME
description: "Self-hosted music server with Subsonic compatibility, smart shuffle, and music acquisition." # MINSTREL_BRANDING_DESCRIPTION
subsonic:
# Gate for the legacy `p=` plaintext password parameter on /rest/*.
# Leave disabled unless a specific client requires it — Minstrel prefers
# apiKey (OpenSubsonic) and falls back to u+t+s token auth.
# Env: MINSTREL_SUBSONIC_ALLOW_PLAINTEXT_PASSWORD
allow_plaintext_password: false
# Accept the plaintext `p=` password on /rest/*. Leave off unless a client
# needs it; apiKey and token auth work without it.
allow_plaintext_password: false # MINSTREL_SUBSONIC_ALLOW_PLAINTEXT_PASSWORD
events:
# Idle gap (minutes) between play_events that closes a play_session and
# starts a new one. Spec §6.
# Minutes of silence that end a listening session.
session_timeout_minutes: 30
# Skip rule (spec §6): a play counts as a SKIP if completion ratio is below
# this threshold AND duration played (ms) is below the next threshold.
# A play is a skip when it stops before this fraction of the track AND
# before this many milliseconds.
skip_max_completion_ratio: 0.5
skip_max_duration_played_ms: 30000
recommendation:
# Base score every candidate gets before adjustments. Spec §6.
base_weight: 1.0
# Bonus for tracks the user has liked (general_likes).
like_boost: 2.0
# Multiplier on recency_decay (1.0 for tracks ≥ 30 days stale, 0 for fresh).
recency_weight: 1.0
# Penalty multiplier on skip_ratio (skips/plays); 1.0 = full penalty.
skip_penalty: 1.0
# ± random jitter applied to every candidate; breaks ties without dominating.
jitter_magnitude: 0.1
# Hard-suppression window: tracks played within this many hours never appear.
# Scoring weights are tuned in Admin › Tuning, not here.
# Tracks played within this many hours are left out of radio.
recently_played_hours: 1
# Default radio size when ?limit= is not specified.
# Radio length when ?limit= is not given, and the most ?limit= may ask for.
radio_size: 50
# Maximum allowed ?limit= (server caps to this regardless).
radio_size_max: 200