- π Global Radio Stream - Everyone listens to the same music together in real-time
- π€ Upload & Share - Upload music files that are automatically added to the shared queue
- β‘ Real-time Updates - WebSocket-powered live queue and track updates
- π€ Simple Username System - No registration required, just pick a name
- π± Progressive Web App - Install on mobile and desktop devices
- π¨ Beautiful UI - Modern, responsive design with smooth animations
- π Auto-cleanup - Configurable storage limit (default: 300MB) with automatic deletion of oldest files
- Backend: Rust with Actix-web for HTTP/WebSocket serving (connects to MPD as client)
- Frontend: React + TypeScript PWA built with Vite
- Streaming: Music Player Daemon (MPD) for audio playback and HTTP streaming (separate service)
- Real-time: WebSocket for live queue and track updates
Before you begin, ensure you have the following installed:
- Rust (1.83.0 or newer) - https://rustup.rs/
# Install or update Rust curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh rustup update stable
- Node.js (v18+) - https://nodejs.org/
- Music Player Daemon (MPD):
- macOS:
brew install mpd - Ubuntu/Debian:
sudo apt install mpd - Arch Linux:
sudo pacman -S mpd
- macOS:
# Start MPD service
docker compose up -d mpd
# Start backend (in another terminal)
cd backend
cargo runcd backend
# Create MPD config from example (first time only)
cp mpd.conf.example mpd.conf
# Edit mpd.conf if needed
# Start MPD
mpd mpd.confOr use the development script:
cd backend
./start-dev.sh # Starts MPD and backendcd backend
cargo runBackend starts on http://localhost:8080 and connects to MPD at 127.0.0.1:6600
cd frontend
npm install
npm run devFrontend will be available at http://localhost:5173
Navigate to http://localhost:5173 and start listening!
muchas-radio/
βββ backend/ # Rust backend server
β βββ src/
β β βββ main.rs # Server entry point
β β βββ mpd_manager.rs
β β βββ api/ # API endpoints
β β β βββ upload.rs
β β β βββ playlist.rs
β β β βββ stream.rs
β β βββ models.rs
β β βββ state.rs
β βββ uploads/ # Uploaded music files (gitignored)
β βββ mpd.conf.example # MPD configuration example (for local dev)
β βββ start-dev.sh # Development startup script
β βββ Cargo.toml
β
βββ mpd/ # MPD Docker container
β βββ Dockerfile # MPD service configuration
β
βββ frontend/ # React TypeScript PWA
βββ src/
β βββ App.tsx
β βββ components/ # UI components
β βββ hooks/ # React hooks
β βββ api/ # API client
β βββ types/ # TypeScript types
βββ public/
βββ package.json
POST /api/upload- Upload a music fileGET /api/current- Get currently playing trackGET /api/queue- Get upcoming tracksPOST /api/queue/add- Add track to queueGET /api/stream- Audio stream proxyWS /api/ws- WebSocket for real-time updates
The backend and MPD containers share the same music storage. By default, Docker named volumes are used, but you can configure bind mounts for easier access.
Current Setup:
- Backend writes to:
/app/uploads(mounted frommusic-uploadsvolume) - MPD reads from:
/music(mounted from samemusic-uploadsvolume) - Both containers share the same data
For production or easier file access:
- Use bind mounts by setting
MUSIC_STORAGE_PATHenvironment variable - Default:
./data/music(relative to docker-compose.yml) - Example:
export MUSIC_STORAGE_PATH=/var/muchas-radio/music && docker compose up -d
MPD Connection:
MPD_HOST- MPD server hostname/IP to connect to (default: 127.0.0.1)MPD_PORT- MPD server port (default: 6600)
Backend API:
BIND_ADDR- HTTP server address (default: 127.0.0.1:8080)RUST_LOG- Log level (default: info)MAX_TOTAL_STORAGE- Maximum total storage size (default: 300MB). Supports formats like "500MB", "1GB", or bytes as a number.
Production Example:
export MPD_HOST=mpd # Use service name in Docker, or IP/hostname otherwise
export MPD_PORT=6600
export BIND_ADDR=0.0.0.0:8080
cargo run --releaseNote: In Docker deployments, MPD runs in a separate container. The backend connects to it via MPD_HOST=mpd (the service name).
VITE_API_URL- Backend API URL (default: http://localhost:8080)VITE_WS_URL- WebSocket URL (default: ws://localhost:8080)
- MP3
- FLAC
- OGG
- M4A
- WAV
Storage Limits:
- Maximum file size: 100MB
- Total storage: 300MB by default (configurable via
MAX_TOTAL_STORAGEenvironment variable). Oldest files are auto-deleted when limit is reached.
The easiest and most reliable way to deploy Muchas Radio is using Docker:
# On your server
git clone https://github.com/yourusername/muchas-radio.git
cd muchas-radio
# Run the deployment script
./docker-deploy.sh yourdomain.com
# or with an IP address
./docker-deploy.sh 192.168.1.100The deployment script will:
- Configure environment variables for your domain/IP
- Build all Docker images
- Start all services (MPD, Backend, Frontend, Nginx)
- Display service status and useful commands
# Set your domain or IP
export VITE_API_URL=http://your-domain.com
export VITE_WS_URL=ws://your-domain.com
# Build and start
docker compose up -d
# Check status
docker compose ps
# View logs
docker compose logs -fOnce deployed, you'll have:
- Frontend: Port 3000 (nginx serving React app)
- Backend API: Port 8080 (connects to MPD service)
- MPD Server: Port 6600 (separate container, internal network)
- Audio Stream: Port 8001 (from MPD container, internal network)
Music files are stored in a shared Docker volume (music-uploads) accessible by both backend and MPD containers:
- Backend writes to:
/app/uploads - MPD reads from:
/music - Both point to the same volume
For production deployments, consider using bind mounts to a host directory by setting the MUSIC_STORAGE_PATH environment variable (default: ./data/music).
# Pull latest changes
git pull
# Rebuild and restart
docker compose up -d --build
# Or use the shortcut
docker compose build && docker compose up -dFor production with HTTPS, you'll need to configure SSL certificates separately. Consider using:
- Traefik - Automatic Let's Encrypt certificates
- Caddy - Automatic HTTPS
- Nginx Proxy Manager - Web UI for reverse proxy + SSL
See DOCKER_DEPLOYMENT.md for advanced configuration options.
cd backend
cargo watch -x run # Auto-reload on changes
cargo test # Run testscd frontend
npm run dev # Hot reload enabled
npm run build # Build for production
npm run preview # Preview production build
npm run lint # Run linterError: Failed to bind to socket
- Kill existing MPD:
pkill mpdand try again
Error: Failed to open database
- Delete
backend/mpd.dband restart MPD
Error: Failed to connect to MPD
- Ensure MPD is running:
mpd backend/mpd.conf(development) or check Docker service:docker compose ps mpd - Verify MPD_HOST and MPD_PORT environment variables are correct
- In Docker: ensure the
mpdservice is running and the backend can reach it on the Docker network - Check logs:
tail -f backend/mpd.log(development) ordocker compose logs mpd(Docker)
- Check MPD stream:
curl http://localhost:8001 - Verify port 8001 is not blocked
- Check MPD logs for encoding errors
- Ensure backend is on port 8080:
curl http://localhost:8080/api/current - Check CORS settings in backend
- Verify firewall allows connections
# View all logs
docker compose logs -f
# View specific service logs
docker compose logs -f backend
docker compose logs -f frontend
docker compose logs -f mpd
# Check service status
docker compose ps
# Check resource usage
docker stats# Backend logs (if using cargo run)
# Logs will appear in the terminal
# MPD logs
tail -f backend/mpd.log
# Check MPD status
mpc statusContributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Music Player Daemon (MPD) - Audio playback daemon
- Actix Web - Rust web framework
- React - Frontend framework
- Vite - Build tool
- Tailwind CSS - CSS framework
