A large release: most of the codebase has been reviewed for security, performance and correctness, and Supysonic can now be extended with third-party scrobblers, lyrics providers and cover art providers.
Upgrade notes
- Back up your database first. Migrations run automatically on startup and convert playlists, user passwords and scrobbling account links. Once a user has logged in, their password can't be read by older versions: downgrading requires restoring the backup
- Playlist entries pointing to tracks that no longer exist are dropped during the migration
- Run a scan of your folders afterwards so file sizes get recorded (
--forceisn't needed) - Upgrade and restart the web application and the daemon together: their communication format changed and versions can't be mixed
index_ignored_prefixesmoved from[webapp]to the new[api]section. The old location still works for now but logs a warning- If you run
supysonic-serverdirectly exposed to the network, pass--host 0.0.0.0(or the address you want) as it now only listens on localhost by default
Changes
Added:
- Pluggable scrobblers, lyrics providers and cover art providers, selected in the new
[plugins]configuration section. Last.fm, ListenBrainz, embedded and sidecar lyrics, folder and embedded covers are all built on this.
Writing your own is documented under Extending Supysonic - Option to answer failed API requests with a matching HTTP error status (
[api] use_http_error_status, off by default since some clients don't like it) - Last.fm API URL can be configured
- Verified support for Python 3.13, up to 3.15
Improvements:
- Much faster API on large libraries: playlists are now stored as proper database rows (no more slow
getPlaylistswith long playlists), annotations (stars, ratings) and related data are fetched in batches, and file sizes are stored in the database instead of being read from disk on every listing - Stronger password hashing; existing passwords are upgraded transparently on the user's next login
- Paginated endpoints (album lists, search) now return stable pages
- Email addresses are checked everywhere, and no longer required when creating a user through the API
- Configuration values are checked when the configuration is read: an invalid value is reported at startup instead of failing later
- Scrobbling services now receive a proper identification of Supysonic
- Lyrics lookup on large libraries is bounded
Security:
- CSRF protection on the web interface, and every action that changes something now requires a POST request
- Session cookies are HttpOnly and SameSite=Lax
- No more open redirect on the web interface login page
- Protection against timing attacks on authentication (including user enumeration)
- Fixed a possible remote code execution through the daemon socket (required access to both the socket and the daemon key)
- Fixed a path traversal through the transcoding cache
- Fixed HTTP header injection
- Error responses no longer leak internal details, these go to the log
supysonic-servernow listens on localhost by default instead of all
interfaces
Fixes:
- Fixed
oggdecusage in the sample transcoding configuration - Fixed the watcher mishandling its queue and its timing
- Fixed an error deleting a folder containing tracks used in a playlist
- Fixed
getStarredon PostgreSQL - Fixed configuration files overwriting defaults with untyped values
- Fixed failures when the cache directory gets deleted while running
- MySQL/MariaDB dates now keep their sub-second precision
- Various small fixes in the scanner, jukebox and daemon
Removed:
- ChartLyrics integration, the service no longer exists. The
online_lyricsoption is now ignored - Support for Python 3.9 and below
Note to package maintainers
- Packaging now relies solely on
pyproject.toml;setup.py,setup.cfgandMANIFEST.inare gone - The source distribution no longer ships prebuilt man pages nor
config.sample, and the wheel no longer installs man pages. Both come from the source tree (git tag archive): see PACKAGING.md - New dependency:
flask-wtf.werkzeugis now declared explicitly. Every dependency has a minimum version, checked in CI