Docker Compose Examples

Production-ready Compose files for common deployment scenarios.

Basic Setup (SQLite + HTTPS)

The simplest production setup — single container with automatic TLS.

version: "3.8"
services:
  blackcandystore:
    image: ghcr.io/ajeskey/blackcandystore:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./storage_data:/rails/storage
      - /path/to/music:/media_data
    environment:
      - MEDIA_PATH=/media_data
      - SECRET_KEY_BASE=your_64_char_hex_secret
      - TLS_DOMAIN=music.example.com
    restart: unless-stopped

Multiple Libraries

Mount several music directories and create a library for each in the admin UI.

version: "3.8"
services:
  blackcandystore:
    image: ghcr.io/ajeskey/blackcandystore:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./storage_data:/rails/storage
      - /mnt/nas/jazz:/media/jazz
      - /mnt/nas/electronic:/media/electronic
      - /mnt/nas/vinyl-rips:/media/vinyl
      - /mnt/nas/podcasts:/media/podcasts
    environment:
      - SECRET_KEY_BASE=your_64_char_hex_secret
      - TLS_DOMAIN=music.example.com
    restart: unless-stopped

When using multiple libraries, don't set MEDIA_PATH — instead, configure each library's path individually through the admin UI after startup.

PostgreSQL

For larger collections or multi-user deployments. Includes a dedicated PostgreSQL container.

version: "3.8"
services:
  blackcandystore:
    image: ghcr.io/ajeskey/blackcandystore:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./storage_data:/rails/storage
      - /path/to/music:/media_data
    environment:
      - MEDIA_PATH=/media_data
      - SECRET_KEY_BASE=your_64_char_hex_secret
      - TLS_DOMAIN=music.example.com
      - DB_ADAPTER=postgresql
      - DB_URL=postgresql://blackcandy:secretpassword@db:5432/blackcandystore
      - CABLE_DB_URL=postgresql://blackcandy:secretpassword@db:5432/blackcandystore_cable
      - QUEUE_DB_URL=postgresql://blackcandy:secretpassword@db:5432/blackcandystore_queue
      - CACHE_DB_URL=postgresql://blackcandy:secretpassword@db:5432/blackcandystore_cache
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=blackcandy
      - POSTGRES_PASSWORD=secretpassword
      - POSTGRES_DB=blackcandystore
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U blackcandy"]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped

volumes:
  pgdata:

Cross-Server Sharing

Full setup with encryption keys for secure cross-server library sharing.

version: "3.8"
services:
  blackcandystore:
    image: ghcr.io/ajeskey/blackcandystore:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./storage_data:/rails/storage
      - /path/to/music:/media_data
    environment:
      - MEDIA_PATH=/media_data
      - SECRET_KEY_BASE=your_64_char_hex_secret
      - TLS_DOMAIN=music.example.com
      - SERVER_BASE_URL=https://music.example.com
      - AR_ENCRYPTION_PRIMARY_KEY=your_primary_key
      - AR_ENCRYPTION_DETERMINISTIC_KEY=your_deterministic_key
      - AR_ENCRYPTION_KEY_DERIVATION_SALT=your_salt
      - CATALOG_SYNC_POLL_INTERVAL=15
    restart: unless-stopped

Generate your encryption keys with:

# Generate all three keys
openssl rand -hex 32  # AR_ENCRYPTION_PRIMARY_KEY
openssl rand -hex 32  # AR_ENCRYPTION_DETERMINISTIC_KEY
openssl rand -hex 32  # AR_ENCRYPTION_KEY_DERIVATION_SALT

Behind a Reverse Proxy (Caddy)

If you prefer to manage TLS externally with Caddy:

version: "3.8"
services:
  blackcandystore:
    image: ghcr.io/ajeskey/blackcandystore:latest
    expose:
      - "80"
    volumes:
      - ./storage_data:/rails/storage
      - /path/to/music:/media_data
    environment:
      - MEDIA_PATH=/media_data
      - SECRET_KEY_BASE=your_64_char_hex_secret
      - FORCE_SSL=true
    restart: unless-stopped

  caddy:
    image: caddy:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
    restart: unless-stopped

volumes:
  caddy_data:

With a Caddyfile:

music.example.com {
    reverse_proxy blackcandystore:80
}

Generating Secrets

For any of the above, generate your SECRET_KEY_BASE with:

openssl rand -hex 64

Never reuse secrets between environments or share them publicly.

Next Steps