Alfira is a self-hosted Discord music bot with a web UI as the primary interface. The bot handles joining voice channels and audio playback; the web app handles browsing songs, managing playlists, and controlling playback in real time.
Status: This project is actively maintained but considered experimental and pre-release. Expect rough edges and potential breaking changes. Built primarily for personal use — YMMV.
- Discord bot
- Slash commands:
/join,/leave,/play,/skip,/stop,/queue,/loop,/shuffle,/playlist play,/nowplaying. - Queue management with loop modes (
off,song,queue) and shuffle. - Audio playback via
yt-dlp+ffmpeg+@discordjs/voice.
- Slash commands:
- Web UI
- Discord OAuth2 login with role-based permissions (Admin vs Member).
- Song library: add-by-URL via YouTube, delete, add to playlists (admins only).
- Playlists: create/delete/rename, add/remove songs, play into the queue with sequential/random order and loop mode.
- Player page + global Now Playing bar with live progress, queue view, and admin controls.
- Real-time sync
Socket.ioevents keep the UI in sync with the in-memory player state and library changes (no polling).
- Single-guild focus
- Scoped to a single Discord server (guild), with admin status determined by Discord role IDs.
Built with Node.js, TypeScript, Discord.js, React, PostgreSQL, and more. See the Tech Stack Documentation for details.
Requirements: Docker with Compose plugin.
git clone https://github.com/ebears/alfira-bot.git
cd alfira-bot
cp .env.example .envEdit .env with values from the Discord Developer Portal:
| Variable | Required | Description |
|---|---|---|
DISCORD_CLIENT_ID |
✅ | Discord application client ID |
DISCORD_CLIENT_SECRET |
✅ | Discord application client secret |
DISCORD_BOT_TOKEN |
✅ | Discord bot token |
GUILD_ID |
✅ | Your Discord server ID |
ADMIN_ROLE_IDS |
✅ | Role ID(s) for admin permissions |
JWT_SECRET |
✅ | Random secret string for JWT signing |
POSTGRES_PASSWORD |
✅ | Database password |
docker compose -f docker-compose.prod.yml up -dThis pulls the pre-built images and starts PostgreSQL, the API + bot, and the web UI.
Slash commands are automatically registered with Discord on startup. By default, this happens every time the bot starts (configurable via AUTO_DEPLOY_COMMANDS).
If you need to manually register or re-register commands (e.g., after adding or modifying commands while the bot is running):
docker compose -f docker-compose.prod.yml exec api npm run bot:deployNote: Commands are registered as guild commands, which update instantly. You must re-run this after adding, removing, or renaming commands if auto-deploy is disabled.
- Web UI:
http://localhost:8080 - API:
http://localhost:3001
For production deployment with a reverse proxy and HTTPS, see the Full Installation Guide.
| Document | Description |
|---|---|
| Installation Guide | Development and production setup, Discord configuration, reverse proxy setup |
| Configuration Reference | Complete environment variables reference |
| Tech Stack | Technology stack and project structure |
| Troubleshooting | Common issues and solutions |
The use of fs-capacitor for audio streaming was inspired by muse, a self-hosted Discord music bot.
This project is licensed under the MIT License — see the LICENSE file for details.



