The Ultimate Guide to Compiling FreeSWITCH v1.10.12 from Source

When deploying a production-grade communications platform, the foundation you build upon dictates the stability, scalability, and flexibility of your entire system. FreeSWITCH stands as one of the most powerful telephony engines available today, but installing it correctly is often the highest hurdle for new telephony engineers.
While many opt for simple pre-compiled packages, understanding how to install FreeSWITCH from source grants you the ultimate control over your deployment environment. It allows you to patch specific modules, optimize for your target CPU architecture, and deeply understand the dependency chain that makes real-time communications possible.
[!IMPORTANT] This guide focuses exclusively on compiling FreeSWITCH from source. If you prefer the convenience of official pre-compiled packages, you must first register an account at SignalWire and map a Personal Access Token (PAT) to authorize access to their official APT repositories.
In this deep-dive article, we will walk through the complete process of compiling FreeSWITCH v1.10.12 on a Debian-based system (such as Debian 11/12 or Ubuntu 20.04/22.04). More importantly, we'll explain why each step is necessary.
Step 1: System Preparation & Core Build Tools
Before configuring specific telecom libraries, we need the standard Linux compilation toolchain. This includes compilers (build-essential), configuration tools (autoconf, cmake), and various media formatting headers (libavformat-dev, libssl-dev).
Execute the following commands as root (or using sudo):
[!TIP] Ensure you have an updated system (
apt upgrade) before beginning to avoid conflicts with shared object libraries during the linking phase.
Step 2: Compiling SpanDSP (Specific Commit Requirement)
SpanDSP development is highly active, but FreeSWITCH v1.10.12 requires an exact snapshot of the library to maintain API compatibility. Using the wrong version will cause cryptic failures during the main FreeSWITCH make process.
Instead of downloading a random tarball, we will clone the repository, check out the specific commit hash 0d2e6ac, and perform a hard reset. This guarantees our environment matches the FreeSWITCH team's target baseline.
cd /usr/local/src
# Clone the repository to get the full git history
git clone https://github.com/freeswitch/spandsp.git
cd spandsp
# Lock the repository to the precise commit required
git reset --hard 0d2e6ac65e0e8f53d652665a743015a88bf048d4
# Bootstrapping prepares the autotools configuration
./bootstrap.sh
./configure
# Compile and install
make && make install
# Refresh dynamic linker bindings
/sbin/ldconfig -v | grep spandsp
If successful, the ldconfig output will list libspandsp.so.
Step 3: Integrating the Sofia-SIP Stack
Sofia-SIP handles session initiation, tear-down, and the complex state machine required for VoIP endpoints. Since the master branch of the FreeSWITCH fork is generally stable for this library, we can safely pull the latest master archive.
cd /usr/local/src
# Download the unified master archive
wget https://github.com/freeswitch/sofia-sip/archive/refs/heads/master.tar.gz -O sofia-sip.tar.gz
tar -zxvf sofia-sip.tar.gz
cd sofia-sip-master
# Standard compilation sequence
./bootstrap.sh
./configure
make && make install
# Inform the system of the new library
/sbin/ldconfig -v | grep sofia
Step 4: Adding Modern Cloud Hooks (LibKS & SignalWire-C)
As FreeSWITCH evolved, the architecture was modernized to support broader cloud integrations and more efficient internal communication structures. This necessitates compiling libks and signalwire-c.
Unlike the previous libraries, these utilize CMake rather than Autotools.
Part A: Installing LibKS
git clone https://github.com/signalwire/libks.git /usr/local/src/libks
cd /usr/local/src/libks
# Note the specific installation prefix required for seamless FS integration
cmake . -DCMAKE_INSTALL_PREFIX=/usr
make && make install
Part B: Installing SignalWire-C
cd /usr/local/src
wget https://github.com/signalwire/signalwire-c/archive/refs/heads/master.tar.gz -O signalwire-c.tar.gz
tar -zxvf signalwire-c.tar.gz
cd signalwire-c-master
cmake .
make && make install
/sbin/ldconfig -v | grep signalwire
Step 6: The Final FreeSWITCH Core Compilation
At last, with our environment meticulously prepared, we can turn our attention to the main event. We will download the official v1.10.12 release tag.
cd /usr/local/src
wget https://github.com/signalwire/freeswitch/archive/refs/tags/v1.10.12.tar.gz
tar -zxvf v1.10.12.tar.gz
cd freeswitch-1.10.12
# Bootstrap with multi-core support (-j)
./bootstrap.sh -j
# Configure the build parameters mapping to our compiled libraries
./configure \
CFLAGS="-Wno-error -Wno-implicit-function-declaration -Wno-incompatible-pointer-types" \
CXXFLAGS="-Wno-error" \
PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
# Compile the engine (this will take several minutes depending on CPU)
make
# Install the binaries to /usr/local/freeswitch
make install
# Optional but highly recommended: Install standard IVR sounds and Hold Music
make sounds-install moh-install
Module Configuration (modules.conf)
Before your final make, it's worth checking modules.conf. This file dictates which modules (mod_spandsp, mod_sofia, mod_event_socket, etc.) are compiled. If you manually linked Sofia-SIP and SpanDSP but they were commented out in modules.conf, they won't be explicitly available upon startup. FreeSWITCH 1.10.x usually enables the necessities by default, but a quick inspection never hurts.
Verification and Next Steps
The ultimate proof of a successful build is starting the interactive console. Switch directories and fire up the FreeSWITCH executable, asking it strictly for its version output:
/usr/local/freeswitch/bin/freeswitch -version
If you see FreeSWITCH version: 1.10.12-..., congratulations. You have successfully navigated the intricate dependency web and compiled a professional-grade telephony engine from scratch.
Post Installation Setup
Create Symlinks (Optional)
By default, FreeSWITCH will install its binaries and configurations in /usr/local/bin and /usr/local/freeswitch. To make them available system-wide, you can create the following symlinks:
ln -s /usr/local/freeswitch/conf /etc/freeswitch
ln -s /usr/local/freeswitch/bin/fs_cli /usr/bin/fs_cli
ln -s /usr/local/freeswitch/bin/freeswitch /usr/sbin/freeswitch
Create an Unprivileged User
For security, you should run the FreeSWITCH daemon under a dedicated, unprivileged system user instead of root.
groupadd freeswitch
adduser --quiet --system --home /usr/local/freeswitch --gecos 'FreeSWITCH open source softswitch' --ingroup freeswitch freeswitch --disabled-password
chown -R freeswitch:freeswitch /usr/local/freeswitch/
chmod -R ug=rwX,o= /usr/local/freeswitch/
chmod -R u=rwx,g=rx /usr/local/freeswitch/bin/*
Running as a Systemd Service
In order to run FreeSWITCH in the background seamlessly, open /etc/systemd/system/freeswitch.service in your favorite editor (like nano or vim) and copy the following configuration into it:
[Unit]
Description=FreeSWITCH open source softswitch
Wants=network-online.target
Requires=network.target local-fs.target
After=network.target network-online.target local-fs.target
[Service]
Type=forking
PIDFile=/usr/local/freeswitch/run/freeswitch.pid
Environment="DAEMON_OPTS=-nonat"
Environment="USER=freeswitch"
Environment="GROUP=freeswitch"
EnvironmentFile=-/etc/default/freeswitch
ExecStartPre=/bin/chown -R ${USER}:${GROUP} /usr/local/freeswitch
ExecStart=/usr/local/freeswitch/bin/freeswitch -u ${USER} -g ${GROUP} -ncwait ${DAEMON_OPTS}
TimeoutSec=45s
Restart=always
[Install]
WantedBy=multi-user.target
Reload the systemctl daemon so it registers the new service file:
systemctl daemon-reload
Start the FreeSWITCH daemon:
systemctl start freeswitch
Ensure the daemon started successfully without exiting:
systemctl status freeswitch
That's it! From here, your next journey revolves around mastering XML configuration, dialgroups, and SIP profiles.
Next Steps
Once your FreeSWITCH instance is operational, explore some of our advanced engineering guides to further scale and customize your deployment:
Discussion0
Join the conversation. Sign in to leave a comment.