PBX Deploy Script with SSH Multiplexing
PBX Deploy Script with SSH Multiplexing
This script automates the deployment of Asterisk configuration files to a remote server. It verifies local files, backs up the server-side configs, uploads, reloads the relevant modules, and checks the result. SSH multiplexing reuses one connection instead of opening a new session for each command.
The Script
#!/bin/bash
# deploy.sh - Deploy Asterisk configuration to remote server
# Usage: ./deploy.sh [server]
set -euo pipefail
SERVER="${1:-voip.example.com}"
USER="admin"
ASTERISK_CONF="/etc/asterisk"
SCRIPTS_DIR="/opt/pbx-scripts"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_DIR="${SCRIPT_DIR}/../configs"
# Config files to deploy
CONFIGS=(
pjsip.conf
extensions.conf
voicemail.conf
followme.conf
confbridge.conf
)
# SSH multiplexing - reuse a single connection for all operations
SSH_CONTROL_DIR=$(mktemp -d)
SSH_CONTROL_PATH="${SSH_CONTROL_DIR}/mux-%r@%h:%p"
SSH_OPTS="-o ControlMaster=auto -o ControlPath=${SSH_CONTROL_PATH} -o ControlPersist=60"
ssh_cmd() { ssh ${SSH_OPTS} ${USER}@${SERVER} "$@"; }
scp_cmd() { scp ${SSH_OPTS} "$@"; }
cleanup() {
ssh -o ControlPath="${SSH_CONTROL_PATH}" -O exit ${USER}@${SERVER} 2>/dev/null || true
rm -rf "${SSH_CONTROL_DIR}"
}
trap cleanup EXIT
echo "Deploying to ${SERVER}..."
# ---- Verify local files exist ----
echo "Verifying local files..."
for conf in "${CONFIGS[@]}"; do
if [[ ! -f "${CONFIG_DIR}/${conf}" ]]; then
echo "ERROR: Missing ${CONFIG_DIR}/${conf}"
exit 1
fi
done
echo "All files present."
# ---- Open master connection ----
ssh -fN ${SSH_OPTS} ${USER}@${SERVER}
# ---- Backup existing configs on server ----
echo "Creating server-side backup..."
BACKUP_TS=$(date +%Y%m%d%H%M%S)
ssh_cmd "sudo mkdir -p ${ASTERISK_CONF}/backup-${BACKUP_TS} && \
for f in ${CONFIGS[*]}; do \
[ -f ${ASTERISK_CONF}/\$f ] && \
sudo cp ${ASTERISK_CONF}/\$f ${ASTERISK_CONF}/backup-${BACKUP_TS}/; \
done"
echo "Backup: ${ASTERISK_CONF}/backup-${BACKUP_TS}/"
# ---- Deploy config files ----
echo "Deploying configs..."
for conf in "${CONFIGS[@]}"; do
scp_cmd "${CONFIG_DIR}/${conf}" ${USER}@${SERVER}:/tmp/
ssh_cmd "sudo mv /tmp/${conf} ${ASTERISK_CONF}/ && \
sudo chown asterisk:asterisk ${ASTERISK_CONF}/${conf}"
echo " ${conf}"
done
# ---- Reload Asterisk modules ----
echo "Reloading Asterisk..."
ssh_cmd "sudo asterisk -rx 'module reload res_pjsip'"
ssh_cmd "sudo asterisk -rx 'dialplan reload'"
ssh_cmd "sudo asterisk -rx 'voicemail reload'"
ssh_cmd "sudo asterisk -rx 'module reload app_followme'"
ssh_cmd "sudo asterisk -rx 'module reload app_confbridge'"
# ---- Verify ----
echo ""
echo "--- Trunk Registration ---"
ssh_cmd "sudo asterisk -rx 'pjsip show registrations'"
echo ""
echo "--- Endpoints (first 20) ---"
ssh_cmd "sudo asterisk -rx 'pjsip show endpoints' | head -20"
echo ""
echo "Deployment complete!"
How It Works
SSH Multiplexing
The key performance trick is SSH multiplexing via ControlMaster. The first SSH connection opens a Unix socket (ControlPath), and all subsequent ssh and scp calls reuse that socket instead of negotiating new TCP connections and SSH handshakes. This reduces deployment time from tens of seconds to a few seconds.
The ControlPersist=60 setting keeps the master connection alive for 60 seconds after the last command finishes, and the trap cleanup EXIT ensures it gets closed when the script ends.
Module-Specific Reloads
Instead of a full core restart, the script reloads only the modules whose configs changed:
res_pjsip: picks up trunk and endpoint changesdialplan reload: picks up extensions.conf changesvoicemail reload: picks up voicemail.conf changesapp_followme/app_confbridge: pick up their respective config changes
This avoids dropping active calls.
Pre-Deploy Backup
Before overwriting anything, the script creates a timestamped backup directory on the server. If something goes wrong, you can restore with:
sudo cp /etc/asterisk/backup-20260214153000/*.conf /etc/asterisk/
sudo asterisk -rx 'core reload'
Installation
chmod +x deploy.sh
# First run - verify SSH access
./deploy.sh voip.example.com
Ensure your SSH key is authorized on the remote server and your user has passwordless sudo for asterisk, mv, cp, chown, and mkdir.
Extending
Add a --dry-run flag to show what would be deployed without doing it:
if [[ "${1}" == "--dry-run" ]]; then
echo "Would deploy:"
for conf in "${CONFIGS[@]}"; do
echo " ${CONFIG_DIR}/${conf} -> ${SERVER}:${ASTERISK_CONF}/${conf}"
done
exit 0
fi
Add a diff check to show what changed before deploying:
for conf in "${CONFIGS[@]}"; do
echo "--- Changes in ${conf} ---"
ssh_cmd "sudo cat ${ASTERISK_CONF}/${conf}" | \
diff - "${CONFIG_DIR}/${conf}" || true
done
User Notes
No notes yet. Be the first to contribute a tip or example.
Contribute a note
Share a tip, gotcha, or practical example. Keep it under 2000 characters. No questions (use the Asterisk community forums for support). Wrap code in backticks.