Soulseek Music Server

soulseek music server

A music library that fills itself

Six containers on the server that between them share my music collection on Soulseek and download new stuff automatically. I used to run a Soulseek client on my desktop and drag files around by hand. Now it just runs.

  • slskd — the actual Soulseek daemon. Shares my curated collection read-only and handles transfers.
  • Lidarr — the wishlist. I add an artist or album and it goes on the wanted list.
  • Soularr — the bridge. Polls what Lidarr wants, searches Soulseek for it, queues the download.
  • beets — the tagger. Takes finished downloads and files them into the library properly.
  • Filebrowser — how I promote an album into the Jellyfin music folder.
  • Dockge — manages all the compose stacks from a web UI.

The loop

Lidarr holds a wanted list. Soularr checks it every five minutes, searches Soulseek through slskd's API, and queues whatever it finds. When a download finishes, beets picks it up, tags it, and moves it into the library. Then slskd rescans so people downloading from me can see the new files.

A few cron jobs keep it honest:

  • Hourly — import anything new with beets, then trigger a share rescan.
  • Every 15 minutes — another rescan, so worst case a new file is visible to peers in about 15 minutes.
  • Every 10 minutes — a disk ceiling script that stops downloads when the library gets too big and restarts them once it drops back down.
  • Nightly — ZFS snapshot, then dedupe (keeps the highest quality copy of each track), then delete empty folders.
Note: The dedupe does a dry run first and aborts if it would delete more than 20% of the library. That check has never fired, which is exactly the point — I want it there the one time something goes wrong.

Three good ones

The pool filled up. Soularr moves downloads that Lidarr refuses to import into a failed_imports folder. Nothing ever emptied it. It quietly grew to 373 GB and took the pool to 94% full, at which point beets died with "no space left on device." My disk ceiling script only watched the library folder, so it never noticed the downloads folder ballooning. Now the cleanup wipes that folder every night and the ceiling script measures both.

Lidarr kept re-monitoring everything. I only want a specific list of artists monitored, but Lidarr's nightly refresh sets monitored=true on any artist it finds files for. Turning off the obvious settings did nothing — they control different rescans. I ended up writing a script that runs at 11pm, reads a text file of the artists I actually want, and reconciles everything else back off.

beets skipped clean albums. Quiet mode skips anything without a perfect MusicBrainz match, which turned out to be most of my existing collection. For backfilling a library you already organized yourself, importing without autotag is the right call — it keeps your tags and just files things.

← back to projects