services: # ============================================================================== # LIDIFY CORE APPLICATION # ============================================================================== # Backend API - Your Lidify Express.js server backend: build: context: ./backend dockerfile: Dockerfile container_name: lidify_backend environment: # Database DATABASE_URL: postgresql://${POSTGRES_USER:-lidifydb}:${POSTGRES_PASSWORD:-changeme}@postgres:5432/${POSTGRES_DB:-lidify} POSTGRES_USER: ${POSTGRES_USER:-lidifydb} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme} POSTGRES_DB: ${POSTGRES_DB:-lidify} REDIS_URL: redis://redis:6379 # Server config PORT: 3006 NODE_ENV: ${NODE_ENV:-production} SESSION_SECRET: ${SESSION_SECRET:-changeme-generate-secure-key} SETTINGS_ENCRYPTION_KEY: ${SETTINGS_ENCRYPTION_KEY:-} # Music library (required) # IMPORTANT: Inside Docker, music is always at /music (mounted from host MUSIC_PATH) # Don't use ${MUSIC_PATH} here as it contains the host path, not container path MUSIC_PATH: /music TRANSCODE_CACHE_PATH: /app/cache/transcodes TRANSCODE_CACHE_MAX_GB: ${TRANSCODE_CACHE_MAX_GB:-10} # CORS ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-http://localhost:3000,http://localhost:3030} # Lidarr webhook callback URL - how Lidarr can reach Lidify # Use backend:3006 for same-network communication, or external IP:3030 for external Lidarr LIDIFY_CALLBACK_URL: ${LIDIFY_CALLBACK_URL:-http://backend:3006} # Debug: enable extra podcast stream/cache logging PODCAST_DEBUG: ${PODCAST_DEBUG:-0} volumes: - ${MUSIC_PATH:-./music}:/music - backend_cache:/app/cache - backend_logs:/app/logs ports: - "${BACKEND_PORT:-3006}:3006" depends_on: postgres: condition: service_healthy redis: condition: service_healthy restart: unless-stopped healthcheck: test: ["CMD", "node", "healthcheck.js"] interval: 30s timeout: 10s retries: 3 # Frontend Web UI - Your Lidify Next.js app frontend: build: context: ./frontend dockerfile: Dockerfile args: # Prefer relative /api requests (Next.js rewrites will proxy to backend). # If you need a custom API URL, set NEXT_PUBLIC_API_URL explicitly. NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-} container_name: lidify_frontend environment: NODE_ENV: ${NODE_ENV:-production} # Used by next.config.ts rewrites() inside the container. # IMPORTANT: "localhost" inside a container refers to itself, not the host. BACKEND_URL: ${BACKEND_URL:-http://backend:3006} # Exposed to the browser; leave empty by default so the app uses /api via rewrites. NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-} ports: - "${FRONTEND_PORT:-3030}:3030" depends_on: - backend restart: unless-stopped healthcheck: test: ["CMD", "node", "healthcheck.js"] interval: 30s timeout: 10s retries: 3 # ============================================================================== # INFRASTRUCTURE (Database & Cache) # ============================================================================== postgres: image: postgres:16-alpine container_name: lidify_db environment: POSTGRES_USER: ${POSTGRES_USER:-lidifydb} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme} POSTGRES_DB: ${POSTGRES_DB:-lidify} volumes: - postgres_data:/var/lib/postgresql/data ports: - "${POSTGRES_PORT:-5432}:5432" restart: unless-stopped healthcheck: # IMPORTANT: # pg_isready defaults to connecting to a database with the same name as the user. # Our default user is "lidifydb" but default database is "lidify", # so without -d this will spam logs with: FATAL: database "lidifydb" does not exist test: [ "CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-lidifydb} -d ${POSTGRES_DB:-lidify}", ] interval: 10s timeout: 5s retries: 5 redis: image: redis:7-alpine container_name: lidify_redis ports: - "${REDIS_PORT:-6379}:6379" restart: unless-stopped healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 # ============================================================================== # EXTERNAL SERVICES (Music Management) # ============================================================================== # Lidarr - Music collection manager lidarr: image: lscr.io/linuxserver/lidarr:latest container_name: lidify_lidarr environment: - PUID=1000 - PGID=1000 - TZ=${TZ:-UTC} volumes: - lidarr_config:/config - ${MUSIC_PATH:-./music}:/music - ${DOWNLOAD_PATH:-./downloads}:/downloads ports: - "8686:8686" restart: unless-stopped # Prowlarr - Indexer manager prowlarr: image: lscr.io/linuxserver/prowlarr:latest container_name: lidify_prowlarr environment: - PUID=1000 - PGID=1000 - TZ=${TZ:-UTC} volumes: - prowlarr_config:/config ports: - "9696:9696" restart: unless-stopped # FlareSolverr - Cloudflare bypass for Prowlarr flaresolverr: image: ghcr.io/flaresolverr/flaresolverr:latest container_name: lidify_flaresolverr environment: - LOG_LEVEL=${LOG_LEVEL:-info} - LOG_HTML=${LOG_HTML:-false} - CAPTCHA_SOLVER=${CAPTCHA_SOLVER:-none} - TZ=${TZ:-UTC} ports: - "8191:8191" restart: unless-stopped # NOTE: Soulseek is now handled directly by the backend using slsk-client # No Docker container needed - downloads go straight to Singles/Artist/Album/ # qBittorrent - Torrent client qbittorrent: image: lscr.io/linuxserver/qbittorrent:latest container_name: lidify_qbittorrent environment: - PUID=1000 - PGID=1000 - TZ=${TZ:-UTC} - WEBUI_PORT=8080 volumes: - qbittorrent_config:/config - ${MUSIC_PATH:-./music}/torrents:/music/torrents - ${DOWNLOAD_PATH:-./downloads}:/downloads ports: - "8080:8080" - "6881:6881" - "6881:6881/udp" restart: unless-stopped # SABnzbd - Usenet client sabnzbd: image: lscr.io/linuxserver/sabnzbd:latest container_name: lidify_sabnzbd environment: - PUID=1000 - PGID=1000 - TZ=${TZ:-UTC} volumes: - sabnzbd_config:/config - ${DOWNLOAD_PATH:-./downloads}:/downloads ports: - "8085:8080" restart: unless-stopped # ============================================================================== # AUDIO ANALYSIS SERVICE (Essentia) # ============================================================================== # Audio Analyzer - Extracts BPM, key, mood, and other audio features audio-analyzer: build: context: ./services/audio-analyzer container_name: lidify_audio_analyzer environment: REDIS_URL: redis://redis:6379 DATABASE_URL: postgresql://${POSTGRES_USER:-lidifydb}:${POSTGRES_PASSWORD:-changeme}@postgres:5432/${POSTGRES_DB:-lidify} MUSIC_PATH: /music BATCH_SIZE: ${AUDIO_ANALYSIS_BATCH_SIZE:-10} SLEEP_INTERVAL: ${AUDIO_ANALYSIS_INTERVAL:-5} NUM_WORKERS: ${AUDIO_ANALYSIS_WORKERS:-8} volumes: - ${MUSIC_PATH:-./music}:/music:ro - audio_analyzer_models:/app/models depends_on: postgres: condition: service_healthy redis: condition: service_healthy restart: unless-stopped # Disabled by default - enable when needed profiles: - audio-analysis volumes: # Lidify core postgres_data: backend_cache: backend_logs: # Audio analysis audio_analyzer_models: # External services lidarr_config: prowlarr_config: qbittorrent_config: sabnzbd_config: networks: default: name: lidify_network