# 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). server: address: ":4533" storage: # On-disk root for cached runtime artifacts (currently playlist cover # collages under /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" database: # Postgres connection string, e.g. postgres://minstrel:minstrel@localhost:5432/minstrel?sslmode=disable url: "" log: level: "info" # debug | info | warn | error format: "text" # text | json library: # Filesystem roots to scan for music. Each path is walked recursively. # 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 # 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 Lidarr integration." 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 events: # Idle gap (minutes) between play_events that closes a play_session and # starts a new one. Spec §6. 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. 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. recently_played_hours: 1 # Default radio size when ?limit= is not specified. radio_size: 50 # Maximum allowed ?limit= (server caps to this regardless). radio_size_max: 200