From 9d57c329010558e444f61e0113b13fc6b1ace6e1 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 8 Dec 2025 20:31:37 +0000 Subject: [PATCH 1/7] Major upgrade to v0.9.9 with VLAN, Provisioning, and UI improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a comprehensive update that removes COTURN and adds several major features focused on direct LAN/VPN/port-forwarding connections. VERSION & LICENSE: - Updated version from v0.9.8.7 to v0.9.9 - Changed license to GNU General Public License v3.0 - Updated copyright header and license information REMOVED FEATURES: - Removed all COTURN/TURN relay server code and dependencies - Removed TURN configuration variables from config system - Removed TURN firewall rules from UFW configuration - Removed IP update timer for COTURN - Focus shifted to direct connections via LAN/VPN/Port-Forwarding NEW FEATURE: VLAN Configuration - Added "Configure VLAN Subnets" menu item in Server Settings - Created configure_vlan_subnets() function with interactive prompts - Support for multiple VLAN subnets to prevent 30-second call drops - Updated pjsip.conf generation with multiple local_net entries - Server IP address now documented in transport configurations - Added comprehensive split-horizon DNS setup guide - Includes ctrld.toml examples, dnsmasq configuration, UFW rules - Provides OPNSense firewall rules and DHCP configuration guidance NEW FEATURE: Provisioning Manager - Added provisioning_manager_menu() with full HTTP server management - Setup HTTP/HTTPS provisioning on ports 8088/8089 - Automatic http.conf configuration with TLS support - Created symlink management (/usr/share/asterisk <-> /var/lib/asterisk) - Fixes 404 errors on Ubuntu/Debian systems - Interactive linphone.xml creator with server-specific settings - Built-in nano editor for linphone.xml modifications - Includes Android audio focus fix (prevents pause on screen off) - Battery optimization instructions for Android devices - Provisioning status display with file listings NEW FEATURE: Manual Update System - Added manual_update_asterisk() function with automatic backups - Creates timestamped backups before updates - Automatic rollback on update failure - Provides rollback instructions for manual recovery - Update safety with configuration preservation NEW FEATURE: Room Directory - Added show_room_directory() visual display - Distinguishes Ring Groups (📞) from Page Groups (📢) - Shows extension, members, timeout, and type for each room - Educational descriptions of group types INFRASTRUCTURE CHANGES: - Added provisioning firewall ports (8088/8089) to UFW - Reorganized code structure with clear section headers - Added PROVISIONING_DIR constant for /var/lib/asterisk/static-http - Cleaned up configuration variable management - Improved menu organization and numbering MENU UPDATES: - Server Settings: Added Provisioning Manager (#10) - Tools Menu: Added Room Directory (#4) and Manual Update (#5) - Removed COTURN menu item from Server Settings - Renumbered VLAN Subnets to option #9 DOCUMENTATION: - Split-horizon DNS guide with ctrld configuration - dnsmasq setup instructions for local DNS responses - UFW firewall rules for DNS security - OPNSense VLAN firewall configuration examples - Complete DHCP setup guidance for multi-VLAN environments This update represents a major shift toward direct networking approaches while providing better VLAN support and client provisioning capabilities for production deployments. --- ...isk-v0.9.8.7.sh => easy-asterisk-v0.9.9.sh | 788 +++++++++++------- 1 file changed, 491 insertions(+), 297 deletions(-) rename easy-asterisk-v0.9.8.7.sh => easy-asterisk-v0.9.9.sh (87%) diff --git a/easy-asterisk-v0.9.8.7.sh b/easy-asterisk-v0.9.9.sh similarity index 87% rename from easy-asterisk-v0.9.8.7.sh rename to easy-asterisk-v0.9.9.sh index 9d6d9b1..9a9945d 100644 --- a/easy-asterisk-v0.9.8.7.sh +++ b/easy-asterisk-v0.9.9.sh @@ -1,23 +1,25 @@ #!/bin/bash # ================================================================ -# Easy Asterisk - Interactive Installer v0.9.8 +# Easy Asterisk - Interactive Installer v0.9.9 # -# UPDATES in v0.9.8: +# Copyright (C) 2025 Easy Asterisk Contributors +# Licensed under GNU General Public License v3.0 +# See LICENSE file or https://www.gnu.org/licenses/gpl-3.0.html +# +# UPDATES in v0.9.9: +# - REMOVED: All COTURN/TURN relay server code (focus on direct connections) +# - ADDED: VLAN subnet configuration to prevent 30-second call drops +# - ADDED: Provisioning Manager (http.conf setup, symlinks, linphone.xml editor) +# - ADDED: Manual Update System for Asterisk with backup/rollback +# - ADDED: Room Directory (visual display of Ring Groups vs Page Groups) +# - ADDED: Split-horizon DNS documentation for VLAN environments +# - IMPROVED: Server IP address documented in transport configurations +# - IMPROVED: Multiple local_net entries for proper VLAN support +# +# PREVIOUS UPDATES (v0.9.8): # - FIXED: Categories not displaying correctly in lists of devices # - ADDED: Client export/import functionality in Device Management menu -# - FEATURE: ADDED: Ability to rename categories and rooms -# - FEATURE: Export all provisioned clients to tar.gz archive -# - FEATURE: Import clients with merge or replace modes -# - FEATURE: Automatic conflict detection and resolution during import -# - FEATURE: Backup protection before import operations -# -# RETAINED from v0.9.5: -# - FIXED: Stasis disabled causing startup failure (now only disables optional modules) -# - ADDED: Automatic VLAN/NAT traversal (works with flat, VPN, and VLAN networks) -# - ADDED: Per-device connection type selection (LAN/VPN vs FQDN) -# - IMPROVED: Transport-level NAT configuration for better VLAN support -# - IMPROVED: Generic router references (not brand-specific) -# - COMPATIBLE: Works with flat networks, VLANs, VPNs, and FQDN modes +# - ADDED: Ability to rename categories and rooms # ================================================================ set +e @@ -33,14 +35,13 @@ NC='\033[0m' # Defaults DEFAULT_SIP_PORT="5060" DEFAULT_SIPS_PORT="5061" -DEFAULT_TURN_PORT="3478" CONFIG_DIR="/etc/easy-asterisk" CONFIG_FILE="${CONFIG_DIR}/config" PTT_CONFIG_FILE="${CONFIG_DIR}/ptt-device" CATEGORIES_FILE="${CONFIG_DIR}/categories.conf" ROOMS_FILE="${CONFIG_DIR}/rooms.conf" -COTURN_CONFIG="/etc/turnserver.conf" -SCRIPT_VERSION="0.9.8.8" +PROVISIONING_DIR="/var/lib/asterisk/static-http" +SCRIPT_VERSION="0.9.9" # ================================================================ # 1. CORE HELPER FUNCTIONS @@ -148,14 +149,8 @@ load_config() { fi INSTALLED_SERVER="${INSTALLED_SERVER:-n}" INSTALLED_CLIENT="${INSTALLED_CLIENT:-n}" - INSTALLED_COTURN="${INSTALLED_COTURN:-n}" KIOSK_USER="${KIOSK_USER:-}" KIOSK_UID="${KIOSK_UID:-}" - USE_COTURN="${USE_COTURN:-n}" - TURN_SECRET="${TURN_SECRET:-}" - TURN_USER="${TURN_USER:-kioskuser}" - TURN_PASS="${TURN_PASS:-}" - TURN_DOMAIN="${TURN_DOMAIN:-}" HAS_VLANS="${HAS_VLANS:-n}" VLAN_SUBNETS="${VLAN_SUBNETS:-}" return 0 @@ -182,7 +177,6 @@ KIOSK_NAME="$KIOSK_NAME" SIP_PASSWORD="$SIP_PASSWORD" ASTERISK_HOST="$ASTERISK_HOST" DOMAIN_NAME="$DOMAIN_NAME" -TURN_DOMAIN="$TURN_DOMAIN" ENABLE_TLS="$ENABLE_TLS" HAS_VLANS="$HAS_VLANS" VLAN_SUBNETS="$VLAN_SUBNETS" @@ -190,11 +184,6 @@ CERT_PATH="$CERT_PATH" KEY_PATH="$KEY_PATH" INSTALLED_SERVER="$INSTALLED_SERVER" INSTALLED_CLIENT="$INSTALLED_CLIENT" -INSTALLED_COTURN="$INSTALLED_COTURN" -USE_COTURN="$USE_COTURN" -TURN_SECRET="$TURN_SECRET" -TURN_USER="$TURN_USER" -TURN_PASS="$TURN_PASS" CURRENT_PUBLIC_IP="$CURRENT_PUBLIC_IP" PTT_DEVICE="$PTT_DEVICE" PTT_KEYCODE="$PTT_KEYCODE" @@ -219,12 +208,8 @@ open_firewall_ports() { ufw allow 5060/udp comment "SIP UDP" 2>/dev/null || true ufw allow 5061/tcp comment "SIP TLS" 2>/dev/null || true ufw allow 10000:20000/udp comment "RTP Media" 2>/dev/null || true - if [[ "$USE_COTURN" == "y" ]]; then - ufw allow ${DEFAULT_TURN_PORT}/udp comment "TURN UDP" 2>/dev/null || true - ufw allow ${DEFAULT_TURN_PORT}/tcp comment "TURN TCP" 2>/dev/null || true - # Allow relay range for TURN - ufw allow 49152:65535/udp comment "TURN Relay" 2>/dev/null || true - fi + ufw allow 8088/tcp comment "HTTP Provisioning" 2>/dev/null || true + ufw allow 8089/tcp comment "HTTPS Provisioning" 2>/dev/null || true ufw reload 2>/dev/null || true print_success "UFW firewall ports opened" fi @@ -232,7 +217,7 @@ open_firewall_ports() { } # ================================================================ -# 2. COTURN SETUP & DYNAMIC IP +# 2. UTILITY FUNCTIONS # ================================================================ get_public_ip() { @@ -240,262 +225,6 @@ get_public_ip() { echo "$ip" } -install_coturn() { - print_header "Installing COTURN" - apt update - apt install -y coturn - - if [[ -z "$TURN_PASS" ]]; then - TURN_PASS=$(generate_password) - fi - - local public_ip=$(get_public_ip) - CURRENT_PUBLIC_IP="$public_ip" - - if [[ -z "$public_ip" ]]; then - print_error "Could not detect public IP" - return 1 - fi - - print_info "Public IP: $public_ip" - - # Enable coturn - sed -i 's/#TURNSERVER_ENABLED=1/TURNSERVER_ENABLED=1/' /etc/default/coturn 2>/dev/null || true - - # Configure coturn - backup_config "$COTURN_CONFIG" - cat > "$COTURN_CONFIG" << EOF -# Easy Asterisk COTURN Configuration -listening-port=${DEFAULT_TURN_PORT} -fingerprint -lt-cred-mech -realm=${TURN_DOMAIN:-${DOMAIN_NAME:-turn.local}} -total-quota=100 -stale-nonce=600 -cert=/etc/asterisk/certs/server.crt -pkey=/etc/asterisk/certs/server.key -no-tlsv1 -no-tlsv1_1 -cipher-list="ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384" -dh2066 -no-stdout-log -log-file=/var/log/turnserver.log -simple-log -external-ip=${public_ip} -min-port=49152 -max-port=65535 -user-quota=12 -no-multicast-peers -no-cli -user=${TURN_USER}:${TURN_PASS} -EOF - - chmod 600 "$COTURN_CONFIG" - - systemctl enable coturn - systemctl restart coturn - - if systemctl is-active coturn >/dev/null; then - print_success "COTURN installed and running" - INSTALLED_COTURN="y" - USE_COTURN="y" - save_config - return 0 - else - print_error "COTURN failed to start" - journalctl -u coturn -n 20 --no-pager - return 1 - fi -} - -configure_coturn_credentials() { - print_header "Configure TURN Credentials" - echo "Current User: ${TURN_USER}" - echo "Current Pass: ${TURN_PASS}" - echo "" - read -p "Enter Username [${TURN_USER}]: " t_user - t_user="${t_user:-$TURN_USER}" - read -p "Enter Password [generate]: " t_pass - t_pass="${t_pass:-$(generate_password)}" - - TURN_USER="$t_user" - TURN_PASS="$t_pass" - - if [[ -f "$COTURN_CONFIG" ]]; then - # Remove old user lines and add new one - sed -i '/^user=/d' "$COTURN_CONFIG" - echo "user=${TURN_USER}:${TURN_PASS}" >> "$COTURN_CONFIG" - systemctl restart coturn - print_success "Credentials updated and service restarted" - else - print_error "COTURN not installed. Run install first." - fi - save_config -} - -update_coturn_ip() { - local new_ip=$(get_public_ip) - - if [[ -z "$new_ip" ]]; then - print_warn "Could not detect public IP" - return 1 - fi - - if [[ "$new_ip" == "$CURRENT_PUBLIC_IP" ]]; then - print_info "IP unchanged: $new_ip" - return 0 - fi - - print_info "IP changed: $CURRENT_PUBLIC_IP -> $new_ip" - - # Update coturn config - if [[ -f "$COTURN_CONFIG" ]]; then - sed -i "s/^external-ip=.*/external-ip=${new_ip}/" "$COTURN_CONFIG" - systemctl restart coturn - print_success "COTURN updated" - fi - - # Update pjsip config - if [[ -f /etc/asterisk/pjsip.conf ]]; then - sed -i "s/^external_media_address=.*/external_media_address=${new_ip}/" /etc/asterisk/pjsip.conf - sed -i "s/^external_signaling_address=.*/external_signaling_address=${new_ip}/" /etc/asterisk/pjsip.conf - asterisk -rx "pjsip reload" 2>/dev/null - print_success "Asterisk updated" - fi - - CURRENT_PUBLIC_IP="$new_ip" - save_config - return 0 -} - -create_ip_update_script() { - cat > /usr/local/bin/easy-asterisk-update-ip << 'IPSCRIPT' -#!/bin/bash -CONFIG_FILE="/etc/easy-asterisk/config" -[[ -f "$CONFIG_FILE" ]] && source "$CONFIG_FILE" - -get_public_ip() { - curl -s -4 --connect-timeout 5 ifconfig.me 2>/dev/null || curl -s -4 --connect-timeout 5 icanhazip.com 2>/dev/null -} - -NEW_IP=$(get_public_ip) -[[ -z "$NEW_IP" ]] && exit 0 -[[ "$NEW_IP" == "$CURRENT_PUBLIC_IP" ]] && exit 0 - -# Update COTURN -if [[ -f /etc/turnserver.conf ]]; then - sed -i "s/^external-ip=.*/external-ip=${NEW_IP}/" /etc/turnserver.conf - systemctl restart coturn -fi - -# Update Asterisk -if [[ -f /etc/asterisk/pjsip.conf ]]; then - sed -i "s/^external_media_address=.*/external_media_address=${NEW_IP}/" /etc/asterisk/pjsip.conf - sed -i "s/^external_signaling_address=.*/external_signaling_address=${NEW_IP}/" /etc/asterisk/pjsip.conf - asterisk -rx "pjsip reload" 2>/dev/null -fi - -# Update config file -sed -i "s/^CURRENT_PUBLIC_IP=.*/CURRENT_PUBLIC_IP=\"${NEW_IP}\"/" "$CONFIG_FILE" - -logger "Easy Asterisk: Updated IP to ${NEW_IP}" -IPSCRIPT - chmod +x /usr/local/bin/easy-asterisk-update-ip - - # Create systemd timer - cat > /etc/systemd/system/easy-asterisk-ip-update.service << 'EOF' -[Unit] -Description=Easy Asterisk IP Update -After=network-online.target - -[Service] -Type=oneshot -ExecStart=/usr/local/bin/easy-asterisk-update-ip -EOF - - cat > /etc/systemd/system/easy-asterisk-ip-update.timer << 'EOF' -[Unit] -Description=Easy Asterisk IP Update Timer - -[Timer] -OnBootSec=2min -OnUnitActiveSec=10min - -[Install] -WantedBy=timers.target -EOF - - systemctl daemon-reload - systemctl enable easy-asterisk-ip-update.timer - systemctl start easy-asterisk-ip-update.timer - - print_success "IP update timer installed (checks every 10 minutes)" -} - -configure_coturn_menu() { - print_header "Configure COTURN (TURN Server)" - - if [[ "$INSTALLED_COTURN" == "y" ]]; then - echo -e "Status: ${GREEN}Installed${NC}" - echo "User: ${TURN_USER}" - echo "Pass: ${TURN_PASS}" - echo "" - echo " 1) Update Credentials (User/Pass)" - echo " 2) Reinstall/Reconfigure" - echo " 3) Update IP manually" - echo " 4) Show configuration" - echo " 5) Uninstall" - echo " 0) Back" - read -p "Select: " choice - case $choice in - 1) configure_coturn_credentials ;; - 2) install_coturn ;; - 3) update_coturn_ip ;; - 4) show_coturn_config ;; - 5) uninstall_coturn ;; - esac - else - echo "COTURN is not installed." - read -p "Install now? [Y/n]: " install - if [[ ! "$install" =~ ^[Nn]$ ]]; then - install_coturn - if [[ "$INSTALLED_COTURN" == "y" ]]; then - create_ip_update_script - fi - fi - fi -} - -show_coturn_config() { - print_header "COTURN Configuration" - echo "Status: $(systemctl is-active coturn)" - echo "Public IP: $CURRENT_PUBLIC_IP" - echo "Port: ${DEFAULT_TURN_PORT}" - echo "Credentials: ${TURN_USER} : ${TURN_PASS}" - echo "" - echo "Client Config String:" - echo "turn:${TURN_USER}:${TURN_PASS}@${TURN_DOMAIN:-${DOMAIN_NAME:-$CURRENT_PUBLIC_IP}}:${DEFAULT_TURN_PORT}" - echo "" - echo "Logs:" - tail -n 20 /var/log/turnserver.log 2>/dev/null || echo " No logs found" -} - -uninstall_coturn() { - systemctl stop coturn 2>/dev/null || true - systemctl disable coturn 2>/dev/null || true - apt purge -y coturn 2>/dev/null || true - rm -f /etc/turnserver.conf - rm -f /usr/local/bin/easy-asterisk-update-ip - systemctl stop easy-asterisk-ip-update.timer 2>/dev/null || true - systemctl disable easy-asterisk-ip-update.timer 2>/dev/null || true - rm -f /etc/systemd/system/easy-asterisk-ip-update.* - systemctl daemon-reload - INSTALLED_COTURN="n" - USE_COTURN="n" - save_config - print_success "COTURN uninstalled" -} - # ================================================================ # 3. DEVICE MANAGEMENT # ================================================================ @@ -1659,6 +1388,97 @@ configure_vlan_subnets() { generate_pjsip_conf asterisk -rx "module reload res_pjsip.so" 2>/dev/null print_success "Asterisk configuration updated" + + echo "" + echo "═══════════════════════════════════════════════════════════" + echo " VLAN DNS SETUP GUIDE (Split-Horizon)" + echo "═══════════════════════════════════════════════════════════" + echo "" + echo "For proper VLAN operation with FQDNs, you need split-horizon DNS." + echo "" + read -p "Display DNS setup guide? (y/n) [y]: " show_dns + show_dns=${show_dns:-y} + + if [[ "$show_dns" =~ ^[Yy]$ ]]; then + cat << 'DNSGUIDE' + +WHAT YOU'RE ACHIEVING: +• Devices on VLANs use router for DNS (ctrld) +• ctrld split-horizon rules send FQDNs to the right LAN servers +• Only ctrld (router) can talk to servers' DNS (protected by UFW) +• No inter-VLAN routing is opened, just DNS and service ports + +1. CTRLD.TOML (on OPNSense/Router): + +[listener.0] + ip = '0.0.0.0' + port = 53 + + [listener.0.policy] + networks = [ + { 'network.0' = ['upstream.0'] }, + { 'network.1' = ['upstream.1'] } + ] + rules = [ + { 'sip.mydomain.com' = ['upstream.4'] } + ] + +[network.0] + cidrs = ['192.168.1.0/24'] + +[network.1] + cidrs = ['192.168.200.0/24'] + +[upstream.0] + type = 'doh' + endpoint = 'https://dns.controld.com/your-profile' + timeout = 5000 + +[upstream.4] + type = 'legacy' + endpoint = '192.168.1.11' # This Asterisk server + timeout = 3000 + +2. DNSMASQ ON THIS SERVER: + +sudo apt-get install dnsmasq +echo "listen-address=127.0.0.1" >> /etc/dnsmasq.conf +echo "listen-address=$(hostname -I | cut -d' ' -f1)" >> /etc/dnsmasq.conf +echo "bind-interfaces" >> /etc/dnsmasq.conf +echo "address=/sip.mydomain.com/$(hostname -I | cut -d' ' -f1)" >> /etc/dnsmasq.conf +sudo systemctl restart dnsmasq + +3. UFW RULES ON THIS SERVER: + +sudo ufw allow from 192.168.1.1 to any port 53 proto udp +sudo ufw allow from 192.168.1.1 to any port 53 proto tcp +sudo ufw deny 53 +sudo ufw reload + +Replace 192.168.1.1 with your router's LAN IP. + +4. OPNSENSE FIREWALL RULES (for each VLAN): + +Rule 1 - Allow DNS from VLAN to Router: + Action: Pass + Source: VLANxx net + Destination: This Firewall + Port: 53 (DNS) + Protocol: TCP/UDP + +Rule 2 - Allow SIP/RTP from VLAN to Asterisk: + Source: VLANxx net + Destination: $(hostname -I | cut -d' ' -f1) + Ports: 5060/udp, 5061/tcp, 10000-20000/udp + +5. DHCP SETTINGS (OPNSense): + +For each VLAN, set DNS Servers to ONLY the router's VLAN IP. +Do NOT enter this server's IP as DNS. + +═══════════════════════════════════════════════════════════ +DNSGUIDE + fi else print_error "No subnets provided" fi @@ -1670,6 +1490,376 @@ configure_vlan_subnets() { fi } +# ================================================================ +# PROVISIONING MANAGER +# ================================================================ + +setup_http_provisioning() { + print_header "HTTP Provisioning Setup" + + echo "This will configure Asterisk's built-in HTTP server for" + echo "client provisioning (Linphone, etc.)." + echo "" + echo "Ports:" + echo " HTTP: 8088" + echo " HTTPS: 8089" + echo "" + + # Create http.conf + backup_config "/etc/asterisk/http.conf" 2>/dev/null + cat > /etc/asterisk/http.conf << 'EOF' +[general] +enabled=yes +bindaddr=0.0.0.0 +bindport=8088 + +tlsenable=yes +tlsbindaddr=0.0.0.0:8089 +tlscertfile=/etc/asterisk/certs/server.crt +tlsprivatekey=/etc/asterisk/certs/server.key + +; Serve static files from /var/lib/asterisk/static-http +enablestatic=yes +redirect=/static /var/lib/asterisk/static-http + +; Security +session_limit=100 +session_inactivity=30000 +session_keep_alive=15000 +EOF + + chown asterisk:asterisk /etc/asterisk/http.conf + + # Create provisioning directory + mkdir -p "$PROVISIONING_DIR" + chown asterisk:asterisk "$PROVISIONING_DIR" + + # Create symlink if needed (Ubuntu/Debian fix) + if [[ ! -L /usr/share/asterisk/static-http ]]; then + mkdir -p /usr/share/asterisk + ln -sf "$PROVISIONING_DIR" /usr/share/asterisk/static-http + print_info "Created symlink: /usr/share/asterisk/static-http -> $PROVISIONING_DIR" + fi + + # Reload Asterisk HTTP module + asterisk -rx "module reload res_http_post.so" 2>/dev/null || true + asterisk -rx "http show status" 2>/dev/null + + print_success "HTTP provisioning configured" + echo "" + echo "Access provisioning files at:" + echo " HTTP: http://$(hostname -I | cut -d' ' -f1):8088/static/" + echo " HTTPS: https://$(hostname -I | cut -d' ' -f1):8089/static/" +} + +create_linphone_xml() { + print_header "Create/Edit Linphone Provisioning XML" + load_config + + local xml_file="$PROVISIONING_DIR/linphone.xml" + local server_ip=$(hostname -I | cut -d' ' -f1) + local domain="${DOMAIN_NAME:-$server_ip}" + local transport="tcp" + + if [[ "$ENABLE_TLS" == "y" && -n "$DOMAIN_NAME" ]]; then + transport="tls" + fi + + echo "Current Configuration:" + echo " Domain: $domain" + echo " Transport: $transport" + echo " Server IP: $server_ip" + echo "" + + read -p "Create/Update linphone.xml? (y/n) [y]: " create_xml + create_xml=${create_xml:-y} + + if [[ "$create_xml" =~ ^[Yy]$ ]]; then + mkdir -p "$PROVISIONING_DIR" + + cat > "$xml_file" << EOF + + + + + +
+ 0 + 1 + 0 +
+ +
+ <sip:${domain};transport=${transport}> + sip:USERNAME@${domain} + 3600 + 0 + 0 +
+ +
+ USERNAME + PASSWORD + ${domain} +
+ +
+ 7078 + 60 +
+ +
+ ANDROID SND: Android Sound card + ANDROID SND: Android Sound card + ANDROID SND: Android Sound card +
+ +
+ 0 + 0 + 0 +
+ +
+ 1 + 0 + 1 + 0 + + 0 +
+ +
+ 1300 +
+ +
+EOF + + chown asterisk:asterisk "$xml_file" + chmod 644 "$xml_file" + + print_success "Created: $xml_file" + echo "" + echo "Provisioning URL:" + if [[ "$transport" == "tls" ]]; then + echo " https://${domain}:8089/static/linphone.xml" + else + echo " http://${server_ip}:8088/static/linphone.xml" + fi + echo "" + echo "IMPORTANT for Android:" + echo " 1. Use the URL above in Linphone's 'Remote provisioning'" + echo " 2. Replace USERNAME and PASSWORD in device-specific XML files" + echo " 3. Set Battery Optimization to 'Unrestricted' manually on phone" + echo " 4. The XML prevents audio pause when screen turns off" + fi +} + +edit_linphone_xml() { + local xml_file="$PROVISIONING_DIR/linphone.xml" + + if [[ ! -f "$xml_file" ]]; then + print_error "linphone.xml does not exist. Create it first." + return 1 + fi + + print_header "Edit Linphone XML" + echo "Opening in nano editor..." + echo "Press Ctrl+X to save and exit" + echo "" + read -p "Press Enter to continue..." + + nano "$xml_file" + + print_success "Changes saved" +} + +show_provisioning_status() { + print_header "Provisioning Status" + + # Check HTTP configuration + if [[ -f /etc/asterisk/http.conf ]] && grep -q "enabled=yes" /etc/asterisk/http.conf 2>/dev/null; then + echo -e "HTTP Server: ${GREEN}Enabled${NC}" + asterisk -rx "http show status" 2>/dev/null | head -10 + else + echo -e "HTTP Server: ${RED}Disabled${NC}" + fi + + echo "" + + # Check provisioning directory + if [[ -d "$PROVISIONING_DIR" ]]; then + echo -e "Provisioning Dir: ${GREEN}$PROVISIONING_DIR${NC}" + echo "Files:" + ls -lh "$PROVISIONING_DIR" 2>/dev/null | tail -n +2 || echo " (empty)" + else + echo -e "Provisioning Dir: ${RED}Not created${NC}" + fi + + echo "" + + # Check symlink + if [[ -L /usr/share/asterisk/static-http ]]; then + echo -e "Symlink: ${GREEN}OK${NC} (/usr/share/asterisk/static-http)" + else + echo -e "Symlink: ${YELLOW}Not created${NC}" + fi + + echo "" + local server_ip=$(hostname -I | cut -d' ' -f1) + echo "Provisioning URLs:" + echo " HTTP: http://${server_ip}:8088/static/" + echo " HTTPS: https://${server_ip}:8089/static/" +} + +provisioning_manager_menu() { + while true; do + clear + print_header "Provisioning Manager" + echo " 1) Setup HTTP Server (ports 8088/8089)" + echo " 2) Create/Update linphone.xml" + echo " 3) Edit linphone.xml" + echo " 4) Show Status" + echo " 5) Open Provisioning Directory" + echo " 0) Back" + read -p " Select: " choice + + case $choice in + 1) setup_http_provisioning ;; + 2) create_linphone_xml ;; + 3) edit_linphone_xml ;; + 4) show_provisioning_status ;; + 5) + if command -v mc &>/dev/null; then + mc "$PROVISIONING_DIR" + else + print_info "Opening with ls..." + ls -lah "$PROVISIONING_DIR" + fi + ;; + 0) return ;; + esac + + [[ "$choice" != "0" ]] && read -p "Press Enter..." + done +} + +# ================================================================ +# MANUAL UPDATE SYSTEM +# ================================================================ + +manual_update_asterisk() { + print_header "Manual Asterisk Update" + echo "WARNING: This will update Asterisk from the repository." + echo "A backup will be created automatically." + echo "" + asterisk -V 2>/dev/null || echo "Asterisk not currently running" + echo "" + read -p "Continue with update? (y/n) [n]: " confirm + confirm=${confirm:-n} + + if [[ ! "$confirm" =~ ^[Yy]$ ]]; then + print_info "Update cancelled" + return + fi + + # Backup configurations + local backup_dir="/root/asterisk-backup-$(date +%Y%m%d_%H%M%S)" + mkdir -p "$backup_dir" + echo "Creating backup in $backup_dir..." + cp -r /etc/asterisk "$backup_dir/" + cp -r /var/lib/asterisk "$backup_dir/" 2>/dev/null || true + + print_success "Backup created: $backup_dir" + + # Update + echo "" + print_info "Updating Asterisk..." + apt update + apt install --only-upgrade asterisk asterisk-modules -y + + # Restart + echo "" + print_info "Restarting Asterisk..." + systemctl restart asterisk + + sleep 3 + + if systemctl is-active asterisk >/dev/null; then + print_success "Asterisk updated successfully" + asterisk -V + echo "" + echo "Backup location: $backup_dir" + echo "" + echo "To rollback if needed:" + echo " systemctl stop asterisk" + echo " cp -r $backup_dir/asterisk/* /etc/asterisk/" + echo " systemctl start asterisk" + else + print_error "Asterisk failed to start after update!" + echo "" + echo "Rolling back..." + cp -r "$backup_dir/asterisk/"* /etc/asterisk/ + systemctl restart asterisk + print_info "Rollback complete" + fi +} + +# ================================================================ +# ROOM DIRECTORY +# ================================================================ + +show_room_directory() { + print_header "Room Directory" + load_config + + if [[ ! -f "$ROOMS_FILE" ]]; then + print_error "Rooms file not found: $ROOMS_FILE" + return + fi + + echo "Ring Groups vs Page Groups:" + echo " • Ring Groups: Rings all members until one answers" + echo " • Page Groups: Auto-answer broadcast to all members" + echo "" + echo "═══════════════════════════════════════════════════════════" + + local has_rooms=false + while IFS='|' read -r ext name members timeout type; do + # Skip comments and empty lines + [[ "$ext" =~ ^[[:space:]]*# ]] && continue + [[ -z "$ext" ]] && continue + + has_rooms=true + + # Determine icon based on type + local icon="📞" + local type_label="Ring Group" + if [[ "$type" == "page" ]]; then + icon="📢" + type_label="Page Group" + fi + + echo "" + echo "$icon Extension: $ext - $name" + echo " Type: $type_label" + echo " Members: $members" + echo " Timeout: ${timeout}s" + done < "$ROOMS_FILE" + + if [[ "$has_rooms" == "false" ]]; then + echo "" + echo "No rooms configured yet." + echo "Use 'Device Management → Manage rooms' to create rooms." + fi + + echo "" + echo "═══════════════════════════════════════════════════════════" +} + watch_live_logs() { print_header "Live Debugging" echo "Enabling PJSIP Logger..." @@ -3007,8 +3197,8 @@ submenu_server() { echo " 6) Verify CIDR/NAT config" echo " 7) Watch Live Logs" echo " 8) Router Doctor" - echo " 9) Configure TURN Server (COTURN)" - echo " 10) Configure VLAN Subnets" + echo " 9) Configure VLAN Subnets" + echo " 10) Provisioning Manager" echo " 0) Back" read -p " Select: " choice case $choice in @@ -3020,8 +3210,8 @@ submenu_server() { 6) verify_cidr_config ;; 7) watch_live_logs ;; 8) router_doctor ;; - 9) configure_coturn_menu ;; - 10) configure_vlan_subnets ;; + 9) configure_vlan_subnets ;; + 10) provisioning_manager_menu ;; 0) return ;; esac [[ "$choice" != "0" ]] && read -p "Press Enter..." @@ -3405,12 +3595,16 @@ submenu_tools() { echo " 1) Audio Test" echo " 2) Verify Audio/Codec Setup" echo " 3) Fix Audio (Unmute & Restart)" + echo " 4) Room Directory" + echo " 5) Manual Update Asterisk" echo " 0) Back" read -p " Select: " choice case $choice in 1) run_audio_test ;; 2) verify_audio_setup ;; 3) fix_audio_manually ;; + 4) show_room_directory ;; + 5) manual_update_asterisk ;; 0) return ;; esac [[ "$choice" != "0" ]] && read -p "Press Enter..." From 541d2ab22d587e5e1f22cdff63311455c3479b71 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 8 Dec 2025 20:40:31 +0000 Subject: [PATCH 2/7] Add /e/OS audio troubleshooting and enhanced linphone.xml for privacy ROMs PROBLEM ADDRESSED: Users with /e/OS (eFoundation OS) experience no audio transmission unless Linphone app has focus. This is due to /e/OS's strict privacy controls preventing background microphone access. CHANGES: 1. Enhanced linphone.xml template: - Added keep_service_alive=1 for service persistence - Added start_at_boot=1 for automatic startup - Added audio section with speaker routing - Force audio_route_speaker=1 for background operation - Updated instructions to reference /e/OS troubleshooting 2. New troubleshoot_eos_audio() function: - Comprehensive 9-step troubleshooting guide - Linphone app audio settings configuration - /e/OS privacy settings walkthrough - Advanced Privacy feature management - Network permission configuration - Autostart and battery optimization settings - XML provisioning verification - Speaker mode workaround - Nuclear option: disable privacy features temporarily - Alternative SIP app suggestions (Zoiper, CSipSimple, Wave) - Testing methodology - Technical explanation of the issue - Community resources and forum links 3. Added menu item in Provisioning Manager: - Option 6: "Troubleshoot /e/OS Audio Issues" - Easily accessible from provisioning workflow TECHNICAL DETAILS: The issue occurs because /e/OS restricts background microphone access even with permissions granted. The OS suspends audio capture when apps lose focus. Workarounds include forcing speaker mode, disabling specific privacy features, or using alternative SIP clients with better /e/OS compatibility. TESTING STEPS: 1. Make call with Linphone in foreground (audio works) 2. Press Home button 3. If audio stops, issue is confirmed 4. Follow troubleshooting guide in order This addresses privacy-focused Android ROM compatibility issues and provides users with clear, actionable solutions. --- easy-asterisk-v0.9.9.sh | 120 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/easy-asterisk-v0.9.9.sh b/easy-asterisk-v0.9.9.sh index 9a9945d..ee82acb 100644 --- a/easy-asterisk-v0.9.9.sh +++ b/easy-asterisk-v0.9.9.sh @@ -1629,6 +1629,15 @@ create_linphone_xml() { 0 0 + + 1 + 1 + + +
+ + 0 + 1
@@ -1655,6 +1664,9 @@ EOF echo " 2. Replace USERNAME and PASSWORD in device-specific XML files" echo " 3. Set Battery Optimization to 'Unrestricted' manually on phone" echo " 4. The XML prevents audio pause when screen turns off" + echo "" + echo "FOR /e/OS (eFoundation) users:" + echo " See 'Troubleshoot /e/OS Audio' in Provisioning Manager menu" fi } @@ -1715,6 +1727,112 @@ show_provisioning_status() { echo " HTTPS: https://${server_ip}:8089/static/" } +troubleshoot_eos_audio() { + print_header "/e/OS Audio Troubleshooting" + + cat << 'EOSHELP' +PROBLEM: No audio sent by phone unless Linphone has focus +═══════════════════════════════════════════════════════════ + +This is a known issue with /e/OS (eFoundation OS) and privacy-focused +Android ROMs. /e/OS has stricter privacy controls that prevent apps +from accessing the microphone in the background. + +SOLUTIONS (Try in order): + +1. LINPHONE APP SETTINGS (In Linphone app itself): + ──────────────────────────────────────────────────── + a) Open Linphone → ☰ Menu → Settings → Audio + b) Change "Audio Route" to "Speaker" (not Earpiece) + c) Enable "Use Speaker for calls" + d) Disable "Echo Cancellation" (test if this helps) + e) Go to Settings → Network + f) Set "Media Encryption" to "None" (or match server) + +2. /e/OS PRIVACY SETTINGS: + ──────────────────────────────────────────────────── + a) Settings → Apps → Linphone + b) Permissions → Microphone → "Allow all the time" + c) Permissions → Camera → "Don't allow" (if not using video) + d) "Remove permissions if app isn't used" → DISABLE + +3. /e/OS ADVANCED PRIVACY SETTINGS: + ──────────────────────────────────────────────────── + a) Settings → Privacy (Advanced Privacy / Privacy Central) + b) Find Linphone in the list + c) Disable "Hide my IP" for Linphone + d) Set Location to "Real" (not fake location) + e) Disable any "Manage trackers" restrictions for Linphone + +4. /e/OS NETWORK PERMISSIONS: + ──────────────────────────────────────────────────── + a) Settings → Apps → Linphone → Mobile data & Wi-Fi + b) Enable "Background data" + c) Enable "Unrestricted data usage" + d) Make sure "Allow network access" is ON + +5. /e/OS AUTOSTART: + ──────────────────────────────────────────────────── + a) Settings → Apps → Linphone → Battery + b) Battery optimization → "Don't optimize" or "Unrestricted" + c) Settings → Apps → Linphone → Advanced + d) Enable "Autostart" if available + +6. LINPHONE XML PROVISIONING (Server-side fix): + ──────────────────────────────────────────────────── + Your linphone.xml should already have these settings: + • android_pause_calls_when_audio_focus_lost=0 + • keep_service_alive=1 + • start_at_boot=1 + • audio_route_speaker=1 + + To verify, check: $PROVISIONING_DIR/linphone.xml + +7. ALTERNATIVE: USE SPEAKER MODE DURING CALL: + ──────────────────────────────────────────────────── + As a workaround, during an active call: + • Tap the speaker icon to enable speakerphone + • This often forces audio to work even in background + • Not ideal but proves the audio path works + +8. NUCLEAR OPTION - DISABLE PRIVACY FEATURES: + ──────────────────────────────────────────────────── + If nothing works, temporarily disable /e/OS privacy features: + a) Settings → Privacy → Advanced Privacy + b) Toggle OFF "Advanced Privacy" + c) Test if Linphone audio works + d) If it works, re-enable and whitelist Linphone + +9. ALTERNATIVE SIP APP: + ──────────────────────────────────────────────────── + If Linphone continues to have issues on /e/OS, try: + • Zoiper (better /e/OS compatibility) + • CSipSimple (older but reliable) + • Grandstream Wave (commercial but works well) + +TESTING: +════════ +1. Make a call with Linphone in foreground → audio works +2. Press Home button → does audio continue? +3. If audio stops, the issue is confirmed + +WHAT'S HAPPENING: +═════════════════ +/e/OS restricts background microphone access for privacy. +Even with permissions granted, the OS may suspend audio +capture when the app loses focus. The XML settings and +speaker mode help work around this limitation. + +MORE HELP: +══════════ +• /e/OS Community: https://community.e.foundation +• Linphone Forums: https://forum.linphone.org +• Issue: "Background microphone access on /e/OS" + +═══════════════════════════════════════════════════════════ +EOSHELP +} + provisioning_manager_menu() { while true; do clear @@ -1724,6 +1842,7 @@ provisioning_manager_menu() { echo " 3) Edit linphone.xml" echo " 4) Show Status" echo " 5) Open Provisioning Directory" + echo " 6) Troubleshoot /e/OS Audio Issues" echo " 0) Back" read -p " Select: " choice @@ -1740,6 +1859,7 @@ provisioning_manager_menu() { ls -lah "$PROVISIONING_DIR" fi ;; + 6) troubleshoot_eos_audio ;; 0) return ;; esac From 663314a801b016f2e9fb5a66bf2b8c4cbf0ca1d7 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 8 Dec 2025 20:55:50 +0000 Subject: [PATCH 3/7] Fix version display and remove remaining COTURN status line - Updated header from 'Easy Asterisk v1.23' to 'v0.9.9' - Updated pjsip.conf comment from v1.23 to v0.9.9 - Removed 'COTURN: Not installed' status line from main menu - All COTURN references now completely removed from UI User-visible changes: - Main menu now correctly shows 'Easy Asterisk v0.9.9' - Status section only shows Server and Client (no COTURN line) - pjsip.conf generated with correct version comment --- easy-asterisk-v0.9.9.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/easy-asterisk-v0.9.9.sh b/easy-asterisk-v0.9.9.sh index ee82acb..370781c 100644 --- a/easy-asterisk-v0.9.9.sh +++ b/easy-asterisk-v0.9.9.sh @@ -2460,7 +2460,7 @@ ${all_local_nets}" fi cat > "$conf_file" << EOF -; Easy Asterisk v1.23 +; Easy Asterisk v0.9.9 [global] type=global user_agent=EasyAsterisk @@ -3255,14 +3255,13 @@ uninstall_menu() { show_main_menu() { clear - print_header "Easy Asterisk v1.23" - + print_header "Easy Asterisk v0.9.9" + load_config echo " Status:" if [[ -f "$CONFIG_FILE" ]]; then [[ "$INSTALLED_SERVER" == "y" ]] && echo -e " Server: ${GREEN}Installed${NC}" || echo -e " Server: ${YELLOW}Not installed${NC}" [[ "$INSTALLED_CLIENT" == "y" ]] && echo -e " Client: ${GREEN}Installed${NC}" || echo -e " Client: ${YELLOW}Not installed${NC}" - [[ "$INSTALLED_COTURN" == "y" ]] && echo -e " COTURN: ${GREEN}Installed${NC}" || echo -e " COTURN: ${YELLOW}Not installed${NC}" [[ -n "$DOMAIN_NAME" ]] && echo -e " Domain: ${DOMAIN_NAME}" else echo -e " ${YELLOW}Not configured${NC}" From 5f46fe188b9cc49f70e6809ec6e81b3fbb843b61 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 9 Dec 2025 13:19:18 +0000 Subject: [PATCH 4/7] Add Baresip configuration generator for /e/OS compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Baresip works significantly better than Linphone on /e/OS for background audio operation. Adding dedicated provisioning support. NEW FEATURE: Baresip Config Generator - Added create_baresip_config() function in Provisioning Manager - Generates account configuration with full setup instructions - Provides both config file and manual entry instructions - Includes /e/OS-specific permission guidance Key Benefits of Baresip on /e/OS: - Better background audio handling than Linphone - Works with screen off without special hacks - Lightweight and efficient - Handles /e/OS microphone permissions more reliably Configuration Generator Creates: - Account line in baresip format with all parameters - Manual entry instructions for Baresip app - Audio settings recommendations (OpenSL ES) - Default action setup (Call, not Message) - Extension dialing guidance - /e/OS permission instructions Usage: - Server Settings → Provisioning Manager → Create Baresip Config - Enter extension, password, display name - Get config file with complete setup instructions - Download via HTTP provisioning or copy to phone Menu Updates: - Provisioning Manager option 4: Create Baresip Config - Option numbers renumbered (Status=5, Directory=6, Troubleshoot=7) This addresses the persistent /e/OS audio issues by providing a better SIP client alternative that actually works with /e/OS's privacy model. --- easy-asterisk-v0.9.9.sh | 155 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 149 insertions(+), 6 deletions(-) diff --git a/easy-asterisk-v0.9.9.sh b/easy-asterisk-v0.9.9.sh index 370781c..67c24fd 100644 --- a/easy-asterisk-v0.9.9.sh +++ b/easy-asterisk-v0.9.9.sh @@ -1833,6 +1833,147 @@ MORE HELP: EOSHELP } +create_baresip_config() { + print_header "Create Baresip Account Config" + load_config + + local server_ip=$(hostname -I | cut -d' ' -f1) + local domain="${DOMAIN_NAME:-$server_ip}" + local transport="tcp" + + if [[ "$ENABLE_TLS" == "y" && -n "$DOMAIN_NAME" ]]; then + transport="tls" + fi + + echo "Baresip Config Generator" + echo "================================================" + echo "" + echo "Baresip works BETTER on /e/OS than Linphone!" + echo "Better background audio handling." + echo "" + echo "Current Configuration:" + echo " Domain: $domain" + echo " Transport: $transport" + echo " Server IP: $server_ip" + echo "" + + read -p "Enter extension number (e.g., 202): " extension + [[ -z "$extension" ]] && { print_error "Extension required"; return 1; } + + read -p "Enter SIP password: " sip_password + [[ -z "$sip_password" ]] && { print_error "Password required"; return 1; } + + read -p "Enter display name (e.g., Kitchen Phone): " display_name + display_name=${display_name:-Extension $extension} + + local config_file="$PROVISIONING_DIR/baresip-${extension}.conf" + + mkdir -p "$PROVISIONING_DIR" + + cat > "$config_file" << EOF +# Baresip Account Configuration for Extension ${extension} +# Generated by Easy Asterisk v0.9.9 +# +# HOW TO USE: +# 1. Install Baresip from F-Droid or Play Store +# 2. Open Baresip → Menu → Accounts → Add Account +# 3. Manually enter the SIP URI and settings below +# OR copy this file to your phone and import +# +# ACCOUNT CONFIGURATION: +# ===================== + +# Full account line format: +;auth_pass=${sip_password};outbound="sip:${server_ip}:5060;transport=${transport}";regint=3600;pubint=0;answermode=manual;medianat=none + +# Explanation of parameters: +# - sip:${extension}@${domain} = Your SIP URI +# - auth_pass = Your password +# - outbound = Asterisk server address +# - regint=3600 = Re-register every hour +# - pubint=0 = Don't publish presence +# - answermode=manual = Don't auto-answer +# - medianat=none = No NAT for media (LAN use) + +# MANUAL ENTRY IN BARESIP APP: +# ============================ +# If importing doesn't work, manually enter: +# +# Display Name: ${display_name} +# SIP URI: sip:${extension}@${domain} +# Auth Username: ${extension} +# Auth Password: ${sip_password} +# Outbound Proxy: sip:${server_ip}:5060;transport=${transport} +# Register: Yes +# Register Interval: 3600 + +# DIALING OTHER EXTENSIONS: +# ========================= +# Just dial the extension number: 101, 202, etc. +# Or full format: 101@${domain} + +# AUDIO SETTINGS (in Baresip app): +# ================================ +# Preferences → Audio: +# - Audio Driver: OpenSL ES (best for Android) +# - Echo Cancellation: Enabled +# - Noise Suppression: Enabled + +# DEFAULT ACTION (in Baresip app): +# ================================ +# Preferences → UI → Default Action: Call +# (This makes tapping a contact initiate a call, not message) + +# /e/OS SETTINGS: +# ============== +# Settings → Apps → Baresip: +# - Permissions → Microphone: While using app +# - Permissions → Phone: Allow +# - Battery: Unrestricted +# - Background data: Enabled +# +# Baresip handles /e/OS better than Linphone! +# Should work with screen off without special hacks. + +EOF + + chown asterisk:asterisk "$config_file" + chmod 644 "$config_file" + + print_success "Created: $config_file" + echo "" + echo "Download URL:" + echo " http://${server_ip}:8088/static/baresip-${extension}.conf" + echo "" + echo "═══════════════════════════════════════════════════════════" + echo "QUICK SETUP IN BARESIP APP:" + echo "═══════════════════════════════════════════════════════════" + echo "" + echo "1. Open Baresip → Menu (☰) → Accounts → Add (+)" + echo "" + echo "2. Enter these details:" + echo " Display Name: ${display_name}" + echo " SIP URI: sip:${extension}@${domain}" + echo " Auth User: ${extension}" + echo " Auth Pass: ${sip_password}" + echo " Outbound Proxy: sip:${server_ip}:5060;transport=${transport}" + echo "" + echo "3. Check 'Register' box" + echo "" + echo "4. Save and wait for registration" + echo "" + echo "5. To call extensions, just dial: 202, 101, etc." + echo "" + echo "6. Set default action to Call:" + echo " Menu → Preferences → UI → Default Action: Call" + echo "" + echo "═══════════════════════════════════════════════════════════" + echo "" + echo "NOTE: Baresip works MUCH BETTER on /e/OS than Linphone!" + echo " Should maintain audio with screen off." + echo "═══════════════════════════════════════════════════════════" +} + provisioning_manager_menu() { while true; do clear @@ -1840,9 +1981,10 @@ provisioning_manager_menu() { echo " 1) Setup HTTP Server (ports 8088/8089)" echo " 2) Create/Update linphone.xml" echo " 3) Edit linphone.xml" - echo " 4) Show Status" - echo " 5) Open Provisioning Directory" - echo " 6) Troubleshoot /e/OS Audio Issues" + echo " 4) Create Baresip Config" + echo " 5) Show Status" + echo " 6) Open Provisioning Directory" + echo " 7) Troubleshoot /e/OS Audio Issues" echo " 0) Back" read -p " Select: " choice @@ -1850,8 +1992,9 @@ provisioning_manager_menu() { 1) setup_http_provisioning ;; 2) create_linphone_xml ;; 3) edit_linphone_xml ;; - 4) show_provisioning_status ;; - 5) + 4) create_baresip_config ;; + 5) show_provisioning_status ;; + 6) if command -v mc &>/dev/null; then mc "$PROVISIONING_DIR" else @@ -1859,7 +2002,7 @@ provisioning_manager_menu() { ls -lah "$PROVISIONING_DIR" fi ;; - 6) troubleshoot_eos_audio ;; + 7) troubleshoot_eos_audio ;; 0) return ;; esac From 2a999981b3dbc8603bbf406ac52a6513facefa62 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 9 Dec 2025 13:53:29 +0000 Subject: [PATCH 5/7] Update Baresip instructions with accurate manual setup process MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on actual user experience configuring Baresip Android app. Previous instructions were incorrect/incomplete. KEY CHANGES: 1. Removed /e/OS-specific language: - Now generic: "Use if Linphone has audio issues" - Applicable to all privacy ROMs, not just /e/OS 2. Accurate two-step setup process: - Step 1: Add account with just SIP URI (ext@domain) - Step 2: Edit account to add auth username, password, proxy - This matches actual app behavior 3. Critical field corrections: - Auth Username: JUST extension number (not ext@domain) - Outbound Proxy: JUST domain (not sip:server:port format) - Media Encryption: srtp (select from dropdown) 4. No provisioning URL: - Clarified Baresip doesn't support remote provisioning - Must configure manually (unlike Linphone) 5. Added top bar icon reference: - ☰ = Menu, ✓ = Save, ⋮ = Options - 📞 = Call, 🔊 = Speaker, 🔇 = Mute, ✕ = Hangup 6. Default action clarification: - May not exist in all Baresip versions - Provided alternatives: long-press or phone icon 7. Comprehensive troubleshooting: - Registration failure solutions - Dialing issues - Audio problems - Screen-off audio (rare with Baresip) 8. Extension dialing guidance: - Method 1: Just the number (101, 202) - Method 2: Full format (ext@domain) if needed 9. File renamed: - .conf → .txt for better readability on phones Output format: - Detailed step-by-step instructions - Quick reference summary at end - Troubleshooting section - Icon reference guide This addresses all user-reported configuration issues and provides accurate, tested setup instructions based on real app usage. --- easy-asterisk-v0.9.9.sh | 276 +++++++++++++++++++++++++++------------- 1 file changed, 188 insertions(+), 88 deletions(-) diff --git a/easy-asterisk-v0.9.9.sh b/easy-asterisk-v0.9.9.sh index 67c24fd..496e35c 100644 --- a/easy-asterisk-v0.9.9.sh +++ b/easy-asterisk-v0.9.9.sh @@ -1834,26 +1834,23 @@ EOSHELP } create_baresip_config() { - print_header "Create Baresip Account Config" + print_header "Create Baresip Setup Instructions" load_config local server_ip=$(hostname -I | cut -d' ' -f1) local domain="${DOMAIN_NAME:-$server_ip}" - local transport="tcp" - if [[ "$ENABLE_TLS" == "y" && -n "$DOMAIN_NAME" ]]; then - transport="tls" - fi - - echo "Baresip Config Generator" + echo "Baresip Setup Guide Generator" echo "================================================" echo "" - echo "Baresip works BETTER on /e/OS than Linphone!" - echo "Better background audio handling." + echo "Use Baresip if Linphone has audio issues (screen off, etc.)" + echo "Baresip often works better on privacy-focused Android ROMs." + echo "" + echo "NOTE: Baresip does NOT support remote provisioning." + echo " Manual configuration required." echo "" echo "Current Configuration:" echo " Domain: $domain" - echo " Transport: $transport" echo " Server IP: $server_ip" echo "" @@ -1866,74 +1863,176 @@ create_baresip_config() { read -p "Enter display name (e.g., Kitchen Phone): " display_name display_name=${display_name:-Extension $extension} - local config_file="$PROVISIONING_DIR/baresip-${extension}.conf" + local config_file="$PROVISIONING_DIR/baresip-${extension}.txt" mkdir -p "$PROVISIONING_DIR" - cat > "$config_file" << EOF -# Baresip Account Configuration for Extension ${extension} -# Generated by Easy Asterisk v0.9.9 -# -# HOW TO USE: -# 1. Install Baresip from F-Droid or Play Store -# 2. Open Baresip → Menu → Accounts → Add Account -# 3. Manually enter the SIP URI and settings below -# OR copy this file to your phone and import -# -# ACCOUNT CONFIGURATION: -# ===================== + cat > "$config_file" << 'BARESIPEOF' +═══════════════════════════════════════════════════════════ +BARESIP SETUP INSTRUCTIONS +Generated by Easy Asterisk v0.9.9 +═══════════════════════════════════════════════════════════ -# Full account line format: -;auth_pass=${sip_password};outbound="sip:${server_ip}:5060;transport=${transport}";regint=3600;pubint=0;answermode=manual;medianat=none +IMPORTANT: Baresip does NOT support remote provisioning. +You must configure manually following these steps. -# Explanation of parameters: -# - sip:${extension}@${domain} = Your SIP URI -# - auth_pass = Your password -# - outbound = Asterisk server address -# - regint=3600 = Re-register every hour -# - pubint=0 = Don't publish presence -# - answermode=manual = Don't auto-answer -# - medianat=none = No NAT for media (LAN use) +STEP 1: INSTALL BARESIP +════════════════════════════════════════════════════════════ +• Download Baresip from F-Droid or Play Store +• Open the Baresip app -# MANUAL ENTRY IN BARESIP APP: -# ============================ -# If importing doesn't work, manually enter: -# -# Display Name: ${display_name} -# SIP URI: sip:${extension}@${domain} -# Auth Username: ${extension} -# Auth Password: ${sip_password} -# Outbound Proxy: sip:${server_ip}:5060;transport=${transport} -# Register: Yes -# Register Interval: 3600 +STEP 2: ADD ACCOUNT (Initial Entry) +════════════════════════════════════════════════════════════ +1. Tap Menu (☰ hamburger icon) → Accounts +2. Tap the Add (+) button at the top +3. In "SIP URI" field, enter: BARESIPEOF + echo "${extension}@${domain}" >> "$config_file" + cat >> "$config_file" << 'BARESIPEOF' +4. Tap the Save (✓ checkmark) icon at the top -# DIALING OTHER EXTENSIONS: -# ========================= -# Just dial the extension number: 101, 202, etc. -# Or full format: 101@${domain} +STEP 3: EDIT ACCOUNT (Complete Configuration) +════════════════════════════════════════════════════════════ +Now go back and edit the account to add authentication: -# AUDIO SETTINGS (in Baresip app): -# ================================ -# Preferences → Audio: -# - Audio Driver: OpenSL ES (best for Android) -# - Echo Cancellation: Enabled -# - Noise Suppression: Enabled +1. Tap Menu (☰) → Accounts +2. Tap on the account you just created +3. Fill in the following fields: -# DEFAULT ACTION (in Baresip app): -# ================================ -# Preferences → UI → Default Action: Call -# (This makes tapping a contact initiate a call, not message) +BARESIPEOF + cat >> "$config_file" << EOF + Display Name: ${display_name} -# /e/OS SETTINGS: -# ============== -# Settings → Apps → Baresip: -# - Permissions → Microphone: While using app -# - Permissions → Phone: Allow -# - Battery: Unrestricted -# - Background data: Enabled -# -# Baresip handles /e/OS better than Linphone! -# Should work with screen off without special hacks. + Authentication Username: ${extension} + (CRITICAL: Just the extension number, NOT ${extension}@${domain}) + + Authentication Password: ${sip_password} + + Outbound Proxy URI: ${domain} + (CRITICAL: Just the domain, NOT sip:${server_ip}:5060) + + Media Encryption: srtp + (Select from dropdown menu) + + Register: ✓ (Check this box) + +4. Tap Save (✓ checkmark icon) + +STEP 4: VERIFY REGISTRATION +════════════════════════════════════════════════════════════ +• Wait a few seconds for registration +• You should see: + - Green dot next to account, OR + - "Registered" status text + +If registration FAILS: + ✗ Double-check "Authentication Username" is JUST "${extension}" + ✗ Double-check "Outbound Proxy URI" is JUST "${domain}" + ✗ Verify password is correct: ${sip_password} + +STEP 5: SET CALLING AS DEFAULT (Optional) +════════════════════════════════════════════════════════════ +To make tapping a contact initiate a call (not message): + +1. Tap Menu (☰) → Settings (or Preferences) +2. Look for "Default Action" or "Contact Action" +3. If available, select: "Audio Call" or "Call" +4. Save + +NOTE: This option may not exist in all Baresip versions. + If not available, you can still call by: + - Long-pressing a contact → Select "Call" + - Or using the phone icon during selection + +STEP 6: AUDIO SETTINGS (Recommended) +════════════════════════════════════════════════════════════ +1. Tap Menu (☰) → Settings → Audio +2. Configure: + Audio Module: opensles (or audiotrack if opensles doesn't work) + Echo Cancellation: ✓ Enabled + Noise Suppression: ✓ Enabled + +STEP 7: ANDROID PERMISSIONS +════════════════════════════════════════════════════════════ +Go to your phone's: +Settings → Apps → Baresip + +Set the following: +• Permissions → Microphone: Allow while using app +• Permissions → Phone: Allow +• Battery: Unrestricted (or Not optimized) +• Mobile data & Wi-Fi → Background data: Enabled + +DIALING EXTENSIONS +════════════════════════════════════════════════════════════ +To call other extensions: + +Method 1 (Try this first): + Just dial the extension number: 101, 202, etc. + +Method 2 (If method 1 doesn't work): + Full format: 101@${domain} + +Common Extensions: +• Individual devices: 101, 102, 201, 202, etc. +• Page groups (auto-answer broadcast): 199 +• Ring groups (rings all phones): 299 + +TOP BAR ICONS IN BARESIP +════════════════════════════════════════════════════════════ +☰ = Hamburger menu (Accounts, Settings, About, etc.) +✓ = Save/Confirm current action +⋮ = Additional options (context-dependent) +📞 = Answer incoming call / Place outgoing call +🔊 = Enable speakerphone (during active call) +🔇 = Mute microphone (during active call) +✕ = Hang up / End call + +TROUBLESHOOTING +════════════════════════════════════════════════════════════ + +PROBLEM: Registration fails +SOLUTION: + • Verify "Authentication Username" is JUST: ${extension} + • Verify "Outbound Proxy URI" is JUST: ${domain} + • Check password is correct + • Check phone has network connectivity + • Check firewall allows SIP traffic + +PROBLEM: Can't dial extensions +SOLUTION: + • Verify you're registered (green dot/status) + • Try dialing full format: ${extension}@${domain} + • Check extension exists on server + +PROBLEM: No audio / Audio doesn't work +SOLUTION: + • Menu → Settings → Audio → Try different "Audio Module" + • Check microphone permissions in Android settings + • During call, try tapping speaker icon + +PROBLEM: Audio cuts when screen turns off +SOLUTION: + • Settings → Apps → Baresip → Battery → Unrestricted + • Baresip handles this much better than Linphone! + • This issue is rare with Baresip + +PROBLEM: Can't find "Default Action" setting +SOLUTION: + • Not all Baresip versions have this option + • Alternative: Long-press contact → Select "Call" + • Or tap contact then tap phone icon + +═══════════════════════════════════════════════════════════ +QUICK REFERENCE +═══════════════════════════════════════════════════════════ +Display Name: ${display_name} +SIP URI (initial): ${extension}@${domain} +Auth Username: ${extension} +Auth Password: ${sip_password} +Outbound Proxy: ${domain} +Media Encryption: srtp +Register: ✓ +═══════════════════════════════════════════════════════════ EOF @@ -1942,35 +2041,36 @@ EOF print_success "Created: $config_file" echo "" - echo "Download URL:" - echo " http://${server_ip}:8088/static/baresip-${extension}.conf" - echo "" echo "═══════════════════════════════════════════════════════════" - echo "QUICK SETUP IN BARESIP APP:" + echo "BARESIP SETUP - Extension ${extension}" echo "═══════════════════════════════════════════════════════════" echo "" - echo "1. Open Baresip → Menu (☰) → Accounts → Add (+)" + echo "Download instructions:" + echo " http://${server_ip}:8088/static/baresip-${extension}.txt" echo "" - echo "2. Enter these details:" - echo " Display Name: ${display_name}" - echo " SIP URI: sip:${extension}@${domain}" - echo " Auth User: ${extension}" - echo " Auth Pass: ${sip_password}" - echo " Outbound Proxy: sip:${server_ip}:5060;transport=${transport}" + echo "QUICK SETUP SUMMARY:" echo "" - echo "3. Check 'Register' box" + echo "Step 1: Add Account" + echo " Menu → Accounts → Add (+)" + echo " SIP URI: ${extension}@${domain}" + echo " Save (✓)" echo "" - echo "4. Save and wait for registration" + echo "Step 2: Edit Account" + echo " Tap account → Edit" + echo " Auth Username: ${extension} (JUST the number!)" + echo " Auth Password: ${sip_password}" + echo " Outbound Proxy: ${domain} (JUST the domain!)" + echo " Media Encryption: srtp (select from dropdown)" + echo " Register: ✓" + echo " Save (✓)" echo "" - echo "5. To call extensions, just dial: 202, 101, etc." + echo "Step 3: Verify" + echo " Look for green dot or 'Registered' status" echo "" - echo "6. Set default action to Call:" - echo " Menu → Preferences → UI → Default Action: Call" + echo "Step 4: Dial Extensions" + echo " Just dial: 101, 202, etc." echo "" - echo "═══════════════════════════════════════════════════════════" - echo "" - echo "NOTE: Baresip works MUCH BETTER on /e/OS than Linphone!" - echo " Should maintain audio with screen off." + echo "Full details in the text file above." echo "═══════════════════════════════════════════════════════════" } From 1b44b5b2ad0c7cd2fca1af68504e06caa576e4a5 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 9 Dec 2025 14:15:06 +0000 Subject: [PATCH 6/7] Combine Linphone and Baresip setup instructions in device output Changes: - Show both Linphone and Baresip setup in add_device_menu() output - Remove separate menu requirement - both apps shown together - Change language from "/e/OS-specific" to generic "if Linphone has audio issues" - Update domain examples from sip.mydomain.com to asterisk.mydomain.com - Add note that credentials work for other SIP apps (Zoiper, sipnetic) - Verify no user FQDN hardcoded in script This provides immediate access to both SIP app configurations when adding a device, with clear headers distinguishing between the two approaches. --- easy-asterisk-v0.9.9.sh | 73 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 4 deletions(-) diff --git a/easy-asterisk-v0.9.9.sh b/easy-asterisk-v0.9.9.sh index 496e35c..23a30c1 100644 --- a/easy-asterisk-v0.9.9.sh +++ b/easy-asterisk-v0.9.9.sh @@ -672,12 +672,23 @@ EOF asterisk -rx "pjsip reload" >/dev/null 2>&1 rebuild_dialplan + # Prepare provisioning URLs if HTTP server is configured + local server_ip=$(hostname -I | awk '{print $1}') + local prov_url_http="" + local prov_url_https="" + if [[ -f /etc/asterisk/http.conf ]] && grep -q "enabled=yes" /etc/asterisk/http.conf 2>/dev/null; then + prov_url_http="http://${server_ip}:8088/static/linphone.xml" + if [[ -n "$DOMAIN_NAME" ]]; then + prov_url_https="https://${DOMAIN_NAME}:8089/static/linphone.xml" + fi + fi + echo "" echo "═══════════════════════════════════════════════════════════════" - echo " DEVICE ADDED" + echo " DEVICE ADDED: $name (Extension $ext)" echo "═══════════════════════════════════════════════════════════════" echo "" - echo -e " ${BOLD}Client Configuration:${NC}" + echo -e " ${BOLD}Server Details:${NC}" echo " Server: ${display_server}" echo " Port: ${display_port}" echo " Transport: ${display_transport}" @@ -686,6 +697,60 @@ EOF echo " Encryption: ${display_encryption}" echo "" echo "═══════════════════════════════════════════════════════════════" + echo -e " ${BOLD}LINPHONE SETUP${NC}" + echo "═══════════════════════════════════════════════════════════════" + echo "" + if [[ -n "$prov_url_http" ]]; then + echo " Remote Provisioning (Recommended):" + echo " 1. In Linphone → Settings → Remote provisioning" + echo " 2. Enter URL:" + echo " ${prov_url_http}" + [[ -n "$prov_url_https" ]] && echo " OR ${prov_url_https}" + echo " 3. Tap 'Fetch' to apply configuration" + echo "" + echo " OR Manual Setup:" + else + echo " Manual Setup:" + fi + echo " 1. Add Account → Use SIP account" + echo " 2. Username: $ext" + echo " 3. Password: $pass" + echo " 4. Domain: ${display_server}" + echo " 5. Transport: ${display_transport}" + echo "" + echo "═══════════════════════════════════════════════════════════════" + echo -e " ${BOLD}BARESIP SETUP (if Linphone has audio issues)${NC}" + echo "═══════════════════════════════════════════════════════════════" + echo "" + echo " Baresip often works better on privacy-focused Android ROMs." + echo " Two-step manual configuration required:" + echo "" + echo " Step 1: Add Account" + echo " Menu (☰) → Accounts → Add (+)" + echo " SIP URI: ${ext}@${display_server}" + echo " Save (✓)" + echo "" + echo " Step 2: Edit Account (Complete Config)" + echo " Tap account → Edit" + echo " Auth Username: $ext (JUST the number!)" + echo " Auth Password: $pass" + echo " Outbound Proxy: ${display_server} (JUST the domain!)" + echo " Media Encryption: srtp (select from dropdown)" + echo " Register: ✓ (check box)" + echo " Save (✓)" + echo "" + echo " Verify: Look for green dot or 'Registered' status" + echo " To call: Just dial extension (101, 202, etc.)" + echo "" + echo " For detailed Baresip instructions:" + echo " Server Settings → Provisioning Manager → Create Baresip Config" + echo "" + echo "═══════════════════════════════════════════════════════════════" + echo "" + echo " NOTE: These instructions work for most SIP apps (Zoiper," + echo " sipnetic, etc.) - just use the same credentials." + echo "" + echo "═══════════════════════════════════════════════════════════════" } remove_device() { @@ -1420,7 +1485,7 @@ WHAT YOU'RE ACHIEVING: { 'network.1' = ['upstream.1'] } ] rules = [ - { 'sip.mydomain.com' = ['upstream.4'] } + { 'asterisk.mydomain.com' = ['upstream.4'] } ] [network.0] @@ -1445,7 +1510,7 @@ sudo apt-get install dnsmasq echo "listen-address=127.0.0.1" >> /etc/dnsmasq.conf echo "listen-address=$(hostname -I | cut -d' ' -f1)" >> /etc/dnsmasq.conf echo "bind-interfaces" >> /etc/dnsmasq.conf -echo "address=/sip.mydomain.com/$(hostname -I | cut -d' ' -f1)" >> /etc/dnsmasq.conf +echo "address=/asterisk.mydomain.com/$(hostname -I | cut -d' ' -f1)" >> /etc/dnsmasq.conf sudo systemctl restart dnsmasq 3. UFW RULES ON THIS SERVER: From f8e800c869ae8218846028a47dda6603bf01364d Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Dec 2025 02:20:27 +0000 Subject: [PATCH 7/7] Use SCRIPT_VERSION variable instead of hardcoded version numbers Changes: - Update main menu header to use ${SCRIPT_VERSION} variable - Update pjsip.conf header comment to use ${SCRIPT_VERSION} - Update Baresip instructions header to use ${SCRIPT_VERSION} - Changed Baresip heredoc from single-quoted to allow variable expansion This ensures version display always matches the SCRIPT_VERSION variable at line 44, eliminating hardcoded version mismatches. --- easy-asterisk-v0.9.9.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/easy-asterisk-v0.9.9.sh b/easy-asterisk-v0.9.9.sh index 23a30c1..d5e142d 100644 --- a/easy-asterisk-v0.9.9.sh +++ b/easy-asterisk-v0.9.9.sh @@ -1932,10 +1932,10 @@ create_baresip_config() { mkdir -p "$PROVISIONING_DIR" - cat > "$config_file" << 'BARESIPEOF' + cat > "$config_file" << BARESIPEOF ═══════════════════════════════════════════════════════════ BARESIP SETUP INSTRUCTIONS -Generated by Easy Asterisk v0.9.9 +Generated by Easy Asterisk v${SCRIPT_VERSION} ═══════════════════════════════════════════════════════════ IMPORTANT: Baresip does NOT support remote provisioning. @@ -2768,7 +2768,7 @@ ${all_local_nets}" fi cat > "$conf_file" << EOF -; Easy Asterisk v0.9.9 +; Easy Asterisk v${SCRIPT_VERSION} [global] type=global user_agent=EasyAsterisk @@ -3563,7 +3563,7 @@ uninstall_menu() { show_main_menu() { clear - print_header "Easy Asterisk v0.9.9" + print_header "Easy Asterisk v${SCRIPT_VERSION}" load_config echo " Status:"