BeatDock
🎵 Free, open-source, self-hosted Discord music bot with slash commands and Docker deployment. Features YouTube playback, queue management, and multilingual support.
Install / Use
/learn @lazaroagomez/BeatDockREADME
BeatDock
A Discord music bot powered by Lavalink. Simple to deploy, easy to use.
Table of Contents
- Features
- Quick Start
- Commands
- Configuration
- Managing the Bot
- Troubleshooting
- Built With
- Contributing
- Links
- License
Features
- Play music from YouTube, SoundCloud, Bandcamp, Twitch, and Vimeo
- Optional Spotify support (search and resolve via YouTube)
- Autoplay mode for continuous music playback
- Queue management with shuffle, loop, and play-next
- Interactive search with track selection
- Multi-language support (English, Spanish, Turkish, Italian)
- Role-based access control
- Runs entirely in Docker, no host dependencies
- Works without a self-hosted Lavalink server (automatic public server fallback)
Quick Start
Prerequisites
- A Discord bot token from the Developer Portal
- Docker installed
When creating your bot, enable all 3 Privileged Gateway Intents (Presence, Server Members, Message Content).
Option A: Deploy with Docker (recommended)
Uses the pre-built GHCR image, no cloning needed.
1. Create a project directory:
mkdir beatdock && cd beatdock
2. Create .env:
TOKEN=your_discord_bot_token
3. Create docker-compose.yml:
services:
bot:
container_name: beatdock
image: ghcr.io/lazaroagomez/beatdock:latest
depends_on:
lavalink:
condition: service_healthy
networks:
- beatdock-network
env_file: .env
lavalink:
container_name: beatdock-lavalink
image: ghcr.io/lavalink-devs/lavalink:4
ports:
- "2333:2333"
networks:
- beatdock-network
volumes:
- ./application.yml:/opt/Lavalink/application.yml
environment:
- LAVALINK_PASSWORD=${LAVALINK_PASSWORD:-youshallnotpass}
- SPOTIFY_ENABLED=${SPOTIFY_ENABLED:-false}
- SPOTIFY_CLIENT_ID=${SPOTIFY_CLIENT_ID:-}
- SPOTIFY_CLIENT_SECRET=${SPOTIFY_CLIENT_SECRET:-}
healthcheck:
test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/2333'"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
beatdock-network:
name: beatdock_network
4. Create application.yml:
server:
port: 2333
address: 0.0.0.0
plugins:
youtube:
enabled: true
allowSearch: true
allowDirectVideoIds: true
allowDirectPlaylistIds: true
clients:
- MUSIC
- WEB
- ANDROID_VR
lavalink:
plugins:
- dependency: "dev.lavalink.youtube:youtube-plugin:1.16.0"
snapshot: false
server:
password: "${LAVALINK_PASSWORD:youshallnotpass}"
sources:
youtube: false
soundcloud: true
bandcamp: true
twitch: true
vimeo: true
http: true
local: false
bufferDurationMs: 200
frameBufferDurationMs: 1000
youtubePlaylistLoadLimit: 3
playerUpdateInterval: 2
trackStuckThresholdMs: 5000
useSeekGhosting: true
youtubeSearchEnabled: true
logging:
level:
root: INFO
lavalink: INFO
5. Deploy:
docker compose up -d
Option B: Deploy from Source
git clone https://github.com/lazaroagomez/BeatDock.git
cd BeatDock
Create .env with your credentials (see .env.example for all options):
TOKEN=your_discord_bot_token
docker compose up -d
No Self-Hosted Lavalink Required
BeatDock can run without a self-hosted Lavalink server. If LAVALINK_HOST, LAVALINK_PORT, and LAVALINK_PASSWORD are not set, the bot automatically fetches free public Lavalink v4 servers and connects to one. If a public server goes down, it rotates to the next available node.
To use public servers, simply comment out the Lavalink variables in your .env:
# LAVALINK_HOST=lavalink
# LAVALINK_PORT=2333
# LAVALINK_PASSWORD=youshallnotpass
Commands
| Command | Description |
|---------|-------------|
| /play <query> [next] | Play a song (optionally add to front of queue) |
| /search <query> | Search and select tracks |
| /pause | Pause/resume |
| /skip | Skip track |
| /back | Previous track |
| /stop | Stop and disconnect |
| /queue | Show queue |
| /shuffle | Shuffle queue |
| /autoplay | Toggle autoplay mode |
| /loop | Toggle loop mode |
| /clear | Clear queue |
| /volume <1-100> | Set volume |
| /lyrics | Show lyrics for the current song |
| /filter | Apply audio effects and EQ presets |
| /nowplaying | Current track info |
| /invite | Get bot invite link |
| /about | Bot info |
Configuration
All configuration is done through the .env file. Only TOKEN is required.
| Variable | Default | Description |
|----------|---------|-------------|
| TOKEN | - | Discord bot token (required) |
| SPOTIFY_ENABLED | false | Enable Spotify search support |
| SPOTIFY_CLIENT_ID | - | Spotify app client ID |
| SPOTIFY_CLIENT_SECRET | - | Spotify app client secret |
| DEFAULT_LANGUAGE | en | Bot language (en, es, tr, it) |
| DEFAULT_VOLUME | 80 | Default playback volume (0-100) |
| AUTOPLAY_DEFAULT | false | Enable autoplay by default when music starts |
| ALLOWED_ROLES | - | Comma-separated role IDs to restrict access |
| DEFAULT_SEARCH_PLATFORM | ytmsearch | Default search platform for user queries |
| LAVALINK_PASSWORD | youshallnotpass | Lavalink server password |
| QUEUE_EMPTY_DESTROY_MS | 30000 | Disconnect after queue empties (ms) |
| EMPTY_CHANNEL_DESTROY_MS | 60000 | Disconnect from empty channel (ms) |
Managing the Bot
docker compose logs -f # View logs
docker compose restart # Restart
docker compose down # Stop
docker compose pull && docker compose up -d # Update
Troubleshooting
Audio not working on Raspberry Pi
Raspberry Pi 5 (Debian 13) may use a 16KB memory page size, which is incompatible with Lavalink's DAVE encryption library. Check with:
getconf PAGE_SIZE
If the result is not 4096, add kernel=kernel8.img under the [all] section in /boot/firmware/config.txt, then reboot and restart the containers. See #109 for details.
Built With
- discord.js - Discord API client
- Lavalink - Audio player server
- lavalink-client - Lavalink client library
- Docker - Containerized deployment
- Node.js 22+ - Runtime
Contributing
Contributions are welcome. Bug fixes, new features, translations, docs - all good. Check the guide below to get started.
See CONTRIBUTING.md for setup instructions and guidelines.
