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.
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 linesAsterisk 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-00000012channel. ALocal/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_*, applicationsapp_*, functionsfunc_*, shared resourcesres_*, file formatsformat_*, codecscodec_*, bridging technologiesbridge_*, and CDR/CEL backendscdr_*/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
- 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. chan_pjsipcreates a channel and places it in the endpoint'scontextat extension${EXTEN}, priority 1.pbx_config(which loadedextensions.conf) walks the priorities. Each line runs an application.Dial(PJSIP/bob)creates a second channel and rings it. On answer, the two channels are joined bybridge_native_rtp(media flows peer to peer through Asterisk's RTP engine) orbridge_simple/bridge_softmixif transcoding or mixing is needed.- On hangup, the
hextension 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:
| Version | What changed that matters |
|---|---|
| 16 LTS | Bundled pjproject is the default. chan_sip still present but already deprecated. |
| 17 | chan_sip officially deprecated with load-time warning. |
| 18 LTS | Codec preference controls on endpoints (codec_prefs_*); PCAP output from the PJSIP logger is present here and in late 16 point releases. |
| 20 LTS | app_voicemail split into separate ODBC/IMAP build variants. |
| 21 | chan_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; disablechan_sip(16–20) unless migrating; disablechan_alsa,chan_consoleand, where it still exists,chan_osson servers. - Codec Translators:
codec_ulaw,codec_alaw,codec_g722,codec_gsm,codec_opusif 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_OPTIMIZEandBETTER_BACKTRACESon staging so core dumps are readable; leave them off in production. - Add-ons:
format_mp3for MP3 music on hold;res_config_mysql/cdr_mysqlonly 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.
| Path | Contents |
|---|---|
/etc/asterisk | All configuration (asterisk.conf, modules.conf, pjsip.conf, extensions.conf, queues.conf, ...) |
/var/lib/asterisk | sounds/<lang>/, moh/, agi-bin/, keys/, phoneprov/, astdb.sqlite3 (the internal key/value store), documentation/ |
/var/spool/asterisk | voicemail/, monitor/ (recordings), outgoing/ (call files), tmp/, recording/ |
/var/log/asterisk | messages, full, security, queue_log, cdr-csv/Master.csv, cdr-custom/, cel-custom/ |
/var/run/asterisk | asterisk.ctl (CLI socket) and asterisk.pid |
/usr/lib/asterisk/modules or /usr/lib64/asterisk/modules | All loadable .so modules |
/usr/sbin/asterisk | The 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.
| Command | Use |
|---|---|
core show version | Confirms which binary is actually running |
core show settings | Effective directories, run user, max calls, timing source |
core show sysinfo, core show uptime | Host 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 reload | Reload everything or one subsystem |
core restart gracefully / core stop when convenient | Wait for calls to finish before bouncing |
core set verbose 5, core set debug 3 | Runtime log levels (per module: core set debug 3 res_pjsip) |
core show translation | Codec translation table and per-hop cost |
core show application Dial, core show function CALLERID | Built-in documentation, always version-accurate |
logger rotate, logger reload | Log management after editing logger.conf |
First Boot Checks
systemctl enable --now asterisk, thenasterisk -rx "core show version". If the console refuses to connect, check/var/run/asterisk/asterisk.ctlownership andastctlpermissionsinasterisk.conf.core show settings: confirm run user isasterisk, not root, and the timing source istimerfd.module show like pjsip:res_pjsip,res_pjsip_session,chan_pjsipand the endpoint identifier modules must be Running. ANot Runningmodule usually means a missing dependency;tail /var/log/asterisk/messagesnames it.pjsip show transports: at least one transport bound on the expected interface and port.core show translation:ulaw,alaw,slinandg722should appear with finite costs. Missing rows mean the codec module was not built.core show file formats:wav,wav49,gsm,sln,ulaw,alawat minimum.ls /var/lib/asterisk/sounds/en | head: prompts installed in the language directorylanguageprefixexpects.grep -c ERROR /var/log/asterisk/messagesafter a clean restart; every line is a real problem.- Place a test call to
Echo()from one phone, then a call between two phones. Watchcore show channelsandpjsip show channelstatsduring the call. core show taskprocessorsafter ten minutes: no queue growing without bound.
Checklist Before Declaring a Host Production-Ready
- Running as
asteriskuser; config, spool and log directories owned by it chan_sipnot loaded; only required channel drivers presentsystemnameset and unique per host- Log rotation configured (
logrotatefor/var/log/asterisk/*pluslogger 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 installdid not create a user. Toll-fraud or an AGI bug becomes a root compromise. - Autoload everything. Loading
chan_sipalongsidechan_pjsipon the same port produces bind failures and hours of confusion. Loading HEP modules with no collector adds CPU for nothing. - Forgetting
ldconfigafter a source build, then reading "error while loading shared libraries" at startup. - Editing sample configs in place.
make sampleswrites hundreds of lines of commented examples; production configs should be short files you can read in one sitting. - Assuming
core reloadreloads transports. PJSIP transports needallow_reload=yesor 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 asteriskandcore show versionmust 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
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.
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.
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.
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.
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.
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.