Phase 1 installation completed (8/10 tasks): - Ubuntu 24.04, Asterisk 20.18.2 compiled from source - FreePBX 17.0.25 with PJSIP extensions (1001, 1002) - MariaDB 10.11.14, Apache 2.4, PHP 8.3 - nftables firewall and Fail2ban security configured Pending: softphone testing, IVR/queues config, Phase 2 (PSTN trunks) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
27 KiB
VoIP PBX Empresarial — Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Deploy a production-ready Asterisk 20 LTS + FreePBX 17 PBX on a physical Debian 12 server, with internal SIP extensions first (Phase 1) and PSTN connectivity via SIP trunks for Mexico + US later (Phase 2).
Architecture: Two-phase deployment. Phase 1 installs the full PBX stack (Asterisk, FreePBX, MariaDB, Apache, security) for internal-only SIP communication. Phase 2 adds SIP trunk providers (Telnyx recommended) for external calling to Mexico and US phone numbers. All configuration is done via FreePBX web GUI where possible, with manual Asterisk config only where necessary.
Tech Stack: Debian 12, Asterisk 20 LTS, FreePBX 17, MariaDB 10.11+, PHP 8.2, Apache 2.4, Fail2ban, nftables
Design doc: docs/plans/2026-02-15-voip-asterisk-freepbx-design.md
PHASE 1: PBX INTERNO
Task 1: Prepare the OS — Base System
Context: Fresh Debian 12 (Bookworm) installation on bare metal. This task gets the OS ready with all prerequisites before touching any VoIP software. Everything runs as root.
Step 1: Verify Debian 12 is installed and updated
cat /etc/os-release | grep -E "PRETTY_NAME|VERSION_ID"
Expected: Debian GNU/Linux 12 (bookworm) and VERSION_ID="12"
apt update && apt upgrade -y
Expected: System fully updated, no errors.
Step 2: Set hostname and timezone
hostnamectl set-hostname pbx.tudominio.local
timedatectl set-timezone America/Mexico_City
Verify:
hostname -f
timedatectl
Expected: Hostname shows pbx.tudominio.local, timezone shows America/Mexico_City.
Step 3: Configure static IP (if not already done)
Edit /etc/network/interfaces (or use NetworkManager) to assign a static IP on the LAN interface. Example:
auto eth0
iface eth0 inet static
address 192.168.1.10
netmask 255.255.255.0
gateway 192.168.1.1
dns-nameservers 8.8.8.8 1.1.1.1
Then:
systemctl restart networking
ip addr show eth0
Expected: Static IP assigned, connectivity verified with ping 8.8.8.8.
Step 4: Install base dependencies
apt install -y build-essential git curl wget sudo \
linux-headers-$(uname -r) libncurses5-dev libssl-dev \
libxml2-dev libsqlite3-dev uuid-dev libjansson-dev \
libedit-dev pkg-config autoconf libtool automake \
sox mpg123 ffmpeg lame unixodbc unixodbc-dev \
libcurl4-openssl-dev libvorbis-dev libspeex-dev \
libspeexdsp-dev libopus-dev subversion
Verify:
gcc --version && git --version
Expected: Both commands return version info without errors.
Step 5: Commit — checkpoint note
Create a log file to track installation progress:
mkdir -p /root/VOIP/logs
echo "$(date) - Task 1 complete: OS base prepared" >> /root/VOIP/logs/install.log
Task 2: Install MariaDB
Context: FreePBX stores all configuration (extensions, trunks, routes, CDR) in MariaDB. This must be installed and secured before FreePBX.
Step 1: Install MariaDB server
apt install -y mariadb-server mariadb-client
systemctl enable mariadb
systemctl start mariadb
Verify:
systemctl status mariadb
mariadb --version
Expected: Active (running), version 10.11+.
Step 2: Secure MariaDB
mariadb-secure-installation
During the interactive prompts:
- Switch to unix_socket authentication: N (keep current)
- Change root password: Y (set a strong password, save it securely)
- Remove anonymous users: Y
- Disallow root login remotely: Y
- Remove test database: Y
- Reload privilege tables: Y
Verify:
mariadb -u root -p -e "SELECT VERSION();"
Expected: Returns MariaDB version, login works with your password.
Step 3: Create Asterisk databases
mariadb -u root -p -e "
CREATE DATABASE IF NOT EXISTS asterisk CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE DATABASE IF NOT EXISTS asteriskcdrdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'asterisk'@'localhost' IDENTIFIED BY 'CHANGE_THIS_STRONG_PASSWORD';
GRANT ALL PRIVILEGES ON asterisk.* TO 'asterisk'@'localhost';
GRANT ALL PRIVILEGES ON asteriskcdrdb.* TO 'asterisk'@'localhost';
FLUSH PRIVILEGES;
"
Verify:
mariadb -u asterisk -p -e "SHOW DATABASES;"
Expected: Shows asterisk and asteriskcdrdb databases.
Step 4: Log progress
echo "$(date) - Task 2 complete: MariaDB installed and configured" >> /root/VOIP/logs/install.log
Task 3: Install PHP 8.2 and Apache
Context: FreePBX's web GUI runs on Apache with PHP. FreePBX 17 requires PHP 8.2.
Step 1: Install Apache
apt install -y apache2
systemctl enable apache2
systemctl start apache2
Verify:
systemctl status apache2
curl -s -o /dev/null -w "%{http_code}" http://localhost
Expected: Active (running), HTTP 200.
Step 2: Install PHP 8.2 and required modules
apt install -y php8.2 php8.2-cli php8.2-common php8.2-mysql \
php8.2-gd php8.2-mbstring php8.2-intl php8.2-xml \
php8.2-curl php8.2-zip php8.2-bcmath php8.2-soap \
php8.2-ldap libapache2-mod-php8.2
Verify:
php -v
php -m | grep -E "mysql|gd|mbstring|xml|curl"
Expected: PHP 8.2.x, all listed modules present.
Step 3: Configure PHP for FreePBX
Edit /etc/php/8.2/apache2/php.ini:
upload_max_filesize = 120M
post_max_size = 120M
memory_limit = 256M
max_execution_time = 120
max_input_time = 120
max_input_vars = 5000
Also enable the short_open_tag if not already:
short_open_tag = On
Step 4: Enable Apache modules
a2enmod rewrite
a2enmod headers
systemctl restart apache2
Verify:
apache2ctl -M | grep -E "rewrite|headers"
Expected: Both modules listed.
Step 5: Log progress
echo "$(date) - Task 3 complete: Apache + PHP 8.2 installed" >> /root/VOIP/logs/install.log
Task 4: Install Asterisk 20 LTS from Source
Context: Asterisk is the core PBX engine. We compile from source to get the LTS version with all modules we need. This is the longest task.
Important: Asterisk runs as user asterisk, not root.
Step 1: Create asterisk user
adduser --system --group --home /var/lib/asterisk --no-create-home asterisk
usermod -aG audio,dialout asterisk
Verify:
id asterisk
Expected: Shows uid, gid, and groups including audio, dialout.
Step 2: Download Asterisk 20 LTS
cd /usr/src
wget https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-20-current.tar.gz
tar xzf asterisk-20-current.tar.gz
cd asterisk-20.*/
Verify:
ls -la /usr/src/asterisk-20.*/
Expected: Asterisk source tree present.
Step 3: Install prerequisites script
contrib/scripts/install_prereq install
Expected: Script installs any missing dependencies, exits with "install completed successfully".
Step 4: Download MP3 decoder (for music on hold)
contrib/scripts/get_mp3_source.sh
Expected: Downloads mp3 source to addons/mp3/.
Step 5: Configure Asterisk
./configure --libdir=/usr/lib64 --with-pjproject-bundled --with-jansson-bundled
Expected: Configure completes with no errors. Look for configure: Package configured for: linux at the end.
Step 6: Select modules with menuselect
make menuselect.makeopts
menuselect/menuselect \
--enable app_macro \
--enable format_mp3 \
--enable CORE-SOUNDS-EN-WAV \
--enable CORE-SOUNDS-EN-ULAW \
--enable CORE-SOUNDS-ES-WAV \
--enable CORE-SOUNDS-ES-ULAW \
--enable MOH-ORSOUND-WAV \
--enable MOH-ORSOUND-ULAW \
--enable EXTRA-SOUNDS-EN-WAV \
--enable EXTRA-SOUNDS-EN-ULAW \
menuselect.makeopts
Note: We enable Spanish sounds (ES) since the PBX will serve Mexico. app_macro is needed by FreePBX for older dialplan compatibility.
Verify:
menuselect/menuselect --check-deps menuselect.makeopts
Expected: No unmet dependencies.
Step 7: Compile and install
make -j$(nproc)
make install
make samples
make config
make install-logrotate
ldconfig
Expected: Each command completes without errors.
Step 8: Set permissions
chown -R asterisk:asterisk /var/run/asterisk \
/etc/asterisk /var/lib/asterisk \
/var/log/asterisk /var/spool/asterisk \
/usr/lib64/asterisk
chmod -R 750 /var/spool/asterisk
Step 9: Configure Asterisk to run as user asterisk
Edit /etc/default/asterisk:
AST_USER="asterisk"
AST_GROUP="asterisk"
Edit /etc/asterisk/asterisk.conf:
[options]
runuser = asterisk
rungroup = asterisk
Step 10: Start Asterisk and verify
systemctl enable asterisk
systemctl start asterisk
asterisk -rvvv -x "core show version"
Expected: Shows Asterisk 20.x.x version string, running as user asterisk.
Step 11: Log progress
echo "$(date) - Task 4 complete: Asterisk 20 LTS compiled and running" >> /root/VOIP/logs/install.log
Task 5: Install FreePBX 17
Context: FreePBX provides the web-based GUI for managing Asterisk. It handles extensions, trunks, routes, IVR, voicemail, and more. Installed on top of a running Asterisk.
Step 1: Install Node.js (required by FreePBX 17)
curl -fsSL https://deb.nodesource.com/setup_18.x | bash -
apt install -y nodejs
Verify:
node -v && npm -v
Expected: Node 18.x and npm version.
Step 2: Download FreePBX 17
cd /usr/src
wget https://mirror.freepbx.org/modules/packages/freepbx/freepbx-17.0-latest-EDGE.tgz
tar xzf freepbx-17.0-latest-EDGE.tgz
cd freepbx/
Note: Check https://www.freepbx.org/downloads/ for the latest FreePBX 17 URL. The filename may differ.
Step 3: Run FreePBX installer
./install -n --dbuser asterisk --dbpass CHANGE_THIS_STRONG_PASSWORD --webroot /var/www/html
Flags:
-n: Non-interactive--dbuser/--dbpass: MariaDB credentials from Task 2--webroot: Apache document root
Expected: Installer completes with "You have successfully installed FreePBX".
Step 4: Install FreePBX base modules
fwconsole ma installall
fwconsole reload
fwconsole chown
Expected: Modules install without errors, fwconsole reload completes.
Step 5: Configure Apache for FreePBX
cat > /etc/apache2/sites-available/freepbx.conf << 'EOF'
<VirtualHost *:80>
DocumentRoot /var/www/html
ServerName pbx.tudominio.local
<Directory /var/www/html>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
EOF
a2dissite 000-default.conf
a2ensite freepbx.conf
systemctl restart apache2
Step 6: Verify FreePBX web GUI
curl -s -o /dev/null -w "%{http_code}" http://localhost/admin/
Expected: HTTP 200 or 302 (redirect to setup wizard).
Open a browser and navigate to http://<SERVER_IP>/admin/. You should see the FreePBX setup wizard. Create an admin user with a strong password.
Step 7: Enable FreePBX cron and service
fwconsole chown
fwconsole reload
Verify crontab exists:
crontab -u asterisk -l
Expected: Shows FreePBX cron entries.
Step 8: Log progress
echo "$(date) - Task 5 complete: FreePBX 17 installed, web GUI accessible" >> /root/VOIP/logs/install.log
Task 6: Configure Firewall (nftables)
Context: VoIP servers are constant targets for SIP brute-force attacks and toll fraud. A properly configured firewall is mandatory before exposing any ports.
Step 1: Install nftables (if not present)
apt install -y nftables
systemctl enable nftables
Step 2: Create firewall rules
cat > /etc/nftables.conf << 'NFTEOF'
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
# Loopback
iif "lo" accept
# Established connections
ct state established,related accept
# Drop invalid
ct state invalid drop
# ICMP (ping)
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
# SSH (restrict to your admin IP if possible)
tcp dport 22 accept
# HTTP/HTTPS (FreePBX web GUI - restrict to LAN)
tcp dport { 80, 443 } ip saddr 192.168.0.0/16 accept
# SIP signaling (restrict to LAN + trunk provider IPs)
udp dport { 5060, 5061 } ip saddr 192.168.0.0/16 accept
tcp dport { 5060, 5061 } ip saddr 192.168.0.0/16 accept
# RTP media (audio)
udp dport 10000-20000 accept
# IAX2 (optional, only if using IAX trunks)
# udp dport 4569 accept
# Log and drop everything else
log prefix "nftables-drop: " limit rate 5/minute
drop
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
NFTEOF
Step 3: Apply and verify
nft -f /etc/nftables.conf
nft list ruleset
Expected: Rules listed, no errors.
Step 4: Test connectivity
# From the server itself
curl -s -o /dev/null -w "%{http_code}" http://localhost/admin/
# SSH should still work from your admin machine
Expected: HTTP 200, SSH still accessible.
Step 5: Log progress
echo "$(date) - Task 6 complete: nftables firewall configured" >> /root/VOIP/logs/install.log
Task 7: Configure Fail2ban for Asterisk
Context: Fail2ban monitors Asterisk logs for failed SIP authentication attempts and automatically bans offending IPs. Critical for preventing toll fraud.
Step 1: Install Fail2ban
apt install -y fail2ban
systemctl enable fail2ban
Step 2: Configure Asterisk security logging
Edit /etc/asterisk/logger.conf and ensure this line exists under [logfiles]:
[logfiles]
security_log => security
Reload Asterisk logger:
asterisk -rx "logger reload"
Verify:
ls -la /var/log/asterisk/security_log
Expected: File exists (may be empty initially).
Step 3: Create Fail2ban jail for Asterisk
cat > /etc/fail2ban/jail.d/asterisk.conf << 'EOF'
[asterisk]
enabled = true
filter = asterisk
action = nftables-allports[name=asterisk, protocol=all]
logpath = /var/log/asterisk/security_log
maxretry = 3
findtime = 600
bantime = 3600
ignoreip = 127.0.0.1/8 192.168.0.0/16
EOF
This means: 3 failed attempts within 10 minutes = banned for 1 hour. LAN IPs are whitelisted.
Step 4: Start Fail2ban and verify
systemctl restart fail2ban
fail2ban-client status
fail2ban-client status asterisk
Expected: Shows asterisk jail active with 0 currently banned.
Step 5: Log progress
echo "$(date) - Task 7 complete: Fail2ban configured for Asterisk" >> /root/VOIP/logs/install.log
Task 8: Create SIP Extensions in FreePBX
Context: Extensions are the internal "phone numbers" for each user. We use PJSIP (not the deprecated chan_sip). All configuration is done via the FreePBX web GUI.
Step 1: Access FreePBX GUI
Open http://<SERVER_IP>/admin/ in a browser. Log in with the admin credentials created in Task 5.
Step 2: Verify PJSIP is the default driver
Navigate to: Settings > Advanced Settings
Find SIP Channel Driver and ensure it is set to chan_pjsip. This is the default in FreePBX 17.
Step 3: Create test extensions
Navigate to: Applications > Extensions > Add Extension > Add New PJSIP Extension
Create at least 2 extensions for testing:
| Field | Extension 1 | Extension 2 |
|---|---|---|
| User Extension | 1001 | 1002 |
| Display Name | Usuario Prueba 1 | Usuario Prueba 2 |
| Secret | (auto-generated, 16+ chars) | (auto-generated, 16+ chars) |
| Voicemail | Enabled | Enabled |
| VM Password | 1001 | 1002 |
Click Submit after each, then click the red Apply Config button.
Step 4: Verify extensions registered in Asterisk
asterisk -rx "pjsip show endpoints"
Expected: Shows endpoints 1001 and 1002 (status will be "Unavailable" until phones connect).
Step 5: Log progress
echo "$(date) - Task 8 complete: SIP extensions created" >> /root/VOIP/logs/install.log
Task 9: Connect Softphones and Test Internal Calls
Context: We connect two softphones to the PBX and verify that internal calls work end-to-end. This validates the entire Phase 1 stack.
Recommended softphones:
- Desktop: Zoiper5 (free), MicroSIP (free, Windows)
- Mobile: Zoiper, Obrafonos, Obrafonos Groundwire
Step 1: Configure Softphone 1 (extension 1001)
In the softphone, create a new SIP account:
| Setting | Value |
|---|---|
| Username | 1001 |
| Password | (secret from FreePBX) |
| Domain/Server | 192.168.1.10 (server IP) |
| Transport | UDP |
| Port | 5060 |
Step 2: Configure Softphone 2 (extension 1002)
Same settings but with extension 1002 credentials. Use a different device or a second softphone instance.
Step 3: Verify registration
asterisk -rx "pjsip show endpoints" | grep -E "1001|1002"
Expected: Both endpoints show status "Not in use" (meaning registered and idle).
Step 4: Make a test call
From softphone 1001, dial 1002. Softphone 2 should ring. Answer. Verify:
- Audio flows in both directions
- Call quality is good (no choppy audio, no one-way audio)
- Caller ID shows "Usuario Prueba 1 <1001>"
Step 5: Test voicemail
From 1001, dial *981002 (direct voicemail for 1002). Leave a message. Then from 1002, dial *97 to check voicemail. Verify the message plays back.
Step 6: Log progress
echo "$(date) - Task 9 complete: Internal calls working, Phase 1 DONE" >> /root/VOIP/logs/install.log
Task 10: Configure IVR, Queues, and Ring Groups (Optional Enhancements)
Context: These features make the PBX useful for business. All configured via FreePBX web GUI.
Step 1: Create a Ring Group
Navigate to: Applications > Ring Groups > Add Ring Group
| Field | Value |
|---|---|
| Ring Group Number | 600 |
| Group Description | Oficina Principal |
| Extension List | 1001, 1002 |
| Ring Strategy | ringall |
| Ring Time | 20 seconds |
| Destination if no answer | Voicemail (1001) |
Submit and Apply Config.
Step 2: Create an IVR
Navigate to: Applications > IVR > Add IVR
| Field | Value |
|---|---|
| IVR Name | Menu Principal |
| Timeout | 10 seconds |
| Option 1 | Extension 1001 (Ventas) |
| Option 2 | Extension 1002 (Soporte) |
| Option 0 | Ring Group 600 (Operadora) |
| Invalid/Timeout Destination | Ring Group 600 |
Record or upload a greeting audio file in Spanish.
Submit and Apply Config.
Step 3: Create a Call Queue (optional)
Navigate to: Applications > Queues > Add Queue
| Field | Value |
|---|---|
| Queue Number | 400 |
| Queue Name | Soporte |
| Static Agents | 1001, 1002 |
| Ring Strategy | rrmemory (round-robin with memory) |
| Max Wait Time | 300 seconds |
| Music on Hold | default |
Submit and Apply Config.
Step 4: Test
- Dial 600 from any extension — both phones should ring
- Dial the IVR number — menu should play, options should route correctly
- Dial 400 — queue should play hold music and ring agents
Step 5: Log progress
echo "$(date) - Task 10 complete: IVR, Ring Groups, Queues configured" >> /root/VOIP/logs/install.log
PHASE 2: CONEXION PSTN (TRUNK SIP)
Prerequisites: Phase 1 must be fully working. You need an account with your chosen SIP trunk provider and internet access from the PBX server.
Task 11: Contract SIP Trunk Provider
Context: This is a manual/administrative task. You need to sign up with a provider and get your SIP credentials.
Recommended: Telnyx (best balance for MX+US)
Step 1: Create Telnyx account
- Go to https://telnyx.com and sign up
- Complete identity verification
- Add payment method (credit card or prepay)
Step 2: Create a SIP Connection (Credential Auth)
In Telnyx Mission Control portal:
- Navigate to Voice > SIP Connections
- Click Add SIP Connection
- Name:
freepbx-office - Connection type: Credential Authentication
- Username: (save this)
- Password: (save this)
- Note the SIP server address (e.g.,
sip.telnyx.com)
Step 3: Purchase DIDs
- Navigate to Numbers > Buy Numbers
- Buy 1 US number (for testing)
- (Later) Buy 1 Mexico number
- Assign both numbers to the
freepbx-officeSIP connection
Step 4: Note your credentials
Save securely:
- SIP Username
- SIP Password
- SIP Server:
sip.telnyx.com - Outbound Proxy:
sip.telnyx.com - DID numbers purchased
Task 12: Configure SIP Trunk in FreePBX
Context: Connect FreePBX to your SIP trunk provider so calls can reach the PSTN.
Step 1: Add trunk in FreePBX
Navigate to: Connectivity > Trunks > Add Trunk > Add SIP (chan_pjsip) Trunk
General tab:
| Field | Value |
|---|---|
| Trunk Name | Telnyx |
| Outbound CallerID | +1NXXNXXXXXX (your US DID) |
| Maximum Channels | 0 (unlimited) |
PJSIP Settings tab — General:
| Field | Value |
|---|---|
| Username | (from Telnyx) |
| Secret | (from Telnyx) |
| Authentication | Outbound |
| Registration | Send |
| SIP Server | sip.telnyx.com |
| SIP Server Port | 5060 |
| Context | from-pstn |
PJSIP Settings tab — Advanced:
| Field | Value |
|---|---|
| From Domain | sip.telnyx.com |
| From User | (your Telnyx username) |
| DTMF Mode | RFC 4733 |
| Codecs | ulaw, alaw (priority order) |
Submit and Apply Config.
Step 2: Verify trunk registration
asterisk -rx "pjsip show registrations"
Expected: Telnyx trunk shows Registered status.
Step 3: Log progress
echo "$(date) - Task 12 complete: SIP trunk configured and registered" >> /root/VOIP/logs/install.log
Task 13: Configure Outbound Routes
Context: Outbound routes tell FreePBX which trunk to use for different dialed numbers. We create separate patterns for US, Mexico, and emergency calls.
Step 1: Create US outbound route
Navigate to: Connectivity > Outbound Routes > Add Outbound Route
| Field | Value |
|---|---|
| Route Name | US-Outbound |
| Trunk Sequence | 0: Telnyx |
| Route CID | (leave blank, uses trunk default) |
Dial Patterns:
| Prepend | Prefix | Match Pattern |
|---|---|---|
| +1 | NXXNXXXXXX | |
| +1 | 1 | NXXNXXXXXX |
| 911 |
This handles:
- 10-digit US dialing (prepends +1)
- 1+10-digit US dialing (prepends +1, strips leading 1... actually keeps it)
- 911 emergency
Step 2: Create Mexico outbound route
Add another outbound route:
| Field | Value |
|---|---|
| Route Name | MX-Outbound |
| Trunk Sequence | 0: Telnyx |
Dial Patterns:
| Prepend | Prefix | Match Pattern |
|---|---|---|
| +52 | 52 | XXXXXXXXXX |
| +52 | 011 52 | XXXXXXXXXX |
This handles:
- Dialing 52 + 10 digits (Mexico format, prepends +52)
- Dialing 011 52 + 10 digits (US international format)
Step 3: Set route priority
Ensure routes are ordered correctly:
- Emergency (911) — highest priority
- US-Outbound
- MX-Outbound
Apply Config.
Step 4: Log progress
echo "$(date) - Task 13 complete: Outbound routes configured" >> /root/VOIP/logs/install.log
Task 14: Configure Inbound Routes
Context: Inbound routes determine what happens when someone calls your DIDs from the outside.
Step 1: Create inbound route for US DID
Navigate to: Connectivity > Inbound Routes > Add Inbound Route
| Field | Value |
|---|---|
| Description | US-Main-Number |
| DID Number | +1NXXNXXXXXX (your US DID) |
| CallerID Number | (leave blank — any caller) |
| Destination | IVR: Menu Principal (or Ring Group 600) |
Submit and Apply Config.
Step 2: Create inbound route for Mexico DID (when purchased)
Same process, different DID:
| Field | Value |
|---|---|
| Description | MX-Main-Number |
| DID Number | +52XXXXXXXXXX (your MX DID) |
| Destination | IVR: Menu Principal |
Step 3: Test inbound call
From any external phone (cell phone), call your US DID number. Verify:
- Call connects to the PBX
- IVR greeting plays (or Ring Group rings)
- You can reach an extension
Step 4: Log progress
echo "$(date) - Task 14 complete: Inbound routes configured" >> /root/VOIP/logs/install.log
Task 15: Configure Firewall for Trunk Provider IPs
Context: Now that we have a trunk provider, we need to allow their SIP traffic through the firewall. Telnyx publishes their signaling IPs.
Step 1: Get Telnyx signaling IPs
Check Telnyx documentation for current IP ranges. As of writing:
52.2.64.0/2352.41.52.0/23169.55.30.0/23- (verify current list at https://support.telnyx.com)
Step 2: Add Telnyx IPs to nftables
Add these rules to /etc/nftables.conf in the input chain, before the final drop:
# Telnyx SIP trunk signaling
udp dport { 5060, 5061 } ip saddr { 52.2.64.0/23, 52.41.52.0/23, 169.55.30.0/23 } accept
tcp dport { 5060, 5061 } ip saddr { 52.2.64.0/23, 52.41.52.0/23, 169.55.30.0/23 } accept
Step 3: Apply and verify
nft -f /etc/nftables.conf
nft list ruleset | grep telnyx -i
Verify trunk is still registered:
asterisk -rx "pjsip show registrations"
Expected: Trunk still registered.
Step 4: Log progress
echo "$(date) - Task 15 complete: Firewall updated for trunk provider" >> /root/VOIP/logs/install.log
Task 16: End-to-End Testing
Context: Final validation that everything works together.
Step 1: Test internal call
Dial from 1001 to 1002. Verify two-way audio.
Step 2: Test outbound US call
From extension 1001, dial a US number (e.g., your cell phone). Verify:
- Call connects
- CallerID shows your DID number
- Two-way audio works
Step 3: Test outbound Mexico call
From extension 1001, dial a Mexico number (52 + 10 digits). Verify same as above.
Step 4: Test inbound call
From an external phone, call your US DID. Verify:
- IVR plays
- Can reach extensions
- Audio works both ways
Step 5: Test voicemail on external call
Call your DID, navigate to an extension, let it ring to voicemail. Leave a message. Check from the extension.
Step 6: Check CDR (Call Detail Records)
Navigate to: Reports > CDR Reports
Verify all test calls appear with correct source, destination, duration, and disposition.
Step 7: Final log
echo "$(date) - Task 16 complete: End-to-end testing PASSED. System ready." >> /root/VOIP/logs/install.log
echo "$(date) - === PHASE 2 COMPLETE ===" >> /root/VOIP/logs/install.log
POST-INSTALLATION CHECKLIST
After both phases are complete:
- All extensions can call each other (internal)
- Outbound calls work to US and Mexico numbers
- Inbound calls reach the IVR/ring group
- Voicemail works (leave and retrieve messages)
- CDR records all calls
- Firewall blocks unauthorized SIP traffic
- Fail2ban is active and monitoring
- FreePBX admin password is strong and unique
- SIP extension passwords are 16+ random characters
- Backup strategy is in place (FreePBX Backup module)
- UPS protects the server from power outages