Home Docs GitHub

Documentation

Everything you need to deploy, configure, and extend Crate.

Overview

Crate is a self-hosted music manager for collectors. It connects to music metadata providers (MusicBrainz, Deezer, or your own) to search and browse artists, then downloads tracks from Soulseek via slskd. Downloaded files are automatically organized, tagged with full metadata and cover art, and placed in your library.

The stack is a Go backend with SQLite, a React frontend, and standalone gRPC provider binaries — all shipped in a single Docker image.

crate (main process) ├── HTTP API + React SPA ├── Provider Manager │ ├── gRPC → provider-musicbrainz (:50051) │ ├── gRPC → provider-deezer (:50052) │ └── gRPC → custom external provider ├── Scheduler (new releases, auto-queue, quality upgrades) ├── Downloader (slskd integration) ├── Organizer (file moves + renaming) ├── Tagger (ID3/FLAC metadata + cover art) └── Navidrome notifier (optional library scan trigger)

Deployment

The recommended deployment is via Docker Compose with slskd as a sidecar. Crate needs a Soulseek account (provided through slskd) to download music.

# docker-compose.yml
services:
  crate:
    image: ghcr.io/theoutdoorprogrammer/crate:latest
    ports:
      - "6969:6969"
    volumes:
      - ./crate-data:/app/data        # databases (crate.db, cache.db, activity.db)
      - ./slskd/downloads:/app/downloads
      - ./library:/app/library
    environment:
      - CRATE_SLSKD_URL=http://slskd:5030
      - CRATE_SLSKD_API_KEY=your_api_key
      - CRATE_DOWNLOADS_DIR=/app/downloads
      - CRATE_LIBRARY_PATH=/app/library
      - CRATE_DB_PATH=/app/data/crate.db
      - CRATE_CACHE_PATH=/app/data/cache.db
      - CRATE_ACTIVITY_PATH=/app/data/activity.db
    depends_on:
      - slskd
    restart: unless-stopped

  slskd:
    image: slskd/slskd:latest
    ports:
      - "5030:5030"
    volumes:
      - ./slskd:/app
      - ./library:/crate
    environment:
      - SLSKD_REMOTE_CONFIGURATION=true
      - SLSKD_API_KEY=your_api_key
      - SLSKD_SOULSEEK_USERNAME=your_username
      - SLSKD_SOULSEEK_PASSWORD=your_password
    restart: unless-stopped
Tip: The CRATE_SLSKD_API_KEY must match the SLSKD_API_KEY you set for slskd. These two services communicate over the slskd REST API.

Volumes

Three volume mounts are important:

Authentication

Crate does not include built-in authentication. It's designed to run behind your existing auth layer — a reverse proxy with basic auth, Authelia, Authentik, Cloudflare Access, a VPN, or whatever you prefer. If it's only accessible on your local network, no auth may be necessary.

Environment Variables

These are set at startup and control core paths, ports, and provider configuration. All have sensible defaults — only CRATE_SLSKD_API_KEY is required.

Variable Default Description
CRATE_PORT 6969 HTTP port the web UI and API listen on.
CRATE_DB_PATH ./crate.db Path to the main SQLite database.
CRATE_CACHE_PATH ./cache.db Path to the provider cache database. Stores cached search results and metadata with a configurable TTL.
CRATE_ACTIVITY_PATH ./activity.db Path to the activity log database. Records download events, errors, and system events.
CRATE_DOWNLOADS_DIR ./downloads Directory where slskd places completed downloads. Crate reads from here.
CRATE_LIBRARY_PATH ./library Directory where organized music files are placed. Structure: Artist/Album/Track.ext
CRATE_SCAN_INTERVAL 6h How often the scheduler runs (new release detection, auto-queue, quality upgrades). Accepts Go duration strings: 30m, 6h, 24h, etc.
CRATE_SLSKD_URL http://localhost:5030 Base URL of your slskd instance.
CRATE_SLSKD_API_KEY none API key for slskd. Required for downloads to work.
CRATE_PROVIDERS musicbrainz:./provider-musicbrainz:50051,deezer:./provider-deezer:50052 Comma-separated list of providers. Format: name:binary:port. See Providers.
CRATE_MB_USER_AGENT Crate/0.1.0 ... User-Agent string for MusicBrainz API requests. MusicBrainz requires a descriptive User-Agent.

UI Settings

These settings are stored in the database and configurable from the Settings page in the web UI. Changes take effect immediately without restarting.

Setting Default Description
provider_primary musicbrainz Default provider for search and browse. Can be switched on the fly from the search UI.
cache_ttl_hours 24 How long provider search results and metadata are cached before re-fetching.
quality_tiers FLAC > MP3 320 > MP3 256 Priority-ordered list of acceptable download formats. The downloader picks the highest-tier match from available sources. Stored as JSON.
max_concurrent_slskd 10 Maximum number of simultaneous downloads from Soulseek.
max_auto_queue 50 Maximum tracks the scheduler will auto-queue per cycle. Prevents flooding the download queue.
requeue_cooldown_days 7 Minimum days before a failed track can be re-queued by the scheduler.
activity_retention_days 30 How long activity log entries are kept before automatic cleanup.
scan_interval from env Override the scheduler interval at runtime (same format as CRATE_SCAN_INTERVAL).
slskd_url from env Override the slskd URL at runtime.
slskd_api_key from env Override the slskd API key at runtime. Treated as sensitive (masked in the UI).
library_path from env Override the library path at runtime.
download_format_preference none Preferred download format when multiple options are equivalent in quality tier.
navidrome_url none Base URL of your Navidrome instance. See Navidrome Integration.
navidrome_user none Navidrome username for triggering library scans.
navidrome_password none Navidrome password. Treated as sensitive (masked in the UI).
Note: Settings like slskd_url, slskd_api_key, library_path, and scan_interval can be set via environment variables at startup or overridden in the UI. The UI value takes precedence when set.

Providers

Providers supply music metadata (artist search, discography browsing, album/track details, cover art). Crate ships with two built-in providers and supports adding custom ones via gRPC.

Built-in Providers

Provider Source Rate Limit Notes
MusicBrainz MusicBrainz.org API 1 req/s Open database. Best for completeness and accuracy. Default provider.
Deezer Deezer public API 10 req/s Faster browsing, good cover art. Useful as a secondary provider.

How Providers Work

Provider Configuration

The CRATE_PROVIDERS environment variable defines which providers to load. Format:

# Built-in providers (binary path relative to crate binary)
CRATE_PROVIDERS=musicbrainz:./provider-musicbrainz:50051,deezer:./provider-deezer:50052

# External provider (network address instead of binary path)
CRATE_PROVIDERS=musicbrainz:./provider-musicbrainz:50051,spotify:external:192.168.1.10:50053

Built-in providers are started as child processes by Crate. External providers connect to a remote gRPC server you run separately.

Download Flow

When you watch an artist, album, or track, here's what happens:

  1. Queuing — watched items are saved with status wanted. The scheduler checks for new wanted tracks every scan interval.
  2. Search — Crate searches slskd (Soulseek) for each wanted track, scoring results by quality tier, file format, and bitrate.
  3. Selection — the best result is selected based on your quality tiers. Blacklisted sources are excluded.
  4. Download — the file is downloaded via slskd. Track status changes to downloading. The downloader checks progress every 10 seconds.
  5. Organize — completed downloads are moved into the library with the naming convention Artist/Album/Track.ext.
  6. Tag — metadata (artist, album, track name, track number, year) and cover art are embedded into the file.
  7. Notify — if Navidrome is configured, a library scan is triggered. Track status becomes owned.

Retry & Blacklist

Not every download succeeds on the first try. Crate handles failures automatically:

Concurrency

The max_concurrent_slskd setting (default 10) limits how many downloads run simultaneously. The max_auto_queue setting (default 50) caps how many tracks the scheduler adds per cycle, preventing the queue from growing unbounded.

Quality Upgrades

Crate continuously improves your library quality. The quality system works as follows:

  1. Quality tiers are priority-ordered in settings (default: FLAC > MP3 320 > MP3 256). Higher in the list = better.
  2. When a track is downloaded, its format and bitrate are recorded.
  3. The scheduler scans one artist per day (round-robin), checking if any owned tracks can be upgraded to a higher quality tier.
  4. Upgradeable tracks are re-queued automatically. The new download replaces the old file.

The requeue_cooldown_days setting (default 7) prevents the scheduler from re-queuing the same track too frequently if better quality isn't available yet.

Crate can trigger a Navidrome library scan after each successful download, so new music appears in your streaming library immediately.

Setup

Configure these three settings in the Crate UI (Settings page):

Setting Example
navidrome_url http://navidrome:4533
navidrome_user admin
navidrome_password your_password

All three fields are required. If any are empty, the Navidrome integration is silently disabled. Crate authenticates via the Subsonic API token+salt scheme.

Tip: Point both Crate's CRATE_LIBRARY_PATH and Navidrome's music folder to the same directory (or use a shared volume). Crate organizes files into Artist/Album/Track.ext which Navidrome indexes automatically.

Supported Formats

Format Extension Type
FLAC.flacLossless
WAV.wavLossless
MP3.mp3Lossy
Ogg Vorbis.oggLossy
Opus.opusLossy
AAC.aacLossy
MPEG-4 Audio.m4aLossy

The downloader recognizes all these formats when scoring search results. The tagger embeds metadata into FLAC (Vorbis comments) and MP3 (ID3v2) files. Cover art is embedded in both formats.

API Reference

Crate exposes a REST API on the same port as the web UI. All endpoints return JSON.

Status

MethodPathDescription
GET/api/statusHealth check and system status.

Search & Browse

MethodPathDescription
GET/api/search?q=&limit=&offset=Search for artists via the active provider. Paginated.
GET/api/browse/artist/{id}Browse an artist's full discography from the provider.
GET/api/browse/album/{id}Browse an album's track listing from the provider.

Library

MethodPathDescription
GET/api/library/search?q=Search your local library.
GET/api/artistsList all watched/owned artists.
GET/api/artists/{id}Get artist details with albums.
DELETE/api/artists/{id}Remove artist and all associated data.
GET/api/albums/{id}Get album details with tracks.
DELETE/api/albums/{id}Remove album.
GET/api/tracks/{id}Get track details.
DELETE/api/tracks/{id}Remove track.

Watching

MethodPathDescription
POST/api/watch/artistWatch an artist (full discography tracking).
POST/api/watch/albumWatch a specific album.
POST/api/watch/trackWatch a specific track.

Downloads

MethodPathDescription
GET/api/downloadsList current download queue.
POST/api/downloads/{id}/retryRetry a failed download.
DELETE/api/downloads/{id}Cancel/remove a download.

Providers

MethodPathDescription
GET/api/providersList all configured providers with health status.
POST/api/relink/artist/{id}Relink an artist to a different provider.
POST/api/relink/album/{id}Relink an album to a different provider.
POST/api/relink/track/{id}Relink a track to a different provider.

Settings & Activity

MethodPathDescription
GET/api/settingsGet all settings (sensitive values masked).
PUT/api/settingsUpdate settings.
GET/api/activity?limit=&offset=Get activity log. Paginated.
DELETE/api/cacheClear the provider cache.

Custom Providers

You can build your own metadata provider by implementing the gRPC service defined in proto/provider/provider.proto. The service interface includes:

Run your provider as a standalone gRPC server and add it to the CRATE_PROVIDERS env var:

CRATE_PROVIDERS=musicbrainz:./provider-musicbrainz:50051,my-provider:external:my-host:50053

Use the external keyword as the binary path to tell Crate it should connect to a remote server instead of launching a child process. Community-built providers and the database schema are documented in DATABASE.md.

Database

Crate uses three SQLite databases:

The full database schema is documented in DATABASE.md in the repository.