#!/usr/bin/env bash # Shared notification helper for BMM ops scripts. # # Sends an alert via: # - Twilio SMS (if TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_SMS_FROM, # ADMIN_PHONE are all set in /opt/buildmymcpserver/.env.production) # - HEALTHCHECKS_FAIL_URL (if set — generic webhook fallback) # - syslog (always) # # Usage: notify.sh "subject" "body" # # Designed to never fail loudly: if Twilio is misconfigured we still log # to syslog so failures aren't silent. Backup/uptime scripts trust this # helper to handle their own delivery failures gracefully. set -uo pipefail SUBJECT="${1:-bmm-alert}" BODY="${2:-}" # Always syslog — covers the case where notification channels are broken logger -t bmm-ops "$SUBJECT: $BODY" # Grep-parse the env file rather than `source`-ing it: the file is managed # for Docker compose (KEY=value, often unquoted text values like names), # and `source` evaluates unquoted RHS as shell — breaking on any value # with whitespace or shell metachars. This pulls only the keys we need. ENV_FILE="/opt/buildmymcpserver/.env.production" read_env() { grep -E "^$1=" "$ENV_FILE" 2>/dev/null | head -1 | cut -d= -f2- | sed 's/^"\(.*\)"$/\1/; s/^'"'"'\(.*\)'"'"'$/\1/' } if [ -f "$ENV_FILE" ]; then TWILIO_ACCOUNT_SID="${TWILIO_ACCOUNT_SID:-$(read_env TWILIO_ACCOUNT_SID)}" TWILIO_AUTH_TOKEN="${TWILIO_AUTH_TOKEN:-$(read_env TWILIO_AUTH_TOKEN)}" TWILIO_SMS_FROM="${TWILIO_SMS_FROM:-$(read_env TWILIO_SMS_FROM)}" ADMIN_PHONE="${ADMIN_PHONE:-$(read_env ADMIN_PHONE)}" HEALTHCHECKS_FAIL_URL="${HEALTHCHECKS_FAIL_URL:-$(read_env HEALTHCHECKS_FAIL_URL)}" fi # Twilio SMS — only if all four vars set if [ -n "${TWILIO_ACCOUNT_SID:-}" ] && \ [ -n "${TWILIO_AUTH_TOKEN:-}" ] && \ [ -n "${TWILIO_SMS_FROM:-}" ] && \ [ -n "${ADMIN_PHONE:-}" ]; then curl -sS -o /dev/null --max-time 10 \ -X POST "https://api.twilio.com/2010-04-01/Accounts/${TWILIO_ACCOUNT_SID}/Messages.json" \ --data-urlencode "From=${TWILIO_SMS_FROM}" \ --data-urlencode "To=${ADMIN_PHONE}" \ --data-urlencode "Body=[BMM] ${SUBJECT}: ${BODY}" \ -u "${TWILIO_ACCOUNT_SID}:${TWILIO_AUTH_TOKEN}" \ || logger -t bmm-ops "twilio-sms-failed: $SUBJECT" fi # Generic webhook (for healthchecks.io, BetterStack, etc.) — POST body if [ -n "${HEALTHCHECKS_FAIL_URL:-}" ]; then curl -fsS -o /dev/null --max-time 10 --retry 2 \ --data "${SUBJECT}: ${BODY}" "${HEALTHCHECKS_FAIL_URL}" \ || logger -t bmm-ops "healthcheck-webhook-failed" fi exit 0