From 1414aa480e25cb4daf4dd6741563efc5403884c8 Mon Sep 17 00:00:00 2001 From: hermes Date: Wed, 30 Sep 2026 21:59:34 +0200 Subject: [PATCH] add vps/DEPLOY.md --- vps/DEPLOY.md | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 vps/DEPLOY.md diff --git a/vps/DEPLOY.md b/vps/DEPLOY.md new file mode 100644 index 0000000..43701cf --- /dev/null +++ b/vps/DEPLOY.md @@ -0,0 +1,88 @@ +# VPS deployment + +Target: any VPS with Docker + Docker Compose, ports 80/443 free (and 8000 +if you want plain HTTP for very old stereos). + +## 1. Lay out the bundle + +```bash +ssh root@YOUR_VPS +mkdir -p /opt/airstudio/web/ai-radio && cd /opt/airstudio +# copy from the repo: docker-compose.yml, Dockerfile.streamer, icecast.xml, Caddyfile +``` + +## 2. Configure + +```bash +cp .env.vps.example .env +$EDITOR .env # set ICECAST_SOURCE_PASSWORD, station name, MQTT +$EDITOR icecast.xml # set the 3 passwords + hostname +$EDITOR Caddyfile # set your domain +``` + +`ICECAST_SOURCE_PASSWORD` in `.env` **must** match `` in +`icecast.xml` — the streamer authenticates with it. + +## 3. Firewall + +```bash +ufw allow 22,80,443/tcp +# optional plain-HTTP fallback for old stereos: +ufw allow 8000/tcp +``` + +## 4. Boot + +```bash +docker compose up -d --build +docker compose ps # icecast, radio-streamer, caddy all Up +docker compose logs -f radio-streamer +``` + +Expected streamer log: `live on icecast:8000/ai-radio.mp3` then +`played .mp3` lines as songs roll. + +## 5. Verify + +```bash +# direct icecast: +curl -sI http://localhost:8000/ai-radio.mp3 | head -1 +# via caddy (after DNS + cert issuance): +curl -sI https://radio.example.com/ai-radio.mp3 | head -1 +``` + +In a desktop player: open the URL — you should hear the shipped playlist +looping. (Empty web root → streamer waits; run the shipper once first.) + +## 6. Ship from the generator + +On the generator machine: + +```bash +SHIP_REMOTE_TARGET=root@YOUR_VPS:/opt/airstudio/web/ai-radio/ \ +SHIP_SSH_KEY=~/.ssh/id_ed25519_vps \ +LIBRARY_DIR=~/ai-radio/library \ +go run ./cmd/shipper +``` + +New songs appear on air within one playlist lap. + +## Operations + +- **Restart everything:** `docker compose restart` +- **Update streamer code:** `docker compose build streamer && docker compose up -d streamer` +- **Admin UI:** `http://:8000/admin/` (user `admin`, your admin password) + — shows listeners, mount status, kick sources. +- **Logs:** `docker compose logs -f icecast radio-streamer caddy` +- **MQTT check:** `mosquitto_sub -h BROKER -t airstudio/nowplaying -v` + +## Troubleshooting + +| Symptom | Cause / fix | +|---|---| +| streamer: `icecast rejected source 401` | password mismatch between `.env` and `icecast.xml` | +| streamer: `no playable files` | shipper hasn't run; check `web/ai-radio/` contents | +| silence but stream "connected" | stale playlist pointing at missing mp3s — re-run shipper | +| caddy 502 | icecast container down: `docker compose ps` | +| no HTTPS cert | DNS not pointing at this VPS yet; check `docker compose logs caddy` | +| stereo shows garbage titles | very old ID3v1-only player: titles come from ID3v1 — re-transcode (already written by shipper) |