- Debian 12 with a static IP, 2+ vCPU, 4 GB RAM and 40 GB disk, plus space for call recordings.
- The sng_freepbx_debian_install.sh script, first login to the web interface, module updates.
- Asterisk SIP Settings: external address, local networks, RTP 10000-20000. Skip this and you get calls with no audio.
- Trunk, extensions, inbound route by DID. Then call forwarding, Follow Me, recording and paging.
Restart without dropping calls: the core restart when convenient command in Asterisk. Full restart: fwconsole restart. Call recordings live in /var/spool/asterisk/monitor/year/month/day.
Diagnosis: FreePBX 17 is installed, but there’s no one to call
FreePBX 17 installs in half an hour. Then the real work starts. The call connects, but there’s no audio. An inbound caller hears “this number is not in service.” Transfer with ## doesn’t work. Call recordings show up in reports, but where the actual files are is anyone’s guess. Sound familiar?
Half the articles about FreePBX are written for version 13 on CentOS. Menus moved, modules got renamed, CentOS died, and app_macro got ripped out of Asterisk. You’re reading a guide, and your screen shows a different button.
This article is built for FreePBX 17 on Debian 12. One pass from an empty VM to a PBX that accepts calls, transfers them, records conversations and handles overhead paging.
What you’ll end up with
- FreePBX 17 on Debian 12, installed the official way.
- Correctly configured network and NAT: audio in both directions.
- Inbound routing by number plus a fallback route.
- Call forwarding, Follow Me, and call transfer that work on the first try.
- Call recording with a clear understanding of where the files live and how much space they take.
- Multicast paging for overhead announcements.
- Restart without dropping calls, backups, and safe upgrades.
Time: 1.5-2 hours total. Half an hour of that is the install, which runs on its own.
What you need: a VM or server for Debian 12, console access to the hypervisor, a SIP trunk from your provider with login and password, one or two IP phones or a softphone for testing.
FreePBX 17 system requirements
The official install page doesn’t publish hard hardware requirements. It just says you need Debian 12. The numbers below come from practice. They comfortably cover a small office.
| Parameter | Up to 20 extensions | 20-100 extensions | Comment |
|---|---|---|---|
| OS | Debian 12 Bookworm | Debian 12 Bookworm | Clean install only, no extra packages |
| CPU | 2 vCPU | 4 vCPU | Transcoding and recording eat CPU |
| RAM | 4 GB | 8 GB | 2 GB works for testing, not for production |
| System disk | 40 GB | 60 GB | SSD, logs and backups grow |
| Recording disk | see formula below | see formula below | A separate volume is better |
| FreePBX | 17.x | 17.x | Supported until 2028-06-30 |
| Asterisk | 22 LTS | 22 LTS | Supported range 18-23, 23 is testing only for now |
| Database | MariaDB 10.11 | MariaDB 10.11 | Installed via script from Debian repository |
| PHP | 8.2 | 8.2 | Installed via script |
Formula for recording storage. WAV 8 kHz, 16-bit, mono, that’s 128 kbit/s, almost 1 MB per minute of conversation. An hour is about 58 MB. An office with 10 agents doing 3 hours of calls a day records roughly 1.7 GB per day and 37 GB per month. Calculate this up front, not after the disk fills up.
As of publication, the current version is FreePBX 17 on Debian 12. FreePBX 18 is planned for Debian 13, with a beta in November 2026 and release on January 1, 2027. Before installing, check the latest releases on the FreePBX Versions page.
FreePBX 17 ports
| Port | Protocol | Purpose | Exposed externally? |
|---|---|---|---|
| 5060 | UDP/TCP | SIP, PJSIP | Only from the provider’s IP and remote staff |
| 5061 | TCP | SIP over TLS | Only if you use TLS |
| 10000-20000 | UDP | RTP, voice | Yes, for the provider and remote extensions |
| 80/443 | TCP | Web interface and UCP | No, only from the admin network or VPN |
| 22 | TCP | SSH | No, only from the admin network |
| 3306 | TCP | MariaDB | No, listens on localhost |
| 239.x.x.x:10000 | UDP multicast | Multicast paging announcements | No, only inside the voice VLAN |
Architecture
Here’s a typical setup. The PBX sits behind a router with NAT, the provider connects from outside, phones are internal. The NAT boundary is exactly where audio breaks most often.
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'lineColor': '#64748b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
A["SIP provider"] --> B["Router with NAT"]
B --> C["FreePBX 17 on Debian 12"]
C --> D["Asterisk 22 PJSIP"]
D --> E["Inbound routes"]
E --> F["Ring groups and Follow Me"]
F --> G["IP phones"]
D --> H["Recordings in monitor"]
D --> I["CDR in MariaDB"]
G --> J["Multicast VLAN"]
style A fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style G fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style B fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#9a3412
style C fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style D fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
What’s in this article
- Why a fresh FreePBX 17 doesn’t work the way you expect.
- Installation on Debian 12 and an honest answer about Ubuntu.
- Network setup in the OS and in FreePBX.
- Trunk, extensions and inbound routing.
- Call forwarding, Follow Me, call transfer.
- Call recording and where the files are stored.
- Multicast paging, restarts, verification, troubleshooting, backup, upgrades and FAQ.
Causes: why a fresh FreePBX 17 doesn’t work as expected
It’s not FreePBX that breaks. It’s your expectations of it that break. Seven causes cover almost every complaint about a fresh install.
| Cause | Why it breaks things |
|---|---|
| Installed on Ubuntu or a “not quite clean” Debian | The install script is only tested on vanilla Debian 12. Other packages and library versions cause build errors and odd module behavior. |
| External address and local networks aren’t set | Asterisk writes its internal IP into the SDP. The provider sends audio to nowhere. Result: silence in one or both directions. |
| The RTP range is blocked | SIP goes through, the call connects, but the firewall blocks UDP 10000-20000. Silence again. |
| No inbound route matching the DID format | The provider sends the number in a format different from what’s set in the route. The call lands on “this number is not in service.” |
| DTMF mode mismatch | Codes like ## and *2 during a call are DTMF. If the phone sends them the wrong way, Asterisk never sees them. |
| Apt repository with the stable alias | After Debian 13 is released, the stable alias points to trixie. A plain apt upgrade pulls packages from the wrong release. |
| Call recordings filled the disk | MariaDB and Asterisk crash when space runs out. Nobody cleans up recordings until it’s too late. |
Here’s the key point. Causes 2 and 3 account for more than half the questions on forums. If after installation you see a call with no audio, don’t touch the codecs and don’t reinstall the system. Go to the NAT section.
Installing FreePBX 17 on Debian 12
Let’s agree on names. The PBX server is pbx01, IP 10.0.10.20/24, gateway 10.0.10.1. The hypervisor is a Proxmox node. Substitute your own values, the commands don’t change.
Preparation: VM and a clean Debian 12
Why: the Sangoma script is built for a vanilla system. No GUI, no web server, nothing extra. Install the netinst image from debian.org and at the software selection step keep only “SSH server” and “standard system utilities.”
Host: the Proxmox node, as root. Substitute your own VMID 120 and storage name. Upload the ISO to the local storage beforehand.
qm create 120 --name pbx01 --ostype l26 --cores 2 --memory 4096 \
--scsihw virtio-scsi-single --scsi0 local-lvm:40 \
--net0 virtio,bridge=vmbr0 --agent enabled=1 \
--cdrom local:iso/debian-12-amd64-netinst.iso --boot order='scsi0;ide2'
qm start 120
Result: the VM is running, the Proxmox console shows the Debian installer. Go through it, set the root password and a regular user.
Installing on bare metal is the same, just from a flash drive. Installing in the cloud: get the official Debian 12 image from your provider, the script works with it fine.
Step 1. Configure Debian 12 networking before installing FreePBX
Why: the PBX needs a permanent address. Phones, the provider and firewall rules all bind to the IP. A DHCP address that changes after a reboot means a department with no phones on Monday morning.
In Debian 12, by default, networking is managed by ifupdown via /etc/network/interfaces. First find out the interface name.
Host: pbx01, as root, via the Proxmox console. Not over SSH: a config mistake and you lose access.
ip -br link
ip -br addr
Result: the interface name, usually ens18 on Proxmox. Now set a static address.
Host: pbx01, file /etc/network/interfaces. Replace the block for the main interface entirely.
auto lo
iface lo inet loopback
auto ens18
iface ens18 inet static
address 10.0.10.20/24
gateway 10.0.10.1
Set DNS servers in /etc/resolv.conf. Debian ignores the dns-nameservers line in interfaces without the resolvconf package, a common trap.
cat > /etc/resolv.conf <<'EOF'
nameserver 10.0.10.1
nameserver 1.1.1.1
EOF
hostnamectl set-hostname pbx01
sed -i 's/^127\.0\.1\.1.*/127.0.1.1 pbx01/' /etc/hosts
systemctl restart networking
ip -br addr show ens18
ping -c 3 10.0.10.1
ping -c 3 deb.debian.org
Result: the interface has the address 10.0.10.20/24, the gateway responds to ping, deb.debian.org resolves. Without internet access the install script won’t work, so check this now.
Update the system before installing. The script installs packages on top, and the fresher the base, the fewer surprises.
apt update && apt -y full-upgrade
apt install -y tmux wget
reboot
Step 2. Run the install script
Why: this is the official method. The sng_freepbx_debian_install script installs Asterisk, MariaDB, PHP 8.2, Apache, NodeJS and FreePBX 17 itself, then configures the services. Doing it by hand is half a day of work with a dozen places to get it wrong.
Run it inside tmux. If your SSH session drops at minute 20, the install doesn’t die with it.
Host: pbx01, as root, can already be over SSH.
tmux new -s install
cd /tmp
wget https://github.com/FreePBX/sng_freepbx_debian_install/raw/master/sng_freepbx_debian_install.sh -O /tmp/sng_freepbx_debian_install.sh
bash /tmp/sng_freepbx_debian_install.sh
Watch the log in a second window. Detach from tmux with Ctrl+B, then D. Reattach with tmux attach -t install.
ls -lt /var/log/pbx/
tail -f /var/log/pbx/freepbx17-install*.log
Result: after 20-40 minutes the script reports a successful install. Time depends on your network and hardware. Don’t interrupt it even if it looks stuck during a build, it’s not stuck.
The script has flags. Useful ones: –dahdi installs drivers for analog and E1 Sangoma cards and pins the kernel version, –opensourceonly installs only open modules without commercial ones. For plain SIP without cards, you don’t need any flags.
What about Ubuntu?
Let’s be direct, since “install FreePBX on Ubuntu” is a search people run constantly. FreePBX 17 is not officially supported on Ubuntu. The script is written and tested for Debian 12. There are manual install guides for Ubuntu 24.04 out there, for example from geekrewind, and they work as of this writing.
But look at what you’re actually getting. Every module and Asterisk update is tested on Debian. On Ubuntu, you’re the first tester. The forum answer will be “move to Debian.” Ubuntu and Debian differ less than you’d think, but the difference shows up at 3 AM during an update.
If the reason is “everything we run is on Ubuntu,” spin up a separate VM for Debian 12. That’s 512 MB of extra memory and a good night’s sleep. More on alternatives later.
Step 3. First login and module updates
Open http://10.0.10.20/ in a browser. FreePBX will ask you to create an administrator: login, password, email for notifications. Make the password long, not “admin123.” This login unlocks the entire PBX, including trunks that can rack up charges on someone else’s dime.
Next, the wizard offers language, time zone and activation. Activation is only needed for commercial modules and access to their store. For an open PBX, you can skip it.
Update modules right after install. The script installs whatever was in the repository when it ran, and fixes keep coming out.
Host: pbx01, as root.
fwconsole ma refreshsignatures
fwconsole ma upgradeall
fwconsole chown
fwconsole reload
asterisk -rx "core show version"
fwconsole ma list | head -n 30
Result: Asterisk 22.x, all modules showing Enabled, no red “Please run fwconsole reload” banner in the web interface.
Step 4. Check your apt repositories
This is specific to 2025-2026. Don’t skip it: the step is small, the consequences aren’t.
The script added the Sangoma repository with the stable alias. While Debian 12 was stable, everything was fine. Debian 13 came out in August 2025, and stable now means trixie. There’s a dedicated thread on the FreePBX forum about this. FreePBX 17 stays on Debian 12, don’t move to 13.
Host: pbx01, as root.
grep -rnw stable /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null
grep -rn trixie /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null
Result: empty output is good. If you find lines with stable, replace the alias with bookworm in the matching file. Take the filename from the grep output, the example below is just a placeholder.
cp /etc/apt/sources.list.d/FILE_NAME.list /root/
sed -i 's/\bstable\b/bookworm/g' /etc/apt/sources.list.d/FILE_NAME.list
apt update
Step 5. Configure FreePBX networking: NAT and local networks
Why: this is what “FreePBX network setup” really means from a telephony standpoint. The OS knows its own IP. Asterisk needs to know two more things: what address the outside world sees, and which networks count as local. Without this, it writes the internal address into the SDP, and the provider’s audio ends up going to 10.0.10.20, which is unreachable from the internet.
Open Settings → Asterisk SIP Settings. On the general settings tab, find the NAT Settings block. Field descriptions are in the Asterisk SIP Settings guide.
| Field | Value | Why |
|---|---|---|
| External Address | Office public IP | Asterisk substitutes this address in the SDP for external callers |
| Local Networks | 10.0.10.0/24 and all internal networks, including VPN | No NAT rewriting needed for these networks |
| Detect Network Settings | Click once | Fills both fields automatically, then double-check them |
| RTP Port Ranges | 10000-20000 | Default value, don’t change without reason |
Save, click Apply Config. PJSIP transports don’t always reload on their own, so after changing network settings you need to restart Asterisk. If there are no active calls, do it right away. If there are, do it gracefully, more on that in the restart section.
Host: pbx01, as root.
fwconsole restart
asterisk -rx "pjsip show transports"
On the router, you need port forwarding in two cases: the provider sends inbound calls to your public IP without registration, or you have remote staff. Forward 5060/UDP and 10000-20000/UDP to 10.0.10.20, and make sure to restrict source IPs for 5060. If the trunk registers itself outward, the provider usually doesn’t need forwarding.
Step 6. Trunk and extensions
This is the baseline, without it there’s nothing for inbound routing to hook into. Brief, because the parameters depend on your provider.
Trunk: Connectivity → Trunks → Add Trunk → Add SIP (chan_pjsip) Trunk. FreePBX 17 only has PJSIP, chan_sip is gone. On the pjsip Settings tab, fill in the provider’s details.
| Field | What to enter |
|---|---|
| Username / Auth username | Login from the provider |
| Secret | Password from the provider |
| Authentication / Registration | Outbound / Send, if the provider requires registration |
| SIP Server / Port | Provider’s address and port |
| Context | from-pstn, by default |
| Outbound CallerID | Your landline number in the format the provider expects |
Extensions: Applications → Extensions → Add Extension → PJSIP. Number, name, password. FreePBX generates the password itself, leave it, don’t set “1234.” SIP password brute-forcing runs around the clock, this isn’t theoretical.
Host: pbx01, as root. Check that the trunk is registered and the phones are visible.
asterisk -rx "pjsip show registrations"
asterisk -rx "pjsip show endpoints"
asterisk -rx "pjsip show contacts"
Result: the trunk shows Registered, connected phones show a contact with status Avail.
Step 7. Configure inbound routing
Why: the Inbound Route decides where an incoming call goes. Without a matching route, the call ends up on “this number is not in service,” even if the trunk is registered and everything shows green.
A route is matched by two fields: DID, the number that was dialed, and CallerID, the number of whoever is calling. An empty field means “any.” A more specific route wins over a less specific one.
First find out what format the provider sends the DID in. This is the main place for mistakes: the route has 3432223344 configured, but the provider sends 73432223344.
Host: pbx01, as root. Call your landline from a mobile and watch the output.
asterisk -rvvvv
Look for a line with the from-pstn context. The number before @from-pstn is the DID. If the call already happened, find it in the log:
grep -E '@from-pstn:' /var/log/asterisk/full | tail -n 10
Now create routes in Connectivity → Inbound Routes → Add Inbound Route.
| Route | DID Number | CallerID Number | Destination |
|---|---|---|---|
| Main number | 73432223344 | empty | Time Condition or IVR |
| Direct number for sales | 73432223355 | empty | Sales ring group |
| VIP customer to main number | 73432223344 | 79161234567 | Manager’s extension |
| Fallback, catches everything else | empty | empty | Receptionist or IVR |
A fallback route with empty fields is mandatory. Your provider will eventually change the number format, and instead of silence, calls will land on the receptionist. You’ll find out about the issue from a “wrong number is ringing” complaint, not “can’t reach you at all.”
Here’s how an inbound call typically flows through a small office.
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#ffffff',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'lineColor': '#64748b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'flowchart': {'curve': 'linear', 'nodeSpacing': 50, 'rankSpacing': 50}
}}%%
flowchart TD
A["Inbound call"] --> B["Inbound Route by DID"]
B --> C{"Business hours?"}
C -->|Yes| D["IVR"]
C -->|No| E["Voicemail"]
D --> F["Ring Group"]
F --> G["Extension with Follow Me"]
G --> H["Employee's mobile"]
G --> I["Forward on busy"]
B --> J["Fallback route"]
style A fill:#f8fafc,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style C fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#9a3412
style J fill:#f8fafc,stroke:#f97316,stroke-width:2px,color:#9a3412
style F fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
style G fill:#f8fafc,stroke:#22c55e,stroke-width:2px,color:#15803d
Business hours are set with the Time Groups and Time Conditions modules under Applications. First create a group with a schedule like “Mon-Fri 9:00-18:00,” then a condition that routes one way during those hours and another way outside them. Check the server time zone with timedatectl: if it’s UTC, an office in a different time zone will get calls routed as “after hours” before lunch.
Step 8. Configure call forwarding
FreePBX has three types of forwarding. Unconditional: all calls go to another number. On busy: if the line is busy. On no answer: if the call isn’t picked up within a set time. They’re controlled by feature codes from the phone, through the UCP user panel, or by an administrator.
Default codes are from the Sangoma feature code reference. You can check and change them under Admin → Feature Codes.
| Action | Enable | Disable |
|---|---|---|
| Unconditional forwarding | *72 | *73 |
| On busy | *90 | *91 |
| On no answer or unreachable | *52 | *53 |
| Unconditional toggle | *96 | *96 |
| Do not disturb | *78 | *79 |
| Follow Me on/off | *21 | *21 |
The user dials *72, the system asks for a number, they enter 89161234567 and the pound sign. Done. Doing it from the phone is faster than explaining where the button is in the web panel.
Administrators find it more convenient to view and change forwarding settings from the console. FreePBX stores them in the Asterisk database under the families CF, CFB and CFU: unconditional, on busy, and on no answer.
Host: pbx01, as root.
asterisk -rx "database show CF"
asterisk -rx "database show CFB"
asterisk -rx "database show CFU"
asterisk -rx "database put CF 101 89161234567"
asterisk -rx "database del CF 101"
Result: the first three commands show who has what enabled. The second pair turns unconditional forwarding on and off for extension 101.
Here’s the key point. Forwarding to an external number is an outbound call through your trunk. It goes through outbound routes and runs on your bill. If an outbound route blocks mobile numbers, forwarding won’t work. If it allows international calls, forwarding to a paid number abroad can be enabled by anyone who cracked an extension’s password.
FreePBX Follow Me
Follow Me is smart call forwarding. A call rings the desk phone first, then pulls in the mobile, then falls back to voicemail. People don’t miss calls, and the caller never hears “subscriber unavailable.”
Open Applications → Follow Me and pick an extension. Or go to the extension’s own settings, Find Me/Follow Me tab. Key fields:
| Field | What to set | Comment |
|---|---|---|
| Enabled | Yes | Users can toggle it with code *21 |
| Initial Ring Time | 10-15 seconds | How long only the desk phone rings |
| Ring Strategy | ringallv2 | Ring everyone on the list at once |
| Ring Time | 20-25 seconds | How long the list rings after the initial period |
| Follow-Me List | 101 and 89161234567# | External numbers must end with a pound sign |
| Confirm External Calls | Yes | Mobile will prompt to press 1 to accept |
| No Answer Destination | Extension’s voicemail | Where it goes if nobody picks up |
The pound sign after an external number isn’t a typo. Without it, FreePBX treats 89161234567 as an internal extension, looks for one that doesn’t exist, and silently skips it.
Confirming calls on the mobile is the most underrated checkbox. Without it, the mobile carrier’s voicemail picks up the call, and the customer leaves a message in a mailbox nobody checks. With it, the carrier’s voicemail won’t press 1, and the call falls back to the PBX for the next step.
FreePBX call transfer
Transfer comes in two flavors: blind and attended. Blind: hand off the call and move on. Attended: talk to a colleague first, then connect them. In FreePBX both are done two ways: a phone button or codes during the call.
| Method | Blind | Attended | How it works |
|---|---|---|---|
| Transfer button on the phone | Yes | Yes | SIP REFER, handled by the phone itself and PJSIP |
| Codes during the call | ## | *2 | DTMF, handled by Asterisk |
Practical advice: teach people the phone’s transfer button. It works regardless of DTMF settings and is more intuitive for users. Codes are needed for softphones without a dedicated transfer button and for analog phones through a gateway.
For the ## and *2 codes to work, three conditions must be met:
- In Settings → Advanced Settings, the Asterisk Dial Options parameter contains the letters T and t. By default it’s Ttr, don’t touch it.
- The extension’s DTMF Signaling is set to RFC 4733, and the phone uses the same DTMF mode.
- The In-Call Asterisk Blind Transfer and Attended Transfer codes are enabled in Feature Codes.
- For the phone button, Allow Transfer isn’t disabled on the extension.
You can check an extension’s DTMF mode from the console.
Host: pbx01, as root.
asterisk -rx "pjsip show endpoint 101" | grep -Ei 'dtmf_mode|allow_transfer'
asterisk -rx "features show" | grep -Ei 'blindxfer|atxfer'
Result: dtmf_mode: rfc4733, allow_transfer: true, blindxfer ##, atxfer *2.
Step 11. Call recording: setup
Recording in FreePBX 17 is configured in several places, each with its own priority. This is the main source of confusion: you enable recording on an extension, but the call isn’t recorded because a route says “never.”
Where recording gets enabled:
- On an extension: Applications → Extensions → Advanced tab → Recording Options. Separate settings for inbound and outbound, internal and external.
- On an inbound route: Advanced tab, Call Recording parameter.
- On a ring group and a queue: its own Call Recording parameter.
- On demand during a call: code *1, if On Demand Recording is allowed for the extension.
Recording parameter values and how they interact:
| Value | What it does |
|---|---|
| Force | Always record, overrides No from other call participants |
| Yes | Record, unless a higher-priority setting forbids it |
| Don’t Care | Let other participants in the route decide |
| No | Don’t record, unless someone else set Force |
| Never | Never record, overrides everything |
A simple working scheme for an office: Force on inbound routes, Yes on extensions for external calls, Don’t Care for internal calls. This records every conversation with customers but not internal chatter between coworkers.
And don’t forget to notify callers. Put a message at the start of the IVR or inbound route saying the call is recorded. It’s both a legal requirement and a trust question with customers.
Where FreePBX call recordings are stored
Recordings live in /var/spool/asterisk/monitor/ split by date: year, month, day. For example, /var/spool/asterisk/monitor/2026/10/25/. Default format is WAV. The filename starts with the call type: in for inbound, out for outbound, rg for ring groups, q for queues. Then numbers, date, time and a unique call ID.
Host: pbx01, as root.
ls -lh /var/spool/asterisk/monitor/$(date +%Y/%m/%d)/ | tail -n 10
du -sh /var/spool/asterisk/monitor/*/*
df -h /var/spool/asterisk
Result: today’s recordings, per-month sizes, and free space on the partition. If the partition is shared with the system, that’s a reason to move recordings to a separate disk.
The link between a recording and a call is stored in the CDR. The recordingfile column contains the filename. That’s exactly what the Reports → CDR Reports web interface uses to show the playback button.
Host: pbx01, in a mariadb client as root.
SELECT calldate, src, dst, duration, recordingfile
FROM asteriskcdrdb.cdr
WHERE recordingfile <> ''
ORDER BY calldate DESC
LIMIT 10;
Want to store recordings on a separate disk? Don’t change the path in Asterisk’s configs by hand. Mount the disk directly at /var/spool/asterisk/monitor. The path for FreePBX stays the same, the CDR player keeps working, and space comes from the new volume. Before mounting, move the existing files over and check the asterisk owner.
Host: pbx01, as root. Example for a second disk /dev/sdb1, already formatted as ext4. Do this during quiet hours, with no calls in progress.
fwconsole stop
mkdir -p /mnt/rec-tmp
mount /dev/sdb1 /mnt/rec-tmp
rsync -a /var/spool/asterisk/monitor/ /mnt/rec-tmp/
umount /mnt/rec-tmp
echo "UUID=$(blkid -s UUID -o value /dev/sdb1) /var/spool/asterisk/monitor ext4 defaults,noatime 0 2" >> /etc/fstab
mv /var/spool/asterisk/monitor /var/spool/asterisk/monitor.old
mkdir /var/spool/asterisk/monitor
systemctl daemon-reload
mount -a
chown -R asterisk:asterisk /var/spool/asterisk/monitor
fwconsole start
Result: df -h /var/spool/asterisk/monitor shows the new disk, old recordings still play from CDR. Remove the monitor.old directory a week later, once you’ve confirmed everything’s in place.
Step 12. FreePBX multicast paging
Paging is an overhead announcement: press a button, say “Smith, come to the manager’s office,” and every phone in the group hears it. Regular paging in FreePBX makes a separate call to each phone. Multicast sends one stream to the network, and phones listen to it themselves. For 50 phones on a warehouse floor, that’s a huge difference.
There are four options. Pick based on budget and whether the PBX needs to stay in the loop.
| Option | Cost | Load on PBX | Limitation |
|---|---|---|---|
| Paging and Intercom | Free | Calls each phone | Not multicast, recommended up to 25 phones per group |
| Page Pro | Commercial module | Single stream | Paid, multicast groups defined as IP:port |
| Phone sends multicast itself | Free | None | Local network only, button configured on each phone |
| Page with MulticastRTP in a custom dialplan | Free | Single stream | Manual config, check codec compatibility with your phones |
Sangoma’s official stance: RTP multicast in FreePBX is configured only through the commercial Page Pro module. That’s stated in the Paging and Intercom guide. Also there: Force, Skip and Whisper don’t work with multicast, and page priority is set on the phones themselves.
The free path with the PBX in the loop is the Page application in Asterisk with a MulticastRTP channel. Add your number to the from-internal-custom context, which FreePBX plugs into the internal dialplan.
Host: pbx01, file /etc/asterisk/extensions_custom.conf. Number 7001 shouldn’t overlap with extensions or feature codes.
[from-internal-custom]
exten => 7001,1,NoOp(Multicast paging to warehouse)
same => n,Page(MulticastRTP/basic/239.255.10.1:10000,iq)
same => n,Hangup()
fwconsole reload
asterisk -rx "dialplan show 7001@from-internal-custom"
The i option ignores forwarding, q disables the beep before the announcement. Dial 7001 and speak. The stream goes to the group 239.255.10.1, port 10000, G.711 codec. On the phones, in the multicast listening section, add the address 239.255.10.1:10000 and set the priority. The exact steps depend on the model, Sangoma covers it in their multicast paging on phones article.
Why 239.x.x.x and not 224.0.0.x from the examples. The 224.0.0.0/24 range is reserved for control protocols, and switches flood it to every port. The 239.0.0.0/8 range is administratively scoped, for internal use. With it, IGMP snooping on switches behaves predictably.
Here’s how traffic flows for multicast compared to regular paging.
%%{init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#f8fafc',
'primaryTextColor': '#1e293b',
'primaryBorderColor': '#94a3b8',
'noteBkgColor': '#fefce8',
'noteTextColor': '#713f12',
'noteBorderColor': '#fbbf24',
'actorBkg': '#f8fafc',
'actorBorder': '#94a3b8',
'actorTextColor': '#1e293b',
'fontSize': '15px',
'fontFamily': 'ui-sans-serif, system-ui, sans-serif'
},
'sequence': {
'mirrorActors': false,
'messageAlign': 'center',
'actorMargin': 120,
'width': 160,
'noteMargin': 12
}
}}%%
sequenceDiagram
participant U as Employee
participant A as Asterisk
participant S as Switch
participant T as Warehouse phones
U->>A: Dial 7001
A->>S: Single RTP stream to 239.255.10.1
S->>T: Stream copy to each listener
Note over S,T: IGMP snooping decides who gets it
U->>A: Hang up
A->>S: Stream stopped
Multicast doesn’t cross a router without extra configuration. If the phones are on a different VLAN than the PBX, you need PIM or a separate PBX interface in the voice VLAN. The simplest approach is keeping the PBX and phones on the same voice VLAN.
How to restart FreePBX 17 correctly
“Restart it and see” is the favorite remedy of people who don’t know what broke. But sometimes a restart really is needed. The question is which kind, because there are five, and only one of them doesn’t drop active calls.
| What you need | Command | Drops calls? |
|---|---|---|
| Apply changes from the GUI | fwconsole reload | No |
| Restart Asterisk when there are no calls | core restart when convenient | No, waits for zero calls |
| Restart Asterisk without accepting new calls | core restart gracefully | No, but won’t accept new ones |
| Restart FreePBX and Asterisk immediately | fwconsole restart | Yes |
| Reboot the OS | reboot | Yes, plus boot time |
Host: pbx01, as root. Graceful restart is the first command. It returns control immediately, and the actual restart happens once the last call hangs up.
asterisk -rx "core show channels count"
asterisk -rx "core restart when convenient"
fwconsole restart
systemctl list-units --type=service | grep -Ei 'freepbx|asterisk'
The last command shows which systemd unit runs the PBX on your install. It’s usually freepbx.service, which starts Asterisk itself through fwconsole. So systemctl restart freepbx does the same thing as fwconsole restart.
When you need an OS reboot: the kernel or system libraries were updated. You can check with the needrestart utility. After a regular FreePBX module update, you don’t need to reboot the server.
apt install -y needrestart
needrestart -r l
needrestart -k
A web-interface reboot only exists in the commercial System Admin module. Without it, use the console. That’s fine: whoever restarts the PBX should be watching what’s happening.
Verification: is everything working in FreePBX 17
One pass through the checklist after setup. If every item is green, the PBX is ready to hand over to people.
Host: pbx01, as root.
asterisk -rx "core show uptime"
asterisk -rx "pjsip show registrations"
asterisk -rx "pjsip show contacts"
asterisk -rx "core show channels"
fwconsole ma list | grep -vi enabled
df -h / /var/spool/asterisk/monitor
timedatectl | grep -Ei 'time zone|synchronized'
Result: uptime is growing, the trunk shows Registered, phones show Avail, no modules outside Enabled status, disks have free space, time is synced and the time zone is correct.
Next, live tests. Each one is a single call:
- Inbound from a mobile to the landline: audio both ways for over 60 seconds. Exactly 30-32 seconds and a drop is a sign of NAT problems.
- Outbound to a mobile: your landline number shows up as caller ID.
- Transfer with the phone’s button and with code ## to another extension.
- Follow Me: don’t pick up the desk phone, the mobile should ring and ask for a key press to accept.
- Recording: a file shows up in today’s folder and plays from the CDR.
- Multicast: dial 7001, voice plays on all phones in the group.
- After hours: the call routes where it should.
For troubleshooting, check logs in /var/log/asterisk/full. The easiest way to filter a specific call is by the caller’s number.
grep 79161234567 /var/log/asterisk/full | tail -n 50
tail -f /var/log/asterisk/full | grep -Ei 'warning|error'
Troubleshooting: common FreePBX 17 errors
It’s not as bad as it looks after your first call with no audio. It’s a lot more predictable than that. Almost every error below has happened to me more than once.
| Error | Cause | Fix |
|---|---|---|
| One-way audio | External Address or Local Networks not set | NAT Settings in Asterisk SIP Settings, restart |
| Drops exactly at 30-32 seconds | ACK doesn’t arrive due to NAT or SIP ALG | Set External Address, disable SIP ALG |
| “Number not in service” on inbound | DID doesn’t match the route | Check the DID in the log, fix the route, add a fallback |
| ## and *2 don’t work | DTMF mode or Dial options | RFC 4733, T and t in Asterisk Dial Options |
| Forwarding to mobile doesn’t go through | Outbound route blocks the number, or provider rejects CallerID | Route pattern, trunk CID Options |
| Follow Me doesn’t ring the mobile | External number missing the pound sign | Add # after the number |
| Recordings show in CDR but won’t play | Wrong recording path or permissions | Check the directory, run fwconsole chown |
| Multicast is silent | Different VLANs, IGMP snooping with no querier, codec mismatch | Single VLAN, querier on the switch, G.711 on the phone |
Calls with no audio or dropping at 30 seconds
Cause: Asterisk tells the other party its internal address instead of the external one. Or a router with SIP ALG is rewriting packets. A drop at exactly 30-32 seconds is classic: the response confirmation doesn’t arrive, and one side’s timer hangs up.
Fix: confirm Asterisk sees the correct external address and local networks, and watch the live SIP dialog.
Host: pbx01, as root.
asterisk -rx "pjsip show transport 0.0.0.0-udp" | grep -Ei 'external|local_net'
asterisk -rx "pjsip set logger on"
asterisk -rvvv
In the logger output, find the c=IN IP4 line in the SDP. For an external call, it should show the public IP, not 10.0.10.20. Turn off the logger with pjsip set logger off after diagnosing, otherwise the log will balloon. The transport name on your install might differ, get the list with pjsip show transports.
Inbound call doesn’t match a route
Cause: the provider sends the DID in a format that no route matches. Sometimes it sends the number not in the To header but elsewhere, and then the DID arrives as the trunk’s login instead.
Fix: find the real DID in the log and build a route for it. If the provider sends the login instead of the number, the trunk’s pjsip Settings → Advanced tab has a Context parameter and an option for pulling the DID from the To header. For a quick route test without the provider, use code 777, an inbound call simulator.
grep -E '@from-pstn:1\]' /var/log/asterisk/full | tail -n 5
Forwarding or Follow Me to mobile doesn’t work
Cause one: the outbound route doesn’t match the dialed number. Cause two: during forwarding, the PBX substitutes the original caller’s number, and many providers reject calls with a mismatched CallerID.
Fix: check the dial patterns in the outbound route, for example 8XXXXXXXXXX. On the trunk’s General tab, set CID Options to Force Trunk CID, that way your landline number goes out on the mobile call. Downside: the employee won’t see the customer’s number. Upside: the call goes through. Some providers allow a foreign CallerID on request.
grep -Ei 'chan_pjsip.*(403|404|503|Forbidden)' /var/log/asterisk/full | tail -n 10
Recordings won’t play from CDR
Cause: the file isn’t where FreePBX looks for it, or the web server lacks read permissions. Typical after manually changing the recordings directory or copying files as root.
Fix: find the file by name from the recordingfile column and restore permissions.
Host: pbx01, as root. Substitute the filename from the CDR.
find /var/spool/asterisk -name 'in-73432223344-79161234567-*' 2>/dev/null | head
fwconsole chown
“Please run fwconsole reload” error
Cause: changes were saved in the GUI but not applied, or a previous reload failed on a module error. The red banner stays up, and the Apply Config button doesn’t help.
Fix: run reload from the console with verbose output. The error will show up right away, with the module name.
fwconsole reload --verbose
fwconsole ma list | grep -Ei 'disabled|broken|needs upgrade'
ionCube modules after a reboot
Cause: commercial modules are encrypted with ionCube. If the ionCube loader isn’t wired into PHP, they stop working, sometimes after a PHP update or a reboot.
Fix: check that PHP sees the loader. If it doesn’t and you don’t need the commercial modules, it’s simpler to remove them. If you need them, reinstall the loader package from the Sangoma repository.
php -v | grep -i ioncube
fwconsole ma list | grep -i commercial
Alternatives: Ubuntu, ISO, FreePBX 16 and others
The main recipe is FreePBX 17 via script on Debian 12. We chose it because it’s the only officially supported path through 2028. But other options exist, and here’s an honest take on each.
| Option | Pros | Cons | When to pick it |
|---|---|---|---|
| Debian 12 + script | Official, supported until 2028 | Debian 12 only | Default choice |
| Sangoma SNGDEB ISO | Installs Debian and FreePBX in one pass | Less control over partitioning and packages | Bare metal, quick start |
| Manual install on Ubuntu 24.04 | One OS across the rest of your infrastructure | Unofficial, you’re your own tester | Lab, not production |
| FreePBX 16 on SNG7 | Familiar interface | OS unsupported since 2024, FreePBX 16 EOL in 2027 | Only while migrating to 17 |
| Wait for FreePBX 18 | Debian 13, newer Asterisk | Beta in November 2026, release in January 2027 | If your PBX launch isn’t before spring 2027 |
| Plain Asterisk without a GUI | Minimalism, full control | Everything manual, harder to hand off to colleagues | Niche tasks, gateways, lab work |
ISO image instead of the script
Sangoma publishes an ISO that installs Debian 12 and immediately launches the FreePBX installer. Handy on bare metal where you don’t want to deal with netinst. It runs the same script internally. If you’re installing on a Proxmox VM, there’s barely any difference, but with the script you control disk partitioning and can immediately carve out a separate volume for recordings.
Installing FreePBX on Ubuntu
If you still want Ubuntu, install it in a separate VM, snapshot before every update, and keep a migration plan toward Debian. The Sangoma script isn’t built for Ubuntu, so you’ll be following a third-party guide. Test every module update on a copy of the VM first. This isn’t a hard rule against it, it’s the cost of ownership you should know about up front.
FreePBX 16 and migration
FreePBX 16 ran on SNG7, which is CentOS 7, whose support ended in 2024. FreePBX 16 itself is scheduled to reach EOL on January 1, 2027. If you’re running one of these, migrate now: a new VM with FreePBX 17, a backup made with the Backup & Restore module on the old system, a restore on the new one. The module converts data on its own, but check commercial modules and custom dialplan manually.
Host: the old PBX on FreePBX 16 and the new pbx01. Backups are created in the GUI with the Backup & Restore module, the file is transferred to the new machine. Restore commands on the new system:
ls -lh /var/spool/asterisk/backup/
fwconsole backup --restore=/var/spool/asterisk/backup/ARCHIVE_NAME.tar.gz
fwconsole reload
Prevention: keeping FreePBX 17 from falling over on a Monday
A PBX doesn’t break from load. It breaks from a full disk, a bad update and a cracked password. All three are preventable in advance, and the prevention is boring.
Security
Firewall. FreePBX 17 has a Firewall module under Connectivity. If you use it, don’t run UFW alongside it, two rule managers on the same box conflict. If you don’t have the module or prefer managing rules yourself, here’s a minimal UFW set. Replace 203.0.113.10 with your provider’s IP, and 10.0.10.0/24 with your office network.
Host: pbx01, as root. Do this through the hypervisor console, not over SSH.
apt install -y ufw
ufw default deny incoming
ufw default allow outgoing
ufw allow from 10.0.10.0/24 to any port 22 proto tcp
ufw allow from 10.0.10.0/24 to any port 80,443 proto tcp
ufw allow from 10.0.10.0/24 to any port 5060 proto udp
ufw allow from 203.0.113.10 to any port 5060 proto udp
ufw allow 10000:20000/udp
ufw enable
ufw status numbered
fail2ban. Check whether it’s installed and whether there’s a jail for Asterisk. If not, install it and enable one. The asterisk filter already ships with Debian, and FreePBX logs to /var/log/asterisk/full.
apt install -y fail2ban
cat > /etc/fail2ban/jail.d/asterisk.local <<'EOF'
[asterisk]
enabled = true
logpath = /var/log/asterisk/full
maxretry = 5
findtime = 600
bantime = 86400
EOF
systemctl restart fail2ban
fail2ban-client status asterisk
SSH hardening goes in a separate file. Replace admin with your actual user. Verify key-based login works before applying this.
Host: pbx01, file /etc/ssh/sshd_config.d/10-hardening.conf.
PermitRootLogin prohibit-password
PasswordAuthentication no
MaxAuthTries 3
AllowUsers admin
sshd -t && systemctl reload ssh
A separate database user is needed if external systems read the CDR, for example a CRM or reporting tool. Don’t hand them the FreePBX user. Create your own, SELECT-only, scoped to asteriskcdrdb.
CREATE USER 'cdr_ro'@'10.0.10.50' IDENTIFIED BY 'REPLACE_WITH_A_LONG_PASSWORD';
GRANT SELECT ON asteriskcdrdb.cdr TO 'cdr_ro'@'10.0.10.50';
FLUSH PRIVILEGES;
For access from another machine, MariaDB needs to listen on more than just localhost, and the firewall should only allow port 3306 from 10.0.10.50. If you don’t have this requirement, don’t open it.
Backups
Configuration is backed up by the built-in Admin → Backup & Restore module. It’s better not to include call recordings there: the archive will balloon to dozens of gigabytes, and restoring the configuration will take an hour instead of a minute.
| What to back up | How often | Where to store it | How to restore |
|---|---|---|---|
| FreePBX configuration | Daily | Remote storage via the Backup module, SFTP or S3 | Restore module or fwconsole backup –restore |
| CDR | Daily, as part of the module backup | Same location | Along with the configuration |
| Call recordings | Daily, incremental | NAS or separate storage | rsync back into monitor |
| VM snapshot | Before every update | Proxmox storage | qm rollback |
It’s convenient to pull recordings onto a NAS with rsync. Incremental, without re-copying files already transferred.
Host: pbx01, as root. Substitute nas01 and the path with your own storage, accessed via SSH key.
rsync -a --partial /var/spool/asterisk/monitor/ backup@nas01:/srv/pbx01-recordings/
Test a restore at least once. A backup nobody’s tried to restore isn’t a backup, it’s hope in tar.gz format.
Recording rotation
Recordings need to be deleted after a retention period. Otherwise the disk fills up, and it always happens at the worst possible moment. The retention period is a business decision, not yours to make. Example: 180 days.
Host: pbx01, file /etc/systemd/system/rec-cleanup.service.
[Unit]
Description=Delete call recordings older than 180 days
[Service]
Type=oneshot
ExecStart=/usr/bin/find /var/spool/asterisk/monitor -type f -name '*.wav' -mtime +180 -delete
ExecStart=/usr/bin/find /var/spool/asterisk/monitor -mindepth 1 -type d -empty -delete
File /etc/systemd/system/rec-cleanup.timer.
[Unit]
Description=Daily call recordings cleanup
[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable --now rec-cleanup.timer
systemctl list-timers rec-cleanup.timer
Why a timer and not crontab. One careless line in crontab with find -delete and a typo in the path can wipe a year’s worth of recordings. A timer shows up in the unit list, logs to the journal, and is easier to double-check before enabling.
Monitoring
What to monitor: trunk registration, free disk space for recordings, service status, number of active calls. Example for a Zabbix agent.
Host: pbx01, file /etc/zabbix/zabbix_agent2.d/asterisk.conf. The agent needs permission to run asterisk -rx, add the zabbix user to the asterisk group.
UserParameter=asterisk.calls,asterisk -rx "core show channels count" | awk '/active call/ {print $1}'
UserParameter=asterisk.trunk.unregistered,asterisk -rx "pjsip show registrations" | grep -c -E 'Rejected|Unregistered|Failed'
UserParameter=asterisk.uptime.sec,asterisk -rx "core show uptime seconds" | awk '/System uptime/ {print $3}'
usermod -aG asterisk zabbix
systemctl restart zabbix-agent2
zabbix_agent2 -t asterisk.trunk.unregistered
Triggers: asterisk.trunk.unregistered above zero for more than 5 minutes, free space on /var/spool/asterisk/monitor under 15%, uptime reset, meaning a restart happened, worth knowing why.
Startup on boot
After a server reboot, everything should come back up on its own. Check this once, not after an outage.
systemctl is-enabled freepbx mariadb apache2 fail2ban
systemctl is-enabled rec-cleanup.timer
Result: enabled across the board. If a unit has a different name, check the output of systemctl list-unit-files | grep -Ei ‘freepbx|asterisk’.
Upgrading without surprises
What to check before upgrading:
- A fresh VM snapshot and a fresh backup via the Backup module.
- Apt repositories without the stable alias, see step 4 in this article.
- No active calls, or a maintenance window is scheduled.
- A list of what will be updated: modules and OS packages.
Host: the Proxmox node for the snapshot, then pbx01 for the upgrade.
qm snapshot 120 pre-update-$(date +%Y%m%d)
fwconsole ma showupgrades
fwconsole ma upgradeall
fwconsole reload
apt update
apt list --upgradable
apt upgrade
needrestart -k
During apt upgrade, decline any offer to move to Debian 13. FreePBX 17 stays on Debian 12 for its entire lifecycle. After upgrading, run the five test calls from the Verification section. Something broke? Roll back with the snapshot on the Proxmox node: qm rollback 120 and the snapshot name.
FAQ: common FreePBX 17 questions
What are the system requirements for FreePBX 17?
Officially, just a clean Debian 12. Sangoma doesn’t publish specific hardware numbers. In practice, for an office of up to 20 people, 2 vCPU, 4 GB RAM and 40 GB SSD is enough. Calculate recording storage separately: around 58 MB per hour of conversation in WAV.
Can you install FreePBX 17 on Ubuntu?
Technically yes, following third-party guides, but it’s not officially supported. The install script and all updates are tested only on Debian 12. For production, run Debian 12 in a separate VM.
How do you restart FreePBX without dropping calls?
Run asterisk -rx “core restart when convenient” in the console. Asterisk waits for all calls to finish and restarts on its own. You don’t need a restart to apply GUI settings, fwconsole reload is enough.
Where are FreePBX call recordings stored?
In /var/spool/asterisk/monitor/ with year/month/day subdirectories. Default format is WAV. The filename links to the call through the recordingfile column in the asteriskcdrdb.cdr table.
Why doesn’t call transfer with ## work?
Usually a DTMF mode mismatch. Both the extension and the phone need RFC 4733. Check that Asterisk Dial Options includes the letters T and t. The simplest fix is teaching people to use the phone’s Transfer button, it doesn’t depend on DTMF.
Why doesn’t Follow Me ring the mobile?
The external number in the Follow Me list needs a pound sign at the end: 89161234567#. Without it, FreePBX looks for an internal extension with that number. The second common cause is the outbound route or the provider blocking a call with a mismatched CallerID.
What’s the difference between Follow Me and call forwarding?
Forwarding sends the call to another number instead of the desk phone. Follow Me rings the desk phone first, then adds other numbers, and can ask for confirmation on the mobile. For employees who are often out of the office, Follow Me is more convenient.
Is there multicast paging in free FreePBX?
Not in the free Paging and Intercom module, it calls each phone individually. Officially, multicast is done through the commercial Page Pro. For free, you can set up the Page application with a MulticastRTP channel in extensions_custom.conf, or configure a multicast button directly on the phones.
Do you need to move to Debian 13 with FreePBX 17?
No. FreePBX 17 is built for Debian 12 through the end of its support in 2028. Debian 13 will be the base for FreePBX 18, planned for release in January 2027.
Outlook
What we did. Installed FreePBX 17 the official way on Debian 12 with a static address and clean repositories. Configured NAT so audio flows in both directions. Set up inbound routing with a fallback route, call forwarding, Follow Me with mobile confirmation, and call transfer. Enabled call recording, figured out where it’s stored and how much space it takes, moved it to a separate disk, and set up rotation. Added multicast paging without a paid module.
What works now. The PBX survives a reboot, an update, and the loss of a recordings disk. You know which restart drops calls and which doesn’t. The trunk and disk space are monitored, and international calls are blocked before anyone can run them up on your dime. A year from now, you’ll remember this install only because nothing went wrong.
Оставайтесь на связи
Рецепты от IT-боли. Без воды, без рекламы, без маркетинговой шелухи.
Подписаться на IT-Аптеку →




