Add Navidrome and SUB/WAVE AI radio station
Navidrome indexes the existing music library on nas_media for Subsonic access. SUB/WAVE (byo-proxy variant, LAN-only) provides the Icecast broadcast, Liquidsoap crossfade/ducking, and AI DJ controller, reusing the existing Ollama instance over npm-network for the LLM and Piper for TTS.
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
# SUB/WAVE — self-hosted AI radio station.
|
||||
# Deployed as the "byo-proxy" variant (no bundled Caddy): web/controller/
|
||||
# broadcast bind host ports directly since this station is LAN-only for now.
|
||||
# Upstream project: https://github.com/perminder-klair/subwave
|
||||
#
|
||||
# Values are hardcoded rather than relying on ${VAR} compose substitution,
|
||||
# since Portainer git-linked stacks don't read this repo's local .env for
|
||||
# that purpose (see deployment-procedures.md). ADMIN_USER/ADMIN_PASS still
|
||||
# come from a real (gitignored) ./.env file next to this compose file, read
|
||||
# directly by Docker's env_file mechanism.
|
||||
|
||||
x-logging: &default-logging
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
services:
|
||||
# -------------------------------------------------------------------------
|
||||
# BROADCAST — icecast2 + liquidsoap in one container
|
||||
# -------------------------------------------------------------------------
|
||||
broadcast:
|
||||
image: ghcr.io/perminder-klair/subwave-broadcast:latest
|
||||
container_name: sub-wave-broadcast
|
||||
restart: unless-stopped
|
||||
logging: *default-logging
|
||||
environment:
|
||||
- TZ=America/New_York
|
||||
ports:
|
||||
- 7702:7702
|
||||
volumes:
|
||||
- /srv/subwave/state:/var/sub-wave
|
||||
- /srv/subwave/logs:/var/log/liquidsoap
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -fsS http://localhost:7702/status-json.xsl > /dev/null"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 12
|
||||
start_period: 15s
|
||||
networks:
|
||||
- npm-network
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# CONTROLLER — AI DJ brain + admin API
|
||||
# -------------------------------------------------------------------------
|
||||
controller:
|
||||
image: ghcr.io/perminder-klair/subwave-controller:latest
|
||||
container_name: sub-wave-controller
|
||||
restart: unless-stopped
|
||||
logging: *default-logging
|
||||
depends_on:
|
||||
broadcast:
|
||||
condition: service_healthy
|
||||
docker-socket-proxy:
|
||||
condition: service_started
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- TZ=America/New_York
|
||||
- STATE_DIR=/var/sub-wave
|
||||
- SOUNDS_DIR=/sounds
|
||||
- ANALYZE_URL=http://analyzer:8080
|
||||
- DOCKER_HOST=tcp://docker-socket-proxy:2375
|
||||
env_file:
|
||||
- ./.env
|
||||
ports:
|
||||
- 7701:7701
|
||||
volumes:
|
||||
- /srv/subwave/state:/var/sub-wave
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -fsS http://localhost:7701/health > /dev/null"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 6
|
||||
start_period: 20s
|
||||
networks:
|
||||
- npm-network
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# DOCKER-SOCKET-PROXY — locked-down, read-only Docker API for the admin
|
||||
# Stats panel. Remove this + the controller's DOCKER_HOST/depends_on entry
|
||||
# for zero Docker-socket exposure.
|
||||
# -------------------------------------------------------------------------
|
||||
docker-socket-proxy:
|
||||
image: ghcr.io/tecnativa/docker-socket-proxy:0.3.0
|
||||
container_name: sub-wave-docker-proxy
|
||||
restart: unless-stopped
|
||||
logging: *default-logging
|
||||
environment:
|
||||
- CONTAINERS=1
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
networks:
|
||||
- npm-network
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# WEB — Next.js listener UI + admin console
|
||||
# -------------------------------------------------------------------------
|
||||
web:
|
||||
image: ghcr.io/perminder-klair/subwave-web:latest
|
||||
container_name: sub-wave-web
|
||||
restart: unless-stopped
|
||||
logging: *default-logging
|
||||
depends_on:
|
||||
controller:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- SUBWAVE_HOMEPAGE=player
|
||||
- CONTROLLER_INTERNAL_URL=http://controller:7701
|
||||
env_file:
|
||||
- ./.env
|
||||
ports:
|
||||
- 7700:7700
|
||||
networks:
|
||||
- npm-network
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# ANALYZER — lean acoustic-analysis sidecar (bpm/key/loudness/outro
|
||||
# detection for ending-aware crossfades). No GPU needed.
|
||||
# -------------------------------------------------------------------------
|
||||
analyzer:
|
||||
image: ghcr.io/perminder-klair/subwave-analyzer:latest
|
||||
container_name: sub-wave-analyzer
|
||||
restart: unless-stopped
|
||||
logging: *default-logging
|
||||
mem_limit: 6g
|
||||
volumes:
|
||||
- /srv/subwave/state:/var/sub-wave
|
||||
- analyzer-cache:/opt/analyzer/hf-cache
|
||||
networks:
|
||||
- npm-network
|
||||
|
||||
volumes:
|
||||
analyzer-cache:
|
||||
|
||||
networks:
|
||||
npm-network:
|
||||
external: true
|
||||
Reference in New Issue
Block a user