Skip to content

Container

Installationยถ

Deploying Mixtape Society with Docker is the recommended way to run your private mixtape serverโ€”perfect for home servers, VPS, or NAS devices.

๐Ÿ‹ Why Docker?ยถ

Benefit Explanation
Zero-setup No manual Python or dependency installation. Everything runs in an isolated container.
Portability Works on Linux, macOS, Windows, and ARM devices (Raspberry Pi) without code changes.
Isolation The app runs securely with limited system access through volume mounts.
Persistence Your data (database, mixtapes, covers, cache) survives container updates and restarts.
Easy Updates Pull the latest image and restartโ€”new version runs in seconds.

โœ… Official Imageยถ

The official, automatically-built image is available at:

ghcr.io/mark-me/mixtape-society:latest

Images are rebuilt automatically on every release. Use specific version tags (e.g., v1.4.2) for reproducible deployments.

๐Ÿš€ Quick-Start One-Linerยถ

Replace the placeholders with your actual paths:

docker run -d \
  --name mixtape-society \
  --restart unless-stopped \
  -p 5000:5000 \
  -v /path/to/your/music:/music:ro \
  -v mixtape_data:/app/collection-data \
  -e PASSWORD=YourStrongPassword123! \
  -e APP_ENV=production \
  ghcr.io/mark-me/mixtape-society:latest

What this does:

Flag Effect
-p 5000:5000 Exposes the web interface on host port 5000.
-v /path/to/your/music:/music:ro Mounts your music library read-only.
-v mixtape_data:/app/collection-data Persists database, mixtapes, covers, and cache.
-e PASSWORD=... Sets your login password (required).
-e APP_ENV=production Enables production configuration (required).
--restart unless-stopped Automatically restarts after crashes or reboots.

After the container starts:

  1. Open http://localhost:5000
  2. Log in with your password
  3. Wait for initial music indexing to complete (check progress with docker logs -f mixtape-society)

Directory Structureยถ

Create a deployment directory:

mkdir ~/mixtape-society
cd ~/mixtape-society

docker-compose.ymlยถ

Create this file in your deployment directory:

services:
  mixtape:
    image: ghcr.io/mark-me/mixtape-society:latest
    container_name: mixtape-society
    restart: unless-stopped
    ports:
      - "5000:5000"
    volumes:
      - ${MUSIC_HOST_PATH}:/music:ro
      - mixtape_data:/app/collection-data
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Amsterdam
      - PASSWORD=${PASSWORD}
      - APP_ENV=production
      - LOG_LEVEL=INFO

volumes:
  mixtape_data:

.envยถ

Create this file next to docker-compose.yml:

# Path to your music collection on the host
MUSIC_HOST_PATH=/home/user/Music

# Strong password for web interface (required!)
PASSWORD=YourVeryStrongPasswordHere!

Security Note

Never commit .env files to version control. Add it to .gitignore if you're tracking your deployment configuration.

Starting the Serviceยถ

docker compose up -d

First-time setup:

  • The container will start indexing your music library automatically
  • Monitor progress: docker compose logs -f
  • Indexing time depends on library size (e.g., ~5 minutes for 10,000 tracks)

Updating to a Newer Versionยถ

docker compose pull
docker compose up -d

Your data (database, mixtapes, covers) is preserved in the mixtape_data volume.

๐Ÿ“ Data Storageยถ

Volume Layoutยถ

Inside the container, data is stored at /app/collection-data:

/app/collection-data/
โ”œโ”€โ”€ collection.db              # Music library database
โ”œโ”€โ”€ mixtapes/
โ”‚   โ”œโ”€โ”€ <slug>.json           # Mixtape definitions
โ”‚   โ””โ”€โ”€ covers/
โ”‚       โ””โ”€โ”€ <slug>.jpg        # Custom cover images
โ””โ”€โ”€ cache/
    โ””โ”€โ”€ audio/
        โ””โ”€โ”€ <artist>/<album>/<track>.mp3   # Transcoded audio cache

Using Named Volumes (Default)ยถ

Named volumes are managed by Docker and are the recommended approach:

volumes:
  - mixtape_data:/app/collection-data

Advantages:

  • Automatic management by Docker
  • Good performance
  • Easy to backup with docker volume commands

Inspect volume location:

docker volume inspect mixtape_data
# Usually at: /var/lib/docker/volumes/mixtape_data/_data

Using Bind Mounts (Alternative)ยถ

If you prefer direct access to data files:

volumes:
  - /path/on/host/mixtape-data:/app/collection-data

Advantages:

  • Easy to browse/backup with regular tools
  • Direct file system access

Requirements:

  • Directory must be writable by UID 1000 (default container user)
  • Run: sudo chown -R 1000:1000 /path/on/host/mixtape-data

๐Ÿ”ง Configuration Referenceยถ

Environment Variablesยถ

Variable Required Default Description
PASSWORD Yes (none) Login password for the web interface
APP_ENV Yes development Must be set to production for deployment
MUSIC_ROOT No /music Container path to music (matches volume mount)
LOG_LEVEL No INFO Logging verbosity: DEBUG, INFO, WARNING, ERROR
TZ No UTC Timezone for timestamps (e.g., America/New_York)
PUID No 1000 User ID for file permissions
PGID No 1000 Group ID for file permissions

Port Configurationยถ

Default port mapping:

ports:
  - "5000:5000"    # host:container

To use a different host port (e.g., 8080):

ports:
  - "8080:5000"    # Access at http://localhost:8080

๐ŸŒ Running Behind a Reverse Proxyยถ

For external access with HTTPS and a custom domain, use a reverse proxy.

Traefikยถ

Add these labels to your docker-compose.yml:

services:
  mixtape:
    # ... existing configuration ...
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.mixtape.rule=Host(`mixtape.yourdomain.com`)"
      - "traefik.http.routers.mixtape.entrypoints=websecure"
      - "traefik.http.routers.mixtape.tls.certresolver=letsencrypt"
      - "traefik.http.services.mixtape.loadbalancer.server.port=5000"

What this does:

  • Routes mixtape.yourdomain.com to your service
  • Automatically obtains Let's Encrypt certificates
  • Terminates TLS at the proxy level

Nginx Proxy Managerยถ

  1. In NPM web interface, add a new Proxy Host
  2. Set:
  3. Domain: mixtape.yourdomain.com
  4. Forward Hostname: mixtape-society (container name)
  5. Forward Port: 5000
  6. Enable SSL: Yes (request Let's Encrypt certificate)

Caddyยถ

Create a Caddyfile:

mixtape.yourdomain.com {
    reverse_proxy mixtape-society:5000
}

Caddy automatically handles HTTPS certificates.

Tailscale with TSDProxyยถ

If using Tailscale for private access:

services:
  mixtape:
    # ... existing configuration ...
    environment:
      - TSDPROXY_ENABLE=true
      - TSDPROXY_HOST=mixtape.yourtailnet.ts.net
      - TSDPROXY_HTTP_PORT=5000
      - TSDPROXY_TLS_EMAIL=you@example.com

What this does:

  • Exposes your service on your Tailscale network
  • Automatically provisions TLS certificates
  • Private access without exposing to public internet

โš ๏ธ Troubleshootingยถ

Container Won't Startยถ

Check logs:

docker compose logs

Common causes:

  • Missing required environment variables (PASSWORD, APP_ENV)
  • Port 5000 already in use
  • Volume mount paths don't exist

Music Library Not Indexingยถ

Verify music mount:

docker compose exec mixtape ls -la /music

Check permissions:

  • Container user (UID 1000) must be able to read music files
  • For bind mounts: chmod -R 755 /path/to/music

Monitor indexing progress:

docker compose logs -f | grep -i index

Cannot Access Web Interfaceยถ

Check container is running:

docker compose ps

Verify port mapping:

docker compose port mixtape 5000

Test from inside container:

docker compose exec mixtape curl -I http://localhost:5000

Permission Errors When Writing Dataยถ

Verify volume ownership:

# For bind mounts
ls -la /path/to/mixtape-data

# Should be owned by UID 1000
sudo chown -R 1000:1000 /path/to/mixtape-data

Adjust container user (if needed):

environment:
  - PUID=1001
  - PGID=1001

Database Corruptionยถ

If you encounter database errors:

  1. Stop the container:
docker compose down
  1. Backup current data:
docker run --rm -v mixtape_data:/data -v $(pwd):/backup \
  alpine tar czf /backup/mixtape-backup.tar.gz /data
  1. Reset database (this will re-index your library):
  2. Through web UI: Settings โ†’ Reset Database
  3. Manual: Delete collection.db and restart

  4. Restore only mixtapes (if needed):

tar xzf mixtape-backup.tar.gz data/mixtapes/ --strip-components=1

Audio Not Playingยถ

Check audio cache:

docker compose exec mixtape ls -la /app/collection-data/cache/audio/

Verify browser console for errors:

  • Open browser DevTools (F12)
  • Check Console and Network tabs for failed requests

Test direct audio access:

curl -I http://localhost:5000/play/<mixtape-slug>/stream/<track-id>

๐Ÿ“Š Monitoring and Maintenanceยถ

View Logsยถ

# Real-time logs
docker compose logs -f

# Last 100 lines
docker compose logs --tail=100

# Logs for specific time
docker compose logs --since="2024-01-20T10:00:00"

Container Resource Usageยถ

docker stats mixtape-society

Backup Dataยถ

Using named volume:

docker run --rm \
  -v mixtape_data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/mixtape-backup-$(date +%Y%m%d).tar.gz /data

Using bind mount:

tar czf mixtape-backup-$(date +%Y%m%d).tar.gz /path/to/mixtape-data

Restore Backupยถ

docker compose down
docker run --rm \
  -v mixtape_data:/data \
  -v $(pwd):/backup \
  alpine sh -c "cd /data && tar xzf /backup/mixtape-backup.tar.gz --strip-components=1"
docker compose up -d

๐Ÿ”„ Upgrade Checklistยถ

Before upgrading to a new version:

  1. โœ… Backup your data (see above)
  2. โœ… Read release notes for breaking changes
  3. โœ… Pull new image: docker compose pull
  4. โœ… Restart: docker compose up -d
  5. โœ… Verify functionality: Check web interface and play a mixtape
  6. โœ… Monitor logs: docker compose logs -f for any errors