This guide is intentionally narrow: it focuses on DVRTC's current failure modes instead of generic Docker or operating system setup.
Run these first before chasing a specific symptom:
# Check service state
./scripts/compose.sh --scenario pbx1 ps
# Validate .env and certificate prerequisites
./scripts/validate_env.sh
# Look at logs for the failing service
./scripts/compose.sh --scenario pbx1 logs kamailio
./scripts/compose.sh --scenario pbx1 logs asterisk
./scripts/compose.sh --scenario pbx1 logs db
./scripts/compose.sh --scenario pbx1 logs nginx
./scripts/compose.sh --scenario pbx1 logs coturn
# Run the baseline smoke test
./scripts/testing-smoke.shKeep these repo-specific behaviors in mind while reading service state and logs:
testingandattackerare behind thetestingprofile, so they do not appear indocker compose psunless you run them explicitly or start the profile.testingis host-networked and uses127.0.0.1for host-local checks;attackeris bridge-networked and usesPUBLIC_IPV4for remote-vantage checks.certbotis not useful unlessDOMAINandEMAILare set. For normal lab use, self-signed certificates from./scripts/init-selfsigned.share the expected path.- plain
docker compose up -dis not enough to start DVRTC because the base file atcompose/base.ymldoes not include a runtime scenario by itself; use./scripts/compose.sh --scenario pbx1 ...or./scripts/compose.sh --scenario pbx2 ... - the examples below use
pbx1service names; when you are troubleshootingpbx2, swap in--scenario pbx2and the corresponding service names such asopensips,freeswitch,rtpproxy, andnginx-pbx2
DVRTC expects three setup steps before starting a scenario:
./scripts/setup_networking.sh
./scripts/generate_passwords.sh
./scripts/init-selfsigned.sh
./scripts/validate_env.sh
./scripts/compose.sh --scenario pbx1 up -d./scripts/validate_env.sh checks the current repo assumptions:
.envexistsPUBLIC_IPV4is set to a real IPv4 addressMYSQL_ROOT_PASSWORDandSIPCALLER1_PASSWORDwere generated- TLS material exists in
data/certs/ PUBLIC_IPV6, if set, is a raw IPv6 literal without bracketsMYSQL_PORT, if set, is a valid TCP port
Rerun it after destructive resets or .env edits so you catch setup drift immediately.
Symptoms usually look like this:
- SIP registration works inconsistently or fails outright
- no audio or one-way audio
- RTP bleed or TURN exercises fail even though containers are up
Fix the addressing first:
./scripts/setup_networking.sh
./scripts/validate_env.sh
grep '^PUBLIC_IPV' .envRules that matter for this repo:
PUBLIC_IPV4must not be a loopback address (127.x.x.x),0.0.0.0, orlocalhostPUBLIC_IPV6is optional, but if set it must be a raw IPv6 literal such as2001:db8::1- do not use brackets in
.env - do not use
::1or link-localfe80::addresses
Kamailio, Nginx, coturn, the conferencing1 frontend, and the one-off conferencing1-attacker-console HTTPS server all expect TLS material under data/certs/.
For normal lab use:
./scripts/init-selfsigned.shFor public-domain TLS:
# Set DOMAIN and EMAIL in .env first
./scripts/init-letsencrypt.shIf TLS or WSS is failing and you are using self-signed certificates, verify the files exist:
ls -la data/certs/The main services to care about are:
dbasteriskrtpenginekamailionginxcoturn
Start with:
./scripts/compose.sh --scenario pbx1 ps
./scripts/compose.sh --scenario pbx1 logs db
./scripts/compose.sh --scenario pbx1 logs asterisk
./scripts/compose.sh --scenario pbx1 logs rtpengine
./scripts/compose.sh --scenario pbx1 logs kamailio
./scripts/compose.sh --scenario pbx1 logs nginx
./scripts/compose.sh --scenario pbx1 logs coturnCommon current causes:
- setup was incomplete and a required environment variable is empty
data/certs/is missing- another service on the host is already using SIP, HTTP, HTTPS, TURN, or MySQL ports
PUBLIC_IPV4points to the wrong host address
Use the service name directly:
./scripts/compose.sh --scenario pbx1 logs kamailio
./scripts/compose.sh --scenario pbx1 logs asterisk
./scripts/compose.sh --scenario pbx1 logs rtpengine
./scripts/compose.sh --scenario pbx1 logs db
./scripts/compose.sh --scenario pbx1 logs nginx
./scripts/compose.sh --scenario pbx1 logs coturnCurrent repo-specific checks:
db: verifyMYSQL_ROOT_PASSWORDexists in.envasterisk: verifySIPCALLER1_PASSWORDexists in.envkamailio: verify both the database and certificates are availablenginx: verifydata/certs/fullchain.pem,data/certs/privkey.pem, anddata/certs/ssl-dhparams.pemexistcoturn: verify certificates exist andPUBLIC_IPV4is correct
DVRTC relies on host networking for the core RTC services. If you already have SIP, TURN, HTTP, HTTPS, or MySQL services running on the host, DVRTC may fail to bind. This also means DVRTC scenarios cannot run at the same time on the same host: they may reuse overlapping host ports and RTP ranges.
The most important ports are:
5060UDP/TCP for SIP (Kamailio)5061TCP for SIP/TLS (Kamailio)5090TCP for SIP (Asterisk, Kamailio routes to this)8000TCP for WS8443TCP for WSS inpbx1/pbx2, and for the one-offconferencing1-attacker-consoleHTTPS server when launched3478UDP/TCP for TURN/STUN80and443TCP for Nginx inpbx1/pbx2or the conferencing frontend inconferencing123306TCP for MySQL by default10000-15000UDP for Asterisk RTP35000-40000UDP for rtpengine8088and8188TCP for theconferencing1Janus APIs, bound to localhost on the DVRTC host40001-45000UDP forconferencing1Janus RTP
Quick checks:
sudo lsof -nP -i :5060
sudo lsof -nP -i :5061
sudo lsof -nP -i :3478
sudo lsof -nP -i :80
sudo lsof -nP -i :443
sudo lsof -nP -i :8443
sudo lsof -nP -i :23306
sudo lsof -nP -i :8088
sudo lsof -nP -i :8188Use the repo's transport checks instead of guessing:
./scripts/compose.sh --scenario pbx1 run --rm testing dvrtc-checks sip-transport --host 127.0.0.1
./scripts/compose.sh --scenario pbx1 run --rm testing dvrtc-checks wss-register --host 127.0.0.1wss-register applies to pbx1. When troubleshooting pbx2, use ./scripts/compose.sh --scenario pbx2 run --rm testing dvrtc-checks sip-transport --scenario pbx2 --host 127.0.0.1 instead because pbx2 does not expose a browser/WebRTC WSS endpoint.
If only TLS or WSS is failing, check certificates first:
ls -la data/certs/
./scripts/compose.sh --scenario pbx1 logs kamailio
./scripts/compose.sh --scenario pbx1 logs nginxIf the stack is reachable on IPv4 but not IPv6, re-check PUBLIC_IPV6 in .env. When you browse or test an IPv6 HTTP endpoint, use brackets in the URL, for example http://[2001:db8::1]/.
Check the advertised address from .env first:
grep '^PUBLIC_IPV4=' .env
. ./.env
curl "http://${PUBLIC_IPV4}/"
./scripts/compose.sh --scenario pbx1 logs nginxPlatform note:
- on a native Linux Docker host,
curl http://127.0.0.1/is also a useful local-bind check - on macOS with Colima or any other Linux VM workflow, prefer the bridged
PUBLIC_IPV4from.envfor host-side checks because it matches the VM's real advertised service identity - on current Colima releases,
127.0.0.1on macOS may also reach forwarded services, but that is a convenience path rather than the canonical address for the stack - if you specifically want to test loopback inside a Colima VM, run
colima ssh -- curl http://127.0.0.1/
For HTTPS with self-signed certificates:
curl -k "https://${PUBLIC_IPV4}/"If the advertised-address check fails, the problem is usually firewalling, a wrong PUBLIC_IPV4, or testing the wrong network namespace.
Start it as a one-off attacker container and publish TCP 8443:
./scripts/compose.sh --scenario conferencing1 run --rm \
-p 8443:8443 \
attacker conferencing1-attacker-consoleThe console should print the HTTPS URL to open from the user's computer. If the browser cannot connect:
- verify the command is still running
- verify TCP
8443is open on the host firewall or cloud security group - verify no other service is already using
8443 - if self-signed certificates are in use, accept the browser certificate warning
The attacker console is only the static operator UI. Its normal signaling target is the conferencing frontend WebSocket proxy at /janus/<secret>, not a public Janus WSS listener.
For DVRTC, the usual causes are:
PUBLIC_IPV4is wrong- RTP UDP ranges are blocked
- the host platform does not support the required host-networking model
- the call generators are not active, so there is no RTP traffic to inspect
Check the current state:
grep '^PUBLIC_IPV' .env
./scripts/compose.sh --scenario pbx1 logs asterisk
./scripts/compose.sh --scenario pbx1 logs rtpengine
./scripts/compose.sh --scenario pbx1 logs baresip-callgen
./scripts/compose.sh --scenario pbx1 logs baresip-callgen-b
./scripts/compose.sh --scenario pbx1 logs baresip-callgen-c
./scripts/compose.sh --scenario pbx1 run --rm testing dvrtc-checks callgen-active --host 127.0.0.1
./scripts/compose.sh --scenario pbx1 run --rm testing dvrtc-checks rtp-bleed --host 127.0.0.1If SIP works but media does not, fix addressing and UDP reachability before changing service configs.
The current TURN-specific check is:
./scripts/compose.sh --scenario pbx1 logs coturn
. ./.env
./scripts/compose.sh --scenario pbx1 run --rm attacker turn-probe tcp-http-get --host "$PUBLIC_IPV4" --username user --password joshua --peer 127.0.0.1 --path /secret/If you want the broader remote-vantage suite after the TURN probe passes, run ./scripts/attacker-run-all.sh.
Verify these repo assumptions:
- coturn is listening on
3478 - the weak credential pair is
user/joshua PUBLIC_IPV4is reachable from the attacking client
If the problem only appears after rebuilding images locally, use the maintainer workflow in development.md.
The most common mistake is forgetting --profile testing when building testing or attacker. The platform: linux/amd64 constraint is set on the scenario runtime services, so no DOCKER_DEFAULT_PLATFORM env var is needed when the base and scenario compose files are used together.
If you want to restart the services without deleting state:
docker compose --project-directory . -p dvrtc-pbx1 -f compose/base.yml -f compose/pbx1.yml down
./scripts/compose.sh --scenario pbx1 up -dIf you want a clean reset and are willing to delete voicemail, MySQL state, and generated web artifacts:
docker compose --project-directory . -p dvrtc-pbx1 -f compose/base.yml -f compose/pbx1.yml down -v
./scripts/setup_networking.sh
./scripts/generate_passwords.sh
./scripts/init-selfsigned.sh
./scripts/validate_env.sh
./scripts/compose.sh --scenario pbx1 up -dUse the destructive reset only when you are explicitly okay with losing lab state.
DVRTC's core services use host networking. The supported path is a Linux Docker host.
- direct Docker Desktop deployment on macOS or Windows is not supported
- on macOS, use the Colima workflow in colima-setup.md or run DVRTC inside a Linux VM
- if you are rebuilding images locally on Apple Silicon, keep the
linux/amd64requirement from development.md in mind
When you report a problem, include the commands that answer these questions:
./scripts/compose.sh --scenario pbx1 ps
./scripts/validate_env.sh
./scripts/compose.sh --scenario pbx1 logs kamailio
./scripts/compose.sh --scenario pbx1 logs asterisk
./scripts/compose.sh --scenario pbx1 logs db
./scripts/compose.sh --scenario pbx1 logs nginx
./scripts/compose.sh --scenario pbx1 logs coturn
./scripts/testing-smoke.shThat output is usually enough to distinguish setup, port-binding, certificate, signaling, and RTP problems in the current repo.