📞 Part 2: Compiling and Packaging Telephony Server Engine on Debian 13 (Trixie)
Welcome to the second installment of our “Debian 13 Packaging & Distribution” series. In the previous post, we successfully built and secured our custom Debian APT repository server. In this guide, we will focus on compiling the core communications engine, Telephony Server (v1.11.1), along with its custom dependencies (SpanDSP, Sofia-SIP, libks2, signalwire-c, and libbroadvoice) from source. We will also address complex VM and clock-skew compilation traps, generate modular .deb packages, and publish them to our central repository.
🛠️ Phase 1: Setting Up the Build Environment
Section titled “🛠️ Phase 1: Setting Up the Build Environment”Debian 13 (Trixie) utilizes modern compiler toolchains. To prepare your build node (which can be a dedicated VM or container running Debian 13), install the core development utilities.
1.1 Install Packaging and Compiling Tools
Section titled “1.1 Install Packaging and Compiling Tools”apt-get updateapt-get install -y \ sudo git build-essential devscripts dpkg-dev equivs fakeroot \ autoconf automake libtool libtool-bin cmake pkg-config \ wget curl unzip python-is-python3 python3-all-dev \ erlang-dev libtpl-dev libgdbm-dev libdb-dev \ python3-setuptools docbook-xsl xsltproc \ libglib2.0-dev graphviz dh-make dh-python1.2 Install Telephony Server Compilation Prerequisites
Section titled “1.2 Install Telephony Server Compilation Prerequisites”Telephony Server relies on system libraries for features like SSL, database connectivity, and codecs. Run the following command to install the required header files:
apt-get install -y \ uuid-dev zlib1g-dev libjpeg-dev libsqlite3-dev libcurl4-openssl-dev \ libpcre2-dev libspeex-dev libspeexdsp-dev libldns-dev libedit-dev \ libtiff5-dev yasm libopus-dev libsndfile1-dev libavformat-dev \ libswscale-dev liblua5.2-dev liblua5.2-0 libpq-dev unixodbc-dev \ libxml2-dev libpq5 sngrep libswresample-dev bison doxygen \ libjansson-dev libopencv-dev libhiredis-dev libmemcached-dev \ libsphinxbase-dev libpocketsphinx-dev libopencore-amrnb-dev \ libmariadb-dev libperl-dev libgdbm-compat-dev librabbitmq-dev \ libsnmp-dev libmagickcore-dev libopusfile-dev libmp3lame-dev \ libshout3-dev libvlc-dev default-jdk mono-mcs libasound2-dev \ libcodec2-dev python-dev-is-python3[!NOTE] PCRE Library Warning: Debian 13 completely removes
libpcre3-dev(PCRE 8.x, which has reached End-of-Life). We use the modern replacement,libpcre2-dev, which Telephony Server supports natively.
📦 Phase 2: Building Telephony Dependencies
Section titled “📦 Phase 2: Building Telephony Dependencies”Several libraries required by Telephony Server are either outdated in Debian’s official repository or require specific patches for stability. We compile them first, generate their .deb files, and install them so they are recognized during the main Telephony Server configuration phase.
2.1 spandsp (libspandsp4)
Section titled “2.1 spandsp (libspandsp4)”SpanDSP handles critical telephony tasks such as T.38 faxing, tone detection, and classic modems.
cd /usr/srcgit clone https://github.com/freeswitch/spandsp.gitcd spandsp./bootstrap.sh./configure
fakeroot debian/rules cleandpkg-buildpackage -us -uc -b
# Isolate packagesmkdir -p /usr/src/freeswitch/debmv /usr/src/libspandsp*.deb /usr/src/freeswitch/deb/
# Install dependencies locally to build Telephony Servercd /usr/src/freeswitch/debapt install -y ./libspandsp4_*.deb ./libspandsp4-dev_*.debapt-get install -f -y2.2 libks (v2.0)
Section titled “2.2 libks (v2.0)”This SignalWire communication library requires a custom Debian packaging structure.
cd /usr/srcgit clone https://github.com/signalwire/libks.gitcd libksmkdir -p debianCreate the required packaging files in the debian/ directory directly:
2.2.1 Control File (debian/control)
Section titled “2.2.1 Control File (debian/control)”Defines the source and binary packages, their metadata, build-time dependencies, and runtime dependencies.
cat <<'EOF' > debian/controlSource: libksSection: libsPriority: optionalMaintainer: [YOUR_FULL_NAME] <[EMAIL_ADDRESS]>Build-Depends: debhelper-compat (= 13), cmake, libpcre2-dev, uuid-devStandards-Version: 4.6.2Homepage: https://github.com/signalwire/libks
Package: libks2Architecture: anyDepends: ${shlibs:Depends}, ${misc:Depends}Description: SignalWire libks library A library for communication protocols developed by SignalWire.
Package: libks2-devArchitecture: anyDepends: libks2 (= ${binary:Version}), ${misc:Depends}Description: Development files for libks Development headers and libraries for libks.EOF2.2.2 Rules File (debian/rules)
Section titled “2.2.2 Rules File (debian/rules)”The makefile containing rules that dictate how the package is configured, built, and installed into temporary directories.
cat <<'EOF' > debian/rules#!/usr/bin/make -f%: dh $@
override_dh_auto_configure: cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release .
override_dh_auto_install: dh_auto_install --destdir=debian/tmp
override_dh_auto_clean: dh_clean
override_dh_installdocs: dh_installdocs dh_installdocs -plibks2-dev --link-doc=libks2EOFMake the script executable:
chmod +x debian/rules2.2.3 Changelog File (debian/changelog)
Section titled “2.2.3 Changelog File (debian/changelog)”Maintains the release history, package versioning, and change list.
cat <<'EOF' > debian/changeloglibks (2.0-7) unstable; urgency=medium
* Initial packaging for Debian 13.
-- [YOUR_FULL_NAME] <[EMAIL_ADDRESS]> Mon, 08 Sep 2025 20:30:00 +0000EOF2.2.4 Copyright File (debian/copyright)
Section titled “2.2.4 Copyright File (debian/copyright)”Documents the license and copyright information for the package.
cat <<'EOF' > debian/copyrightFormat: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/Files: *Copyright: 2025 SignalWire, Inc.License: MPL-1.1EOF2.2.5 Library Install File (debian/libks2.install)
Section titled “2.2.5 Library Install File (debian/libks2.install)”Specifies which built files (libraries) go into the runtime binary package (libks2).
cat <<'EOF' > debian/libks2.installusr/lib/libks2.so*EOF2.2.6 Development Install File (debian/libks2-dev.install)
Section titled “2.2.6 Development Install File (debian/libks2-dev.install)”Specifies development assets (header files and pkg-config manifests) that go into the development package.
cat <<'EOF' > debian/libks2-dev.installusr/include/libks2/*usr/lib/pkgconfig/libks2.pcEOF2.2.7 Unpackaged Files List (debian/not-installed)
Section titled “2.2.7 Unpackaged Files List (debian/not-installed)”Tells the build system to ignore generated files that are intentionally not packaged (such as the default changelog and copyright files).
cat <<'EOF' > debian/not-installedusr/share/doc/libks2/changelog.Debian.gzusr/share/doc/libks2/copyrightEOFNow, clean, build, and install the package:
# Clean potential CMake residuals from manual buildsrm -rf CMakeCache.txt CMakeFiles/ cmake_install.cmake Makefile obj-*fakeroot debian/rules cleanDEB_BUILD_OPTIONS="nocheck" dpkg-buildpackage -us -uc -b
mv /usr/src/libks2*.deb /usr/src/freeswitch/deb/cd /usr/src/freeswitch/debdpkg -i libks2_*.deb libks2-dev_*.debapt-get install -f -y2.3 sofia-sip
Section titled “2.3 sofia-sip”Sofia-SIP is the underlying SIP user-agent library used by Telephony Server’s endpoint module mod_sofia.
[!IMPORTANT] Preventing Collisions with Official Debian Repository Packages: The official Debian repositories distribute standard (unpatched) versions of Sofia-SIP (
libsofia-sip-ua0andlibsofia-sip-ua-dev). To prevent routine system updates (apt upgrade) from overwriting our custom patched Sofia-SIP packages, we rename all Sofia-SIP binary packages to use the prefixfreeswitch-sofia-sipinstead oflibsofia-sip. We declare versionedProvides,Conflicts, andReplacesdirectives pointing to the official Debian package names indebian/controlso that Telephony Server’s compilation and runtime dependencies are fully satisfied without conflicts.
cd /usr/srcgit clone https://github.com/freeswitch/sofia-sip.gitcd sofia-sip./bootstrap.sh./configure
# Rename source and binary packages in debian/control and add versioned Provides/Conflicts/Replacespython3 -c "import re, oscontent = open('debian/control').read()content = content.replace('libsofia-sip', 'freeswitch-sofia-sip')content = re.sub(r'(?<!freeswitch-)sofia-sip', 'freeswitch-sofia-sip', content)
packages = { 'freeswitch-sofia-sip-bin': 'sofia-sip-bin', 'freeswitch-sofia-sip-ua0': 'libsofia-sip-ua0', 'freeswitch-sofia-sip-ua-dev': 'libsofia-sip-ua-dev', 'freeswitch-sofia-sip-ua-glib3': 'libsofia-sip-ua-glib3', 'freeswitch-sofia-sip-ua-glib-dev': 'libsofia-sip-ua-glib-dev',}for pkg, orig in packages.items(): pattern = rf'(Package:\s*{pkg}\s*\nArchitecture:\s*any\s*\n)' replacement = rf'\1Provides: {orig} (= \${{binary:Version}})\nConflicts: {orig}\nReplaces: {orig}\n' content = re.sub(pattern, replacement, content)
open('debian/control', 'w').write(content)
for f in os.listdir('debian'): if 'sofia-sip' in f and not f.startswith('freeswitch-'): if f.startswith('libsofia-sip'): new_f = 'freeswitch-sofia-sip' + f[len('libsofia-sip'):] elif f.startswith('sofia-sip'): new_f = 'freeswitch-sofia-sip' + f[len('sofia-sip'):] else: new_f = f os.rename(os.path.join('debian', f), os.path.join('debian', new_f))"
# Update source package name in debian/changelogsed -i 's/^sofia-sip/freeswitch-sofia-sip/g' debian/changelog
# Dynamically extract current upstream version from debian/changelog (e.g., 1.13.18)CURRENT_VER=$(dpkg-parsechangelog -S Version | sed 's/-.*//')
# Add a custom changelog entry with the +softswitch version suffixdch -b -v "${CURRENT_VER}-0+softswitch" "Custom compile with versioned Provides"
# Clean packaging workspace and compile unsigned binary-only Debian packagesfakeroot debian/rules cleandpkg-buildpackage -us -uc -b
# Isolate generated packages into the staging directorymkdir -p /usr/src/freeswitch/debmv /usr/src/freeswitch-sofia-sip*.deb /usr/src/freeswitch/deb/
# Install custom Sofia-SIP packages locally so Telephony Server can link against them during compilationcd /usr/src/freeswitch/debapt install -y ./freeswitch-sofia-sip-ua0_*.deb ./freeswitch-sofia-sip-ua-dev_*.deb ./freeswitch-sofia-sip-bin_*.debapt-get install -f -y2.4 libbroadvoice
Section titled “2.4 libbroadvoice”This codec library handles BroadVoice 16/32-bit audio profiles.
cd /usr/srcgit clone https://github.com/freeswitch/libbroadvoice.gitcd libbroadvoice./autogen.sh./configure
fakeroot debian/rules cleandpkg-buildpackage -us -uc -b
mv /usr/src/libbroadvoice*.deb /usr/src/freeswitch/deb/cd /usr/src/freeswitch/debdpkg -i libbroadvoice1_*.deb libbroadvoice-dev_*.deb2.5 signalwire-c
Section titled “2.5 signalwire-c”Create the SignalWire C API library.
cd /usr/srcgit clone https://github.com/signalwire/signalwire-c.gitcd signalwire-cmkdir -p debianCreate the required packaging files in the debian/ directory directly:
2.5.1 Control File (debian/control)
Section titled “2.5.1 Control File (debian/control)”Defines the source and binary packages, their metadata, build-time dependencies, and runtime dependencies.
cat <<'EOF' > debian/controlSource: signalwire-cSection: libsPriority: optionalMaintainer: [YOUR_FULL_NAME] <[EMAIL_ADDRESS]>Build-Depends: debhelper-compat (= 13), cmake, libpcre2-dev, uuid-dev, libssl-dev, libjansson-devStandards-Version: 4.6.2Homepage: https://github.com/signalwire/signalwire-c
Package: signalwire-client-c2Architecture: anyDepends: ${shlibs:Depends}, ${misc:Depends}, libks2Description: SignalWire C client library (version 2)
Package: signalwire-client-c2-devArchitecture: anyDepends: signalwire-client-c2 (= ${binary:Version}), ${misc:Depends}, libks2-devDescription: Development files for SignalWire C client library (version 2)EOF2.5.2 Rules File (debian/rules)
Section titled “2.5.2 Rules File (debian/rules)”The makefile containing rules that dictate how the package is configured, built, and installed into temporary directories.
cat <<'EOF' > debian/rules#!/usr/bin/make -fexport DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
%: dh $@
override_dh_auto_configure: cmake -DCMAKE_INSTALL_PREFIX=/usr \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_SHARED_LIBS=ON \ -DINSTALL_PKGCONFIG_DIR=/usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig .
override_dh_auto_install: dh_auto_install --destdir=debian/tmp mkdir -p debian/tmp/usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig mv debian/tmp/usr/lib/pkgconfig/signalwire_client2.pc debian/tmp/usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig/ rmdir debian/tmp/usr/lib/pkgconfig
override_dh_auto_test: : # Skip tests
override_dh_auto_clean: dh_clean
override_dh_installdocs: dh_installdocs dh_installdocs -psignalwire-client-c2-dev --link-doc=signalwire-client-c2EOFMake the script executable:
chmod +x debian/rules2.5.3 Changelog File (debian/changelog)
Section titled “2.5.3 Changelog File (debian/changelog)”Maintains the release history, package versioning, and change list.
cat <<'EOF' > debian/changelogsignalwire-c (1.0-13) unstable; urgency=medium
* Initial package packaging for Debian 13.
-- [YOUR_FULL_NAME] <[EMAIL_ADDRESS]> Mon, 08 Sep 2025 22:00:00 +0000EOF2.5.4 Install File (debian/signalwire-client-c2.install)
Section titled “2.5.4 Install File (debian/signalwire-client-c2.install)”Specifies which built files (libraries) go into the runtime binary package (signalwire-client-c2).
cat <<'EOF' > debian/signalwire-client-c2.installusr/lib/libsignalwire_client2.so*EOF2.5.5 Development Install File (debian/signalwire-client-c2-dev.install)
Section titled “2.5.5 Development Install File (debian/signalwire-client-c2-dev.install)”Specifies development assets (header files and pkg-config manifests) that go into the development package.
cat <<'EOF' > debian/signalwire-client-c2-dev.installusr/include/signalwire-client-c2/*usr/lib/*/pkgconfig/signalwire_client2.pcEOF2.5.6 Unpackaged Files List (debian/not-installed)
Section titled “2.5.6 Unpackaged Files List (debian/not-installed)”Tells the build system to ignore generated files that are intentionally not packaged (such as the default changelog and copyright files).
cat <<'EOF' > debian/not-installedusr/share/doc/signalwire-client-c2/changelog.Debian.gzusr/share/doc/signalwire-client-c2/copyrightEOFBuild and install:
fakeroot debian/rules cleandpkg-buildpackage -us -uc -b
mv /usr/src/signalwire-client-c2*.deb /usr/src/freeswitch/deb/cd /usr/src/freeswitch/debdpkg -i signalwire-client-c2_*.deb signalwire-client-c2-dev_*.debapt-get install -f -y⚙️ Phase 3: Compiling & Packaging Telephony Server
Section titled “⚙️ Phase 3: Compiling & Packaging Telephony Server”Now that our compilation node is loaded with all custom dependencies, we clone Telephony Server and structure our Debian builds.
3.1 Clone the Source Code & Configure
Section titled “3.1 Clone the Source Code & Configure”We will dynamically fetch and clone the latest stable Telephony Server release tag (or you may target a specific release like v1.11.1):
cd /usr/src
# Dynamically resolve the latest release tag (e.g., v1.11.1)FS_TAG=$(git ls-remote --tags --sort="v:refname" https://github.com/signalwire/freeswitch.git | grep -o 'refs/tags/v[0-9].*' | cut -d/ -f3 | grep -v '\^{}' | tail -n1)
# Clone the latest stable releasegit clone -b "${FS_TAG}" --depth 1 https://github.com/signalwire/freeswitch.git /usr/src/freeswitch/srccd /usr/src/freeswitch/src
./bootstrap.sh -j
# Prevent file system timestamp skew loopfind . -type f -exec touch {} +
./configure \ --enable-core-odbc-support \ --enable-core-pgsql-support \ --enable-pcre2 \ --prefix=/usr \ --sysconfdir=/etc \ --localstatedir=/var \ --disable-maintainer-mode \ --disable-dependency-tracking⚙️ Configuration Flags Breakdown:
Section titled “⚙️ Configuration Flags Breakdown:”--enable-core-odbc-support&--enable-core-pgsql-support: Compiles native database connectivity (ODBC & direct PostgreSQL) directly into Telephony Server’s core library (libfreeswitch), enabling channel state persistence, multi-tenant directory lookups, and real-time CDR logging.--enable-pcre2: Mandates the use of modern Perl-Compatible Regular Expressions (PCRE2). This is strictly required for Debian 13 (Trixie), where legacylibpcre3has been completely deprecated.--prefix=/usr,--sysconfdir=/etc,--localstatedir=/var: Conforms Telephony Server directory paths to standard Debian Filesystem Hierarchy Standard (FHS) conventions (/usr/bin,/etc/freeswitch,/var/log/freeswitch,/var/lib/freeswitch).--disable-maintainer-mode&--disable-dependency-tracking: Prevents Autotools from triggering automatic and infinite Makefile regeneration loops due to container/VM filesystem timestamp skew, while significantly reducing overall build time.
3.2 Add Custom Workarounds for Debian 13 Packaging
Section titled “3.2 Add Custom Workarounds for Debian 13 Packaging”Before launching dpkg-buildpackage, we must bypass several known packaging issues:
- Incompatible Modules: Exclude legacy features like V8/Javascript and obsolete audio codecs (silk, ilbc, flite) that are not compatible with Debian 13 build environments.
dh_auto_cleanRecursion Loop: Autotools comparisons can trigger an infinite build cleaner recursion loop. We override this loop as a no-op.- Parallel Race Condition: Generating
modules.incunder concurrent build jobs (e.g.,-j8) results in race conditions. We force sequential module packaging.
Run these adjustments:
cd /usr/src/freeswitch/src/debian
# Exclude incompatible modules from packaging bootstrapsed -i '/xml_int\/mod_xml_ldap/a\ languages/mod_v8\n languages/mod_basic\n asr_tts/mod_flite\n codecs/mod_ilbc\n codecs/mod_silk\n languages/mod_managed' bootstrap.sh
# Re-run bootstrap to regenerate control and rules definitions./bootstrap.sh -c trixie
# Prevent auto clean recursive loops in rulesecho "" >> rulesecho "override_dh_auto_clean:" >> rulesprintf "\t:\n" >> rules
# Clean up missing dependencies in control metadatased -i '/freeswitch-meta-codecs (= ${binary:Version}),/d' controlsed -i '/freeswitch-music,/d' controlsed -i '/freeswitch-sounds,/d' controlsed -i '/freeswitch-mod-flite (= ${binary:Version}),/d' controlUpdate debian/changelog dynamically with the cloned version metadata:
# Dynamically extract version from configure.ac (or fallback to FS_TAG)FS_VER=$(sed -n 's/.*AC_INIT(\[freeswitch\],[ ]*\[\([^]]*\)\].*/\1/p' ../configure.ac)FS_VER=${FS_VER:-${FS_TAG#v}}
cat > changelog <<EOFfreeswitch (${FS_VER}-1) unstable; urgency=medium
* Repackage Telephony Server ${FS_VER} for Debian 13. * Disable incompatible audio modules and configure make workarounds.
-- [YOUR_FULL_NAME] <[EMAIL_ADDRESS]> $(date -R)EOF3.3 Compile and Isolate
Section titled “3.3 Compile and Isolate”Synchronize all file timestamps to prevent GNU Make from triggering file skew regenerations, then run the sequential build command:
cd /usr/src/freeswitch/srcfind . -type f -exec touch {} +
# Clean out temporary debug assetsfakeroot debian/rules cleanrm -rf debian/python-esl-dbg debian/libfreeswitch1-dbg
# Execute sequential packagingDEB_BUILD_OPTIONS="parallel=1" dpkg-buildpackage -us -uc -b -dOnce compilation completes, move all created .deb files into the local directory /usr/src/freeswitch/deb/:
mkdir -p /usr/src/freeswitch/debmv /usr/src/freeswitch/*.deb /usr/src/freeswitch/deb/ 2>/dev/null || truemv /usr/src/freeswitch/libfreeswitch*.deb /usr/src/freeswitch/deb/ 2>/dev/null || truemv /usr/src/freeswitch/libesl*.deb /usr/src/freeswitch/deb/ 2>/dev/null || truemv /usr/src/freeswitch/python-esl*.deb /usr/src/freeswitch/deb/ 2>/dev/null || true🌐 Phase 4: Publishing to the APT Repository Server
Section titled “🌐 Phase 4: Publishing to the APT Repository Server”Now that our packages are compiled and isolated locally in /usr/src/freeswitch/deb/, we upload them to our repository server (IP: <YOUR_REPO_IP>, configured in Part 1).
4.1 Setup SSH Key Authentication (Optional but Recommended)
Section titled “4.1 Setup SSH Key Authentication (Optional but Recommended)”To upload packages without entering the remote server password every time, configure SSH key-based authentication from your build node to the repository server:
-
Generate SSH Key on your build node (if you do not have one):
Terminal window ssh-keygen -t rsa -b 4096 -C "build-node"# Press Enter to accept defaults (do not set a passphrase for automation) -
Copy the public key to the repository server:
Terminal window ssh-copy-id -i ~/.ssh/id_rsa.pub root@<YOUR_REPO_IP># Alternatively, using cat:# cat ~/.ssh/id_rsa.pub | ssh root@<YOUR_REPO_IP> "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys" -
Verify passwordless access:
Terminal window ssh root@<YOUR_REPO_IP> "echo 'SSH Connection Successful!'"
4.2 Upload Packages
Section titled “4.2 Upload Packages”From your build node, secure copy the packages directly to the repository upload directory:
scp /usr/src/freeswitch/deb/*.deb root@<YOUR_REPO_IP>:/usr/src/4.3 Sort and Sign on the Repo Server
Section titled “4.3 Sort and Sign on the Repo Server”Log into your repository server over SSH, organize the files into their target component directories, and rebuild the repository signatures:
ssh root@<YOUR_REPO_IP>
# Sort packages into pool components (base, extras, devel, etc.)CopyPackagesToRepo
# Rebuild package indexes and sign Release signaturesBuildRepoRing2AllOnce completed, the packages are immediately ready for secure deployment.
⏭️ What’s Next?
Section titled “⏭️ What’s Next?”Our repository server now serves Telephony core engines and custom dependencies over HTTPS. In Part 3: Compiling and Packaging Kamailio on Debian 13, we will complete our setup by packaging the high-performance SIP router Kamailio (v6.1), publishing it, and executing our end-to-end client installation.

