Asterisk deployment guide

Asterisk configuration for Voice AI, from SIP invite to model audio.

A provider-neutral starting point for inbound and outbound calling. It shows which file owns each decision, how ARI receives the channel, how media reaches an AI service, and what to check before a real caller hears it.

recommended baselineAsterisk 22 LTS

Use a currently supported point release and test the exact modules you deploy.

call controlARI + Stasis

The dialplan hands the live channel to your application.

media bridgeRTP or WebSocket

Choose by Asterisk version and adapter capability.

Know which process owns each part

Asterisk is the telephony edge. It should not contain your prompt, business workflow, or model credentials.

  1. 01SIP carrier

    Sends the inbound INVITE or accepts the outbound dial.

  2. 02Asterisk PJSIP

    Authenticates the trunk and maps the call into a dialplan context.

  3. 03Dialplan

    Answers, sets policy, and calls Stasis(voice-ai).

  4. 04ARI control app

    Creates a mixing bridge and manages call state.

  5. 05Media adapter

    Moves caller audio to the AI runtime and returns generated audio.

  6. 06AI runtime

    Runs STT, LLM, TTS, or a native realtime speech model.

Start with explicit PJSIP objects

A registration, auth object, address of record, endpoint, and identify rule solve different parts of the trunk. Some carriers omit registration or use IP authentication, so keep the provider's requirements beside this template.

The NAT settings advertise the public address outside your private network.direct_media=no keeps Asterisk in the audio path, which is required when your ARI application needs the media. Use carrier-published signaling networks formatch, not a broad internet range.

SIP and NAT/etc/asterisk/pjsip.conf
[transport-udp-nat]
type=transport
protocol=udp
bind=0.0.0.0:5060
local_net=<PRIVATE_CIDR>
external_signaling_address=<PUBLIC_IP>
external_media_address=<PUBLIC_IP>

[carrier-registration]
type=registration
transport=transport-udp-nat
outbound_auth=carrier-auth
server_uri=sip:<SIP_HOST>
client_uri=sip:<ACCOUNT_ID>@<SIP_HOST>
contact_user=voice-ai
retry_interval=60

[carrier-auth]
type=auth
auth_type=userpass
username=<SIP_USERNAME>
password=<SIP_PASSWORD>

[carrier-aor]
type=aor
contact=sip:<SIP_HOST>:5060
qualify_frequency=30

[carrier-endpoint]
type=endpoint
transport=transport-udp-nat
context=from-carrier
disallow=all
allow=ulaw
outbound_auth=carrier-auth
aors=carrier-aor
direct_media=no
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes

[carrier-identify]
type=identify
endpoint=carrier-endpoint
match=<CARRIER_SIGNALING_CIDR>

Hand only the intended calls to ARI

The endpoint context is a security boundary. Keep carrier traffic out of internal extension contexts and keep outbound dialing in its own context.

Inbound and outbound routing/etc/asterisk/extensions.conf
[from-carrier]
exten => voice-ai,1,NoOp(Inbound Voice AI call)
 same => n,Answer()
 same => n,Stasis(voice-ai)
 same => n,Hangup()

[voice-ai-outbound]
exten => _+X.,1,NoOp(Outbound Voice AI call to ${EXTEN})
 same => n,Set(CALLERID(num)=<OWNED_CALLER_ID>)
 same => n,Dial(PJSIP/${EXTEN}@carrier-endpoint,45)
 same => n,Hangup()
provider detailThe inbound extension may be the DID, the registration contact_user, ors. Confirm it from a SIP trace. Do not guess after the first 404.

Keep the control API private

ARI uses Asterisk's HTTP server for REST and WebSocket events. Bind to loopback when the controller is on the same host. Use a private network or VPN plus TLS when it is remote.

HTTP listener/etc/asterisk/http.conf
[general]
enabled=yes
bindaddr=127.0.0.1
bindport=8088
ARI user/etc/asterisk/ari.conf
[general]
enabled=yes
pretty=no

[voice-ai]
type=user
read_only=no
password_format=crypt
password=<CRYPT_PASSWORD_HASH>
Never expose ARI directly to the public internet.

The ARI user can answer, originate, bridge, record, and hang up calls. Store its secret outside source control, restrict the listener, and rotate the credential.

Make the media range boring and observable

Asterisk selects RTP ports from the configured range. Open the same UDP range in the host firewall and upstream NAT, then verify the public address placed in SDP.

RTP port range/etc/asterisk/rtp.conf
[general]
rtpstart=10000
rtpend=20000

The common 10000 to 20000 range is intentionally broad. You may choose a smaller range after sizing concurrency and understanding how many RTP streams each call creates. Signal on 5060 does not carry the audio.

Choose the bridge your application can operate

ARI creates an external-media channel, adds it to the call bridge, and receives or injects audio through the selected transport.

widest compatibility

RTP over UDP

Available since Asterisk 16.6. Your adapter owns RTP packets, timing, codec framing, jitter behavior, and the return address.

ARI requestRTP external media
POST /ari/channels/externalMedia
  ?app=voice-ai
  &external_host=127.0.0.1%3A60000
  &format=ulaw
simpler application media

chan_websocket

Available in Asterisk 20.16+, 21.11+, 22.6+, and 23.0+. It can frame and time most codecs, generate silence, and signal flow control. Opus remains a passthrough case.

ARI requestWebSocket external media
POST /ari/channels/externalMedia
  ?app=voice-ai
  &transport=websocket
  &encapsulation=none
  &external_host=<WEBSOCKET_CLIENT_ID>
  &format=ulaw
codec ruleStart with ulaw when the carrier and model adapter both support it. Every transcode adds work and another place for sample-rate mistakes.

Use Cloudflare for the web control plane, not the PBX process

Cloudflare Workers can serve HTTP APIs and WebSockets, and Durable Objects can coordinate sessions. Asterisk still needs a Linux host that accepts SIP and RTP.

Workers currently create outbound TCP connections but do not accept arbitrary inbound TCP sockets. SIP and RTP also use transport behavior outside a normal Worker request. If you need Cloudflare in front of a TCP or UDP service, Spectrum is the relevant Layer 4 product and custom applications require an Enterprise plan. It proxies traffic to Asterisk; it does not replace Asterisk.

A practical OSS stack is Asterisk on a small regional VM, an ARI and media adapter close to it, and Cloudflare for the public API, dashboard, authentication, configuration, audit events, and deployment automation.

Treat a phone system like an internet-facing payment system

Toll fraud can become expensive before a dashboard notices it. Reduce what can connect, what can dial, and what every credential can do.

  • Allow SIP signaling only from the carrier's published networks when the carrier supports fixed source ranges.
  • Restrict outbound number patterns, destinations, concurrency, call duration, and spend at both Asterisk and carrier layers.
  • Use TLS for SIP signaling and SRTP for media when every hop supports them.
  • Bind ARI and AMI to loopback or a private interface. Use separate credentials and least privilege.
  • Keep passwords and carrier credentials out of Git. Rotate them after any accidental exposure.
  • Alert on registration failures, rejected calls, spend spikes, concurrency spikes, and unfamiliar destinations.
  • Confirm recording consent, retention, data residency, and emergency-calling obligations for every destination.

Prove signaling, routing, control, and media separately

Run the checks before placing a test call. During the call, turn on verbose PJSIP and RTP logging only long enough to isolate the problem.

Read-only checksAsterisk CLI
asterisk -rx "pjsip show registrations"
asterisk -rx "pjsip show endpoints"
asterisk -rx "pjsip show contacts"
asterisk -rx "dialplan show from-carrier"
asterisk -rx "http show status"
asterisk -rx "ari show users"
asterisk -rx "module show like websocket"
401 or 403

Check auth username, realm, From identity, and whether the carrier expects registration or IP authentication.

404 or no route

Inspect the Request-URI and confirm the endpoint context contains the received extension.

488 codec error

Find the codec intersection across carrier, PJSIP endpoint, bridge, and media adapter.

one-way audio

Inspect SDP, public media address, RTP firewall range, and the actual source of inbound media.

call drops near 30 seconds

Look for missing ACK traffic, NAT contact rewriting, and session-timer behavior.

bot hears silence

Confirm the external-media channel is in the mixing bridge and the adapter uses the requested codec and direction.

Configuration claims checked against current project docs

The reusable template comes from Asterisk's own configuration model. Carrier-specific values still belong to the carrier's current trunk guide.

Questions that appear during the first real integration

These are architecture answers. Verify the final number format, authentication, and codec rules with your carrier.

Does Asterisk replace a Voice AI framework?
No. Asterisk terminates SIP calls, routes numbers, and moves media. Your ARI control app and media adapter still connect the call to speech recognition, a language model, speech generation, or a native realtime model.
Should I use RTP or WebSocket external media?
RTP works across older supported releases and many existing media adapters, but your application must handle packet format and timing. chan_websocket removes much of that work on supported point releases. Test codec, framing, flow control, and failure recovery before choosing.
Can Asterisk run inside Cloudflare Workers?
No. Asterisk is a long-running Linux communications server that accepts SIP and RTP traffic. Workers can host HTTP APIs, WebSocket control services, and coordination logic, but the Asterisk process still needs a VM, bare-metal host, or suitable container platform.
Why do calls have audio in only one direction?
The usual causes are an incorrect external media address, an unopened RTP port range, a carrier sending media from an unexpected network, or SDP advertising a private address. Inspect SIP and RTP traces before changing codecs.