FreeSWITCH is an open-source telephony platform designed for routing and interconnecting voice, video, and text communication protocols. It handles SIP, WebRTC, PSTN gateways, IVR systems, conference bridges, and more. The current stable release is FreeSWITCH 1.10.12, and SignalWire maintains pre-built Debian/Ubuntu packages that make installation straightforward.
This guide walks through a complete FreeSWITCH PBX installation on Ubuntu 24.04 using the official SignalWire repository. You will set up the repo with a Personal Access Token, install the packages, verify the service, configure your firewall, and run a basic dialplan test.
Prerequisites
Before starting, make sure you have the following in place:
- A fresh Ubuntu 24.04 server with at least 2 GB RAM and 2 CPU cores
- Root or sudo access
- A SignalWire Personal Access Token (PAT) – free to create at id.signalwire.com/personal_access_tokens
- Ports 5060/UDP (SIP), 5080/UDP (external SIP profile), and 8021/TCP (Event Socket) available
- A public IP or properly configured NAT if this is a production PBX
Step 1: Get a SignalWire Personal Access Token
SignalWire requires authentication to access the FreeSWITCH package repository. You need a free Personal Access Token (PAT) before adding the repo.
Go to https://id.signalwire.com/personal_access_tokens and create a free SignalWire account if you do not have one. Once logged in, generate a new Personal Access Token. Copy the token and keep it safe – you will need it in the next step.
Step 2: Update the System
Start by updating existing packages and installing dependencies needed for the repository setup.
sudo apt update && sudo apt upgrade -y
Install the required packages for HTTPS repo access and GPG key handling.
sudo apt install -y gnupg2 wget lsb-release software-properties-common apt-transport-https curl
Step 3: Add the SignalWire FreeSWITCH Repository
Set your SignalWire Personal Access Token as an environment variable. Replace your_signalwire_pat_here with the actual token you generated.
TOKEN=your_signalwire_pat_here
Download and install the SignalWire GPG signing key. This authenticates the packages from the repository.
curl --http1.1 -fsSL https://freeswitch.signalwire.com/repo/deb/debian-release/signalwire-freeswitch-repo.gpg | sudo gpg --dearmor -o /usr/share/keyrings/signalwire-freeswitch-repo.gpg
Store your token in a file so apt can authenticate with the repository during updates.
echo "machine freeswitch.signalwire.com login signalwire password $TOKEN" | sudo tee /etc/apt/auth.conf.d/freeswitch.conf
sudo chmod 600 /etc/apt/auth.conf.d/freeswitch.conf
Add the FreeSWITCH repository to your apt sources. The SignalWire repo uses Debian Bookworm packages which are compatible with Ubuntu 24.04.
echo "deb [signed-by=/usr/share/keyrings/signalwire-freeswitch-repo.gpg] https://freeswitch.signalwire.com/repo/deb/debian-release/ bookworm main" | sudo tee /etc/apt/sources.list.d/freeswitch.list
Update the package index to pull in the FreeSWITCH packages from the new repo.
sudo apt update
If the update runs without authentication errors, the token and repo configuration are correct.
Step 4: Install FreeSWITCH
Install the FreeSWITCH meta package along with commonly needed modules. The freeswitch-meta-all package pulls in the core daemon plus a full set of modules for codecs, applications, dialplan handling, and more.
sudo apt install -y freeswitch-meta-all
This installs a substantial number of packages. If you prefer a minimal installation, use freeswitch-meta-vanilla instead, which installs only the core modules needed for basic SIP calling.
sudo apt install -y freeswitch-meta-vanilla
For production systems where you know exactly which modules you need, you can also install them individually. Some common packages include:
freeswitch– the core daemonfreeswitch-mod-commands– API commandsfreeswitch-mod-sofia– SIP modulefreeswitch-mod-dptools– dialplan toolsfreeswitch-mod-dialplan-xml– XML dialplan enginefreeswitch-mod-console– console loggingfreeswitch-sounds-en-us-callie– English sound filesfreeswitch-music-default– hold music
Step 5: Enable and Start FreeSWITCH
Enable the FreeSWITCH service to start on boot and start it immediately.
sudo systemctl enable --now freeswitch
Verify the service is running. You should see active (running) in the output.
sudo systemctl status freeswitch
The output confirms the daemon is up and listening for connections:
● freeswitch.service - freeswitch
Loaded: loaded (/lib/systemd/system/freeswitch.service; enabled; preset: enabled)
Active: active (running) since Mon 2026-03-24 10:15:32 UTC; 5s ago
Main PID: 4521 (freeswitch)
Tasks: 35 (limit: 4557)
Memory: 68.2M
CPU: 2.145s
CGroup: /system.slice/freeswitch.service
└─4521 /usr/bin/freeswitch -u freeswitch -g freeswitch -ncwait
Step 6: Verify with fs_cli
FreeSWITCH ships with fs_cli, a command-line client that connects to the running instance through the Event Socket Layer (ESL) on port 8021. Use it to confirm the installation is working properly.
sudo fs_cli -x "version"
You should see the installed FreeSWITCH version confirmed:
FreeSWITCH Version 1.10.12-release~64bit (-release 64bit)
Check the status of the running instance with more detail.
sudo fs_cli -x "status"
This shows uptime, session counts, and the stack size:
UP 0 years, 0 days, 0 hours, 2 minutes, 15 seconds, 342 milliseconds, 128 microseconds
FreeSWITCH (Version 1.10.12-release 64bit) is ready
0 session(s) since startup
0 session(s) - peak 0, last 5min 0
0 session(s) per Sec out of max 30, peak 0, last 5min 0
1000 session(s) max
min idle cpu 0.00/100.00
Current Stack Size/Max 240K/8192K
To enter the interactive FreeSWITCH console, run fs_cli without the -x flag.
sudo fs_cli
Type /quit or press Ctrl+D to exit the console.
You can also list all loaded modules to verify everything initialized correctly.
sudo fs_cli -x "show modules"
Check that the SIP module (mod_sofia) is loaded and listening.
sudo fs_cli -x "sofia status"
You should see the internal and external SIP profiles listed with their listening addresses:
Name Type Data State
=================================================================================================
internal profile sip:[email protected]:5060 RUNNING (0)
external profile sip:[email protected]:5080 RUNNING (0)
external-ipv6 profile sip:mod_sofia@[::1]:5080 RUNNING (0)
internal-ipv6 profile sip:mod_sofia@[::1]:5060 RUNNING (0)
=================================================================================================
4 profiles 0 aliases
Step 7: Configure the Firewall
FreeSWITCH needs several ports open for SIP signaling, RTP media, and management access. On Ubuntu, ufw is the standard firewall tool.
Open port 5060 for SIP on the internal profile (used by your phones/endpoints).
sudo ufw allow 5060/udp comment "FreeSWITCH SIP internal"
sudo ufw allow 5060/tcp comment "FreeSWITCH SIP internal TCP"
Open port 5080 for the external SIP profile (used for trunk/gateway connections).
sudo ufw allow 5080/udp comment "FreeSWITCH SIP external"
sudo ufw allow 5080/tcp comment "FreeSWITCH SIP external TCP"
Open the RTP media port range. FreeSWITCH uses UDP ports 16384 through 32768 for audio/video streams by default.
sudo ufw allow 16384:32768/udp comment "FreeSWITCH RTP media"
The Event Socket Layer (ESL) listens on port 8021. Only open this if you need remote ESL access. For local-only access (which is the default), skip this rule.
sudo ufw allow 8021/tcp comment "FreeSWITCH ESL"
Enable the firewall if it is not already active and verify the rules are in place.
sudo ufw enable
sudo ufw status verbose
The status output should show all the FreeSWITCH rules along with your SSH rule:
Status: active
To Action From
-- ------ ----
22/tcp ALLOW Anywhere
5060/udp ALLOW Anywhere # FreeSWITCH SIP internal
5060/tcp ALLOW Anywhere # FreeSWITCH SIP internal TCP
5080/udp ALLOW Anywhere # FreeSWITCH SIP external
5080/tcp ALLOW Anywhere # FreeSWITCH SIP external TCP
16384:32768/udp ALLOW Anywhere # FreeSWITCH RTP media
8021/tcp ALLOW Anywhere # FreeSWITCH ESL
In production, restrict the ESL port (8021) and SIP ports to specific IP addresses rather than allowing from anywhere. SIP scanners constantly probe port 5060 on public servers.
Step 8: Understand the FreeSWITCH Directory Structure
Knowing where FreeSWITCH keeps its files saves time when troubleshooting and customizing the system.
/etc/freeswitch/– all configuration files (XML)/usr/lib/freeswitch/mod/– compiled modules (.so files)/usr/share/freeswitch/sounds/– sound files and prompts/var/lib/freeswitch/– runtime data, recordings, voicemail/var/log/freeswitch/– log files/usr/bin/freeswitch– the main binary/usr/bin/fs_cli– the CLI client
The main configuration entry point is /etc/freeswitch/freeswitch.xml, which includes all other XML files. The configuration is modular – SIP profiles live in /etc/freeswitch/sip_profiles/, dialplan contexts in /etc/freeswitch/dialplan/, and directory (user) definitions in /etc/freeswitch/directory/.
Step 9: Basic Configuration
The default FreeSWITCH configuration ships with a functional demo setup that includes 20 preconfigured extensions (1000-1019), conference rooms, voicemail, and IVR examples. This is useful for testing but should be replaced with your own configuration for production.
Set the Default Password
All 20 default extensions share the same password: 1234. Change this immediately, even in a lab environment. The default password is set in one place.
Open the vars.xml configuration file.
sudo vi /etc/freeswitch/vars.xml
Find the line that sets the default password and change 1234 to a strong password:
<X-PRE-PROCESS cmd="set" data="default_password=YourStr0ngP@ssword"/>
Configure the External IP Address
If your FreeSWITCH server is behind NAT (common in cloud environments), you need to set the external IP address so SIP and RTP traffic route correctly.
Open the vars.xml file again.
sudo vi /etc/freeswitch/vars.xml
Find and update the external SIP and RTP IP variables. Replace 203.0.113.50 with your actual public IP:
<X-PRE-PROCESS cmd="set" data="external_sip_ip=203.0.113.50"/>
<X-PRE-PROCESS cmd="set" data="external_rtp_ip=203.0.113.50"/>
For servers with dynamic public IPs, you can use the auto-detection methods built into FreeSWITCH:
<X-PRE-PROCESS cmd="set" data="external_sip_ip=stun:stun.freeswitch.org"/>
<X-PRE-PROCESS cmd="set" data="external_rtp_ip=stun:stun.freeswitch.org"/>
Change the Event Socket Password
The ESL (Event Socket Layer) uses the default password ClueCon. Change it to prevent unauthorized access to the FreeSWITCH API.
Open the Event Socket configuration.
sudo vi /etc/freeswitch/autoload_configs/event_socket.conf.xml
Change the password parameter to something unique:
<param name="password" value="YourESLpassword"/>
After making any configuration changes, reload FreeSWITCH to apply them.
sudo systemctl restart freeswitch
Verify the service is still running after the restart.
sudo systemctl status freeswitch
Step 10: Test with a Basic Dialplan Call
The default FreeSWITCH configuration includes a working dialplan with test extensions. You can verify the system works without connecting a SIP phone by using the built-in originate command to trigger a test call.
Call the default echo extension (extension 9196) which echoes back whatever audio it receives. This tests the media path.
sudo fs_cli -x "originate loopback/9196 &echo"
You should see a successful call setup confirmed:
+OK 0f3a5c6e-8b7d-4a1f-9c2e-3d5f7a8b9c0d
Check active calls to confirm the call is running.
sudo fs_cli -x "show calls"
You can also test the music-on-hold extension (9664) or the info/talking clock extension (9170). These built-in test extensions are useful for validating that codecs and audio processing work correctly.
Hang up all active test calls when done.
sudo fs_cli -x "hupall"
Register a SIP Phone
To make real calls, register a SIP softphone (like Zoiper, Linphone, or MicroSIP) using one of the preconfigured extensions. Here are the settings to use:
- Username: 1000 (any number from 1000 to 1019)
- Password: the password you set in
vars.xml(or1234if unchanged) - Domain/Server: your FreeSWITCH server IP address
- Transport: UDP
- Port: 5060
Once registered, dial extension 9196 (echo test) or call between two registered extensions (e.g., 1000 calls 1001) to verify end-to-end SIP calling.
Step 11: View Logs
FreeSWITCH writes detailed logs to /var/log/freeswitch/freeswitch.log. Tail the log in real time while troubleshooting.
sudo tail -f /var/log/freeswitch/freeswitch.log
You can also change the log level from within fs_cli for more verbose output during debugging.
sudo fs_cli -x "console loglevel debug"
For SIP-specific debugging, enable SIP trace on the internal profile to see the raw SIP messages.
sudo fs_cli -x "sofia profile internal siptrace on"
Turn it off when done because SIP tracing generates a lot of output in the log files.
sudo fs_cli -x "sofia profile internal siptrace off"
Troubleshooting FreeSWITCH Installation Issues
Repository Authentication Fails
If apt update returns a 401 Unauthorized error for the SignalWire repo, your token is incorrect or expired. Verify the token at id.signalwire.com and update the auth file.
sudo cat /etc/apt/auth.conf.d/freeswitch.conf
Make sure the file contains the correct format with no extra spaces or line breaks:
machine freeswitch.signalwire.com login signalwire password pat_YOUR_ACTUAL_TOKEN
FreeSWITCH Fails to Start
Check the journal for startup errors.
sudo journalctl -u freeswitch -n 50 --no-pager
Common causes include another process already using port 5060 (like Asterisk or another SIP daemon) or incorrect XML syntax in the configuration files. Check for port conflicts with:
sudo ss -tulnp | grep -E "5060|5080|8021"
fs_cli Cannot Connect
If fs_cli returns a connection refused error, the Event Socket module may not be loaded or FreeSWITCH is not running. First confirm the service is up.
sudo systemctl status freeswitch
If the service is running but fs_cli still fails, check that the Event Socket module is configured to listen on localhost. Verify the ESL configuration.
sudo cat /etc/freeswitch/autoload_configs/event_socket.conf.xml
The listen-ip parameter should be :: or 127.0.0.1. If you changed the ESL password, pass it to fs_cli explicitly.
sudo fs_cli -p YourESLpassword
SIP Phone Cannot Register
If a softphone cannot register, check the following:
- Firewall ports 5060/UDP and 5060/TCP are open
- The phone is pointed at the correct IP and port
- The extension password matches what is configured in
vars.xml - Enable SIP trace to see the registration attempt and any error responses
No Audio on Calls (One-Way or No-Way Audio)
Audio issues are almost always NAT-related. Make sure:
- The
external_sip_ipandexternal_rtp_ipvariables invars.xmlare set to your public IP - The RTP port range (16384-32768/UDP) is open in the firewall and forwarded through any NAT device
- Your SIP phone has STUN enabled or is configured for the correct NAT traversal method
Managing FreeSWITCH
Here are the common service management commands you will use day to day.
Stop the FreeSWITCH service.
sudo systemctl stop freeswitch
Restart FreeSWITCH to apply configuration changes.
sudo systemctl restart freeswitch
Reload the XML configuration without a full restart. This is faster and does not drop active calls.
sudo fs_cli -x "reloadxml"
Reload a specific module without restarting the entire daemon.
sudo fs_cli -x "reload mod_sofia"
Frequently Asked Questions
Is the SignalWire Personal Access Token free?
Yes. You can create a free SignalWire account and generate a Personal Access Token at no cost. The token is only required to authenticate with the FreeSWITCH package repository. You do not need a paid SignalWire plan to use FreeSWITCH.
Can FreeSWITCH handle production call volumes?
FreeSWITCH is built for high-performance telephony. A single server with adequate resources (8 cores, 16 GB RAM) can handle thousands of concurrent calls. The actual capacity depends on your codec choices (G.711 uses more CPU than G.729 with hardware transcoding), whether you are doing transcoding, and how complex your dialplan logic is.
What is the difference between the internal and external SIP profiles?
The internal profile (port 5060) is for your local endpoints – IP phones, softphones, and internal devices that register with FreeSWITCH. The external profile (port 5080) is for connections to SIP trunks, PSTN gateways, and other SIP servers that do not register locally. Keep this separation to apply different security policies to each.
How do I upgrade FreeSWITCH?
Since FreeSWITCH is installed from the SignalWire apt repository, upgrading is a standard apt operation. Always back up your configuration first.
sudo cp -r /etc/freeswitch /etc/freeswitch.bak
sudo apt update && sudo apt upgrade -y
sudo systemctl restart freeswitch
Check the FreeSWITCH release notes before upgrading to understand any breaking changes.