From 909ac2d62dc824d3d5f980816937df0bdf82385f Mon Sep 17 00:00:00 2001 From: iamdoubz Date: Sat, 17 Oct 2026 14:31:05 -0500 Subject: [PATCH] asterisk: 24.0.0-rc2 image built from source with static config Adds stub configs and noloads so a clean boot logs no ERROR lines, ships stock indications.conf, seeds default MOH from the entrypoint. Spec 01 synced with the real files. Task: M0-T5 --- asterisk/Dockerfile | 50 +++++++++++++++++ asterisk/conf/acl.conf | 1 + asterisk/conf/aeap.conf | 1 + asterisk/conf/ari.conf | 2 + asterisk/conf/asterisk.conf | 19 +++++++ asterisk/conf/cdr.conf | 5 ++ asterisk/conf/cdr_manager.conf | 6 ++ asterisk/conf/cel.conf | 2 + asterisk/conf/confbridge.conf | 20 +++++++ asterisk/conf/extensions.conf | 11 ++++ asterisk/conf/features.conf | 11 ++++ asterisk/conf/http.conf | 5 ++ asterisk/conf/logger.conf | 6 ++ asterisk/conf/manager.conf.template | 14 +++++ asterisk/conf/modules.conf | 53 ++++++++++++++++++ asterisk/conf/musiconhold.conf | 5 ++ asterisk/conf/pjproject.conf | 1 + asterisk/conf/pjsip.conf | 2 + asterisk/conf/queues.conf | 7 +++ asterisk/conf/res_parking.conf | 14 +++++ asterisk/conf/rtp.conf | 4 ++ asterisk/conf/udptl.conf | 1 + asterisk/conf/voicemail.conf | 1 + asterisk/conf/websocket_client.conf | 1 + asterisk/entrypoint.sh | 26 +++++++++ docs/spec/01-infrastructure.md | 86 +++++++++++++++++++++++------ docs/spec/09-roadmap.md | 2 +- 27 files changed, 338 insertions(+), 18 deletions(-) create mode 100644 asterisk/Dockerfile create mode 100644 asterisk/conf/acl.conf create mode 100644 asterisk/conf/aeap.conf create mode 100644 asterisk/conf/ari.conf create mode 100644 asterisk/conf/asterisk.conf create mode 100644 asterisk/conf/cdr.conf create mode 100644 asterisk/conf/cdr_manager.conf create mode 100644 asterisk/conf/cel.conf create mode 100644 asterisk/conf/confbridge.conf create mode 100644 asterisk/conf/extensions.conf create mode 100644 asterisk/conf/features.conf create mode 100644 asterisk/conf/http.conf create mode 100644 asterisk/conf/logger.conf create mode 100644 asterisk/conf/manager.conf.template create mode 100644 asterisk/conf/modules.conf create mode 100644 asterisk/conf/musiconhold.conf create mode 100644 asterisk/conf/pjproject.conf create mode 100644 asterisk/conf/pjsip.conf create mode 100644 asterisk/conf/queues.conf create mode 100644 asterisk/conf/res_parking.conf create mode 100644 asterisk/conf/rtp.conf create mode 100644 asterisk/conf/udptl.conf create mode 100644 asterisk/conf/voicemail.conf create mode 100644 asterisk/conf/websocket_client.conf create mode 100755 asterisk/entrypoint.sh diff --git a/asterisk/Dockerfile b/asterisk/Dockerfile new file mode 100644 index 0000000..e7dda48 --- /dev/null +++ b/asterisk/Dockerfile @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: AGPL-3.0-or-later +FROM debian:trixie-slim AS build +ARG ASTERISK_VERSION=24.0.0-rc2 +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential ca-certificates curl wget pkg-config autoconf automake libtool \ + libedit-dev libjansson-dev libxml2-dev uuid-dev libsqlite3-dev libssl-dev \ + libsrtp2-dev libcurl4-openssl-dev libspeexdsp-dev libogg-dev libvorbis-dev \ + libopus-dev subversion bzip2 patch python3 xmlstarlet +WORKDIR /usr/src +RUN curl -fsSLO https://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-${ASTERISK_VERSION}.tar.gz \ + && curl -fsSLO https://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-${ASTERISK_VERSION}.sha256 \ + && sha256sum -c asterisk-${ASTERISK_VERSION}.sha256 \ + && tar xzf asterisk-${ASTERISK_VERSION}.tar.gz +WORKDIR /usr/src/asterisk-${ASTERISK_VERSION} +# The mp3 decoder source (LGPL) must be fetched before configure so menuselect can enable format_mp3. +RUN contrib/scripts/get_mp3_source.sh || echo "mp3 source unavailable, format_mp3 skipped" +RUN ./configure --with-pjproject-bundled --with-jansson-bundled \ + && make menuselect.makeopts \ + && menuselect/menuselect \ + --disable BUILD_NATIVE \ + --enable format_mp3 \ + --enable CORE-SOUNDS-EN-WAV --enable CORE-SOUNDS-EN-G722 \ + --enable EXTRA-SOUNDS-EN-WAV --enable EXTRA-SOUNDS-EN-G722 \ + --enable MOH-OPSOUND-WAV \ + menuselect.makeopts \ + && make -j"$(nproc)" && make install DESTDIR=/out \ + && mkdir -p /out/usr/share/selfphoneng \ + && mv /out/var/lib/asterisk/moh /out/usr/share/selfphoneng/moh-opsound +# Debian's /var/run is a symlink to /run; a real directory here breaks the COPY below. +RUN rm -rf /out/var/run \ + && mkdir -p /out/etc/asterisk \ + && cp configs/samples/indications.conf.sample /out/etc/asterisk/indications.conf + +FROM debian:trixie-slim +ARG ASTERISK_UID=1000 +ARG ASTERISK_GID=1000 +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y --no-install-recommends \ + libedit2 libjansson4 libxml2 libuuid1 libsqlite3-0 libssl3t64 libsrtp2-1 \ + libcurl4t64 libspeexdsp1 libogg0 libvorbis0a libvorbisenc2 libvorbisfile3 libopus0 \ + gettext-base ca-certificates tzdata \ + && rm -rf /var/lib/apt/lists/* \ + && groupadd -g ${ASTERISK_GID} asterisk && useradd -u ${ASTERISK_UID} -g asterisk -d /var/lib/asterisk -s /usr/sbin/nologin asterisk +COPY --from=build /out/ / +COPY conf/ /etc/asterisk/ +COPY entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh && mkdir -p /etc/asterisk/selfphoneng /var/lib/asterisk/db /var/lib/asterisk/moh /var/run/asterisk \ + && chown -R asterisk:asterisk /etc/asterisk /var/lib/asterisk /var/spool/asterisk /var/log/asterisk /var/run/asterisk +ENTRYPOINT ["/entrypoint.sh"] diff --git a/asterisk/conf/acl.conf b/asterisk/conf/acl.conf new file mode 100644 index 0000000..23caf70 --- /dev/null +++ b/asterisk/conf/acl.conf @@ -0,0 +1 @@ +; named ACLs are generated into pjsip (sp-phone-acl), none here diff --git a/asterisk/conf/aeap.conf b/asterisk/conf/aeap.conf new file mode 100644 index 0000000..8931bba --- /dev/null +++ b/asterisk/conf/aeap.conf @@ -0,0 +1 @@ +; no AEAP speech clients diff --git a/asterisk/conf/ari.conf b/asterisk/conf/ari.conf new file mode 100644 index 0000000..4c4b912 --- /dev/null +++ b/asterisk/conf/ari.conf @@ -0,0 +1,2 @@ +[general] +enabled = no diff --git a/asterisk/conf/asterisk.conf b/asterisk/conf/asterisk.conf new file mode 100644 index 0000000..39519fd --- /dev/null +++ b/asterisk/conf/asterisk.conf @@ -0,0 +1,19 @@ +[directories](!) +astetcdir => /etc/asterisk +astmoddir => /usr/lib/asterisk/modules +astvarlibdir => /var/lib/asterisk +astdbdir => /var/lib/asterisk/db +astkeydir => /var/lib/asterisk +astdatadir => /var/lib/asterisk +astagidir => /var/lib/asterisk/agi-bin +astspooldir => /var/spool/asterisk +astrundir => /var/run/asterisk +astlogdir => /var/log/asterisk +astsbindir => /usr/sbin + +[options] +verbose = 3 +documentation_language = en_US +runuser = asterisk +rungroup = asterisk +defaultlanguage = en diff --git a/asterisk/conf/cdr.conf b/asterisk/conf/cdr.conf new file mode 100644 index 0000000..bff347d --- /dev/null +++ b/asterisk/conf/cdr.conf @@ -0,0 +1,5 @@ +[general] +enable = yes +unanswered = yes +congestion = yes +endbeforehexten = yes diff --git a/asterisk/conf/cdr_manager.conf b/asterisk/conf/cdr_manager.conf new file mode 100644 index 0000000..6b08b19 --- /dev/null +++ b/asterisk/conf/cdr_manager.conf @@ -0,0 +1,6 @@ +[general] +enabled = yes +[mappings] +SP_DID => sp_did +SP_DIRECTION => sp_direction +SP_REC => sp_recording diff --git a/asterisk/conf/cel.conf b/asterisk/conf/cel.conf new file mode 100644 index 0000000..31955ac --- /dev/null +++ b/asterisk/conf/cel.conf @@ -0,0 +1,2 @@ +[general] +enable = no diff --git a/asterisk/conf/confbridge.conf b/asterisk/conf/confbridge.conf new file mode 100644 index 0000000..6c6902b --- /dev/null +++ b/asterisk/conf/confbridge.conf @@ -0,0 +1,20 @@ +[general] +[default_bridge] +type = bridge +max_members = 20 +mixing_interval = 20 +internal_sample_rate = auto +record_conference = no + +[default_user] +type = user +music_on_hold_when_empty = yes +announce_user_count = yes +announce_join_leave = no +dsp_drop_silence = yes + +[default_menu] +type = menu +* = playback_and_continue(conf-usermenu) +1 = toggle_mute +#include selfphoneng/confbridge_selfphoneng.conf diff --git a/asterisk/conf/extensions.conf b/asterisk/conf/extensions.conf new file mode 100644 index 0000000..2c373ba --- /dev/null +++ b/asterisk/conf/extensions.conf @@ -0,0 +1,11 @@ +[general] +static = yes +writeprotect = yes +clearglobalvars = yes + +[globals] +#include selfphoneng/extensions_globals_selfphoneng.conf + +; Static helper contexts (sp-sub-*) are generated too (03 ยง5) so that all +; dialplan lives in one place in code. +#include selfphoneng/extensions_selfphoneng.conf diff --git a/asterisk/conf/features.conf b/asterisk/conf/features.conf new file mode 100644 index 0000000..e3efe44 --- /dev/null +++ b/asterisk/conf/features.conf @@ -0,0 +1,11 @@ +[general] +transferdigittimeout = 3 +xfersound = beep +xferfailsound = beeperr +pickupexten = *8 +featuredigittimeout = 1000 + +[featuremap] +blindxfer = ## +atxfer = *2 +automixmon = *1 ; on-demand recording toggle (needs Dial option X) diff --git a/asterisk/conf/http.conf b/asterisk/conf/http.conf new file mode 100644 index 0000000..c65d7c5 --- /dev/null +++ b/asterisk/conf/http.conf @@ -0,0 +1,5 @@ +[general] +enabled = yes +bindaddr = 127.0.0.1 ; only the reverse proxy talks to it +bindport = 8088 +enablestatic = no diff --git a/asterisk/conf/logger.conf b/asterisk/conf/logger.conf new file mode 100644 index 0000000..2427dee --- /dev/null +++ b/asterisk/conf/logger.conf @@ -0,0 +1,6 @@ +[general] +dateformat = %F %T.%3q +[logfiles] +console => notice,warning,error,verbose +messages.log => notice,warning,error +security.log => security ; for fail2ban/CrowdSec diff --git a/asterisk/conf/manager.conf.template b/asterisk/conf/manager.conf.template new file mode 100644 index 0000000..a356610 --- /dev/null +++ b/asterisk/conf/manager.conf.template @@ -0,0 +1,14 @@ +[general] +enabled = yes +port = 5038 +bindaddr = 127.0.0.1 +displayconnects = no +timestampevents = yes + +[selfphoneng] +secret = ${AMI_SECRET} +deny = 0.0.0.0/0.0.0.0 +permit = 127.0.0.1/255.255.255.255 +read = all +write = all +writetimeout = 5000 diff --git a/asterisk/conf/modules.conf b/asterisk/conf/modules.conf new file mode 100644 index 0000000..20a4f50 --- /dev/null +++ b/asterisk/conf/modules.conf @@ -0,0 +1,53 @@ +[modules] +autoload = yes +; channel drivers we do not use +noload = chan_iax2.so +noload = chan_dahdi.so +noload = chan_mgcp.so +noload = chan_skinny.so +noload = chan_unistim.so +noload = chan_ooh323.so +noload = chan_motif.so +noload = res_xmpp.so +noload = res_pjsip_phoneprov.so ; we do our own provisioning +noload = cdr_csv.so +noload = cdr_custom.so +noload = cdr_sqlite3_custom.so +noload = cel_sqlite3_custom.so +noload = cel_custom.so +noload = res_hep.so +noload = res_hep_pjsip.so +noload = res_hep_rtcp.so +noload = pbx_dundi.so +noload = pbx_lua.so +noload = pbx_ael.so +noload = res_config_ldap.so +noload = res_snmp.so +; unused features that only log errors about missing config files +noload = res_config_sqlite3.so +noload = res_statsd.so +noload = app_statsd.so +noload = res_pjsip_config_wizard.so +noload = res_pjsip_notify.so +noload = res_phoneprov.so +noload = res_pjsip_phoneprov_provider.so +noload = app_agent_pool.so +noload = res_calendar.so +noload = res_calendar_caldav.so +noload = res_calendar_ews.so +noload = res_calendar_exchange.so +noload = res_calendar_icalendar.so +noload = res_http_media_cache.so +noload = app_amd.so +noload = res_clialiases.so +noload = res_prometheus.so +noload = app_alarmreceiver.so +noload = app_festival.so +noload = app_followme.so +noload = app_minivm.so +noload = cel_manager.so +noload = res_stun_monitor.so +noload = chan_websocket.so +noload = res_adsi.so +noload = app_getcpeid.so +noload = app_adsiprog.so diff --git a/asterisk/conf/musiconhold.conf b/asterisk/conf/musiconhold.conf new file mode 100644 index 0000000..3d6c504 --- /dev/null +++ b/asterisk/conf/musiconhold.conf @@ -0,0 +1,5 @@ +[default] +mode = files +directory = /var/lib/asterisk/moh/default +sort = random +#include selfphoneng/musiconhold_selfphoneng.conf diff --git a/asterisk/conf/pjproject.conf b/asterisk/conf/pjproject.conf new file mode 100644 index 0000000..d9488b6 --- /dev/null +++ b/asterisk/conf/pjproject.conf @@ -0,0 +1 @@ +; defaults diff --git a/asterisk/conf/pjsip.conf b/asterisk/conf/pjsip.conf new file mode 100644 index 0000000..646d568 --- /dev/null +++ b/asterisk/conf/pjsip.conf @@ -0,0 +1,2 @@ +; Everything is generated. Do not add sections here. +#include selfphoneng/pjsip_selfphoneng.conf diff --git a/asterisk/conf/queues.conf b/asterisk/conf/queues.conf new file mode 100644 index 0000000..0b9e088 --- /dev/null +++ b/asterisk/conf/queues.conf @@ -0,0 +1,7 @@ +[general] +persistentmembers = no ; members come from config; pause state from AstDB/API +autofill = yes +monitor-type = MixMonitor +shared_lastcall = yes +log_membername_as_agent = yes +#include selfphoneng/queues_selfphoneng.conf diff --git a/asterisk/conf/res_parking.conf b/asterisk/conf/res_parking.conf new file mode 100644 index 0000000..4673ce2 --- /dev/null +++ b/asterisk/conf/res_parking.conf @@ -0,0 +1,14 @@ +[general] +parkeddynamic = no + +[default] +parkext = 700 +parkpos = 701-720 +context = sp-parkedcalls +parkingtime = 120 +comebacktoorigin = yes +comebackdialtime = 30 +parkedmusicclass = default +findslot = next +parkext_exclusive = no +parkinghints = yes diff --git a/asterisk/conf/rtp.conf b/asterisk/conf/rtp.conf new file mode 100644 index 0000000..c706694 --- /dev/null +++ b/asterisk/conf/rtp.conf @@ -0,0 +1,4 @@ +[general] +rtpstart = 10000 +rtpend = 20000 +#include selfphoneng/rtp_selfphoneng.conf diff --git a/asterisk/conf/udptl.conf b/asterisk/conf/udptl.conf new file mode 100644 index 0000000..f26de27 --- /dev/null +++ b/asterisk/conf/udptl.conf @@ -0,0 +1 @@ +[general] diff --git a/asterisk/conf/voicemail.conf b/asterisk/conf/voicemail.conf new file mode 100644 index 0000000..038c236 --- /dev/null +++ b/asterisk/conf/voicemail.conf @@ -0,0 +1 @@ +#include selfphoneng/voicemail_selfphoneng.conf diff --git a/asterisk/conf/websocket_client.conf b/asterisk/conf/websocket_client.conf new file mode 100644 index 0000000..4951282 --- /dev/null +++ b/asterisk/conf/websocket_client.conf @@ -0,0 +1 @@ +; no outbound websocket clients diff --git a/asterisk/entrypoint.sh b/asterisk/entrypoint.sh new file mode 100755 index 0000000..b457298 --- /dev/null +++ b/asterisk/entrypoint.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# SPDX-License-Identifier: AGPL-3.0-or-later +set -eu +# 1. Render templates that need secrets from env. +envsubst '${AMI_SECRET}' < /etc/asterisk/manager.conf.template > /etc/asterisk/manager.conf +chown asterisk:asterisk /etc/asterisk/manager.conf +chmod 600 /etc/asterisk/manager.conf +# 2. Make sure every generated include file exists so Asterisk can boot +# before the api has generated anything. +for f in pjsip_selfphoneng.conf extensions_selfphoneng.conf extensions_globals_selfphoneng.conf voicemail_selfphoneng.conf \ + queues_selfphoneng.conf musiconhold_selfphoneng.conf rtp_selfphoneng.conf \ + confbridge_selfphoneng.conf; do + [ -f "/etc/asterisk/selfphoneng/$f" ] || : > "/etc/asterisk/selfphoneng/$f" +done +# 3. First start: seed the default music-on-hold class with the stock opsound files (CC-BY-SA). +if [ -z "$(ls -A /var/lib/asterisk/moh/default 2>/dev/null)" ]; then + mkdir -p /var/lib/asterisk/moh/default + cp /usr/share/selfphoneng/moh-opsound/*.wav /var/lib/asterisk/moh/default/ +fi +# Bind-mounted volumes arrive owned by the host; Asterisk runs as the asterisk user. +for d in /etc/asterisk/selfphoneng /var/lib/asterisk/db /var/lib/asterisk/moh /var/log/asterisk \ + /var/spool/asterisk/voicemail /var/spool/asterisk/monitor /var/lib/asterisk/sounds/custom; do + mkdir -p "$d" && chown -R asterisk:asterisk "$d" +done +# 4. Run in foreground as the asterisk user. +exec /usr/sbin/asterisk -f -U asterisk -G asterisk -vvv diff --git a/docs/spec/01-infrastructure.md b/docs/spec/01-infrastructure.md index c764c00..ff2fdeb 100644 --- a/docs/spec/01-infrastructure.md +++ b/docs/spec/01-infrastructure.md @@ -129,8 +129,9 @@ missing or invalid, it logs a clear message and exits with code 1. ### 1.3 `scripts/install.sh` 1. Check `docker` and `docker compose` exist. Otherwise print how to install them and exit. -2. If `.env` is missing, copy `.env.example` and fill `POSTGRES_PASSWORD`, - `AMI_SECRET`, `APP_SECRET` with `openssl rand -base64 32`. Prompt for +2. If `.env` is missing, copy `.env.example` and fill `POSTGRES_PASSWORD` and + `AMI_SECRET` with `openssl rand -hex 32` (hex, because the Postgres password is embedded in + `DATABASE_URL` and base64 can contain `/`), and `APP_SECRET` with `openssl rand -base64 32`. Prompt for `PUBLIC_HOSTNAME` and the admin email and password. 3. `mkdir -p` every `./data/*` folder and `chown` it to `APP_UID:APP_GID`. 4. Ask "Use bundled Caddy for HTTPS? [y/N]". If yes, run `docker compose --profile caddy up -d --build`. Otherwise run `docker compose up -d --build` and print the path of `deploy/nginx/selfphoneng.conf.example`. @@ -138,9 +139,8 @@ missing or invalid, it logs a clear message and exits with code 1. ## 2. Asterisk image (`asterisk/Dockerfile`) -Build Asterisk **24 LTS from source**. Pin an exact version: replace `24.X.Y` -with the newest 24.x release on the day you write it, and record it here in -the same commit. +Build Asterisk **24 LTS from source**. Pin an exact version: the newest 24.x release on the day you write it, recorded here in +the same commit. **Pinned: `24.0.0-rc2` (2026-10-17).** The file in the repo is the source of truth; this copy is kept in sync. > **Asterisk 24 status (checked 2026-10-17):** Asterisk 24 is the LTS line, but > only release candidates are published so far (24.0.0-rc2). Until 24.0.0 is final, @@ -153,7 +153,7 @@ the same commit. ```dockerfile # SPDX-License-Identifier: AGPL-3.0-or-later FROM debian:trixie-slim AS build -ARG ASTERISK_VERSION=24.X.Y +ARG ASTERISK_VERSION=24.0.0-rc2 ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential ca-certificates curl wget pkg-config autoconf automake libtool \ @@ -166,6 +166,8 @@ RUN curl -fsSLO https://downloads.asterisk.org/pub/telephony/asterisk/releases/a && sha256sum -c asterisk-${ASTERISK_VERSION}.sha256 \ && tar xzf asterisk-${ASTERISK_VERSION}.tar.gz WORKDIR /usr/src/asterisk-${ASTERISK_VERSION} +# The mp3 decoder source (LGPL) must be fetched before configure so menuselect can enable format_mp3. +RUN contrib/scripts/get_mp3_source.sh || echo "mp3 source unavailable, format_mp3 skipped" RUN ./configure --with-pjproject-bundled --with-jansson-bundled \ && make menuselect.makeopts \ && menuselect/menuselect \ @@ -174,24 +176,29 @@ RUN ./configure --with-pjproject-bundled --with-jansson-bundled \ --enable CORE-SOUNDS-EN-WAV --enable CORE-SOUNDS-EN-G722 \ --enable EXTRA-SOUNDS-EN-WAV --enable EXTRA-SOUNDS-EN-G722 \ --enable MOH-OPSOUND-WAV \ - --disable chan_mgcp --disable chan_skinny --disable chan_unistim \ menuselect.makeopts \ - && contrib/scripts/get_mp3_source.sh || true \ - && make -j"$(nproc)" && make install DESTDIR=/out + && make -j"$(nproc)" && make install DESTDIR=/out \ + && mkdir -p /out/usr/share/selfphoneng \ + && mv /out/var/lib/asterisk/moh /out/usr/share/selfphoneng/moh-opsound +# Debian's /var/run is a symlink to /run; a real directory here breaks the COPY below. +RUN rm -rf /out/var/run \ + && mkdir -p /out/etc/asterisk \ + && cp configs/samples/indications.conf.sample /out/etc/asterisk/indications.conf FROM debian:trixie-slim ARG ASTERISK_UID=1000 ARG ASTERISK_GID=1000 ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ - libedit2 libjansson4 libxml2 libuuid1 libsqlite3-0 libssl3 libsrtp2-1 \ - libcurl4 libspeexdsp1 libogg0 libvorbis0a libopus0 gettext-base ca-certificates tzdata \ + libedit2 libjansson4 libxml2 libuuid1 libsqlite3-0 libssl3t64 libsrtp2-1 \ + libcurl4t64 libspeexdsp1 libogg0 libvorbis0a libvorbisenc2 libvorbisfile3 libopus0 \ + gettext-base ca-certificates tzdata \ && rm -rf /var/lib/apt/lists/* \ && groupadd -g ${ASTERISK_GID} asterisk && useradd -u ${ASTERISK_UID} -g asterisk -d /var/lib/asterisk -s /usr/sbin/nologin asterisk COPY --from=build /out/ / COPY conf/ /etc/asterisk/ COPY entrypoint.sh /entrypoint.sh -RUN chmod +x /entrypoint.sh && mkdir -p /etc/asterisk/selfphoneng /var/lib/asterisk/db /var/run/asterisk \ +RUN chmod +x /entrypoint.sh && mkdir -p /etc/asterisk/selfphoneng /var/lib/asterisk/db /var/lib/asterisk/moh /var/run/asterisk \ && chown -R asterisk:asterisk /etc/asterisk /var/lib/asterisk /var/spool/asterisk /var/log/asterisk /var/run/asterisk ENTRYPOINT ["/entrypoint.sh"] ``` @@ -199,8 +206,8 @@ ENTRYPOINT ["/entrypoint.sh"] Notes for the implementer: - Debian package names change between releases. If an `apt-get install` fails on `trixie`, find the right name with `apt-cache search`. Do not switch base image. -- `format_mp3` downloads mp3 decoder source (LGPL). That is allowed. If it - fails, delete that line. Uploaded MP3s are converted by ffmpeg in the api anyway. +- `format_mp3` downloads mp3 decoder source (LGPL) with `get_mp3_source.sh`, which must run before + `configure`. That is allowed. If it fails, the build continues without it. Uploaded MP3s are converted by ffmpeg in the api anyway. - **Do not** enable `codec_opus` or `codec_g729` from menuselect. Those are closed-source binary downloads. Browsers and phones get G.722 / ยต-law instead. - The `.sha256` file name pattern on downloads.asterisk.org may differ. Check @@ -210,9 +217,11 @@ Notes for the implementer: ```bash #!/bin/sh +# SPDX-License-Identifier: AGPL-3.0-or-later set -eu # 1. Render templates that need secrets from env. envsubst '${AMI_SECRET}' < /etc/asterisk/manager.conf.template > /etc/asterisk/manager.conf +chown asterisk:asterisk /etc/asterisk/manager.conf chmod 600 /etc/asterisk/manager.conf # 2. Make sure every generated include file exists so Asterisk can boot # before the api has generated anything. @@ -221,8 +230,17 @@ for f in pjsip_selfphoneng.conf extensions_selfphoneng.conf extensions_globals_s confbridge_selfphoneng.conf; do [ -f "/etc/asterisk/selfphoneng/$f" ] || : > "/etc/asterisk/selfphoneng/$f" done -chown -R asterisk:asterisk /etc/asterisk/selfphoneng /var/lib/asterisk/db || true -# 3. Run in foreground as the asterisk user. +# 3. First start: seed the default music-on-hold class with the stock opsound files (CC-BY-SA). +if [ -z "$(ls -A /var/lib/asterisk/moh/default 2>/dev/null)" ]; then + mkdir -p /var/lib/asterisk/moh/default + cp /usr/share/selfphoneng/moh-opsound/*.wav /var/lib/asterisk/moh/default/ +fi +# Bind-mounted volumes arrive owned by the host; Asterisk runs as the asterisk user. +for d in /etc/asterisk/selfphoneng /var/lib/asterisk/db /var/lib/asterisk/moh /var/log/asterisk \ + /var/spool/asterisk/voicemail /var/spool/asterisk/monitor /var/lib/asterisk/sounds/custom; do + mkdir -p "$d" && chown -R asterisk:asterisk "$d" +done +# 4. Run in foreground as the asterisk user. exec /usr/sbin/asterisk -f -U asterisk -G asterisk -vvv ``` @@ -282,8 +300,40 @@ noload = pbx_lua.so noload = pbx_ael.so noload = res_config_ldap.so noload = res_snmp.so +; unused features that only log errors about missing config files +noload = res_config_sqlite3.so +noload = res_statsd.so +noload = app_statsd.so +noload = res_pjsip_config_wizard.so +noload = res_pjsip_notify.so +noload = res_phoneprov.so +noload = res_pjsip_phoneprov_provider.so +noload = app_agent_pool.so +noload = res_calendar.so +noload = res_calendar_caldav.so +noload = res_calendar_ews.so +noload = res_calendar_exchange.so +noload = res_calendar_icalendar.so +noload = res_http_media_cache.so +noload = app_amd.so +noload = res_clialiases.so +noload = res_prometheus.so +noload = app_alarmreceiver.so +noload = app_festival.so +noload = app_followme.so +noload = app_minivm.so +noload = cel_manager.so +noload = res_stun_monitor.so +noload = chan_websocket.so +noload = res_adsi.so +noload = app_getcpeid.so +noload = app_adsiprog.so ``` +Besides the files below, `asterisk/conf/` holds near-empty `cel.conf` (CEL off), `acl.conf`, `udptl.conf`, +`pjproject.conf`, `ari.conf` (ARI off), `websocket_client.conf` and `aeap.conf`. Without them core modules log +`ERROR` about missing files. The image also installs Asterisk's stock `indications.conf` (needed for `tone_zone = us`). + ### 3.3 `logger.conf` ```ini [general] @@ -378,7 +428,9 @@ directory = /var/lib/asterisk/moh/default sort = random #include selfphoneng/musiconhold_selfphoneng.conf ``` -`install.sh` copies the stock opsound MOH files (CC-BY-SA, open) into `./data/moh/default/` on first install. +The Asterisk image keeps the stock opsound MOH files (CC-BY-SA, open) in `/usr/share/selfphoneng/moh-opsound/`, +and `entrypoint.sh` copies them into `/var/lib/asterisk/moh/default/` (`./data/moh/default/`) when that folder is empty. +(Earlier drafts had `install.sh` do this; the entrypoint also covers installs that skip the script.) ### 3.12 `features.conf` ```ini diff --git a/docs/spec/09-roadmap.md b/docs/spec/09-roadmap.md index aed5742..52096ba 100644 --- a/docs/spec/09-roadmap.md +++ b/docs/spec/09-roadmap.md @@ -26,7 +26,7 @@ Legend: ๐Ÿ“– read ยท ๐Ÿ”จ build ยท โœ… done when โœ… `pnpm --filter @selfphoneng/api dev` serves `/healthz`. A missing `APP_SECRET` exits 1 with a clear message. **M0-T4 web hello** -๐Ÿ”จ Vite + React + Tailwind + react-router. One page "SelfPhoneNG" with a dark-mode toggle. In dev, Vite proxies `/api` and `/ws` to the api. +๐Ÿ”จ Vite + React + Tailwind + react-router. One page "SelfPhoneNG" with a dark-mode toggle. In dev, Vite proxies `/api` to the api and `/ws` to Asterisk (127.0.0.1:8088), the same split as the reverse proxy. โœ… `pnpm --filter @selfphoneng/web build` outputs `dist/`. The page renders at 360 px and desktop widths. **M0-T5 Asterisk image**