steep-balloon-41261
02/24/2026, 7:28 AMtall-airline-16756
02/24/2026, 7:28 AMtall-airline-16756
02/24/2026, 7:29 AMrtc.external_ip (or the equivalent external_ip) to your server's public IP or public DNS name. Also ensure bind.ip is appropriate (for Docker usually 0.0.0.0).
◦ Mount that config into the container when starting so LiveKit skips auto-discovery.
1. Verify outbound DNS/network from inside the container
◦ Run:
▪︎ docker exec -it <container> nslookup ident.me
▪︎ docker exec -it <container> curl -s https://ident.me
◦ If these time out or fail, the container cannot reach the public endpoint used to discover the external IP.
1. Try host networking (quick test)
◦ Start the container with --network=host to see if sharing the host network allows external IP discovery to succeed. If this fixes it, it indicates a Docker network isolation/DNS issue.
1. Check Docker DNS / network mode
◦ If you use a custom Docker network, ensure it allows outbound internet access and has working DNS. You may need to set Docker's DNS or use a network mode that has access.
1. Firewall / NAT / outbound rules
◦ Ensure the host/container can make outbound HTTP(s) requests and STUN requests (if used). Firewalls blocking outbound requests or DNS will cause the timeout.
1. Confirm ports for runtime (so WebRTC will work once server starts)
◦ Ensure host firewall allows inbound WebRTC-related ports (and any TURN ports you use). Common ranges: signaling ports and UDP media port range (e.g., 50000–60000).
Quick troubleshooting checklist
1. Collect logs: docker logs <container> — share any extra lines around the error.
2. Test network from container (nslookup / curl above) and paste results.
3. Share how you start the container (docker run command or docker-compose.yml) so I can check for networking options or misconfiguration.
4. If you set external_ip and still see errors, paste your config.yaml (redact secrets) and the container start command.
If you prefer, paste:
• The docker run or docker-compose snippet you use to start LiveKit, and
• The relevant part of your config.yaml (or tell me whether you’re relying on environment variables)
I’ll guide you step-by-step based on those details.
Sources: Firewall Tips for LiveKit Connectivity | LiveKit | Running LiveKit on AWS | Running LiveKit on AWSsilly-teacher-46683
02/24/2026, 7:31 AMcaddy-1 | {"level":"error","ts":1771918171.5952556,"logger":"layer4","msg":"handling connection","remote":"139.59.9.105:33818","error":"dial tcp [::1]:7880: connect: connection refused"}tall-airline-16756
02/24/2026, 7:31 AM[::1]:7880 but the connection is being refused. That means either LiveKit isn't running/listening on that address/port, or Caddy is pointing to the wrong host/interface.
To diagnose and fix it, please do the following and share the results (I’ll guide you through next steps after each result):
1) Confirm container status and ports
• Run:
◦ docker-compose ps
◦ docker ps --filter name=livekit -a
• Paste the output so I can see whether the LiveKit container is up and its exposed ports.
2) Check LiveKit logs
• Run:
◦ docker-compose logs livekit --tail=200
• Share any errors around startup (especially anything referencing binding, external_ip, or port 7880).
3) Verify LiveKit is listening inside the Compose network
• Exec into the host or a container and try to connect:
◦ From host: curl -v http://127.0.0.1:7880
◦ From Caddy container (preferred): docker exec -it <caddy-container-name> curl -v http://127.0.0.1:7880 and docker exec -it <caddy-container-name> curl -v http//[1]7880
• Share what succeeds or fails. If 127.0.0.1 works but ::1 fails, it's an IPv6 vs IPv4 binding issue.
4) Share your docker-compose.yml (or at least the caddy and livekit service sections) and the LiveKit config
• I need to confirm:
◦ How Caddy is configured to proxy (is it pointing to localhost:7880, 127.0.0.1:7880, or [::1]:7880?)
◦ Whether LiveKit is bound to 0.0.0.0 or only to 127.0.0.1 or IPv4/IPv6.
• Redact any secrets, then paste the relevant snippets.
Common fixes you can try now
• If LiveKit is binding to IPv4 only, update Caddy upstream to use 127.0.0.1:7880 (IPv4) instead of [::1]:7880.
• Ensure LiveKit bind config uses 0.0.0.0 so it listens on all interfaces (both IPv4 and IPv6 if supported).
• If using Docker service names, have Caddy proxy to the livekit service name (e.g., `http://livekit:7880`) rather than localhost — this is usually more reliable in Compose networks.
• Restart both services after config changes: docker-compose up -d caddy livekit
If you share the outputs from steps 1–3 and the compose/config snippets, I’ll point out the exact change to make.silly-teacher-46683
02/24/2026, 7:32 AMNAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
livekit-caddy-1 livekit/caddyl4 "/bin/caddy run --co…" caddy 2 minutes ago Up 2 minutes
livekit-egress-1 livekit/egress:latest "/entrypoint.sh" egress 2 minutes ago Up 2 minutes
livekit-ingress-1 livekit/ingress:latest "ingress" ingress 2 minutes ago Up 33 seconds
livekit-livekit-1 livekit/livekit-server:latest "/livekit-server --c…" livekit 2 minutes ago Up 33 seconds
livekit-redis-1 redis:7-alpine "docker-entrypoint.s…" redis 2 minutes ago Up 2 minutes
livekit-sip-1 livekit/sip:latest "livekit-sip --confi…" sip 2 minutes ago Up 33 seconds
Again
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
livekit-caddy-1 livekit/caddyl4 "/bin/caddy run --co…" caddy 3 minutes ago Up 3 minutes
livekit-egress-1 livekit/egress:latest "/entrypoint.sh" egress 3 minutes ago Up 3 minutes
livekit-ingress-1 livekit/ingress:latest "ingress" ingress 3 minutes ago Up 12 seconds
livekit-livekit-1 livekit/livekit-server:latest "/livekit-server --c…" livekit 3 minutes ago Up 11 seconds
livekit-redis-1 redis:7-alpine "docker-entrypoint.s…" redis 3 minutes ago Up 3 minutes
livekit-sip-1 livekit/sip:latest "livekit-sip --confi…" sip 3 minutes ago Up 12 secondstall-airline-16756
02/24/2026, 7:32 AM[::1]:7880 (or localhost:7880) with 127.0.0.1:7880 or the Compose service name <http://livekit:7880>.
◦ Using the service name (`http://livekit:7880`) is preferred in Compose because it resolves to the livekit container on the shared network.
• Ensure LiveKit binds to all interfaces:
◦ Configure LiveKit to bind to 0.0.0.0 (in config or env) so it accepts connections from other containers. If LiveKit is only bound to 127.0.0.1 inside its container, other containers can’t reach it via the service name.
• Alternative quick test: from host, try curl:
◦ curl -v http://127.0.0.1:7880
If this succeeds but IPv6 fails, it’s an IPv6 vs IPv4 binding mismatch.
Why this happens
• Caddy is attempting IPv6 ([::1]) and the LiveKit process likely isn’t listening on IPv6 loopback. Docker Compose networking and container binding differences cause this common mismatch.
If you paste the outputs from the three checks above (livekit logs + two curl attempts from Caddy + relevant docker-compose / Caddyfile snippets), I’ll tell you the exact line(s) to change and provide the minimal config edits and commands to restart.silly-teacher-46683
02/24/2026, 7:33 AMroot@demo-livekit-ubuntu-s-2vcpu-4gb-120gb-intel-blr1-01:/opt/livekit# docker-compose logs livekit --tail=200
livekit-1 | could not validate RTC config: could not resolve external IP: context deadline exceeded
livekit-1 | could not validate RTC config: could not resolve external IP: context deadline exceeded
livekit-1 | could not validate RTC config: could not resolve external IP: context deadline exceeded
livekit-1 | could not validate RTC config: could not resolve external IP: context deadline exceeded
livekit-1 | could not validate RTC config: could not resolve external IP: context deadline exceededtall-airline-16756
02/24/2026, 7:33 AM[::1]:7880 while LiveKit never successfully completed startup and likely isn't listening where Caddy expects.
Next steps — please run these checks and share the results so I can give exact fixes
1) Confirm LiveKit’s listening interfaces from inside the livekit container
• docker exec -it livekit-livekit-1 /bin/sh -c "ss -ltnp || ss -ltn"
• docker exec -it livekit-livekit-1 /bin/sh -c "ss -lunp || ss -lun"
Share the output so I can see which IPs/ports LiveKit is bound to (IPv4 vs IPv6, TCP 7880 and UDP media ports).
2) Test external IP discovery / outbound network from the livekit container
• docker exec -it livekit-livekit-1 /bin/sh -c "curl -v https://ident.me || true"
• docker exec -it livekit-livekit-1 /bin/sh -c "nslookup ident.me || true"
If those time out or fail, LiveKit cannot reach the public endpoint used for automatic external IP discovery — which explains the timeout error.
3) Test connectivity from the Caddy container to the LiveKit target addresses
• docker exec -it livekit-caddy-1 /bin/sh -c "curl -v http://127.0.0.1:7880 || true"
• docker exec -it livekit-caddy-1 /bin/sh -c "curl -v http//[1]7880 || true"
• docker exec -it livekit-caddy-1 /bin/sh -c "curl -v http://livekit:7880 || true"
These will tell us whether Caddy can reach LiveKit via IPv4 loopback, IPv6 loopback, or the Compose service name.
4) Share these config snippets (redact secrets)
• The livekit service block from docker-compose.yml (ports, networks, environment)
• The caddy service block and the Caddyfile (or caddy config) showing the upstream address it proxies to
• Your LiveKit config.yaml (rtc.bind/ip or any external_ip settings) if you have one
Common fixes I’ll recommend based on what we find
• If curl/nslookup fail inside the livekit container: set rtc.external_ip manually in config.yaml to your public IP or domain and mount that into the container. This bypasses auto-discovery.
• If the livekit process binds only to IPv4 (127.0.0.1) and Caddy is trying IPv6 ([::1]): change Caddy upstream to 127.0.0.1:7880 or use the Compose service name <http://livekit:7880>.
• If LiveKit is bound only to 127.0.0.1 inside its container, change LiveKit bind config to 0.0.0.0 so other containers can reach it via the service name.
• If outbound connections are blocked, enable outbound DNS/HTTP access or use host networking temporarily to allow external IP discovery.
If you run the commands above and paste the outputs, I’ll tell you the exact lines to change and provide the minimal config and docker-compose edits plus the commands to restart safely.silly-teacher-46683
02/24/2026, 7:40 AM# This docker-compose requires host networking, which is only available on Linux
# This compose will not function correctly on Mac or Windows
services:
caddy:
image: livekit/caddyl4
command: run --config /etc/caddy.yaml --adapter yaml
restart: unless-stopped
network_mode: "host"
volumes:
- ./caddy.yaml:/etc/caddy.yaml
- ./caddy_data:/data
livekit:
image: livekit/livekit-server:latest
command: --config /etc/livekit.yaml
restart: unless-stopped
network_mode: "host"
volumes:
- ./livekit.yaml:/etc/livekit.yaml
redis:
image: redis:7-alpine
command: redis-server /etc/redis.conf
restart: unless-stopped
network_mode: "host"
volumes:
- ./redis.conf:/etc/redis.conf
egress:
image: livekit/egress:latest
restart: unless-stopped
environment:
- EGRESS_CONFIG_FILE=/etc/egress.yaml
network_mode: "host"
volumes:
- ./egress.yaml:/etc/egress.yaml
cap_add:
- CAP_SYS_ADMIN
ingress:
image: livekit/ingress:latest
restart: unless-stopped
environment:
- INGRESS_CONFIG_FILE=/etc/ingress.yaml
network_mode: "host"
volumes:
- ./ingress.yaml:/etc/ingress.yaml
sip:
image: livekit/sip:latest
command: --config /etc/sip.yaml
restart: unless-stopped
volumes:
- ./sip.yaml:/etc/sip.yaml
depends_on:
- livekit
- redis
network_mode: "host"
Here is the livekit.yaml file
port: 7880
bind_addresses:
- ""
rtc:
tcp_port: 7881
port_range_start: 50000
port_range_end: 60000
use_external_ip: true
enable_loopback_candidate: false
redis:
address: localhost:6379
username: ""
password: ""
db: 0
use_tls: false
sentinel_master_name: ""
sentinel_username: ""
sentinel_password: ""
sentinel_addresses: []
cluster_addresses: []
max_redirects: null
turn:
enabled: true
domain: demo-livekit-turn.axlai.work
tls_port: 5349
udp_port: 3478
external_tls: true
ingress:
rtmp_base_url: <rtmp://demo-livekit.axlai.work:1935/x>
whip_base_url: <https://demo-livekit-whip.axlai.work/w>
keys:tall-airline-16756
02/24/2026, 7:40 AMrtc.external_ip, and set bind_addresses to the host interface you want LiveKit to bind to. Example additions:
◦ rtc:
external_ip: "YOUR_PUBLIC_IP_OR_DNS"
• bind_addresses:
◦ "0.0.0.0"
• This bypasses LiveKit’s automatic external-IP discovery and avoids the timeout.
2) Ensure LiveKit binds on all interfaces
• You already have:
bind_addresses:
• ""
That can be ambiguous. Replace the empty string with 0.0.0.0 to ensure it binds to IPv4 on the host. If you need IPv6 as well, add the host’s IPv6 address or ensure the host supports IPv6 binding.
Example livekit.yaml changes (minimal)
• Replace:
bind_addresses:
• ""
• With:
bind_addresses:
• "0.0.0.0"
• And add under rtc:
external_ip: "203.0.113.45" # replace with your public IP or DNS
3) Restart LiveKit (and then Caddy)
• After updating livekit.yaml, restart the services:
◦ docker-compose up -d livekit
◦ docker-compose logs livekit --tail=100
• Confirm LiveKit starts without the external IP timeout message.
4) Fix Caddy’s upstream if IPv6 mismatch persists
• Because you use host networking, Caddy runs on the host and should be able to reach LiveKit via localhost. Make sure Caddy is proxying to 127.0.0.1:7880 or your public IP rather than [::1]:7880.
• If your Caddyfile (or caddy.yaml) references localhost:7880, change it to 127.0.0.1:7880 or <http://127.0.0.1:7880>. Using explicit IPv4 prevents Caddy from resolving to IPv6 loopback when LiveKit isn’t listening there.
5) Verify connectivity after changes
• From the host:
◦ curl -v http://127.0.0.1:7880
• From logs:
◦ docker-compose logs livekit --tail=200
◦ docker-compose logs caddy --tail=200
• If curl returns a response and LiveKit logs no longer show the external IP timeout, Caddy should stop reporting connection refused.
If the external IP discovery still fails (network blocked)
• If the livekit container cannot make outbound https/DNS requests (e.g., firewall, outbound rules), automatic discovery will still fail. Setting rtc.external_ip fixes this.
• You can also test outbound connectivity from the livekit container:
◦ docker exec -it livekit-livekit-1 /bin/sh -c "curl -v https://ident.me || true"
◦ If that fails, automatic discovery is blocked and the explicit external_ip is required.
If you want, I can:
• Tell you the exact lines to add to your livekit.yaml (paste the public IP or DNS you want to use).
• Review your caddy.yaml and update the upstream address to 127.0.0.1:7880 (paste the caddy snippet and I’ll edit it).
Next step from you
• Paste the public IP or public DNS you want LiveKit to use (or tell me you prefer to use the host’s IP and I’ll show the exact file snippet), and paste the relevant Caddy upstream block if you want me to suggest the exact replacement. Sources: Support data sovereignty in India | LiveKit | How We Built a Globally Distributed WebRTC Mesh Network | Firewall Tips for LiveKit Connectivity | LiveKit | Running LiveKit on AWS | Running LiveKit on AWS