Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions docker-compose.host.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Override file: switch the bot to host networking so WebRTC ICE works.
#
# Use:
# docker compose -f docker-compose.yml -f docker-compose.host.yml up -d
#
# Effect:
# * The bridge "ts6-net" attachment + the 127.0.0.1:8080 port mapping
# are stripped (compose merges by REPLACING list-valued keys when the
# overlay sets `null`-valued analogues, but Compose v2 needs the
# explicit empty list trick - see below).
# * `network_mode: host` joins the bot to the host's network namespace
# so it sees the real LAN/WAN interface; STUN now returns a usable
# srflx candidate and viewers can NAT-punch back through.
#
# Notes for this mode:
# * The host's port 8080 must be free (nothing else listening there).
# * `TS6_HOST` in .env should resolve from the HOST namespace, not the
# bridge: usually 127.0.0.1 if the TS6 server runs on the same host.
# * No `ports:` section in host mode (port mapping makes no sense).

services:
bot:
network_mode: host
# Compose v2 needs both the explicit reset and the empty list to drop
# the bridge attachment from the base file.
networks: !reset null
ports: !reset null

networks:
ts6-net: !reset null
47 changes: 9 additions & 38 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,24 @@
# voice protocol directly to push the result into a TS6 channel via the
# server's built-in stream feature. No HLS, no second nginx container.
#
# Two networking modes are available via compose profiles:
# Default networking is the standard ts6-net bridge - simple, isolated, but
# WebRTC ICE candidate gathering can struggle behind docker NAT (STUN
# responses don't establish a usable srflx, so peers can't NAT-punch back
# to the bot). If you hit that, layer the host-network override on top:
#
# * default (profile "bridge"): bot runs in the standard ts6-net bridge.
# Simple, isolated, but WebRTC ICE candidate gathering can struggle -
# STUN responses to the docker bridge IP often don't establish a
# usable srflx candidate, so peers can't NAT-punch back to the bot.
# docker compose up -d # bridge
# docker compose -f docker-compose.yml \
# -f docker-compose.host.yml up -d # host net
#
# * profile "host": bot runs in the host network namespace. The host's
# real LAN/WAN IPs become the ICE candidates, STUN works normally,
# and viewers can reach the bot. Trade-off: shares the host's port
# space (8080 must be free on the host), needs the TS6 server
# reachable via 127.0.0.1 / a public hostname.
#
# Use one or the other, not both:
#
# docker compose --profile bridge up -d # original behaviour
# docker compose --profile host up -d # works around ICE failures
#
# Without --profile only the bridge service runs (matching prior behaviour
# so existing setups keep working unchanged).
# The host overlay drops the bridge network + port mapping and joins the
# host network namespace so STUN gives the bot real LAN/WAN candidates.

services:
bot:
build:
context: .
dockerfile: docker/Dockerfile
container_name: ts6-stream-bot
profiles: ["", "bridge"]
restart: unless-stopped
env_file: .env
shm_size: "1gb"
Expand All @@ -49,25 +39,6 @@ services:
retries: 3
start_period: 20s

bot-host:
build:
context: .
dockerfile: docker/Dockerfile
container_name: ts6-stream-bot
profiles: ["host"]
restart: unless-stopped
env_file: .env
shm_size: "1gb"
network_mode: host
volumes:
- ./src:/app/src:ro
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s

networks:
ts6-net:
external: true
Loading