PBX Deploy Script with SSH Multiplexing

Administration -- Last reviewed 2026-03-29 administration deploy ssh automation Found this useful? Upvote it. ×

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:

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.

Moderated before publishing. Email never shown.

Related Snippets