Skip to main content
Glama

MCP Project Orchestrator

user-data.sh10.4 kB
#!/bin/bash # # AWS EC2 User Data Script for Asterisk SIP Trunk Installation # This script runs on first boot to install and configure Asterisk # set -euo pipefail # Error handling trap 'echo "Error on line $LINENO"; exit 1' ERR # Logging LOG_FILE="/var/log/asterisk-setup.log" exec 1> >(tee -a "$LOG_FILE") exec 2>&1 echo "=== Asterisk SIP Trunk Installation Started: $(date) ===" # Variables from Terraform export AWS_REGION="${aws_region}" export ELASTIC_IP="${elastic_ip}" export ELEVENLABS_PHONE_E164="${elevenlabs_phone_e164}" export PROJECT_NAME="${project_name}" export ENABLE_CALL_RECORDINGS="${enable_call_recordings}" export S3_BUCKET_RECORDINGS="${s3_bucket_recordings}" export ASTERISK_LOG_LEVEL="${asterisk_log_level}" export RTP_PORT_START="${rtp_port_start}" export RTP_PORT_END="${rtp_port_end}" export ENABLE_CLOUDWATCH="${enable_cloudwatch}" # Get instance metadata INSTANCE_ID=$(ec2-metadata --instance-id | cut -d " " -f 2) PRIVATE_IP=$(ec2-metadata --local-ipv4 | cut -d " " -f 2) AVAILABILITY_ZONE=$(ec2-metadata --availability-zone | cut -d " " -f 2) echo "Instance ID: $INSTANCE_ID" echo "Private IP: $PRIVATE_IP" echo "Elastic IP: $ELASTIC_IP" # Update system echo "=== Updating system packages ===" yum update -y # Install development tools echo "=== Installing development tools ===" yum groupinstall -y "Development Tools" yum install -y \ wget \ ncurses-devel \ libuuid-devel \ jansson-devel \ libxml2-devel \ sqlite-devel \ openssl-devel \ kernel-devel \ libedit-devel \ libsrtp-devel \ pjproject-devel \ unixODBC-devel \ libtool-ltdl-devel \ git \ vim \ tcpdump \ nmap \ fail2ban \ awscli \ amazon-cloudwatch-agent # Download and compile Asterisk 21 echo "=== Downloading Asterisk 21 ===" cd /usr/src ASTERISK_VERSION="21.5.0" wget "https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-$ASTERISK_VERSION.tar.gz" tar xvfz "asterisk-$ASTERISK_VERSION.tar.gz" cd "asterisk-$ASTERISK_VERSION" echo "=== Configuring Asterisk ===" ./configure \ --with-pjproject-bundled \ --with-jansson-bundled \ --libdir=/usr/lib64 # Install required modules echo "=== Selecting Asterisk modules ===" make menuselect.makeopts menuselect/menuselect \ --enable chan_pjsip \ --enable res_pjsip \ --enable res_pjsip_nat \ --enable res_pjsip_session \ --enable res_pjsip_outbound_registration \ --enable app_dial \ --enable app_playback \ --enable app_voicemail \ --enable codec_ulaw \ --enable codec_alaw \ --enable codec_gsm \ --enable format_wav \ --enable format_pcm \ menuselect.makeopts echo "=== Compiling Asterisk (this may take 10-15 minutes) ===" make -j$(nproc) make install make samples make config # Create Asterisk user echo "=== Creating Asterisk user ===" groupadd asterisk 2>/dev/null || true useradd -r -d /var/lib/asterisk -g asterisk asterisk 2>/dev/null || true chown -R asterisk:asterisk /etc/asterisk /var/{lib,log,spool}/asterisk /usr/lib64/asterisk # Retrieve credentials from Parameter Store echo "=== Retrieving credentials from Parameter Store ===" ELEVENLABS_PASSWORD=$(aws ssm get-parameter \ --name "/$PROJECT_NAME/elevenlabs/sip_password" \ --with-decryption \ --query 'Parameter.Value' \ --output text \ --region "$AWS_REGION") # Configure PJSIP echo "=== Configuring PJSIP ===" cat > /etc/asterisk/pjsip.conf <<EOF ; ; PJSIP Configuration for ElevenLabs SIP Trunk ; Auto-generated by AWS deployment ; [global] max_forwards=70 user_agent=Asterisk-AWS-$INSTANCE_ID default_realm=aws.internal debug=no [transport-tcp] type=transport protocol=tcp bind=0.0.0.0:5060 external_media_address=$ELASTIC_IP external_signaling_address=$ELASTIC_IP local_net=$PRIVATE_IP/16 [elevenlabs] type=endpoint context=from-elevenlabs transport=transport-tcp aors=elevenlabs outbound_auth=elevenlabs-auth allow=!all,ulaw,alaw direct_media=no from_user=$ELEVENLABS_PHONE_E164 callerid=$ELEVENLABS_PHONE_E164 rtp_symmetric=yes force_rport=yes rewrite_contact=yes dtmf_mode=rfc4733 trust_id_inbound=yes trust_id_outbound=yes [elevenlabs] type=aor contact=sip:sip.elevenlabs.io:5060;transport=tcp qualify_frequency=60 qualify_timeout=3 [elevenlabs-auth] type=auth auth_type=userpass username=$ELEVENLABS_PHONE_E164 password=$ELEVENLABS_PASSWORD [elevenlabs] type=identify endpoint=elevenlabs match=sip.elevenlabs.io EOF # Configure RTP echo "=== Configuring RTP ===" cat > /etc/asterisk/rtp.conf <<EOF ; ; RTP Configuration ; [general] rtpstart=$RTP_PORT_START rtpend=$RTP_PORT_END rtpchecksums=no dtmftimeout=3000 rtcpinterval=5000 strictrtp=yes icesupport=no stunaddr= EOF # Configure Extensions (Dialplan) echo "=== Configuring dialplan ===" cat > /etc/asterisk/extensions.conf <<EOF ; ; Asterisk Dialplan for ElevenLabs Integration ; [general] static=yes writeprotect=no clearglobalvars=no [globals] ELEVENLABS_PHONE=$ELEVENLABS_PHONE_E164 RECORDINGS_PATH=/var/spool/asterisk/recordings [from-elevenlabs] ; Incoming calls from ElevenLabs agent exten => _X.,1,NoOp(Incoming call from ElevenLabs: \${CALLERID(all)}) same => n,Set(CDR(accountcode)=elevenlabs) same => n,Answer() same => n,Wait(1) same => n,Playback(hello-world) same => n,Echo() ; Echo test for audio verification same => n,Hangup() [outbound-to-elevenlabs] ; Outgoing calls to ElevenLabs agent exten => _X.,1,NoOp(Dialing ElevenLabs Agent: \${EXTEN}) same => n,Set(CALLERID(num)=\${ELEVENLABS_PHONE}) same => n,Set(CALLERID(name)=AWS-Asterisk) same => n,Set(CDR(accountcode)=elevenlabs) same => n,Dial(PJSIP/\${EXTEN}@elevenlabs,60,tT) same => n,Hangup() [default] ; Default context for safety exten => _X.,1,NoOp(Unauthorized call attempt) same => n,Hangup() EOF # Configure Asterisk logging echo "=== Configuring logging ===" cat > /etc/asterisk/logger.conf <<EOF ; ; Logger Configuration ; [general] dateformat=%F %T [logfiles] console => notice,warning,error messages => notice,warning,error full => $ASTERISK_LOG_LEVEL,notice,warning,error,verbose,dtmf [syslog] facility = local0 EOF # Configure systemd service echo "=== Configuring systemd service ===" cat > /etc/systemd/system/asterisk.service <<EOF [Unit] Description=Asterisk PBX After=network.target [Service] Type=forking User=asterisk Group=asterisk ExecStart=/usr/sbin/asterisk -f -U asterisk -G asterisk ExecReload=/usr/sbin/asterisk -rx 'core reload' Restart=always RestartSec=10 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable asterisk # Configure Fail2Ban for SIP security echo "=== Configuring Fail2Ban ===" cat > /etc/fail2ban/jail.d/asterisk.conf <<EOF [asterisk] enabled = true port = 5060 filter = asterisk logpath = /var/log/asterisk/full maxretry = 5 bantime = 3600 findtime = 600 EOF systemctl enable fail2ban systemctl start fail2ban # Configure CloudWatch Agent (if enabled) if [ "$ENABLE_CLOUDWATCH" = "true" ]; then echo "=== Configuring CloudWatch Agent ===" cat > /opt/aws/amazon-cloudwatch-agent/etc/config.json <<EOF { "agent": { "metrics_collection_interval": 60, "run_as_user": "cwagent" }, "logs": { "logs_collected": { "files": { "collect_list": [ { "file_path": "/var/log/asterisk/full", "log_group_name": "/aws/ec2/$PROJECT_NAME/asterisk", "log_stream_name": "{instance_id}-asterisk-full" }, { "file_path": "/var/log/asterisk/messages", "log_group_name": "/aws/ec2/$PROJECT_NAME/asterisk", "log_stream_name": "{instance_id}-asterisk-messages" } ] } } }, "metrics": { "namespace": "Asterisk/$PROJECT_NAME", "metrics_collected": { "cpu": { "measurement": [ {"name": "cpu_usage_idle", "rename": "CPU_IDLE", "unit": "Percent"}, {"name": "cpu_usage_iowait", "rename": "CPU_IOWAIT", "unit": "Percent"} ], "totalcpu": false }, "disk": { "measurement": [ {"name": "used_percent", "rename": "DISK_USED", "unit": "Percent"} ], "resources": ["/", "/var/spool/asterisk"] }, "mem": { "measurement": [ {"name": "mem_used_percent", "rename": "MEM_USED", "unit": "Percent"} ] } } } } EOF systemctl enable amazon-cloudwatch-agent systemctl start amazon-cloudwatch-agent fi # Create recordings directory (if enabled) if [ "$ENABLE_CALL_RECORDINGS" = "true" ]; then mkdir -p /var/spool/asterisk/recordings chown -R asterisk:asterisk /var/spool/asterisk/recordings fi # Start Asterisk echo "=== Starting Asterisk ===" systemctl start asterisk # Wait for Asterisk to initialize sleep 10 # Verify installation echo "=== Verifying Asterisk installation ===" asterisk -rx "core show version" asterisk -rx "pjsip show endpoints" asterisk -rx "pjsip show transports" # Create health check script cat > /usr/local/bin/asterisk-health-check.sh <<'EOF' #!/bin/bash # Health check script for Asterisk SIP trunk if ! systemctl is-active --quiet asterisk; then echo "ERROR: Asterisk service is not running" exit 1 fi # Check if PJSIP endpoint is registered ENDPOINT_STATUS=$(asterisk -rx "pjsip show endpoint elevenlabs" | grep -c "Avail") if [ "$ENDPOINT_STATUS" -eq 0 ]; then echo "WARNING: ElevenLabs endpoint not available" exit 1 fi echo "OK: Asterisk is healthy" exit 0 EOF chmod +x /usr/local/bin/asterisk-health-check.sh # Setup cron for periodic health checks echo "*/5 * * * * /usr/local/bin/asterisk-health-check.sh >> /var/log/asterisk-health.log 2>&1" | crontab - # Installation complete echo "=== Asterisk SIP Trunk Installation Complete: $(date) ===" echo "" echo "Deployment Summary:" echo "===================" echo "Instance ID: $INSTANCE_ID" echo "Private IP: $PRIVATE_IP" echo "Public IP (Elastic IP): $ELASTIC_IP" echo "SIP Endpoint: sip:$ELASTIC_IP:5060" echo "ElevenLabs Phone: $ELEVENLABS_PHONE_E164" echo "RTP Port Range: $RTP_PORT_START-$RTP_PORT_END" echo "" echo "Useful Commands:" echo "================" echo "Asterisk CLI: asterisk -rx 'command'" echo "View logs: tail -f /var/log/asterisk/full" echo "Check endpoint: asterisk -rx 'pjsip show endpoints'" echo "Enable debug: asterisk -rx 'pjsip set logger on'" echo "" echo "Health check: /usr/local/bin/asterisk-health-check.sh" echo ""

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sparesparrow/mcp-project-orchestrator'

If you have feedback or need assistance with the MCP directory API, please join our Discord server