A self-hosted Discord music bot built with Rust, Serenity, and Songbird. It plays files from a folder on your machine into Discord voice channels.
The app image is published to ghcr.io/ak4duy/soundcrate:
latest- stable build from masternightly- development build from nightly
-
Create an application and bot in the Discord Developer Portal, then copy its bot token.
-
Invite it to your server using the
bot. Grant View Channels, Connect, Speak, Send Messages, Embed Links and Message Content Intent. -
Copy
docker-compose-example.yamltodocker-compose.yamlin your deployment directory. Supply your bot token in that local file (never commit it), and set the music bind mount'ssourceto the absolute host path containing your music. -
Start the bot:
docker compose pull docker compose up -d
| Command | Behavior |
|---|---|
/play track |
Search local files, join your channel, and enqueue the selected track |
/playurl url |
Play or queue audio from a direct HTTP(S) URL |
/playalbum album |
Search tagged albums and queue all their tracks in disc/track order |
/playrandom |
Play or queue one random library track |
/autoplay on/off |
Enable or disable random library playback when the queue runs out |
/library |
Show indexed track and album counts, total audio size, album-tag coverage, and file formats |
/queue |
Browse the current queue |
/pause |
Pause the current track |
/resume |
Resume playback |
/shufflee |
Shuffle tracks |
/skip |
Skip the current track |
/clear track |
Remove one queued track by its /queue index or autocomplete selection |
/stop |
Clear the queue and disconnect |
/seek |
Seek to a position in the current track |
/about |
Show Soundcrate version, build details, and update status |
/help |
Show all commands and their descriptions |
/playlist create name |
Create an empty server playlist |
/playlist add name track |
Append a local-library track |
/playlist remove name track |
Remove a saved track, even if its file is missing |
/playlist play name |
Play or enqueue all saved tracks in order |
/playlist show name |
Show saved track paths and count |
/playlist delete name |
Delete the saved playlist (does not affect queued tracks) |
Check that the mount is readable and inspect the indexed filenames:
docker compose run --rm bot --check-libraryStop the service with docker compose down.
Pull and replace the running container:
docker compose pull
docker compose up -dTo explicitly build and run your local source with Docker (requires BuildKit):
docker compose -f docker-compose.yaml -f docker-compose.dev.yaml up -d --buildWhen running the Rust executable directly, pass configuration through environment variables:
MUSIC_DIR=/path/to/music cargo run -- --check-library
DISCORD_TOKEN=your_token MUSIC_DIR=/path/to/music PLAYLIST_DIR=/path/to/bot-data GUILD_ID=your_server_id cargo runValidation:
cargo fmt --check
cargo check --locked
cargo clippy --locked --bin soundcrate -- -D warnings
docker build -t soundcrate .src/main.rs: Discord event dispatch, shared session state, idle cleanup, shutdown.src/commands/mod.rs: slash-command registration, autocomplete, dispatch, and responses.src/commands/play.rs: playback commands, now-playing and error announcements.src/commands/playlist.rs: server playlists, stable track references, and durable JSON storage.src/commands/queue.rs: paginated queue and track removal.src/commands/voice.rs: playback controls.src/commands/about.rs:/aboutresponse and build update checks.src/commands/library.rs: music indexing, album search, and/librarysummary.docker-compose-example.yaml: prebuilt production image with a read-only host music mount.docker-compose-dev.yaml: explicit override for local source builds..github/workflows/docker.yml: GHCR image publishing and build cache.Dockerfile: multi-stage build with a non-root runtime.