Files
podsteadr/docker-compose.yml
T
ssmithxandClaude Sonnet 5 e04d35b131 feat: recorded-episode pricing, Cashu-token payment, podcast editing
- Editable podcast settings: new /podcasts/:id/settings page, reusing
  PodcastForm.vue in an edit mode (PUT instead of POST) since it was
  previously create-only with no way to fix a field (e.g. lightning
  address) after the fact.
- Recorded episodes can now be priced same as uploads: "Publish
  recording" gained an optional price_sats field, wired through the
  existing episode paywall machinery. Live streams themselves stay
  unpaywalled by design — only the resulting recording can be priced.
- Accept Cashu tokens as an alternative to a Lightning invoice:
  POST .../purchase/token redeems a pasted token directly (via the
  mint's swap/receive flow) and finalizes the purchase in one step,
  no quote/confirm round trip. A token worth more than the price is
  treated as a tip (seller gets the full amount); worth less is
  rejected. Added a "pay with a Cashu token instead" option next to
  the existing invoice flow.
- cashu.ts: fixed payout() always requesting an invoice for the full
  held balance with no room for the mint's routing-fee reserve, which
  made a balance that exactly matched one sale's price permanently
  unwithdrawable (needed slightly more than held to cover the fee).
  Now shrinks the request and requotes once if the first quote doesn't
  fit.
- docker-compose.yml / mediamtx.yml: renamed the podsteadr container's
  DNS alias away from the literal string "podsteadr" — on a host whose
  own hostname is "podsteadr", cloud-init's self-hostname /etc/hosts
  entry shadowed the container-network alias, so mediamtx's auth
  webhook callback resolved to the wrong address and rejected every
  RTMP publish attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 23:18:36 +00:00

67 lines
2.4 KiB
YAML

name: podsteadr
services:
podsteadr:
build: .
# Container/DNS-alias name deliberately NOT "podsteadr" — on hosts whose own hostname is
# "podsteadr" (e.g. a VPS named after the app), the host's own /etc/hosts self-hostname
# entry (127.0.1.1 podsteadr, added by cloud-init) shadows the container network's DNS
# alias for other containers looking up "podsteadr", so mediamtx's auth-webhook callback
# resolved to the host's loopback instead of this container and every RTMP publish got
# rejected with "connection refused" (observed on podsteadr.atobitcoin.io, 2026-07-30).
container_name: podsteadr-app
restart: unless-stopped
ports:
- "8095:8095"
environment:
NODE_ENV: production
PORT: "8095"
DATA_DIR: /data
RECORDINGS_DIR: /recordings
PUBLIC_URL: ${PUBLIC_URL:-http://localhost:8095}
MEDIAMTX_API_URL: http://mediamtx:9997
MEDIAMTX_RTMP_PUBLIC: ${MEDIAMTX_RTMP_PUBLIC:-rtmp://localhost:1935}
MEDIAMTX_WHIP_PUBLIC: ${MEDIAMTX_WHIP_PUBLIC:-http://localhost:8889}
MEDIAMTX_HLS_PUBLIC: ${MEDIAMTX_HLS_PUBLIC:-http://localhost:8890}
BLOSSOM_URL_DEFAULT: ${BLOSSOM_URL_DEFAULT:-http://localhost:8098}
BLOSSOM_URL_INTERNAL: http://blossom:3000
NOSTR_RELAYS: ${NOSTR_RELAYS:-wss://relay.damus.io,wss://nos.lol,wss://relay.nostr.band}
CASHU_MINT_URL_DEFAULT: ${CASHU_MINT_URL_DEFAULT:-https://mint.minibits.cash/Bitcoin}
volumes:
- podsteadr-data:/data
- mediamtx-recordings:/recordings:ro
depends_on:
- mediamtx
- blossom
mediamtx:
image: docker.io/bluenviron/mediamtx:1.19.2
container_name: podsteadr-mediamtx
restart: unless-stopped
ports:
- "1935:1935" # RTMP ingest
- "8889:8889" # WebRTC / WHIP
- "8189:8189/udp" # WebRTC ICE
- "8890:8888" # HLS (host 8890; 8888 kept free for other apps)
environment:
# Browsers need a reachable ICE host candidate; set PUBLIC_HOST in .env
MTX_WEBRTCADDITIONALHOSTS: ${PUBLIC_HOST:-localhost}
volumes:
- ./mediamtx/mediamtx.yml:/mediamtx.yml:ro
- mediamtx-recordings:/recordings
blossom:
image: ghcr.io/hzrd149/blossom-server:4
container_name: podsteadr-blossom
restart: unless-stopped
ports:
- "8098:3000"
volumes:
- ./blossom/config.yml:/app/config.yml:ro
- blossom-data:/app/data
volumes:
podsteadr-data:
mediamtx-recordings:
blossom-data: