Chain Security Dashboard + PSTN trunk setup into the Asterisk install flow

asterisk.sh and asterisk-digital-ocean.sh now offer, at the end of both
their fresh-install and update-mode paths, to also set up the Security
Dashboard and configure a real PSTN trunk in the same run - one script
walks through the whole stack instead of needing to separately remember
and run `sudo ./setup.sh security-dashboard` / `sudo ./setup.sh pstn-trunk`
afterward.

Both target services keep their own register_service call and stay fully
independently invocable - this is purely an additive convenience layer
(_asterisk_offer_dashboard_and_trunk / _asterisk_do_offer_dashboard_and_trunk),
not a replacement. An already-installed piece is silently refreshed
(install_security-dashboard/install_pstn-trunk each already have their own
update/fresh/cancel reinstall-mode gate, so calling them again just does
the right thing); a not-yet-installed piece gets one y/n instead of every
detailed prompt firing.

Guarded with declare -F so a standalone `sudo bash asterisk.sh` copy (no
sibling services/*.sh files sourced) skips both cleanly with an
explanatory message instead of erroring on an undefined function.

Verified: full sourcing simulation resolves all four install_* functions
correctly, `setup.sh --dry-run --unattended asterisk` and
`asterisk-digital-ocean` both complete cleanly end-to-end, and
`setup.sh --list` still shows all four services as independently
selectable.

Documented the pattern in CLAUDE.md under a new "Chaining into another
service from within your own" section for future contributors.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ho9mZgAkVpdz7S5wJkg8Nf
This commit is contained in:
Claude
2026-07-24 12:38:45 +00:00
parent 6f5ed30469
commit ff61e8f733
3 changed files with 132 additions and 0 deletions
+44
View File
@@ -645,6 +645,44 @@ ENV
log_info "never alerts by itself, since there's no prior state to compare against yet."
}
# See services/asterisk.sh's own copy for the full rationale — identical
# here, just calling into the same install_security-dashboard/
# install_pstn-trunk entry points (still independently registered/
# invocable; this is a convenience layer on top, not a replacement).
_asterisk_do_offer_dashboard_and_trunk() {
local EA_DIR="$1"
if ! declare -F install_security-dashboard >/dev/null 2>&1 && ! declare -F install_pstn-trunk >/dev/null 2>&1; then
log_info "Run this from the full ubuntu-post-install repo (not a standalone copy) to also"
log_info "get prompts here for the Security Dashboard and a PSTN trunk — skipping both."
return 0
fi
if declare -F install_security-dashboard >/dev/null 2>&1; then
echo ""
if [[ -f "$DOCKER_DIR/security-dashboard/app.py" ]]; then
log_info "Security Dashboard already installed — refreshing it too..."
install_security-dashboard
else
local _WANT_DASH=""
prompt_yn "Set up the Security Dashboard (Security Log, Extensions, Asterisk Admin, PSTN Trunk, CrowdSec — one page)? (y/n):" "y" _WANT_DASH
[[ "$_WANT_DASH" =~ ^[Yy]$ ]] && install_security-dashboard
fi
fi
if declare -F install_pstn-trunk >/dev/null 2>&1; then
echo ""
if [[ -f "$EA_DIR/config/asterisk/pstn-trunk-dialplan.conf" ]]; then
log_info "PSTN trunk already configured — refreshing it too..."
install_pstn-trunk
else
local _WANT_TRUNK=""
prompt_yn "Configure a real SIP/PSTN trunk (actual outside phone numbers, e.g. Anveo Direct/VoIP.ms)? (y/n):" "n" _WANT_TRUNK
[[ "$_WANT_TRUNK" =~ ^[Yy]$ ]] && install_pstn-trunk
fi
fi
}
# ── Shared: docker-compose.yml ─────────────────────────────────────────────
# Same reasoning as above — one copy of the template used by both fresh
# installs and updates. Must be called with $PWD already at $EA_DIR.
@@ -740,6 +778,9 @@ install_asterisk-digital-ocean() {
echo "[DRY-RUN] gated live on each sender's 'messaging' flag in pstn-permissions.conf (the"
echo "[DRY-RUN] same file/flag the Security Dashboard's checkbox writes) — independent of"
echo "[DRY-RUN] whether the PSTN trunk is installed; migrates any already-existing devices too"
echo "[DRY-RUN] Would offer to also set up the Security Dashboard and a PSTN trunk in this"
echo "[DRY-RUN] same run (calling services/security-dashboard.sh / services/pstn-trunk.sh"
echo "[DRY-RUN] directly — both stay independently invocable via their own service name too)"
return 0
fi
@@ -778,6 +819,7 @@ install_asterisk-digital-ocean() {
fi
_asterisk_do_run_presence_step "$EA_DIR"
_asterisk_do_offer_dashboard_and_trunk "$EA_DIR"
local _EXISTING_DOMAIN _EXISTING_PORT
_EXISTING_DOMAIN="$(grep -E '^DOMAIN_NAME=' .env | cut -d= -f2-)"
@@ -1425,6 +1467,8 @@ MD
|| log_warning "Start failed — check: docker compose logs"
fi
_asterisk_do_offer_dashboard_and_trunk "$EA_DIR"
# ── Summary ───────────────────────────────────────────────────────────────
echo ""
log_success "Easy Asterisk (DigitalOcean edition) installed at $EA_DIR"
+53
View File
@@ -609,6 +609,53 @@ ENV
log_info "never alerts by itself, since there's no prior state to compare against yet."
}
# Offers to add/refresh the Security Dashboard and a PSTN trunk as part of
# this SAME run, instead of needing to separately remember and run
# `sudo ./setup.sh security-dashboard` / `sudo ./setup.sh pstn-trunk`
# afterward. Neither loses its own independent registration/invocability —
# this is purely a convenience layer on top, called from both the fresh-
# install and update-mode paths below. An already-installed piece is just
# silently refreshed (install_security-dashboard/install_pstn-trunk each
# have their own update/fresh/cancel reinstall-mode gate, so calling them
# again here does the right thing automatically); a not-yet-installed piece
# gets a one-line y/n instead of every detailed prompt firing unconditionally.
_asterisk_offer_dashboard_and_trunk() {
local EA_DIR="$1"
# Only available when run through the full repo's setup.sh (which
# sources every services/*.sh file, including these two) — a standalone
# `sudo bash asterisk.sh` copy has neither function defined at all.
if ! declare -F install_security-dashboard >/dev/null 2>&1 && ! declare -F install_pstn-trunk >/dev/null 2>&1; then
log_info "Run this from the full ubuntu-post-install repo (not a standalone copy) to also"
log_info "get prompts here for the Security Dashboard and a PSTN trunk — skipping both."
return 0
fi
if declare -F install_security-dashboard >/dev/null 2>&1; then
echo ""
if [[ -f "$DOCKER_DIR/security-dashboard/app.py" ]]; then
log_info "Security Dashboard already installed — refreshing it too..."
install_security-dashboard
else
local _WANT_DASH=""
prompt_yn "Set up the Security Dashboard (Security Log, Extensions, Asterisk Admin, PSTN Trunk, CrowdSec — one page)? (y/n):" "y" _WANT_DASH
[[ "$_WANT_DASH" =~ ^[Yy]$ ]] && install_security-dashboard
fi
fi
if declare -F install_pstn-trunk >/dev/null 2>&1; then
echo ""
if [[ -f "$EA_DIR/config/asterisk/pstn-trunk-dialplan.conf" ]]; then
log_info "PSTN trunk already configured — refreshing it too..."
install_pstn-trunk
else
local _WANT_TRUNK=""
prompt_yn "Configure a real SIP/PSTN trunk (actual outside phone numbers, e.g. Anveo Direct/VoIP.ms)? (y/n):" "n" _WANT_TRUNK
[[ "$_WANT_TRUNK" =~ ^[Yy]$ ]] && install_pstn-trunk
fi
fi
}
# ── Shared: docker-compose.yml ─────────────────────────────────────────────
# Same reasoning as above — one copy of the template used by both fresh
# installs and updates. Must be called with $PWD already at $EA_DIR.
@@ -700,6 +747,9 @@ install_asterisk() {
echo "[DRY-RUN] Would offer optional ntfy alerts on extension registration going offline/online"
echo "[DRY-RUN] (checked every 2 minutes via systemd timer, cron.d fallback; always asked,"
echo "[DRY-RUN] update mode included)"
echo "[DRY-RUN] Would offer to also set up the Security Dashboard and a PSTN trunk in this"
echo "[DRY-RUN] same run (calling services/security-dashboard.sh / services/pstn-trunk.sh"
echo "[DRY-RUN] directly — both stay independently invocable via their own service name too)"
return 0
fi
@@ -737,6 +787,7 @@ install_asterisk() {
fi
_asterisk_run_presence_step "$EA_DIR"
_asterisk_offer_dashboard_and_trunk "$EA_DIR"
local _EXISTING_DOMAIN _EXISTING_PORT
_EXISTING_DOMAIN="$(grep -E '^DOMAIN_NAME=' .env | cut -d= -f2-)"
@@ -1041,6 +1092,8 @@ MD
|| log_warning "Start failed — check: docker compose logs"
fi
_asterisk_offer_dashboard_and_trunk "$EA_DIR"
# ── Summary ───────────────────────────────────────────────────────────────
echo ""
log_success "Easy Asterisk installed at $EA_DIR"