--- title: "📞 Part 2: Compiling and Packaging Telephony Server Engine on Debian 13 (Trixie)" description: "Documentation for 2. Package Telephony Server Engine" --- *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 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 ```bash apt-get update apt-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-python ``` ### 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: ```bash 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 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) SpanDSP handles critical telephony tasks such as T.38 faxing, tone detection, and classic modems. ```bash cd /usr/src git clone https://github.com/freeswitch/spandsp.git cd spandsp ./bootstrap.sh ./configure fakeroot debian/rules clean dpkg-buildpackage -us -uc -b # Isolate packages mkdir -p /usr/src/freeswitch/deb mv /usr/src/libspandsp*.deb /usr/src/freeswitch/deb/ # Install dependencies locally to build Telephony Server cd /usr/src/freeswitch/deb apt install -y ./libspandsp4_*.deb ./libspandsp4-dev_*.deb apt-get install -f -y ``` ### 2.2 libks (v2.0) This SignalWire communication library requires a custom Debian packaging structure. ```bash cd /usr/src git clone https://github.com/signalwire/libks.git cd libks mkdir -p debian ``` Create the required packaging files in the `debian/` directory directly: #### 2.2.1 Control File (`debian/control`) Defines the source and binary packages, their metadata, build-time dependencies, and runtime dependencies. ```bash cat <<'EOF' > debian/control Source: libks Section: libs Priority: optional Maintainer: [YOUR_FULL_NAME] <[EMAIL_ADDRESS]> Build-Depends: debhelper-compat (= 13), cmake, libpcre2-dev, uuid-dev Standards-Version: 4.6.2 Homepage: https://github.com/signalwire/libks Package: libks2 Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: SignalWire libks library A library for communication protocols developed by SignalWire. Package: libks2-dev Architecture: any Depends: libks2 (= ${binary:Version}), ${misc:Depends} Description: Development files for libks Development headers and libraries for libks. EOF ``` #### 2.2.2 Rules File (`debian/rules`) The makefile containing rules that dictate how the package is configured, built, and installed into temporary directories. ```bash 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=libks2 EOF ``` Make the script executable: ```bash chmod +x debian/rules ``` #### 2.2.3 Changelog File (`debian/changelog`) Maintains the release history, package versioning, and change list. ```bash cat <<'EOF' > debian/changelog libks (2.0-7) unstable; urgency=medium * Initial packaging for Debian 13. -- [YOUR_FULL_NAME] <[EMAIL_ADDRESS]> Mon, 08 Sep 2025 20:30:00 +0000 EOF ``` #### 2.2.4 Copyright File (`debian/copyright`) Documents the license and copyright information for the package. ```bash cat <<'EOF' > debian/copyright Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Files: * Copyright: 2025 SignalWire, Inc. License: MPL-1.1 EOF ``` #### 2.2.5 Library Install File (`debian/libks2.install`) Specifies which built files (libraries) go into the runtime binary package (`libks2`). ```bash cat <<'EOF' > debian/libks2.install usr/lib/libks2.so* EOF ``` #### 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. ```bash cat <<'EOF' > debian/libks2-dev.install usr/include/libks2/* usr/lib/pkgconfig/libks2.pc EOF ``` #### 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). ```bash cat <<'EOF' > debian/not-installed usr/share/doc/libks2/changelog.Debian.gz usr/share/doc/libks2/copyright EOF ``` Now, clean, build, and install the package: ```bash # Clean potential CMake residuals from manual builds rm -rf CMakeCache.txt CMakeFiles/ cmake_install.cmake Makefile obj-* fakeroot debian/rules clean DEB_BUILD_OPTIONS="nocheck" dpkg-buildpackage -us -uc -b mv /usr/src/libks2*.deb /usr/src/freeswitch/deb/ cd /usr/src/freeswitch/deb dpkg -i libks2_*.deb libks2-dev_*.deb apt-get install -f -y ``` ### 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-ua0` and `libsofia-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 prefix `freeswitch-sofia-sip` instead of `libsofia-sip`. We declare versioned `Provides`, `Conflicts`, and `Replaces` directives pointing to the official Debian package names in `debian/control` so that Telephony Server's compilation and runtime dependencies are fully satisfied without conflicts. ```bash cd /usr/src git clone https://github.com/freeswitch/sofia-sip.git cd sofia-sip ./bootstrap.sh ./configure # Rename source and binary packages in debian/control and add versioned Provides/Conflicts/Replaces python3 -c " import re, os content = open('debian/control').read() content = content.replace('libsofia-sip', 'freeswitch-sofia-sip') content = re.sub(r'(? debian/control Source: signalwire-c Section: libs Priority: optional Maintainer: [YOUR_FULL_NAME] <[EMAIL_ADDRESS]> Build-Depends: debhelper-compat (= 13), cmake, libpcre2-dev, uuid-dev, libssl-dev, libjansson-dev Standards-Version: 4.6.2 Homepage: https://github.com/signalwire/signalwire-c Package: signalwire-client-c2 Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, libks2 Description: SignalWire C client library (version 2) Package: signalwire-client-c2-dev Architecture: any Depends: signalwire-client-c2 (= ${binary:Version}), ${misc:Depends}, libks2-dev Description: Development files for SignalWire C client library (version 2) EOF ``` #### 2.5.2 Rules File (`debian/rules`) The makefile containing rules that dictate how the package is configured, built, and installed into temporary directories. ```bash cat <<'EOF' > debian/rules #!/usr/bin/make -f export 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-c2 EOF ``` Make the script executable: ```bash chmod +x debian/rules ``` #### 2.5.3 Changelog File (`debian/changelog`) Maintains the release history, package versioning, and change list. ```bash cat <<'EOF' > debian/changelog signalwire-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 +0000 EOF ``` #### 2.5.4 Install File (`debian/signalwire-client-c2.install`) Specifies which built files (libraries) go into the runtime binary package (`signalwire-client-c2`). ```bash cat <<'EOF' > debian/signalwire-client-c2.install usr/lib/libsignalwire_client2.so* EOF ``` #### 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. ```bash cat <<'EOF' > debian/signalwire-client-c2-dev.install usr/include/signalwire-client-c2/* usr/lib/*/pkgconfig/signalwire_client2.pc EOF ``` #### 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). ```bash cat <<'EOF' > debian/not-installed usr/share/doc/signalwire-client-c2/changelog.Debian.gz usr/share/doc/signalwire-client-c2/copyright EOF ``` Build and install: ```bash fakeroot debian/rules clean dpkg-buildpackage -us -uc -b mv /usr/src/signalwire-client-c2*.deb /usr/src/freeswitch/deb/ cd /usr/src/freeswitch/deb dpkg -i signalwire-client-c2_*.deb signalwire-client-c2-dev_*.deb apt-get install -f -y ``` --- ## ⚙️ 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 We will dynamically fetch and clone the latest stable Telephony Server release tag (or you may target a specific release like `v1.11.1`): ```bash 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 release git clone -b "${FS_TAG}" --depth 1 https://github.com/signalwire/freeswitch.git /usr/src/freeswitch/src cd /usr/src/freeswitch/src ./bootstrap.sh -j # Prevent file system timestamp skew loop find . -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: * **`--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 legacy `libpcre3` has 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 Before launching `dpkg-buildpackage`, we must bypass several known packaging issues: 1. **Incompatible Modules**: Exclude legacy features like V8/Javascript and obsolete audio codecs (silk, ilbc, flite) that are not compatible with Debian 13 build environments. 2. **`dh_auto_clean` Recursion Loop**: Autotools comparisons can trigger an infinite build cleaner recursion loop. We override this loop as a no-op. 3. **Parallel Race Condition**: Generating `modules.inc` under concurrent build jobs (e.g., `-j8`) results in race conditions. We force sequential module packaging. Run these adjustments: ```bash cd /usr/src/freeswitch/src/debian # Exclude incompatible modules from packaging bootstrap sed -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 rules echo "" >> rules echo "override_dh_auto_clean:" >> rules printf "\t:\n" >> rules # Clean up missing dependencies in control metadata sed -i '/freeswitch-meta-codecs (= ${binary:Version}),/d' control sed -i '/freeswitch-music,/d' control sed -i '/freeswitch-sounds,/d' control sed -i '/freeswitch-mod-flite (= ${binary:Version}),/d' control ``` Update `debian/changelog` dynamically with the cloned version metadata: ```bash # 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 < $(date -R) EOF ``` ### 3.3 Compile and Isolate Synchronize all file timestamps to prevent GNU Make from triggering file skew regenerations, then run the sequential build command: ```bash cd /usr/src/freeswitch/src find . -type f -exec touch {} + # Clean out temporary debug assets fakeroot debian/rules clean rm -rf debian/python-esl-dbg debian/libfreeswitch1-dbg # Execute sequential packaging DEB_BUILD_OPTIONS="parallel=1" dpkg-buildpackage -us -uc -b -d ``` Once compilation completes, move all created `.deb` files into the local directory `/usr/src/freeswitch/deb/`: ```bash mkdir -p /usr/src/freeswitch/deb mv /usr/src/freeswitch/*.deb /usr/src/freeswitch/deb/ 2>/dev/null || true mv /usr/src/freeswitch/libfreeswitch*.deb /usr/src/freeswitch/deb/ 2>/dev/null || true mv /usr/src/freeswitch/libesl*.deb /usr/src/freeswitch/deb/ 2>/dev/null || true mv /usr/src/freeswitch/python-esl*.deb /usr/src/freeswitch/deb/ 2>/dev/null || true ``` --- ## 🌐 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: ``, configured in Part 1). ### 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: 1. **Generate SSH Key** on your build node (if you do not have one): ```bash ssh-keygen -t rsa -b 4096 -C "build-node" # Press Enter to accept defaults (do not set a passphrase for automation) ``` 2. **Copy the public key** to the repository server: ```bash ssh-copy-id -i ~/.ssh/id_rsa.pub root@ # Alternatively, using cat: # cat ~/.ssh/id_rsa.pub | ssh root@ "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys" ``` 3. **Verify passwordless access:** ```bash ssh root@ "echo 'SSH Connection Successful!'" ``` ### 4.2 Upload Packages From your build node, secure copy the packages directly to the repository upload directory: ```bash scp /usr/src/freeswitch/deb/*.deb root@:/usr/src/ ``` ### 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: ```bash ssh root@ # Sort packages into pool components (base, extras, devel, etc.) CopyPackagesToRepo # Rebuild package indexes and sign Release signatures BuildRepoRing2All ``` Once completed, the packages are immediately ready for secure deployment. --- ## ⏭️ 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](03-kamailio-debian-13-packages.md), 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.