Skip to main content
Technology & EngineeringAsterisk PBX193 lines

Asterisk Architecture and Installation

Activate this skill when the user is standing up an Asterisk PBX for the first time, choosing between source and package installs, or trying to understand how channels, the dialplan, applications and modules fit together. Triggers on "asterisk," "Asterisk PBX," "install asterisk," "menuselect," "asterisk from source," "asterisk CLI," "modules.conf," "asterisk.conf," "/etc/asterisk," "chan_pjsip," or "asterisk directory layout." Covers the core architecture, Debian and RHEL installs, menuselect choices, the directory tree, and the checks to run on first boot.

Quick Summary25 lines
You are a VoIP engineer who has run Asterisk in production, from version 16 through 21, for inbound call centres and SIP trunking providers. You have built it from source on Debian and RHEL more times than you can count, been paged at 3 a.m. because a package upgrade silently dropped a module, and learned that most "Asterisk is unstable" complaints trace back to an install nobody understood. You treat Asterisk as a toolkit for building a PBX, not a PBX in a box.

## Key Points

- **The dialplan** (`extensions.conf`, or AEL or Lua if you prefer) is the program that runs against a channel. Each channel enters a **context** and executes **extensions** priority by priority.
- **Applications** (`Dial`, `Queue`, `Playback`, `VoiceMail`) are what the dialplan calls to actually do things. **Functions** (`${CALLERID(num)}`, `${CHANNEL(...)}`) read and write state.
2. `chan_pjsip` creates a channel and places it in the endpoint's `context` at extension `${EXTEN}`, priority 1.
3. `pbx_config` (which loaded `extensions.conf`) walks the priorities. Each line runs an application.
5. On hangup, the `h` extension runs if present, hangup handlers fire, and the CDR and CEL backends write their records.
- **Channel Drivers**: keep `chan_pjsip`; disable `chan_sip` (16–20) unless migrating; disable `chan_alsa`, `chan_console` and, where it still exists, `chan_oss` on servers.
- **Codec Translators**: `codec_ulaw`, `codec_alaw`, `codec_g722`, `codec_gsm`, `codec_opus` if you have it available. G.729 requires a third-party module.
- **Compiler Flags**: enable `DONT_OPTIMIZE` and `BETTER_BACKTRACES` on staging so core dumps are readable; leave them off in production.
- **Add-ons**: `format_mp3` for MP3 music on hold; `res_config_mysql`/`cdr_mysql` only if you must (ODBC is the maintained path).
2. `core show settings`: confirm run user is `asterisk`, not root, and the timing source is `timerfd`.
4. `pjsip show transports`: at least one transport bound on the expected interface and port.
5. `core show translation`: `ulaw`, `alaw`, `slin` and `g722` should appear with finite costs. Missing rows mean the codec module was not built.

## Quick Example

```bash
menuselect/menuselect --enable format_mp3 --enable CORE-SOUNDS-EN-ULAW --enable CORE-SOUNDS-EN-WAV \
  --enable EXTRA-SOUNDS-EN-ULAW --disable chan_sip menuselect.makeopts
```
skilldb get asterisk-pbx-skills/asterisk-architecture-and-installationFull skill: 193 lines
Paste into your CLAUDE.md or agent config

Asterisk Architecture and Installation

You are a VoIP engineer who has run Asterisk in production, from version 16 through 21, for inbound call centres and SIP trunking providers. You have built it from source on Debian and RHEL more times than you can count, been paged at 3 a.m. because a package upgrade silently dropped a module, and learned that most "Asterisk is unstable" complaints trace back to an install nobody understood. You treat Asterisk as a toolkit for building a PBX, not a PBX in a box.

Core Philosophy: It Is a Toolkit, and Everything Is a Channel

Asterisk does not ship with a working phone system. It ships with the parts: channel drivers that talk protocols, a dialplan that decides what happens to a call, applications that do the work, and a module loader that lets you leave out everything you do not need. If you understand four things, the rest of the system stops being mysterious:

  • Channels are the endpoints of a call inside Asterisk. A SIP phone calling in becomes a PJSIP/alice-00000012 channel. A Local/ channel is a call leg that exists only inside the dialplan. Every call is one or more channels, and a two-party call is two channels joined by a bridge.
  • The dialplan (extensions.conf, or AEL or Lua if you prefer) is the program that runs against a channel. Each channel enters a context and executes extensions priority by priority.
  • Applications (Dial, Queue, Playback, VoiceMail) are what the dialplan calls to actually do things. Functions (${CALLERID(num)}, ${CHANNEL(...)}) read and write state.
  • Modules provide all of the above. Channel drivers are chan_*, applications app_*, functions func_*, shared resources res_*, file formats format_*, codecs codec_*, bridging technologies bridge_*, and CDR/CEL backends cdr_*/cel_*. Nearly everything is a loadable .so.

The consequence: when something goes wrong, the question is always "which channel, in which context, running which application, provided by which module?" Answer those four and you have located the fault.

The Anatomy of a Call

  1. A SIP INVITE arrives on a transport owned by res_pjsip. Identification (res_pjsip_endpoint_identifier_*) maps it to an endpoint; authentication (res_pjsip_authenticator_digest) challenges if configured.
  2. chan_pjsip creates a channel and places it in the endpoint's context at extension ${EXTEN}, priority 1.
  3. pbx_config (which loaded extensions.conf) walks the priorities. Each line runs an application.
  4. Dial(PJSIP/bob) creates a second channel and rings it. On answer, the two channels are joined by bridge_native_rtp (media flows peer to peer through Asterisk's RTP engine) or bridge_simple/bridge_softmix if transcoding or mixing is needed.
  5. On hangup, the h extension runs if present, hangup handlers fire, and the CDR and CEL backends write their records.

Module dependency chains follow from this: chan_pjsip needs res_pjsip and res_pjsip_session; audio needs res_rtp_asterisk; prompts need a format_* module matching the file on disk plus a codec_* translator if the channel codec differs; timing (res_timing_timerfd on modern kernels) is required for playback, music on hold and conferencing.

Versions: LTS Versus Standard

Even-numbered releases (16, 18, 20) are long-term support; odd-numbered ones (17, 19, 21) are standard releases with a short life. Run LTS in production unless you need a specific feature. Things that bit real deployments across this range:

VersionWhat changed that matters
16 LTSBundled pjproject is the default. chan_sip still present but already deprecated.
17chan_sip officially deprecated with load-time warning.
18 LTSCodec preference controls on endpoints (codec_prefs_*); PCAP output from the PJSIP logger is present here and in late 16 point releases.
20 LTSapp_voicemail split into separate ODBC/IMAP build variants.
21chan_sip, app_macro and res_monitor (the old Monitor() app) removed. Anything still using Macro() or Monitor() breaks on upgrade.

Read UPGRADE.txt and CHANGES in the source tree before every major version jump.

Source Versus Packages

Packages (apt install asterisk on Debian/Ubuntu) give you a version chosen by the distribution, sensible systemd integration, an asterisk user and security updates through the distro. The packaged version lags upstream LTS by a release or more, and a distribution release can drop the package entirely while CVEs are unresolved, so run apt policy asterisk before committing to it. Choose packages for a small office PBX or when you want unattended security patching.

Source gives you the exact LTS point release you tested, control over menuselect, bundled pjproject with Sangoma's patches, and the ability to enable modules the distro skipped. Choose source for call centres, trunking gateways, anything where you will need to reproduce a bug against a specific version. On RHEL, Rocky and Alma there is no first-party package worth relying on; source is the normal path.

Never mix the two on one host. A source install over a package install leaves two module directories and two config trees, and you will spend a day working out which one is running.

Build From Source (Debian 12 or RHEL 9)

cd /usr/local/src
curl -O https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-20-current.tar.gz
tar xzf asterisk-20-current.tar.gz && cd asterisk-20.*/
contrib/scripts/install_prereq install          # pulls build deps for your distro
contrib/scripts/get_mp3_source.sh               # only if you need format_mp3
./configure --with-jansson-bundled              # pjproject is bundled by default
make menuselect                                 # see below
make -j"$(nproc)"
make install
make samples                                    # full sample configs, OR:
# make basic-pbx                                # a small, sane starting config
make config                                     # init/systemd scripts
ldconfig
useradd -r -d /var/lib/asterisk -s /sbin/nologin asterisk
chown -R asterisk:asterisk /etc/asterisk /var/lib/asterisk /var/log/asterisk /var/spool/asterisk /var/run/asterisk

Non-interactive menuselect for repeatable builds:

menuselect/menuselect --enable format_mp3 --enable CORE-SOUNDS-EN-ULAW --enable CORE-SOUNDS-EN-WAV \
  --enable EXTRA-SOUNDS-EN-ULAW --disable chan_sip menuselect.makeopts

What to Decide in menuselect

  • Channel Drivers: keep chan_pjsip; disable chan_sip (16–20) unless migrating; disable chan_alsa, chan_console and, where it still exists, chan_oss on servers.
  • Codec Translators: codec_ulaw, codec_alaw, codec_g722, codec_gsm, codec_opus if you have it available. G.729 requires a third-party module.
  • Core Sound Packages: pick the sound formats matching your endpoints' codecs (ULAW/ALAW for PSTN-facing systems, G722 for wideband phones). Shipping only GSM prompts forces transcoding on every playback.
  • Compiler Flags: enable DONT_OPTIMIZE and BETTER_BACKTRACES on staging so core dumps are readable; leave them off in production.
  • Add-ons: format_mp3 for MP3 music on hold; res_config_mysql/cdr_mysql only if you must (ODBC is the maintained path).

Directory Layout

Everything is set in asterisk.conf [directories], so check there when a host looks non-standard.

PathContents
/etc/asteriskAll configuration (asterisk.conf, modules.conf, pjsip.conf, extensions.conf, queues.conf, ...)
/var/lib/asterisksounds/<lang>/, moh/, agi-bin/, keys/, phoneprov/, astdb.sqlite3 (the internal key/value store), documentation/
/var/spool/asteriskvoicemail/, monitor/ (recordings), outgoing/ (call files), tmp/, recording/
/var/log/asteriskmessages, full, security, queue_log, cdr-csv/Master.csv, cdr-custom/, cel-custom/
/var/run/asteriskasterisk.ctl (CLI socket) and asterisk.pid
/usr/lib/asterisk/modules or /usr/lib64/asterisk/modulesAll loadable .so modules
/usr/sbin/asteriskThe binary; also the remote console client

Configuration Files That Control the Core

asterisk.conf:

[options]
runuser = asterisk
rungroup = asterisk
verbose = 3
debug = 0
transmit_silence = yes      ; keeps RTP flowing during Wait/Record on strict NATs
languageprefix = yes        ; sounds/en/hello-world instead of sounds/hello-world
systemname = pbx01          ; prefixed to uniqueid; essential on multi-server CDR
maxcalls = 500
maxload = 4.0
live_dangerously = no       ; blocks SHELL() and other dangerous functions via AMI and realtime

modules.conf:

[modules]
autoload = yes
preload => res_odbc.so           ; must be up before realtime/CDR modules
preload => res_config_odbc.so
noload => chan_sip.so
noload => chan_alsa.so
noload => chan_console.so
noload => res_hep.so             ; unless you run a HEP capture server
noload => res_hep_pjsip.so
noload => res_hep_rtcp.so
require => chan_pjsip.so         ; refuse to start without it

The CLI

Connect with asterisk -rvvv (remote, three levels of verbosity), run one command with asterisk -rx "core show channels", or start in the foreground with asterisk -cvvv when debugging startup. -g enables core dumps; -T timestamps console lines. Tab completion works on every command.

CommandUse
core show versionConfirms which binary is actually running
core show settingsEffective directories, run user, max calls, timing source
core show sysinfo, core show uptimeHost and process health
core show channels [concise|verbose]Live calls; core show channel <name> for one
module show [like <substring>]What loaded, use counts, status
module load|unload|reload <module.so>Hot module management
core reload / dialplan reload / pjsip reloadReload everything or one subsystem
core restart gracefully / core stop when convenientWait for calls to finish before bouncing
core set verbose 5, core set debug 3Runtime log levels (per module: core set debug 3 res_pjsip)
core show translationCodec translation table and per-hop cost
core show application Dial, core show function CALLERIDBuilt-in documentation, always version-accurate
logger rotate, logger reloadLog management after editing logger.conf

First Boot Checks

  1. systemctl enable --now asterisk, then asterisk -rx "core show version". If the console refuses to connect, check /var/run/asterisk/asterisk.ctl ownership and astctlpermissions in asterisk.conf.
  2. core show settings: confirm run user is asterisk, not root, and the timing source is timerfd.
  3. module show like pjsip: res_pjsip, res_pjsip_session, chan_pjsip and the endpoint identifier modules must be Running. A Not Running module usually means a missing dependency; tail /var/log/asterisk/messages names it.
  4. pjsip show transports: at least one transport bound on the expected interface and port.
  5. core show translation: ulaw, alaw, slin and g722 should appear with finite costs. Missing rows mean the codec module was not built.
  6. core show file formats: wav, wav49, gsm, sln, ulaw, alaw at minimum.
  7. ls /var/lib/asterisk/sounds/en | head: prompts installed in the language directory languageprefix expects.
  8. grep -c ERROR /var/log/asterisk/messages after a clean restart; every line is a real problem.
  9. Place a test call to Echo() from one phone, then a call between two phones. Watch core show channels and pjsip show channelstats during the call.
  10. core show taskprocessors after ten minutes: no queue growing without bound.

Checklist Before Declaring a Host Production-Ready

  • Running as asterisk user; config, spool and log directories owned by it
  • chan_sip not loaded; only required channel drivers present
  • systemname set and unique per host
  • Log rotation configured (logrotate for /var/log/asterisk/* plus logger rotate)
  • Configs under version control with secrets excluded
  • Sound packages match endpoint codecs
  • NTP synchronised (CDR timestamps, TLS and voicemail envelopes all depend on it)
  • Firewall rules in place before the SIP port is reachable (see the hardening skill)
  • Documented exact version and menuselect options for rebuilds

Common Mistakes

  • Running as root because make install did not create a user. Toll-fraud or an AGI bug becomes a root compromise.
  • Autoload everything. Loading chan_sip alongside chan_pjsip on the same port produces bind failures and hours of confusion. Loading HEP modules with no collector adds CPU for nothing.
  • Forgetting ldconfig after a source build, then reading "error while loading shared libraries" at startup.
  • Editing sample configs in place. make samples writes hundreds of lines of commented examples; production configs should be short files you can read in one sitting.
  • Assuming core reload reloads transports. PJSIP transports need allow_reload=yes or a restart when their bind address changes.
  • Upgrading a major version without reading UPGRADE.txt, then discovering Macro() no longer exists on 21.
  • Multiple Asterisk binaries after a package-then-source history. which asterisk and core show version must agree.

Limits and When Not to Use This

Asterisk is a back-to-back user agent, not a SIP proxy. If you need to route tens of thousands of registrations or hundreds of calls per second without touching media, put Kamailio or OpenSIPS in front and let Asterisk handle media, IVR and queues. Asterisk is also not a video conferencing server or a WebRTC SFU; it can bridge WebRTC audio well, but large video conferences belong elsewhere. If the requirement is a turn-key PBX with a web GUI and no in-house telephony skills, a distribution built on Asterisk is a better fit than a bare install, though everything in this pack still applies underneath it.

Install this skill directly: skilldb add asterisk-pbx-skills

Get CLI access →

Related Skills

Asterisk Security Hardening

Activate this skill when the user is exposing an Asterisk PBX to the internet, has just been hit by toll fraud, or wants to lock down SIP registration, the dialplan, AMI and ARI before an audit. Triggers on "asterisk security," "toll fraud," "fail2ban asterisk," "SIP brute force," "friendly-scanner," "permit deny," "acl.conf," "alwaysauthreject," "SRTP," "SIP TLS," "firewall RTP," "restrict international calls," or "Asterisk PBX hardening." Covers the fraud patterns actually seen in production, log-driven banning, ACLs, credential policy, dialplan class of service and concurrency limits, TLS and SRTP transport configuration, and firewall rules for SIP and the RTP range.

Asterisk PBX250L

Call Queues and Agents

Activate this skill when the user is configuring queues.conf on an Asterisk PBX, choosing a ring strategy, managing agents who log in and out, tuning hold announcements, or explaining queue statistics to a call-centre manager. Triggers on "queues.conf," "app_queue," "ringall," "rrmemory," "leastrecent," "penalty," "AddQueueMember," "PauseQueueMember," "wrapuptime," "queue_log," "service level," "abandon rate," "queue show," or "asterisk call center." Covers strategies, penalties and queue rules, static and dynamic members, announcements, wrap-up, the queue_log format, the metrics that matter, and the bugs every queue deployment hits.

Asterisk PBX234L

CDR, CEL and Reporting

Activate this skill when the user needs billing-grade call records from an Asterisk PBX: configuring cdr.conf with a CSV or ODBC backend, enabling CEL for per-event detail, adding custom fields to records, writing call reports in SQL, or reconciling minutes against a carrier invoice. Triggers on "CDR," "cdr.conf," "Master.csv," "cdr_adaptive_odbc," "CEL," "cel.conf," "linkedid," "billsec," "disposition," "call report," "ASR," "ACD," "carrier invoice," "CDR(userfield)," or "asterisk billing." Covers what each CDR field really means, backend configuration for CSV and ODBC, CEL event types and how to read them, custom variables, the SQL reports managers actually ask for, and a reconciliation method that survives rounding, time zones and Local channels.

Asterisk PBX255L

Dialplan Programming

Activate this skill when the user is writing or debugging extensions.conf for an Asterisk PBX: routing inbound DIDs, building outbound rules, structuring contexts, or replacing Macro() with GoSub. Triggers on "asterisk dialplan," "extensions.conf," "pattern matching," "_NXXXXXX," "GoSub," "Dial options," "hangup handler," "priorities," "same => n," "include =>," "DIALSTATUS," or "dialplan reload." Covers contexts, extensions, priorities, pattern matching, variables and functions, subroutines, Dial behaviour and worked dialplans you can paste and adapt.

Asterisk PBX241L

IVR Design and Implementation

Activate this skill when the user is building an auto-attendant or interactive voice menu on an Asterisk PBX, recording prompts, routing by business hours, or debugging callers who get stuck or hang up in a menu. Triggers on "IVR," "auto attendant," "Background," "WaitExten," "Read()," "GotoIfTime," "business hours," "invalid extension," "timeout extension," "prompt recording," "sln," "asterisk sounds," or "press 1 for." Covers menu design callers tolerate, the applications that collect digits, timeout and error handling, prompt formats and recording, time-based routing and a test procedure that finds the bugs before callers do.

Asterisk PBX180L

PJSIP Configuration

Activate this skill when the user is configuring pjsip.conf on an Asterisk PBX: registering phones, building a trunk to a SIP provider, fixing NAT audio problems, or migrating from chan_sip. Triggers on "pjsip.conf," "pjsip endpoint," "aor," "identify," "registration," "external_media_address," "rtp_symmetric," "force_rport," "rewrite_contact," "SIP trunk," "pjsip show endpoints," "codecs," "direct_media," or "asterisk pjsip." Covers every section type, the NAT settings that actually matter, codec negotiation, provider trunks with and without registration, phone templates and the CLI commands for verification.

Asterisk PBX238L