Installation¶
Note
AI Context
This page documents how to self-host the full VoIPBin platform on your
own server using Docker Compose, via the official installer at
https://github.com/voipbin/voipbin (the install/ directory). It is
intended for operators running their own VoIPBin instance, not for
customers of the hosted service at https://voipbin.net.
VoIPBin is an opensource CPaaS platform. The complete stack, including the SIP edge (Kamailio, RTPEngine), the Asterisk media layer, all backend microservices, the database, the message bus, and the admin/talk/meet frontends, runs as a single Docker Compose project on one server.
This section walks through what you need, the four commands that perform the install, the two install modes (a local/LAN evaluation domain or your own real domain), what configuration the installer generates, and the day-to-day CLI used for backup, restore, and upgrades.
Overview¶
The installer is a Docker Compose stack driven by four shell scripts and,
after install, the voipbin interactive CLI. It runs the complete
VoIPBin platform, roughly 50 containers, on a single server.
What gets deployed¶
32 of VoIPBin’s 33 backend Go microservices (
bin-sentinel-managerneeds a Kubernetes API and stays out of this Compose-based install).SIP/media stack: Kamailio (SIP proxy), RTPEngine (RTP media relay), three Asterisk instances (call, registrar, conference) each with an AMI/ARI proxy sidecar.
Supporting infrastructure: MySQL, Redis, RabbitMQ, PostgreSQL (pgvector, for
rag-manager), ClickHouse (timeline-manager), CoreDNS (internal mode only).Three frontend web applications: Admin Console, Talk (agent messenger), Meet (voice conferencing).
Install modes¶
The installer runs in one of two modes, chosen at init time and
recorded in .env as DOMAIN_MODE. Mode is an init-time decision:
extension SIP realms embed the base domain in the database, so init.sh
refuses to switch mode or domain on an existing install.
Internal mode (default) |
External mode |
|
|---|---|---|
Base domain |
|
Your real domain (for example |
DNS |
Automatic. CoreDNS container plus |
Operator-managed A records at your DNS provider |
TLS |
Automatic. mkcert (browser-trusted) or self-signed |
Bring your own certificate |
Reachable from |
This machine and your LAN |
Any host that can route to your IPs |
Best for |
Local development, demos, evaluation |
A production or shared install under a real domain |
Use internal mode unless you specifically need the install reachable under a real domain from machines you do not control. Internal mode requires nothing from you (no domain, no certificate, no DNS provider). External mode targets directly-routable hosts (on-prem, corporate LAN with internal DNS, cloud environments with multiple routable IPs); single-public-IP NAT environments are a documented limitation.
The four-command install¶
The recommended path isolates the one step that needs root:
git clone https://github.com/voipbin/voipbin.git
cd voipbin/install
./scripts/init.sh --yes # 1. Generate .env, certificates, docker-compose.yml
sudo ./scripts/setup-host.sh # 2. The single sudo command (host mutations)
./scripts/start.sh # 3. Start all services
./scripts/check-install.sh # 4. Self-verify the install
setup-host.sh owns every host mutation: mkcert package and CA trust
(internal mode only), CoreDNS setup (internal mode only), the Compose
default Docker network, and the VoIP network interfaces (internal veth
pairs, plus external macvlan for pinned hosting-provider IPs). It is
idempotent; each step probes current state and skips what is already done.
Once installed, sudo ./voipbin is the interactive CLI for day-to-day
operations: status, logs, restart, debug shells, backup/restore, and
version upgrades. See the Install section for the full command reference.
Prerequisites¶
Local tools¶
Install these on the server that will run the stack. The preflight step
in init.sh verifies Docker is present.
Tool |
Min. version |
Notes |
|---|---|---|
Docker Engine |
n/a |
Required. |
Docker Compose |
2.24.4+ |
v2 CLI plugin. The test override file uses
|
mkcert |
n/a |
Recommended (internal mode). Falls back to self-signed certificates if absent. |
No host Python, alembic, or MySQL client is required: database migrations
run inside a container (scripts/migrate.sh, python:3.11-slim on
the Compose network).
Installing prerequisites¶
Ubuntu/Debian:
sudo apt update && sudo apt install -y docker.io docker-compose-v2
sudo usermod -aG docker $USER && newgrp docker
sudo apt install -y mkcert
mkcert -install
macOS:
brew install --cask docker
brew install mkcert
mkcert -install
mkcert -install adds a local Certificate Authority to your system
trust store, so browsers trust the certificates the installer generates
for *.voipbin.test without a warning.
System requirements¶
OS: Linux (Ubuntu/Debian tested) or macOS.
Disk space:
doctor.shenforces a hard minimum of 3 GiB free and warns under 15 GiB. Budget more over time for call recordings and database growth.CPU/RAM: not automatically checked. The stack is roughly 50 containers: 32 backend Go microservices, the SIP/media stack (Kamailio, RTPEngine, 3x Asterisk plus their AMI/ARI proxy sidecars), supporting infrastructure (MySQL, Redis, RabbitMQ, PostgreSQL, ClickHouse, CoreDNS), and 3 frontend apps. A laptop-class multi-core machine with a few GB of RAM headroom works for development; a single-vCPU, 1 GB VM will not keep up.
Networking (external mode only): a directly-routable host with distinct IPs for the host, Kamailio, and RTPEngine. See the Install section’s External mode instructions below.
Credentials generated at install time¶
init.sh generates fresh, random credentials for this install; nothing
is shipped as a shared default.
Service |
Credentials |
|---|---|
MySQL |
Randomly generated per install, in |
RabbitMQ |
Randomly generated per install, in |
JWT signing key |
Auto-generated in |
Admin account and extensions (opt-in) |
|
Before exposing an install beyond localhost, review the TLS mode, the
firewall and network exposure of the ports this stack opens, and confirm
VOIPBIN_SANDBOX_DEV_SEED is unset or false.
Install¶
The recommended path is the four-command flow, then day-to-day operation
through the voipbin CLI.
git clone https://github.com/voipbin/voipbin.git
cd voipbin/install
./scripts/init.sh --yes # 1. Generate .env, certificates, docker-compose.yml
sudo ./scripts/setup-host.sh # 2. The single sudo command (host mutations)
./scripts/start.sh # 3. Start all services
./scripts/check-install.sh # 4. Self-verify the install
init.sh (generate configuration)¶
Generates .env, TLS certificates, and copies docker-compose.yml
from the committed docker-compose.yml.dist. After this first copy,
docker-compose.yml is untracked and operator-owned: a later
git pull in this repo updates docker-compose.yml.dist but never
touches your live file. The same split applies to versions.lock /
versions.lock.dist.
./scripts/init.sh --yes
# external mode (real domain, bring-your-own certificate)
./scripts/init.sh --mode external --domain example.com --tls byo \
--cert fullchain.pem --key privkey.pem --yes
setup-host.sh (the single sudo command)¶
Owns every host mutation: mkcert package and CA trust (internal mode only), CoreDNS setup (internal mode only), the Compose default Docker network, and the VoIP network interfaces. Idempotent; safe to rerun.
sudo ./scripts/setup-host.sh
start.sh (bring the stack up)¶
Starts infrastructure, runs database migrations inside a container, and starts all services.
./scripts/start.sh
check-install.sh (self-verify)¶
Verifies service counts, DNS resolution, API liveness, and (external mode) the TLS chain strictly, without skipping validation.
./scripts/check-install.sh
If anything fails at any of the four steps, run ./scripts/doctor.sh: a
read-only diagnostic that works at any stage and prints the exact recovery
command for every failure. See the Troubleshooting section below.
Once installed, sudo ./voipbin is the interactive CLI for day-to-day
operations.
sudo ./voipbin
voipbin> status
voipbin> logs -f api-manager
Or run single commands directly: sudo ./voipbin status.
Command categories:
Category |
Examples |
|---|---|
Service control |
|
Debug shells |
|
Extension management |
|
Infrastructure |
|
Resource management |
|
Maintenance |
|
See the Environment variables and maintenance section below for the full maintenance command reference (backup, restore, upgrade).
External mode (real domain)¶
External mode runs the install under a real domain with a real certificate. The installer never touches DNS or the trust store in this mode; you own both.
Step 1: create DNS records¶
Record |
Type |
Target |
Purpose |
|---|---|---|---|
|
A |
Host IP |
REST API + WebSocket (:8443) |
|
A |
Host IP |
Web UIs (:3003/:3004/:3005) |
|
A |
Kamailio external IP |
SIP signaling / WSS (:5060/:5066) |
|
A |
Kamailio external IP |
SIP surfaces |
|
A |
Kamailio external IP |
Apex registrar name, not covered by the wildcard below |
|
A |
Kamailio external IP |
Per-customer SIP realm resolution |
Host IP and Kamailio IP are two distinct addresses on the same subnet.
Step 2: obtain a certificate¶
The certificate must cover api., sip., sip-service.,
conference., trunk., and registrar. of your domain; a wildcard
covers all six. A wildcard requires the DNS-01 challenge:
certbot certonly --preferred-challenges dns --manual \
-d example.com -d '*.example.com' -d '*.registrar.example.com'
Step 3: initialize¶
./scripts/init.sh --mode external --domain example.com --tls byo \
--cert /etc/letsencrypt/live/example.com/fullchain.pem \
--key /etc/letsencrypt/live/example.com/privkey.pem \
--yes
The certificate is validated (key match, SAN coverage, expiry) before
.env is written; a bad certificate aborts cleanly.
Step 4: host setup, start, and verify¶
sudo ./scripts/setup-host.sh
./scripts/start.sh
./scripts/check-install.sh
Certificate renewal¶
install-certs.sh is idempotent and usable as a certbot deploy hook:
certbot renew --deploy-hook \
'/path/to/install/scripts/install-certs.sh /etc/letsencrypt/live/example.com/fullchain.pem /etc/letsencrypt/live/example.com/privkey.pem'
Warning
By default, the admin/meet/talk web UIs are plain HTTP on
ports 3003 to 3005 in both modes. On a routable domain this means
credentials travel in the clear. Front them with a TLS-terminating
reverse proxy, restrict those ports to trusted networks, or use the
built-in --web-reverse-proxy flag described next.
Web reverse proxy (port-less URLs)¶
init.sh --web-reverse-proxy (external mode with --tls byo only)
runs a Caddy container that terminates TLS with your certificate and
routes api/admin/meet/talk.<domain> by Host header, so
https://admin.example.com works with no port suffix:
./scripts/init.sh --mode external --domain example.com --tls byo \
--cert fullchain.pem --key privkey.pem \
--web-reverse-proxy --yes
sudo ./scripts/setup-host.sh
./scripts/start.sh
./scripts/check-install.sh
The certificate must additionally cover admin, meet, and talk
(a wildcard already does). Once enabled, admin/meet/talk’s
published ports become loopback-only; Caddy’s 80/443 is the only
externally-reachable path to them.
First login and API access¶
A completed install has a running stack, but no way to sign in yet unless you opted in to the dev-seed account. This section covers how to create a real admin account and start calling the API.
Warning
The admin@localhost account and extensions 1000, 2000,
and 3000 (three specific extensions, not a range) only exist when
the stack was started with VOIPBIN_SANDBOX_DEV_SEED=true. Leave
this flag unset or false on any install reachable beyond
localhost; see the credentials table in Prerequisites.
If your first login attempt fails outright (curl connection errors, browser certificate warnings), confirm TLS trust first: see Troubleshooting’s DNS/certificate checks and, for internal mode, the mkcert CA trust step in Prerequisites. A first-login failure is very often a certificate problem, not an auth problem.
Two ways to create your first account¶
Path A: CLI bootstrap (recommended for a fresh self-hosted install). Works immediately, no email provider required.
Path B: email-based signup, the same flow the hosted service at
voipbin.net uses (POST /auth/signup). This only works if you have
already configured an email provider (SENDGRID_API_KEY or
MAILGUN_API_KEY, see Provider configuration) so the verification
email can actually be delivered. Without one, the signup call succeeds
but the verification email never arrives. Use this path only if you have
already set up email delivery; otherwise use Path A.
Path A: CLI bootstrap¶
Create a customer and an admin agent directly via the manager CLIs, then set the agent’s password explicitly (a fresh admin agent is created with a random, unusable password):
# 1. Create the customer
docker exec voipbin-customer-mgr /app/bin/customer-control customer create \
--name "My Company" \
--email "admin@example.com"
# 2. Get the customer ID
CUSTOMER_ID=$(docker exec voipbin-customer-mgr /app/bin/customer-control customer list 2>/dev/null \
| jq -r '.[] | select(.email == "admin@example.com") | .id')
# 3. Wait a few seconds for agent-manager to process the event via RabbitMQ
sleep 5
# 4. Get the auto-created admin agent's ID
AGENT_ID=$(docker exec voipbin-agent-mgr /app/bin/agent-control agent list \
--customer-id "$CUSTOMER_ID" 2>/dev/null | jq -r '.[0].id')
# 5. Set a real password
docker exec voipbin-agent-mgr /app/bin/agent-control agent update-password \
--id "$AGENT_ID" \
--password "your-secure-password"
Get a JWT token¶
curl -sk -X POST https://api.voipbin.test:8443/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "admin@example.com", "password": "your-secure-password"}'
# Response: {"username": "...", "token": "JWT_TOKEN_HERE"}
Create an API key (accesskey)¶
An accesskey is a long-lived API token, separate from the short-lived JWT above, meant for scripts and integrations:
docker exec voipbin-customer-mgr /app/bin/customer-control accesskey create \
--customer-id "$CUSTOMER_ID" \
--name "API Key" \
--detail "For automation" \
--expire 87600h
--expire 87600h is roughly 10 years, a practically non-expiring key
for automation use. Use a shorter value for keys you intend to rotate.
Create your first extension¶
TOKEN="<jwt_token_from_above>"
curl -sk -X POST https://api.voipbin.test:8443/v1.0/extensions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"extension": "2000", "password": "your-secure-password-here", "name": "Extension 2000"}'
Path B: email-based signup¶
Once an email provider is configured (see Provider configuration), the
hosted-service signup flow works identically for a self-hosted install:
POST /auth/signup against your own api.<domain> endpoint instead
of api.voipbin.net. See the Quickstart guide’s Signup page for the
full request/response shape and troubleshooting; the mechanics are
identical, only the base URL differs.
Provider configuration¶
All third-party providers are optional. Until a provider’s keys are set,
the corresponding flow actions return a “provider not configured” error;
the rest of the platform stays healthy. This page lists every provider
env var in .env, what it enables, and which service to restart after
setting it. All facts below are verified directly against this
installer’s own docker-compose.yml.dist (the Docker Compose
self-hosting stack); a Kubernetes/hosted-service deployment wires some
of these variables differently and is out of scope for this page.
AI voice agent providers¶
Capability |
Providers |
Env var(s) |
|---|---|---|
LLM / conversation (batch, e.g. audit evaluation) |
OpenAI |
|
LLM / conversation (real-time voice pipeline) |
OpenAI, Google Gemini, xAI |
|
Speech-to-text |
Deepgram, AWS Transcribe, Google Cloud Speech-to-Text |
|
Text-to-speech |
ElevenLabs, Cartesia, AWS Polly, Google Cloud TTS |
|
GOOGLE_API_KEY and GOOGLE_APPLICATION_CREDENTIALS are two
unrelated variables that happen to share the “Google” prefix. Do not
confuse them:
GOOGLE_API_KEYis a Gemini API key. It is consumed by two independent features:ai-manager’s batch audit evaluation (mapped internally to a ChatGPT-compatible engine key,ENGINE_KEY_CHATGPT=${OPENAI_API_KEY}, does not actually useGOOGLE_API_KEYfor this) andpipecat-manager’s real-time voice pipeline (the sidecar that actually readsGOOGLE_API_KEYdirectly for live Gemini conversations). Restartpipecat-managerafter changing it for the voice-pipeline use.GOOGLE_APPLICATION_CREDENTIALSis a GCP service-account JSON key file path. It is mounted into five services in this installer’s Docker Compose stack:api-manager,rag-manager,storage-manager,transcribe-manager, andtts-manager.storage-managertreats a missing value as fatal for signed download/upload URLs;tts-managerfalls back to AWS Polly if unset.pipecat-managerdoes not consume this variable in the Docker Compose stack (it only usesGOOGLE_API_KEY, above) – restartingpipecat-managerfor aGOOGLE_APPLICATION_CREDENTIALSchange has no effect.
XAI_API_KEY has no dedicated feature write-up beyond its
.env.template entry; it is consumed by pipecat-manager’s
real-time voice pipeline as an LLM alternative, not by ai-manager.
After setting an AI provider key, restart the service(s) that actually consume that specific variable, per the tables above:
sudo ./voipbin restart ai-manager # OPENAI_API_KEY (batch)
sudo ./voipbin restart pipecat-manager # OPENAI_API_KEY, GOOGLE_API_KEY, XAI_API_KEY (real-time)
sudo ./voipbin restart transcribe-manager # DEEPGRAM_API_KEY, AWS_*, GOOGLE_APPLICATION_CREDENTIALS
sudo ./voipbin restart tts-manager # ELEVENLABS_API_KEY, CARTESIA_API_KEY, AWS_*, GOOGLE_APPLICATION_CREDENTIALS
sudo ./voipbin restart rag-manager # GOOGLE_APPLICATION_CREDENTIALS
sudo ./voipbin restart storage-manager # GOOGLE_APPLICATION_CREDENTIALS
sudo ./voipbin restart api-manager # GOOGLE_APPLICATION_CREDENTIALS
Telephony and messaging providers¶
Provider |
Env var(s) |
Consuming service |
|---|---|---|
Twilio (PSTN numbers) |
|
|
Telnyx (PSTN numbers and messaging) |
|
|
MessageBird (SMS) |
|
|
The .env.template variable names above are what you set;
number-manager itself binds them internally as TWILIO_TOKEN and
TELNYX_TOKEN (docker-compose.yml.dist maps
TWILIO_TOKEN=${TWILIO_API_KEY} and
TELNYX_TOKEN=${TELNYX_API_KEY}), and message-manager binds
MESSAGEBIRD_API_KEY internally as AUTHTOKEN_MESSAGEBIRD. This
only matters if you go looking for the raw variable name inside
number-manager’s or message-manager’s own config; the .env
names above are what you actually set. MessageBird has no dedicated
feature write-up beyond its .env.template entry.
sudo ./voipbin restart number-manager
sudo ./voipbin restart message-manager
Email providers¶
Provider |
Env var |
Consuming service |
|---|---|---|
SendGrid |
|
|
Mailgun |
|
|
sudo ./voipbin restart email-manager
Configuring at least one of these two is required for the email-based signup flow (Path B in First login and API access) to actually deliver its verification email.
Configuration files¶
The installer writes and manages two operator-owned files in the
install/ working directory.
docker-compose.yml (operator-owned copy of .dist)¶
docker-compose.yml is copied once from the committed
docker-compose.yml.dist the first time init.sh runs, then left
alone: a later git pull in this repo updates docker-compose.yml.dist
but never touches your live docker-compose.yml. This means a repo
update never silently changes a running install’s Compose configuration.
To adopt upstream changes (new services, image digest bumps), diff the two
files and merge deliberately, or run scripts/sync-compose-images.sh
with COMPOSE_FILE=docker-compose.yml to pull in just the image digest
updates from versions.lock.dist.
versions.lock gets the identical treatment for the identical reason:
copied once from versions.lock.dist, then untracked. Deploying a new
image and updating versions.lock.dist are deliberately decoupled; the
live versions.lock is yours to manage on your own schedule.
.env (generated secrets and configuration)¶
init.sh auto-generates .env with detected network settings and
freshly generated credentials (MySQL, RabbitMQ, JWT signing key). See the
Environment variables section below for the full variable reference.
CLI configuration (~/.voipbin-cli.conf)¶
The voipbin CLI stores its own settings separately from .env:
voipbin> config # Show all settings
voipbin> config log_lines 100 # Set log lines to 100
voipbin> config reset # Reset to defaults
Setting |
Default |
Description |
|---|---|---|
|
localhost |
API hostname |
|
8443 |
API port |
|
50 |
Number of log lines to display |
|
True |
Enable colored output |
|
voipbin-ast-call |
Default Asterisk container for the |
Environment variables and maintenance¶
Key .env variables¶
Variable |
Purpose |
|---|---|
|
|
|
The base domain all derived domain values are composed from.
Edit and re-run |
|
|
|
|
|
|
|
Host’s LAN or public IP (auto-detected). |
|
Dedicated external IPs for SIP signaling and RTP media (auto-generated; must differ from the host IP). |
|
SIP domain suffix for extensions. Full realm is
|
|
|
Third-party integrations¶
Voice AI, transcription, TTS, phone number provisioning, and email/SMS
providers are configured through their own keys in .env. See the
Provider configuration section for the full list of variables, which
service to restart after setting each, and the AI-provider-specific
details (shared credentials, multi-service consumers). Until a
provider’s keys are set, the corresponding flow actions return a
“provider not configured” error; the rest of the platform stays healthy.
Maintenance commands (the voipbin CLI)¶
Command |
Description |
|---|---|
|
Show pinned image versions |
|
Update Docker images or scripts. |
|
Dry-run to preview updates |
|
Full data backup (MySQL, call recordings, |
|
Restore data from a backup. Destructive; services must be stopped
except |
|
Roll back image versions from override history (unpinned repos
only). For data recovery use |
|
Cleanup sandbox resources |
Scheduled backups¶
schedule-manager runs a nightly database-backup job (MySQL dump
plus gzip of the two databases, written to backups/scheduled-db/,
retaining the newest 7). start.sh enables it on every run. This is
deliberately separate from the manual voipbin backup command above:
different retention, different directory, so neither one’s pruning
touches the other.
docker exec voipbin-schedule-mgr /app/bin/schedule-control schedule list
docker exec voipbin-schedule-mgr /app/bin/schedule-control schedule disable database-backup
Host-side gaps (operator responsibility)¶
Two tasks stay outside the installer’s automation:
Offsite copy of backups.
backups/is local disk; ship it to remote or object storage on your own recovery-objective schedule (for example anrsynccron job).Host-level maintenance. OS package updates, Docker Engine upgrades, disk space and log rotation, and kernel/security patching are the operator’s responsibility.
Scaling¶
The installer starts every backend service at one replica. Scaling a single-server Compose install means raising the host’s own CPU/RAM and, for the SIP/media layer, the RTPEngine port range and Asterisk channel limits. There is no automated horizontal-scale profile in this installer today; track resource usage and scale the host vertically first.
Operations and troubleshooting¶
Install doctor¶
./scripts/doctor.sh (or sudo ./voipbin doctor) is the read-only
diagnostic superset of check-install.sh. It runs at any stage
(pre-install, mid-install, running stack), never mutates anything, and
auto-skips whatever cannot be probed at the current stage.
Output is one line per check, DOCTOR <name>: pass|fail|warn|skip
<detail>; every failure (and every fixable warning) is immediately
followed by a FIX <name>: <exact command> line:
./scripts/doctor.sh
./scripts/doctor.sh | grep '^FIX ' # extract every recovery command
Exit codes: 0 only when nothing failed (warnings and skips do not
fail the run); 1 when any check failed; 2 when the doctor cannot
even start.
Day-to-day commands¶
# Status and logs
sudo ./voipbin status
sudo ./voipbin logs -f api-manager
# Restart a service (Asterisk call/registrar/conference restarts
# its paired proxy sidecar automatically)
sudo ./voipbin restart api-manager
# Debug shells
sudo ./voipbin ast # Asterisk CLI
sudo ./voipbin kam # Kamailio kamcmd
sudo ./voipbin db # MySQL
# Backup and restore
sudo ./voipbin backup
sudo ./voipbin restore <timestamp> --force
# Tear everything down (irreversible, including the database)
sudo ./voipbin clean --all
Common issues¶
Extensions register but calls fail (AMI/ARI mismatch)¶
AMI_USERNAME/AMI_PASSWORD must stay asterisk/asterisk to
match the static account baked into the Asterisk images’ AMI and ARI
configuration. If these were ever changed, SIP registration keeps working
(that path is pjsip plus realtime MySQL) while call control silently
breaks. Fix by restoring the fixed values in .env and recreating the
three proxy sidecars:
docker compose up -d --force-recreate \
asterisk-call-proxy asterisk-conference-proxy asterisk-registrar-proxy
Extensions created with the wrong domain¶
If extensions register under .voipbin.test instead of
.registrar.voipbin.test, a shell-exported DOMAIN_NAME_EXTENSION
is overriding .env:
env | grep DOMAIN_NAME
unset DOMAIN_NAME_EXTENSION DOMAIN_NAME_TRUNK
docker compose config | grep DOMAIN
docker compose rm -fsv registrar-manager && docker compose up -d registrar-manager
Then delete and recreate the affected extensions via the API.
DNS not resolving *.voipbin.test (internal mode)¶
docker ps | grep voipbin-dns # CoreDNS container running?
dig @127.0.0.1 voipbin.test # CoreDNS answering directly?
dig voipbin.test # system resolver picking it up?
cat /etc/resolv.conf # 127.0.0.1 listed first?
sudo ./scripts/setup-dns.sh # re-run DNS setup
A downed CoreDNS container does not take down all host DNS: a captured
upstream nameserver (from the pre-install resolver, or a hardcoded public
fallback) is written into /etc/resolv.conf alongside 127.0.0.1.
Host IP changed after reboot¶
The installer detects a changed host IP on start.sh and regenerates
.env, the CoreDNS Corefile, and TLS certificates automatically. Force
it manually if needed:
sudo ./scripts/setup-dns.sh --regenerate
If a browser then shows ERR_CERT_AUTHORITY_INVALID, the certificate
was regenerated correctly; do a hard refresh or use a non-incognito
window (incognito does not trust user-installed CAs).
Reset everything¶
sudo ./scripts/clean.sh --volumes --purge
Always use the combined --volumes --purge form. --purge alone
keeps the database volume with the old domain’s data, which is the worst
partial state to be in.
Known limitations¶
Single-public-IP NAT is not supported¶
External mode targets directly-routable hosts (on-prem, corporate LAN with internal DNS, cloud environments with multiple routable IPs). Kamailio runs with host networking and binds its dedicated address directly, so there is no port mapping to remap it behind a single public IP shared with other services. See Overview for the internal-mode versus external-mode comparison; internal mode has no domain, certificate, or routability requirements and works behind any NAT.
Restart the Asterisk service and its proxy sidecar together¶
asterisk-call, asterisk-conference, and asterisk-registrar
each pair with a dedicated -proxy sidecar that bridges AMI/ARI to
the rest of the stack. Recreating one side without the other leaves the
AMI/ARI bridge orphaned: SIP registration can keep working (it goes
through pjsip and realtime MySQL, not the proxy) while call control
silently breaks, reproducing the same symptom as the AMI/ARI credential
mismatch above. sudo ./voipbin restart <service> already restarts a
service and its paired proxy together; avoid running
docker compose restart directly on just one side of the pair.
Getting help¶
If doctor.sh does not resolve the issue, open an issue at
https://github.com/voipbin/voipbin or contact support@voipbin.net with
the full output of ./scripts/doctor.sh.