# soundspan all-in-one (AIO) deployment. # # Use this when you want one container that bundles frontend+backend+db+redis. # This is the simplest path for production-style single-host installs. # # Usage: # 1. Set MUSIC_PATH and secrets in your .env # 2. docker compose -f docker-compose.aio.yml up -d # 3. Open http://localhost:3030 # # Add optional acquisition/indexer tools with: # docker compose -f docker-compose.aio.yml -f docker-compose.services.yml up -d services: soundspan: image: ${SOUNDSPAN_AIO_IMAGE:-ghcr.io/soundspan/soundspan}:${VERSION:-latest} container_name: ${SOUNDSPAN_AIO_CONTAINER_NAME:-soundspan} ports: - "${PORT:-3030}:3030" volumes: # REQUIRED: Path to your music library - ${MUSIC_PATH:-/path/to/your/music}:/music # Persistent data (database, cache, etc.) - soundspan_data:/data environment: - TZ=${TZ:-UTC} # AIO honors operator-supplied secrets; they take precedence and persist to /data/secrets. # Empty values generate and persist stable values on first boot. - SESSION_SECRET=${SESSION_SECRET:-} - SETTINGS_ENCRYPTION_KEY=${SETTINGS_ENCRYPTION_KEY:-} - INTERNAL_API_SECRET=${INTERNAL_API_SECRET:-} - METRICS_TOKEN=${METRICS_TOKEN:-} - METRICS_PUBLIC=${METRICS_PUBLIC:-false} # Optional OIDC / SSO authentication - LOCAL_LOGIN_ENABLED=${LOCAL_LOGIN_ENABLED:-true} - OIDC_ENABLED=${OIDC_ENABLED:-false} - OIDC_ISSUER_URL=${OIDC_ISSUER_URL:-} - OIDC_CLIENT_ID=${OIDC_CLIENT_ID:-} - OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET:-} - OIDC_REDIRECT_URI=${OIDC_REDIRECT_URI:-} - OIDC_WEB_BASE_URL=${OIDC_WEB_BASE_URL:-} - OIDC_SCOPES=${OIDC_SCOPES:-openid profile email} - OIDC_AUTO_PROVISION=${OIDC_AUTO_PROVISION:-false} - OIDC_MANAGE_ROLES=${OIDC_MANAGE_ROLES:-false} - OIDC_GROUPS_CLAIM=${OIDC_GROUPS_CLAIM:-groups} - OIDC_ADMIN_GROUP=${OIDC_ADMIN_GROUP:-} - OIDC_EMAIL_CLAIM=${OIDC_EMAIL_CLAIM:-email} - OIDC_NAME_CLAIM=${OIDC_NAME_CLAIM:-name} - OIDC_PROVIDER_NAME=${OIDC_PROVIDER_NAME:-SSO} # AIO uses fixed internal host/user/database components; its verified # credential helper URL-encodes this separately supplied password. - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-} - BROWSE_IMAGE_CACHE_MAX_BYTES=${BROWSE_IMAGE_CACHE_MAX_BYTES:-268435456} - BROWSE_IMAGE_CACHE_MAX_ENTRIES=${BROWSE_IMAGE_CACHE_MAX_ENTRIES:-2048} - SOCKET_KEEPALIVE_DELAY_MS=${SOCKET_KEEPALIVE_DELAY_MS:-30000} # Next-served documents start in report-only CSP mode. - CSP_ENFORCE=${CSP_ENFORCE:-false} - CSP_REPORT_URI=${CSP_REPORT_URI:-} # Runtime streaming-engine selector. Accepted: native | howler. # Leave unset to use the default native engine. - STREAMING_ENGINE_MODE=${STREAMING_ENGINE_MODE:-} # Preserve Redis streams/groups across restarts unless explicitly overridden - REDIS_FLUSH_ON_STARTUP=${REDIS_FLUSH_ON_STARTUP:-false} # Coarse feature flags for ML/recommendation subsystems (default: true) - AUDIO_ANALYSIS_ENABLED=${AUDIO_ANALYSIS_ENABLED:-true} - DISCOVERY_ENABLED=${DISCOVERY_ENABLED:-true} - AUTO_PLAYLISTS_ENABLED=${AUTO_PLAYLISTS_ENABLED:-true} - FEDERATION_ENABLED=${FEDERATION_ENABLED:-false} - FEDERATION_ALLOW_PRIVATE_PEERS=${FEDERATION_ALLOW_PRIVATE_PEERS:-false} - FEDERATION_ALLOW_PROXY=${FEDERATION_ALLOW_PROXY:-false} # Host passthrough (null-form: absent in the container unless set on the # host) so FEDERATION_ALLOW_PROXY=true has a proxy to use. Federation # honors these only with that opt-in; axios-based outbound HTTPS clients # honor them per standard env-proxy semantics when set (Node-native fetch # clients do not). - HTTPS_PROXY - https_proxy - ALL_PROXY - all_proxy - NO_PROXY - no_proxy - FEDERATION_TOMBSTONE_RETENTION_DAYS=${FEDERATION_TOMBSTONE_RETENTION_DAYS:-90} - PROVIDER_TRACK_RETENTION_DAYS=${PROVIDER_TRACK_RETENTION_DAYS:-30} - FEDERATION_SYNC_INTERVAL_MINUTES=${FEDERATION_SYNC_INTERVAL_MINUTES:-15} # DCLAP provider routing, idle unloading, and ONNX CPU concurrency - VIBE_PROVIDER_URL=${VIBE_PROVIDER_URL:-http://localhost:8092} - MODEL_IDLE_TIMEOUT=${MODEL_IDLE_TIMEOUT:-300} - DCLAP_ONNX_INTRA_OP_THREADS=${DCLAP_ONNX_INTRA_OP_THREADS:-1} # MusicCNN queue socket timeout; runtime enforces at least BRPOP timeout + 5s - AUDIO_REDIS_SOCKET_TIMEOUT=${AUDIO_REDIS_SOCKET_TIMEOUT:-35} # Lidarr webhook callback URL - how Lidarr reaches soundspan when downloads complete # Default uses host.docker.internal which works on most setups with extra_hosts below # Override if using custom Docker networks: e.g., http://192.168.0.20:3030 - SOUNDSPAN_CALLBACK_URL=${SOUNDSPAN_CALLBACK_URL:-http://host.docker.internal:3030} # Makes host.docker.internal work on Linux (already works on Docker Desktop) extra_hosts: - "host.docker.internal:host-gateway" restart: unless-stopped healthcheck: test: ["CMD", "node", "/app/healthcheck.js"] interval: 30s timeout: 10s start_period: 60s retries: 3 volumes: soundspan_data: name: ${SOUNDSPAN_AIO_DATA_VOLUME:-soundspan_data}