Welcome to the seventh installment of our “Debian 13 Clustering & Distribution” series. In the previous parts, we explored setting up a custom APT repository, compiling and packaging FreeSWITCH, Kamailio, and RTPEngine, and designing high-availability database and storage clusters. Now, we shift our focus to deployment. In this guide, we will walk through the single-server installation process of the Ring2All platform on Debian 13 (Trixie).
This all-in-one deployment is ideal for small businesses, demonstrations, and development environments where all services run on a single machine. We will cover the automatic one-command script installation using the softswitch-all orchestrator meta-package, a detailed step-by-step manual installation path, system verification, Nginx reverse proxy setup, firewall configuration, SSL bootstrapping, resource optimization tuning, and backup strategies.
Architecture Overview
In a single-server deployment, all components of the Ring2All platform run on the same virtual or physical machine. Nginx acts as the front-facing reverse proxy, distributing requests to the various frontend static React apps, backend REST APIs, and ESL (Event Socket Library) monitoring services. PostgreSQL 17 handles the data store, while FreeSWITCH operates telephony services locally.
┌─────────────────────────────────────────────────────────────────────────────────┐
│ SINGLE SERVER ARCHITECTURE │
│ (All-in-One Deployment) │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ NGINX (Reverse Proxy) │ │
│ │ Port 80 / 443 (HTTP/S) │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ │
│ ┌──────┐ ┌────────┐ ┌───────────┐ ┌─────────┐ ┌──────────────┐ │
│ │Admin │ │Portal │ │Switchboard│ │ API │ │ Monitoring │ │
│ │ Web │ │ Web │ │ Web │ │ :3001 │ │ API :3500 │ │
│ │/admin│ │/portal │ │/switchboard│ │ /api │ │ /monitoring │ │
│ └──────┘ └────────┘ └───────────┘ └─────────┘ └──────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ PostgreSQL 17 │ │
│ │ ss_admin | ss_telephony | ss_cdr | ss_cc | ss_ccr | ss_logs │ │
│ │ ss_switchboard | freeswitch Port 5432 │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────────────────────┐ │
│ │ FreeSWITCH │ │
│ │ SIP UDP/TCP: 5060 | SIP TLS: 5061 | RTP: 16384-32768 │ │
│ └───────────────────────────────────────────────────────────────────────┘ │
│ │
│ Single Server: <SERVER_IP> │
└─────────────────────────────────────────────────────────────────────────────────┘
Server Requirements
Before proceeding, ensure your server meets the following criteria for a standard single-server deployment:
| Component | Minimum | Recommended |
|---|---|---|
| CPU | 4 vCPU | 8 vCPU |
| RAM | 8 GB | 16 GB |
| Storage | 100 GB SSD | 250 GB SSD |
| OS | Debian 13 (Trixie) | Debian 13 (Trixie) |
| Node.js | 22.x LTS | 22.x LTS |
| PostgreSQL | 17 | 17 |
| Concurrent Calls | ~50 | ~100–150 |
Package Suite (11 Packages)
The platform is distributed as a suite of 10 functional packages plus 1 meta-package orchestrator:
| Package | Role | Description |
|---|---|---|
softswitch-all |
AIO Meta-package | Orchestrator package handling the installation order of the suite. |
softswitch-db |
Database Schema | Database schemas, default migrations, and seed data. |
softswitch-api |
REST API | REST API backend (Node.js, listening on Port 3001). |
softswitch-monitoring-api |
Telemetry API | Real-time ESL telemetry & WebSocket server (Port 3500). |
softswitch-admin |
Frontend Admin | Static React administration portal + authoritative Nginx configuration. |
softswitch-portal |
Frontend Portal | Static React end-user self-service portal. |
softswitch-switchboard |
Frontend Switchboard | Static React real-time operator console. |
softswitch-telephony |
Telephony Config | FreeSWITCH configurations, dialplans, Lua scripts, and AI module. |
softswitch-music |
Audio Assets | Default Music on Hold audio assets (WAV, multi-rate). |
softswitch-voiceguide-emma |
Audio Prompts | English (US) system prompts for interactive voice response (IVR). |
softswitch-voiceguide-paloma |
Audio Prompts | Spanish (US/LATAM) system prompts for IVR. |
Automatic Installation (Recommended)
The recommended path is the automated script. Running it as root bootstraps system configurations and installs the softswitch-all meta-package, which installs the remaining suite in the correct dependency order.
wget -O- https://repo.softswitchone.com/apt/install-softswitch.sh | bash
This installer executes the following steps automatically:
- Configures system prerequisites and DNS settings.
- Installs Node.js 22.x, PostgreSQL 17, and security packages (
fail2ban,nftables,openvpn). - Registers the Ring2All APT repository components (
base,core,devel,extras,audios). - Installs all 11 Softswitch packages in the correct dependency order.
- Generates secure, random database credentials in
/etc/softswitch/db-credentials. - Initializes all 8 databases, applies migrations, and seeds default records.
- Deploys Nginx virtual host configurations and starts all system services.
Default Access Credentials (First Login)
- URL:
http://<SERVER_IP>/admin(redirects to HTTPS) - Email:
[email protected] - Password: (leave blank to trigger the initial setup wizard)
Verifying the Automatic Installation
Once the automatic installation script completes, perform the following validation checks to ensure all core services are active and properly configured.
1. Check System Services
Verify that all key components are active and running:
systemctl status postgresql
systemctl status freeswitch
systemctl status softswitch-api
systemctl status softswitch-monitoring-api
systemctl status nginx
2. Verify Database Connection
Check that all 8 databases were created and successfully seeded:
# View the generated database credentials
cat /etc/softswitch/db-credentials
# List all databases
sudo -u postgres psql -c "\l"
Expected databases: ss_admin, ss_telephony, ss_cdr, ss_cc, ss_ccr, ss_logs, ss_switchboard, and freeswitch.
3. Check FreeSWITCH Core Status
Ensure that the FreeSWITCH instance is running and has bound to local databases via ODBC:
fs_cli
# Within the FreeSWITCH CLI:
sofia status
Expected: The internal and external SIP profiles must show as RUNNING.
To exit the CLI, type: /exit
4. API Endpoints Health Check
Validate the health check JSON responses from the backend services:
# Main REST API
curl -s http://127.0.0.1:3001/api/health
# Monitoring / ESL WS API
curl -s http://127.0.0.1:3500/health
Installing Optional Complements & Add-ons
While the automated installer configures the core softswitch backend and includes Nginx and recommended voice guide audio assets (softswitch-music, softswitch-voiceguide-emma, and softswitch-voiceguide-paloma) out of the box, you can customize and expand your deployment with additional frontend web portals.
1. User Self-Service Portal (softswitch-portal)
The User Portal allows end-users to manage their extensions, view personal call detail records (CDRs), configure call forwarding, and manage voicemails.
apt-get install -y softswitch-portal
The post-installation script automatically deploys the static files under /var/www/softswitch/portal/, registers the path within Nginx /portal, and reloads the web service.
2. Operator Switchboard Console (softswitch-switchboard)
The Switchboard is a real-time console designed for operators to monitor extension states, park calls, drag-and-drop transfers, and view queue statistics.
apt-get install -y softswitch-switchboard
The post-installation script automatically deploys the static files under /var/www/softswitch/switchboard/, registers the path within Nginx /switchboard, and reloads the web service.
Nginx Web Server Configuration
The Nginx configuration is fully automated. The softswitch-admin package deploys and activates a production-ready virtual host configuration file at /etc/nginx/sites-available/softswitch during setup.
This automatic configuration handles:
- Redirecting port 80 traffic to secure HTTPS on port 443.
- Proxying REST API requests to the Node.js backend on port 3001 (
/apiand/ws/). - Proxying real-time ESL telemetry WebSockets to port 3500 (
/monitoring-api).
No manual configuration is necessary. Installing optional add-ons (softswitch-portal or softswitch-switchboard) will automatically update the Nginx configuration with the /portal and /switchboard virtual folders and trigger a clean reload.
Firewall Configuration
The platform’s firewall is configured and managed automatically during the initial script installation using nftables and fail2ban. The automated installer sets up all necessary rules to open HTTP/S web ports (80/443), SSH (22), SIP signaling (5060/5061), and media RTP stream port ranges (16384-32768) out of the box.
No manual firewall rule modifications or external tools (such as UFW) are required. Dynamic security rules (such as automatic SIP brute-force blocking) are handled automatically by fail2ban interacting directly with nftables rules via the pre-installed r2a-fail2ban CLI.
SSL Configuration (Let’s Encrypt)
To secure the HTTP interface and allow WebRTC connections (which strictly require secure contexts), configure Certbot:
# Install Certbot and Nginx plugin
apt-get install -y certbot python3-certbot-nginx
# Obtain SSL Certificate (Replace pbx.example.com with your actual domain)
certbot --nginx -d pbx.example.com
# Verify automated renewal checks
systemctl status certbot.timer
Credentials & Privileged Settings
1. Database Credentials File
This file is generated during the softswitch-db package configuration at /etc/softswitch/db-credentials:
DB_USER=ss_db_user
DB_PASSWORD=<RANDOM_GENERATED_PASSWORD>
DB_HOST=127.0.0.1
DB_PORT=5432
Do not share this file. It is read by FreeSWITCH via /etc/odbc.ini and by the REST API via /etc/softswitch/api.env.
2. Sudoers Configuration
The API service requires elevated permissions to manage systemd, nftables, and fail2ban rules dynamically. A custom sudoers file is configured at /etc/sudoers.d/softswitch:
softswitch ALL=(ALL) NOPASSWD: /usr/sbin/r2a-nftables
softswitch ALL=(ALL) NOPASSWD: /usr/bin/fail2ban-client
softswitch ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart fail2ban
softswitch ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload nftables
Ensure permissions are locked down:
chmod 440 /etc/sudoers.d/softswitch
3. Grant Database Permissions
Ensure the application database user has full access to the FreeSWITCH registry schema:
sudo -u postgres psql -d freeswitch -c \
"GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO ss_db_user;"
sudo -u postgres psql -d freeswitch -c \
"GRANT USAGE ON SCHEMA public TO ss_db_user;"
Resource Optimization (Single Server)
Because all platform components share a single operating system instance, tuning service parameters is essential to prevent resources from exhausting during peak call hours.
1. PostgreSQL 17 Optimization
Open /etc/postgresql/17/main/postgresql.conf and adjust memory boundaries based on total RAM:
# Memory allocations (Recommended for a 16 GB RAM server)
shared_buffers = 4GB # 25% of overall memory
effective_cache_size = 12GB # 75% of overall memory
work_mem = 64MB
maintenance_work_mem = 1GB
# Session management
max_connections = 300
# Write-Ahead Log (WAL) performance
wal_buffers = 64MB
checkpoint_completion_target = 0.9
Restart PostgreSQL to apply changes:
systemctl restart postgresql
2. FreeSWITCH Capacity Limits
Open /etc/freeswitch/autoload_configs/switch.conf.xml and scale concurrent session counts to matching boundaries:
<configuration name="switch.conf">
<settings>
<!-- Adjust maximum concurrent call threads based on CPU capabilities -->
<param name="max-sessions" value="200"/>
<param name="sessions-per-second" value="30"/>
<!-- Restrict RTP ports to prevent socket exhaustion -->
<param name="rtp-start-port" value="16384"/>
<param name="rtp-end-port" value="32768"/>
</settings>
</configuration>
Reload configurations dynamically:
fs_cli -x "reloadxml"
Backup Strategy
Set up a daily automated backup script at /opt/softswitch-backup.sh to prevent data loss:
#!/bin/bash
# Softswitch Single Server Backup Script
BACKUP_DIR="/var/backups/softswitch"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7
mkdir -p "$BACKUP_DIR"
# Backup all platform databases
for db in ss_admin ss_telephony ss_cdr ss_cc ss_ccr ss_logs ss_switchboard freeswitch; do
sudo -u postgres pg_dump "$db" | gzip > "$BACKUP_DIR/${db}_${DATE}.sql.gz"
echo " Backed up database: $db"
done
# Backup config directories
tar -czf "$BACKUP_DIR/freeswitch_config_${DATE}.tar.gz" /etc/freeswitch
# Backup local recordings and web uploads
if [ -d "/var/lib/freeswitch/recordings" ]; then
tar -czf "$BACKUP_DIR/recordings_${DATE}.tar.gz" /var/lib/freeswitch/recordings
fi
if [ -d "/var/www/softswitch/uploads" ]; then
tar -czf "$BACKUP_DIR/uploads_${DATE}.tar.gz" /var/www/softswitch/uploads
fi
# Backup configuration env files
cp /etc/softswitch/db-credentials "$BACKUP_DIR/db-credentials_${DATE}"
cp /etc/softswitch/api.env "$BACKUP_DIR/api.env_${DATE}"
# Prune old archives
find "$BACKUP_DIR" -type f -mtime +$RETENTION_DAYS -delete
echo " Backup process finished. Retention check completed."
Apply executable permissions and configure a root cron job:
chmod +x /opt/softswitch-backup.sh
# Run every night at 2:00 AM
echo "0 2 * * * root /opt/softswitch-backup.sh >> /var/log/softswitch-backup.log 2>&1" >> /etc/crontab
Troubleshooting
1. The API Service fails to start (exit code 226/NAMESPACE)
- Cause: Nginx is missing. The systemd unit file is configured to secure the directory
/etc/nginx. If this path does not exist, systemd will fail to mount the system namespaces. - Fix: Install Nginx, and reinstall the API package:
apt-get install -y nginx apt-get install --reinstall softswitch-api
2. FreeSWITCH fails on start (ODBC / CORE DATABASE INITIALIZATION FAILURE)
- Cause: Database access credentials are misaligned in
/etc/odbc.inior/etc/softswitch/db-credentials. - Fix: Test database logging with
isql:isql -v ss_telephony ss_db_user $(grep DB_PASSWORD /etc/softswitch/db-credentials | cut -d= -f2)Ensure
/etc/odbc.inipoints to127.0.0.1and matches the generated credentials password.
In the next and final installment of our series, Part 8: Enterprise-Grade Distributed Deployment, we will scale this architecture by separating all components onto dedicated servers, configuring Patroni database replication, mounting a distributed GlusterFS file cluster, and setting up local HAProxy load balancing for seamless redundancy.
