--- title: "📦 Part 1: Setting up a Custom APT Repository Server on Debian 13 (Trixie)" description: "Documentation for 1. APT Repository Server" --- *Welcome to the first installment of our "Debian 13 Packaging & Distribution" series. In this post, we will walk through the process of building your own secure, public-facing Debian APT repository server from scratch. You will learn how to configure Nginx to serve package indices, generate and use GPG keys to sign your metadata, write utility scripts to manage package sorting and deduplication, and distribute a bootstrap script to make client installation as simple as a single command.* --- ## 🏗️ Why Build a Custom APT Repository? When distributing complex software like **Telephony Server** or **Kamailio** across multiple production servers, relying on manual file transfers or local compilation on every machine is error-prone and inefficient. A custom APT repository provides: 1. **Dependency Management**: APT automatically resolves and installs system prerequisites. 2. **Security**: Cryptographically signed packages ensure that clients only install untampered code. 3. **Consistency**: Ensure all production, staging, and development servers run the exact same versions. 4. **Convenience**: Updates are as simple as running `apt-get update && apt-get upgrade`. --- ## 🛠️ Step 1: Server Preparation & Web Server Installation For this setup, we will use a server running **Debian 13 (Trixie)**. Our repository will be hosted at `repo.softswitchone.com`. ### 1.1 Install System Utilities First, update the package list and install Nginx alongside the tools required to generate repository metadata and manage cryptographic keys: ```bash apt-get update apt-get install -y nginx apt-utils devscripts gnupg2 dpkg-dev gzip python3 certbot python3-certbot-nginx ``` * `nginx`: Serves the repository files over HTTP/HTTPS. * `apt-utils` & `dpkg-dev`: Contains `dpkg-scanpackages` to index package directories. * `gnupg2`: Cryptographically signs repository indexes. --- ## 🌐 Step 2: Web Server Configuration (Nginx & HTTPS) APT repositories are served over simple HTTP/HTTPS directory structures. We will configure Nginx to serve our files and enable directory listing so APT can crawl the pool. ### 2.1 Create the Nginx Virtual Host Create a configuration file at `/etc/nginx/sites-available/repo.softswitchone.com`: ```nginx server { listen 80; server_name repo.softswitchone.com; root /var/www/pbx-repo/ring2all/trixie; access_log /var/log/nginx/repo_access.log; error_log /var/log/nginx/repo_error.log; # Allow directory listing so clients can inspect package folders autoindex on; # Serve the main repository files location /apt/ { alias /var/www/pbx-repo/ring2all/trixie/apt/; autoindex on; } # Public location for client GPG keys location /apt/gpgkey/ { alias /var/www/pbx-repo/ring2all/trixie/apt/gpgkey/; } # Deny access to hidden system files (.git, .htaccess, etc.) location ~ /\. { deny all; } } ``` Enable the configuration and restart Nginx: ```bash ln -sf /etc/nginx/sites-available/repo.softswitchone.com /etc/nginx/sites-enabled/ nginx -t systemctl restart nginx ``` ### 2.2 Secure the Server with Let's Encrypt SSL Run Certbot to acquire and install an SSL certificate, automatically redirecting all HTTP traffic to HTTPS: ```bash certbot --nginx -d repo.softswitchone.com ``` #### Configuring SSL Auto-Renewal Let's Encrypt certificates are valid for 90 days. Set up a daily cron job to run the certbot renewal checks automatically: ```bash echo "0 3 * * * root certbot renew --quiet --post-hook 'systemctl reload nginx'" > /etc/cron.d/certbot-renew chmod 644 /etc/cron.d/certbot-renew ``` --- ## 🔑 Step 3: Cryptographic Signing (GPG Key Setup) Modern APT clients refuse to install packages from repositories that do not sign their index metadata with a trusted GPG key. ### 3.1 Generate the RSA Signing Key Run the key generator on your repository server: ```bash gpg --full-generate-key ``` Select the following configuration options when prompted: 1. **Key type**: Select `1` (RSA and RSA). 2. **Keysize**: Enter `4096` bits. 3. **Validity**: Enter `0` (key does not expire) and confirm with `y`. 4. **Real name**: Enter `Ring2All Repo`. 5. **Email address**: Enter `[EMAIL_ADDRESS]`. 6. **Passphrase**: Leave empty (press Enter twice) for automated, non-interactive index signing. ### 3.2 Find and Copy the Key ID List the keys in your keyring to retrieve the long key fingerprint: ```bash gpg --list-keys --keyid-format long ``` *Example Output:* ```text pub rsa4096/D899B67676A5D2D408C5E30EA4B1437798E981B7 2026-01-26 [SC] D899B67676A5D2D408C5E30EA4B1437798E981B7 uid [ultimate] Ring2All Repo <[EMAIL_ADDRESS]> ``` Identify the long key ID: `D899B67676A5D2D408C5E30EA4B1437798E981B7`. ### 3.3 Export the Public Key for Clients Clients will need your public GPG key to verify the repository signatures. Export it in ASCII-armored format and save it inside your web server root: ```bash mkdir -p /var/www/pbx-repo/ring2all/trixie/apt/gpgkey gpg --armor --export D899B67676A5D2D408C5E30EA4B1437798E981B7 > /var/www/pbx-repo/ring2all/trixie/apt/gpgkey/ring2all.gpg ``` --- ## 📁 Step 4: Repository Structure & Automation Scripts To keep the repository clean and maintainable, we partition packages into five functional **Components**: | Component | Pool Path | Content Description | |-----------|-----------|---------------------| | **base** | `pool/b/base/` | Telephony core, dependencies, and essential modules | | **core** | `pool/c/core/` | Ring2All Softswitch packages (admin panel, APIs, etc.) | | **extras** | `pool/e/extras/` | Auxiliary modules (Perl, Python, MariaDB backends, VLC) | | **devel** | `pool/d/devel/` | Development headers (`-dev`) and debug symbols (`-dbg`) | | **audios** | `pool/a/audios/` | Voice guides (Emma, Paloma) and music files | Let's configure the scripts that automate package sorting, deduplication, metadata indexing, and signing. ### 4.1 Script 1: `/usr/sbin/ReleaseBuilderRing2All` This script parses the index metadata directories and outputs standard Debian release header hashes (MD5, SHA1, SHA256) of all underlying files. Create `/usr/sbin/ReleaseBuilderRing2All`: ```bash cat > /usr/sbin/ReleaseBuilderRing2All <<'EOF' #!/bin/bash set -e while getopts o:l:s:d:c:a: flag; do case "${flag}" in o) ORIGIN=${OPTARG};; l) LABEL=${OPTARG};; s) SUITE=${OPTARG};; d) DESC=${OPTARG};; c) COMP=${OPTARG};; a) ARCH=${OPTARG};; esac done ORIGIN=${ORIGIN:-"Ring2All Repo"} LABEL=${LABEL:-Base} SUITE=${SUITE:-stable} DESC=${DESC:-"Ring2All packages"} COMP=${COMP:-main} ARCH=${ARCH:-"amd64 arm64 armhf all"} do_hash() { HASH_NAME=$1 HASH_CMD=$2 echo "${HASH_NAME}:" for f in $(find -type f); do f=$(echo $f | cut -c3-) [ "$f" = "Release" ] && continue echo " $(${HASH_CMD} ${f} | cut -d' ' -f1) $(wc -c < $f) $f" done } cat < /usr/sbin/CleanPoolRepo <<'EOF' #!/usr/bin/env python3 import os import subprocess import sys def get_pkg_info(deb_path): try: res = subprocess.run( ["dpkg-deb", "-f", deb_path, "Package", "Version", "Architecture"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True ) info = {} for line in res.stdout.strip().split('\n'): if ':' in line: k, v = line.split(':', 1) info[k.strip().lower()] = v.strip() return info.get("package"), info.get("version"), info.get("architecture") except Exception as e: print(f"Error reading {deb_path}: {e}", file=sys.stderr) return None, None, None def compare_versions(v1, v2): res = subprocess.run(["dpkg", "--compare-versions", v1, "lt", v2]) return res.returncode == 0 def clean_pool(pool_dir): if not os.path.isdir(pool_dir): print(f"Directory {pool_dir} does not exist.") return deb_files = [] for root, _, files in os.walk(pool_dir): for f in files: if f.endswith(".deb"): deb_files.append(os.path.join(root, f)) groups = {} for filepath in deb_files: pkg, ver, arch = get_pkg_info(filepath) if not pkg or not ver or not arch: continue key = (pkg, arch) if key not in groups: groups[key] = [] groups[key].append({"path": filepath, "version": ver}) for key, items in groups.items(): if len(items) <= 1: continue for i in range(len(items)): max_idx = i for j in range(i + 1, len(items)): if compare_versions(items[max_idx]["version"], items[j]["version"]): max_idx = j items[i], items[max_idx] = items[max_idx], items[i] latest = items[0] for item in items[1:]: print(f"Removing older version: {item['path']} ({item['version']}) in favor of {latest['version']}") try: os.remove(item["path"]) except Exception as e: print(f"Error removing {item['path']}: {e}", file=sys.stderr) if __name__ == "__main__": if len(sys.argv) < 2: print("Usage: CleanPoolRepo ") sys.exit(1) clean_pool(sys.argv[1]) EOF chmod +x /usr/sbin/CleanPoolRepo ``` ### 4.3 Script 3: `/usr/sbin/BuildRepoRing2All` This script links all pools, triggers the cleanup process, scans packages using `dpkg-scanpackages`, generates compressed metadata indexes (`Packages.gz`), builds the global `Release` files, and signs them cryptographically with GPG. Create `/usr/sbin/BuildRepoRing2All`: ```bash cat > /usr/sbin/BuildRepoRing2All <<'EOF' #!/bin/bash set -e PROJECT_DIR=/var/www/pbx-repo/ring2all/trixie # Detect GPG key matching the administrator's email GPG_KEY=$(gpg --list-secret-keys --keyid-format long "[EMAIL_ADDRESS]" 2>/dev/null | grep -A 1 "^sec" | tail -n 1 | awk '{print $1}') if [ -z "$GPG_KEY" ]; then GPG_KEY=$(gpg --list-secret-keys --keyid-format long 2>/dev/null | grep -A 1 "^sec" | tail -n 1 | awk '{print $1}') fi GPG_KEY=${GPG_KEY:-"D899B67676A5D2D408C5E30EA4B1437798E981B7"} echo "Creating directory structures..." mkdir -p ${PROJECT_DIR}/apt/{gpgkey,base,core,extras,devel,audios} mkdir -p ${PROJECT_DIR}/apt/pool/{a/audios,b/base,c/core,e/extras,d/devel} for section in audios base core extras devel; do mkdir -p ${PROJECT_DIR}/apt/${section}/dists/stable/main/binary-{amd64,all,arm64,armhf} mkdir -p ${PROJECT_DIR}/apt/${section}/pool done # Map virtual symbolic links to resolve the centralized pool ln -sf ${PROJECT_DIR}/apt/pool ${PROJECT_DIR}/apt/audios/pool 2>/dev/null || true ln -sf ${PROJECT_DIR}/apt/pool ${PROJECT_DIR}/apt/base/pool 2>/dev/null || true ln -sf ${PROJECT_DIR}/apt/pool ${PROJECT_DIR}/apt/core/pool 2>/dev/null || true ln -sf ${PROJECT_DIR}/apt/pool ${PROJECT_DIR}/apt/extras/pool 2>/dev/null || true ln -sf ${PROJECT_DIR}/apt/pool ${PROJECT_DIR}/apt/devel/pool 2>/dev/null || true # Copy signing key and client bootstrap script to public web paths [ -f ~/ring2all.gpg ] && cp ~/ring2all.gpg ${PROJECT_DIR}/apt/gpgkey/ring2all.gpg [ -f ~/ring2all_setup_repo ] && cp ~/ring2all_setup_repo ${PROJECT_DIR}/apt/setup_repo # Purge obsolete versions if [ -x /usr/sbin/CleanPoolRepo ]; then echo "Purging old duplicate packages from pool..." /usr/sbin/CleanPoolRepo ${PROJECT_DIR}/apt/pool fi # Rebuild package indexes echo "Generating Packages files..." cd ${PROJECT_DIR}/apt for section in audios base core extras devel; do pool_letter="${section:0:1}" [ "$section" = "audios" ] && pool_letter="a" [ "$section" = "extras" ] && pool_letter="e" for arch in amd64 all arm64 armhf; do dpkg-scanpackages --arch $arch pool/${pool_letter}/${section}/ /dev/null > ${section}/dists/stable/main/binary-${arch}/Packages 2>/dev/null || true gzip -9c ${section}/dists/stable/main/binary-${arch}/Packages > ${section}/dists/stable/main/binary-${arch}/Packages.gz 2>/dev/null || true done done # Create and cryptographically sign release metadata echo "Signing release index..." for section in audios base core extras devel; do cd ${PROJECT_DIR}/apt/${section}/dists/stable/ /usr/sbin/ReleaseBuilderRing2All -l ${section^} -d "Ring2All ${section^} packages" > Release rm -f Release.gpg InRelease if gpg --list-keys "$GPG_KEY" >/dev/null 2>&1; then gpg -u "$GPG_KEY" -abs -o Release.gpg Release cat Release | gpg -u "$GPG_KEY" -abs --clearsign > InRelease else echo "⚠️ WARNING: GPG key $GPG_KEY not found. Skipping metadata signing." fi done echo "✅ Repository rebuild complete!" EOF chmod +x /usr/sbin/BuildRepoRing2All ``` ### 4.4 Script 4: `/usr/sbin/CopyPackagesToRepo` This script acts as the entry-point gatekeeper, sorting incoming compiled Telephony Server `.deb` packages (e.g. core binaries, configuration packs, dynamic modules, and custom telephony dependencies) into their respective repository component directories. Create `/usr/sbin/CopyPackagesToRepo`: ```bash cat > /usr/sbin/CopyPackagesToRepo << 'EOF' #!/bin/bash # CopyPackagesToRepo - Sort uploaded packages into repository categories POOL_DIR="/var/www/pbx-repo/ring2all/trixie/apt/pool" # Detect source directory dynamically SRC_DIR="/usr/src" if [ -d "/usr/src/freeswitch/deb" ] && ls /usr/src/freeswitch/deb/*.deb &>/dev/null; then SRC_DIR="/usr/src/freeswitch/deb" fi echo "==============================================" echo " Moving packages to Ring2All Repository " echo "==============================================" echo "Source directory: $SRC_DIR" echo "Target pool directory: $POOL_DIR" # Create directories if needed mkdir -p $POOL_DIR/{a/audios,b/base,c/core,d/devel,e/extras} # ============================================================ # BASE: Telephony Core + Dependencies + Essential Modules # ============================================================ echo "" echo "=== BASE: Telephony Core ===" # Core Telephony Server mv -v $SRC_DIR/freeswitch_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-all_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-systemd*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-timezones*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/libfreeswitch1_*.deb $POOL_DIR/b/base/ 2>/dev/null # Meta packages mv -v $SRC_DIR/freeswitch-meta-*.deb $POOL_DIR/b/base/ 2>/dev/null # Configuration packages mv -v $SRC_DIR/freeswitch-conf-*.deb $POOL_DIR/b/base/ 2>/dev/null # Language packs mv -v $SRC_DIR/freeswitch-lang*.deb $POOL_DIR/b/base/ 2>/dev/null # Dependencies (spandsp, libks2, sofia-sip, signalwire-c, broadvoice) mv -v $SRC_DIR/libspandsp*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/libks2_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/libbroadvoice1_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/signalwire-client-c2_*.deb $POOL_DIR/b/base/ 2>/dev/null # Legacy Sofia-SIP packages mv -v $SRC_DIR/libsofia-sip-ua0_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/libsofia-sip-ua-glib3_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/sofia-sip-bin_*.deb $POOL_DIR/b/base/ 2>/dev/null # New renamed Sofia-SIP packages mv -v $SRC_DIR/freeswitch-sofia-sip-ua0_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-sofia-sip-ua-glib3_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-sofia-sip-bin_*.deb $POOL_DIR/b/base/ 2>/dev/null # Kamailio SBC packages mv -v $SRC_DIR/sbc-kamailio_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/sbc-kamailio-*-modules_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/sbc-kamailio-nth_*.deb $POOL_DIR/b/base/ 2>/dev/null # Essential endpoint modules mv -v $SRC_DIR/freeswitch-mod-sofia_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-verto_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-rtc_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-loopback_*.deb $POOL_DIR/b/base/ 2>/dev/null # Essential application modules mv -v $SRC_DIR/freeswitch-mod-lua_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-commands_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-dptools_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-dialplan-xml_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-event-socket_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-console_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-logfile_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-syslog_*.deb $POOL_DIR/b/base/ 2>/dev/null # Database modules mv -v $SRC_DIR/freeswitch-mod-pgsql_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-cdr-pg-csv_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-odbc-cdr_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-db_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-hash_*.deb $POOL_DIR/b/base/ 2>/dev/null # Essential codecs mv -v $SRC_DIR/freeswitch-mod-opus_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-spandsp_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-g729_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-codec2_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-amr_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-amrwb_*.deb $POOL_DIR/b/base/ 2>/dev/null # Essential applications mv -v $SRC_DIR/freeswitch-mod-voicemail_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-voicemail-ivr_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-conference_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-fifo_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-callcenter_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-httapi_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-sndfile_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-tone-stream_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-local-stream_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-native-file_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-shout_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-sms_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-valet-parking_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-spy_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-directory_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-lcr_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-nibblebill_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-blacklist_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-cidlookup_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-curl_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-xml-curl_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-http-cache_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-fail2ban_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-expr_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-translate_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-distributor_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-easyroute_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-avmd_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-vmd_*.deb $POOL_DIR/b/base/ 2>/dev/null # Say modules (essential for IVR) mv -v $SRC_DIR/freeswitch-mod-say-en_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-es_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-es-ar_*.deb $POOL_DIR/b/base/ 2>/dev/null # CDR modules mv -v $SRC_DIR/freeswitch-mod-cdr-csv_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-json-cdr_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-xml-cdr_*.deb $POOL_DIR/b/base/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-format-cdr_*.deb $POOL_DIR/b/base/ 2>/dev/null # ============================================================ # EXTRAS: Optional modules # ============================================================ echo "" echo "=== EXTRAS: Optional Modules ===" # Alternative language bindings mv -v $SRC_DIR/freeswitch-mod-perl_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-python3_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-java_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-erlang-event_*.deb $POOL_DIR/e/extras/ 2>/dev/null # Alternative dialplans mv -v $SRC_DIR/freeswitch-mod-dialplan-asterisk_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-dialplan-directory_*.deb $POOL_DIR/e/extras/ 2>/dev/null # Alternative databases mv -v $SRC_DIR/freeswitch-mod-mariadb_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-cdr-sqlite_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-cdr-mongodb_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-hiredis_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-memcache_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-redis_*.deb $POOL_DIR/e/extras/ 2>/dev/null # Media modules mv -v $SRC_DIR/freeswitch-mod-vlc_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-av_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-cv_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-imagick_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-png_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-video-filter_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-yuv_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-fsv_*.deb $POOL_DIR/e/extras/ 2>/dev/null # Alternative endpoints mv -v $SRC_DIR/freeswitch-mod-rtmp_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-skinny_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-alsa_*.deb $POOL_DIR/e/extras/ 2>/dev/null # Additional say modules mv -v $SRC_DIR/freeswitch-mod-say-de_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-fr_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-pt_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-ru_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-it_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-nl_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-he_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-hr_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-hu_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-ja_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-pl_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-sv_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-th_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-zh_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-say-fa_*.deb $POOL_DIR/e/extras/ 2>/dev/null # Additional codecs mv -v $SRC_DIR/freeswitch-mod-bv_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-g723-1_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-opusfile_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-b64_*.deb $POOL_DIR/e/extras/ 2>/dev/null # Miscellaneous mv -v $SRC_DIR/freeswitch-mod-amqp_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-bert_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-enum_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-esf_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-esl_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-event-multicast_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-event-test_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-fsk_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-graylog2_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-ldap_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-pocketsphinx_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-posix-timer_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-prefix_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-random_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-shell-stream_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-signalwire_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-snapshot_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-snmp_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-test_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-timerfd_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-tts-commandline_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-xml-rpc_*.deb $POOL_DIR/e/extras/ 2>/dev/null mv -v $SRC_DIR/freeswitch-mod-xml-scgi_*.deb $POOL_DIR/e/extras/ 2>/dev/null # ============================================================ # DEVEL: Development packages and debug symbols # ============================================================ echo "" echo "=== DEVEL: Development Packages ===" mv -v $SRC_DIR/*-dev_*.deb $POOL_DIR/d/devel/ 2>/dev/null mv -v $SRC_DIR/*-dbg_*.deb $POOL_DIR/d/devel/ 2>/dev/null mv -v $SRC_DIR/*-dbgsym_*.deb $POOL_DIR/d/devel/ 2>/dev/null mv -v $SRC_DIR/*-doc_*.deb $POOL_DIR/d/devel/ 2>/dev/null mv -v $SRC_DIR/python-esl*.deb $POOL_DIR/d/devel/ 2>/dev/null mv -v $SRC_DIR/libesl-perl*.deb $POOL_DIR/d/devel/ 2>/dev/null # ============================================================ # CORE: Ring2All PBX, Ring2All SBC & Ring2All BSS Packages # ============================================================ echo "" echo "=== CORE: Ring2All PBX, Ring2All SBC & Ring2All BSS Packages ===" # Ring2All PBX Packages mv -v $SRC_DIR/softswitch-admin_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-db_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-api_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-monitoring-api_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-billing-api_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-portal_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-switchboard_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-telephony_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-all_*.deb $POOL_DIR/c/core/ 2>/dev/null # Ring2All SBC Packages (Modular Suite & Monolithic) mv -v $SRC_DIR/softswitch-sbc_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-sbc-db_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-sbc-api_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-sbc-admin_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-sbc-telephony_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-sbc-all_*.deb $POOL_DIR/c/core/ 2>/dev/null # Ring2All BSS Packages (Billing, OCS & Customer Store) mv -v $SRC_DIR/softswitch-bss-api_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-bss-web_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-bss-client_*.deb $POOL_DIR/c/core/ 2>/dev/null mv -v $SRC_DIR/softswitch-bss-all_*.deb $POOL_DIR/c/core/ 2>/dev/null # Legacy or generic audios in core (music) mv -v $SRC_DIR/softswitch-music_*.deb $POOL_DIR/c/core/ 2>/dev/null # ============================================================ # AUDIOS: Voice guides (populated by voiceguide builds) # ============================================================ echo "" echo "=== AUDIOS: Voice Guides ===" mv -v $SRC_DIR/softswitch-voiceguide-emma_*.deb $POOL_DIR/a/audios/ 2>/dev/null mv -v $SRC_DIR/softswitch-voiceguide-paloma_*.deb $POOL_DIR/a/audios/ 2>/dev/null # ============================================================ # Count packages per component # ============================================================ echo "" echo "==============================================" echo " Summary " echo "==============================================" echo "BASE: $(ls -1 $POOL_DIR/b/base/*.deb 2>/dev/null | wc -l) packages" echo "CORE: $(ls -1 $POOL_DIR/c/core/*.deb 2>/dev/null | wc -l) packages" echo "EXTRAS: $(ls -1 $POOL_DIR/e/extras/*.deb 2>/dev/null | wc -l) packages" echo "DEVEL: $(ls -1 $POOL_DIR/d/devel/*.deb 2>/dev/null | wc -l) packages" echo "AUDIOS: $(ls -1 $POOL_DIR/a/audios/*.deb 2>/dev/null | wc -l) packages" echo "" echo "✅ Done! Now run: BuildRepoRing2All" EOF chmod +x /usr/sbin/CopyPackagesToRepo ``` --- ## 🚀 Step 5: Client Installation & Bootstrap Configuration On the repository server, we create a script `ring2all_setup_repo` to automate client registration. This script will download the signing GPG key, save it securely under `/etc/apt/keyrings`, and configure the custom repository list. Create `~/ring2all_setup_repo`: ```bash cat > ~/ring2all_setup_repo << 'EOF' #!/bin/bash set -e echo "Installing Ring2All repository keyring and source list..." # Install basic dependencies if missing apt-get update && apt-get install -y wget curl gpg # Create keyrings directory mkdir -p /etc/apt/keyrings # Securely download and import public signing key # Securely download and import public signing key curl -fsSL https://repo.softswitchone.com/apt/gpgkey/ring2all.gpg | gpg --dearmor -o /etc/apt/keyrings/ring2all.gpg chmod 644 /etc/apt/keyrings/ring2all.gpg # Register the components source file cat > /etc/apt/sources.list.d/ring2all.list << 'SOURCES' deb [signed-by=/etc/apt/keyrings/ring2all.gpg] https://repo.softswitchone.com/apt/base stable main deb [signed-by=/etc/apt/keyrings/ring2all.gpg] https://repo.softswitchone.com/apt/devel stable main deb [signed-by=/etc/apt/keyrings/ring2all.gpg] https://repo.softswitchone.com/apt/extras stable main deb [signed-by=/etc/apt/keyrings/ring2all.gpg] https://repo.softswitchone.com/apt/audios stable main deb [signed-by=/etc/apt/keyrings/ring2all.gpg] https://repo.softswitchone.com/apt/core stable main SOURCES echo "✅ Ring2All repository configured successfully!" echo "Run 'apt-get update' to refresh the package cache." EOF chmod +x ~/ring2all_setup_repo ``` Whenever `/usr/sbin/BuildRepoRing2All` is executed, it automatically publishes this setup script to the Nginx web root. --- ## 🔍 Step 6: Client Verification To register a fresh Debian 13 target client server and install packages from our repository, run: ```bash # Bootstrap the client wget -qO- https://repo.softswitchone.com/apt/setup_repo | bash # Refresh APT cache apt-get update # Install from the new repository apt-get install -y freeswitch freeswitch-meta-all ``` --- ## ⏭️ What's Next? Now that the distribution infrastructure is fully operational, we need packages to publish. In [Part 2: Compiling and Packaging Telephony Server Engine on Debian 13](02-freeswitch-debian-13-packages.md), we will compile the Telephony Server communication engine from source, package it as `.deb` binaries, and publish them to our new repository.