diff --git a/README.md b/README.md index 8d48ffa83..4a2ccf9ff 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Asterisk Docker Images -Production-ready Docker images for Asterisk PBX with advanced DRY template system, supporting 24 versions from 1.2.40 to 23.4.1 plus git development builds. +Production-ready Docker images for Asterisk PBX with advanced DRY template system, supporting 27 versions from 1.2.40 to 23.5.0 plus git development builds. ## Quick Start @@ -53,17 +53,21 @@ All supported Asterisk versions with automatic variant detection. Generated buil | **git** | `testing,dev` | Trixie | amd64, arm64 | | **git** | experimental-git | Forky | amd64, arm64 | | **git** | `testing,dev` | Edge | amd64, arm64 | -| **23.4.1** | 23 | Trixie | amd64, arm64 | +| **23.5.0** | 23 | Trixie | amd64, arm64 | +| **23.5.0** | experimental | Forky | amd64, arm64 | +| **23.4.1** | - | Trixie | amd64, arm64 | | **23.4.1** | experimental | Forky | amd64, arm64 | -| **23.4.1** | 23 | 3.24 | amd64, arm64, armv7, armhf | -| **23.4.1** | 23 | Edge | amd64, arm64 | -| **22.10.1** | `latest,stable,22` | Trixie | amd64, arm64 | -| **22.10.1** | `latest,stable,22` | 3.24 | amd64, arm64, armv7, armhf | -| **22.10.1** | `latest,stable,22` | Edge | amd64, arm64 | +| **23.4.1** | - | 3.24 | amd64, arm64, armv7, armhf | +| **23.4.1** | - | Edge | amd64, arm64 | +| **22.11.0** | `latest,stable,22` | Trixie | amd64, arm64 | +| **22.10.1** | - | Trixie | amd64, arm64 | +| **22.10.1** | - | 3.24 | amd64, arm64, armv7, armhf | +| **22.10.1** | - | Edge | amd64, arm64 | | **22.8-cert4** | 22-cert | Trixie | amd64, arm64 | | **21.12.3** | 21 | Trixie | amd64, arm64 | -| **20.20.1** | 20 | Trixie | amd64, arm64 | -| **20.20.1** | 20 | 3.24 | amd64, arm64 | +| **20.21.0** | 20 | Trixie | amd64, arm64 | +| **20.20.1** | - | Trixie | amd64, arm64 | +| **20.20.1** | - | 3.24 | amd64, arm64 | | **20.7-cert11** | 20-cert | Trixie | amd64, arm64 | | **19.8.1** | 19 | Bookworm | amd64 | | **18.26.4** | 18 | Trixie | amd64 | diff --git a/asterisk/20.21.0-trixie/Dockerfile b/asterisk/20.21.0-trixie/Dockerfile new file mode 100644 index 000000000..cd6f14ebf --- /dev/null +++ b/asterisk/20.21.0-trixie/Dockerfile @@ -0,0 +1,177 @@ +# Multi-stage optimized Asterisk Docker build +# Asterisk 20.21.0 on Debian trixie +# Generated from YAML configuration - DO NOT EDIT MANUALLY + +# ============================================================================== +# STAGE 1: Build Environment +# ============================================================================== +FROM debian:trixie AS asterisk-builder + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX Builder" +LABEL org.opencontainers.image.description="Build stage for Asterisk 20.21.0" +LABEL org.opencontainers.image.version="20.21.0" +LABEL org.opencontainers.image.source="https://github.com/andrius/asterisk" + +# Build arguments +ARG ASTERISK_VERSION=20.21.0 +ARG JOBS=8 +ARG DEBIAN_FRONTEND=noninteractive +ARG TARGETARCH + +# Environment variables +ENV ASTERISK_VERSION=${ASTERISK_VERSION} +ENV DEBIAN_FRONTEND=${DEBIAN_FRONTEND} +ENV TMPDIR="/tmp/asterisk_build" + +# Create build directories first +RUN mkdir -p \ + /usr/src/asterisk \ + ${TMPDIR} \ + && chmod 777 ${TMPDIR} + +# EOL distribution setup (if needed) +# Update package lists and install ca-certificates first, then build dependencies +RUN apt-get update \ + && apt-get install -y --no-install-recommends ca-certificates \ + && apt-get install -y --no-install-recommends \ + build-essential autoconf binutils-dev curl file libcurl4-openssl-dev \ + libedit-dev libgsm1-dev libicu-dev libjansson-dev libncurses-dev libogg-dev \ + libpopt-dev libpqxx-dev libresample1-dev libspandsp-dev libspeex-dev \ + libspeexdsp-dev libsqlite3-dev libssl-dev libtool libvorbis-dev libxml2-dev \ + libxslt1-dev make odbcinst patch pkg-config portaudio19-dev procps \ + python3-dev unixodbc unixodbc-dev uuid uuid-dev xmlstarlet libsrtp2-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && mkdir -p ${TMPDIR} && chmod 777 ${TMPDIR} + + +WORKDIR /usr/src/asterisk + +# Download and extract Asterisk source. +# When a sha256 checksum is present (plan 002) verify it before extracting; +# otherwise fall back to the historical unverified pipe (legacy tail / +# versions not yet backfilled). sha256sum ships in coreutils on every +# Debian base, including jessie/stretch - no new build dependency. +RUN curl -fsSL -o /tmp/asterisk-src.tar.gz https://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-20.21.0.tar.gz \ + && echo "13fd6e8f1fbb19a3174af82a388dd72c87eb2c92d32fca83c4d51bfab03f686a /tmp/asterisk-src.tar.gz" | sha256sum -c - \ + && tar --strip-components=1 -xzf /tmp/asterisk-src.tar.gz \ + && rm /tmp/asterisk-src.tar.gz + +# Configure Asterisk build (skip for very old versions that don't have configure script) +RUN ./configure + +# Generate menuselect configuration +RUN make menuselect/menuselect menuselect-tree menuselect.makeopts + + +# Copy and execute build script +COPY build.sh /usr/src/asterisk/build.sh +RUN chmod +x build.sh && ./build.sh + +# ============================================================================== +# STAGE 2: Runtime Environment +# ============================================================================== +FROM debian:trixie AS asterisk-runtime + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX Runtime" +LABEL org.opencontainers.image.description="Runtime environment for Asterisk 20.21.0" + +ARG DEBIAN_FRONTEND=noninteractive +ARG TARGETARCH +ENV DEBIAN_FRONTEND=${DEBIAN_FRONTEND} + +# Install only runtime dependencies +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + binutils ca-certificates curl gettext-base libedit2 libgsm1 libjansson4 \ + libogg0 libopus0 libpopt0 libresample1 libspandsp2 libspeex1 libspeexdsp1 \ + libsqlite3-0 libvorbis0a libxml2 libxslt1.1 odbcinst portaudio19-dev procps \ + python3 unixodbc uuid libcurl4t64 libssl3t64 libsrtp2-1 libncurses6 \ + libpqxx-7.10 libicu76 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Create asterisk user and required directories +RUN useradd --uid 1000 --system --user-group \ + --home-dir /home/asterisk --create-home \ + asterisk \ + && mkdir -p \ + /var/run/asterisk \ + /var/log/asterisk \ + /var/spool/asterisk/monitor \ + /var/spool/asterisk/outgoing \ + /var/spool/asterisk/tmp \ + /var/spool/asterisk/voicemail \ + /var/spool/asterisk/fax \ + /var/lib/asterisk/keys \ + /var/lib/asterisk/phoneprov \ + /var/lib/asterisk/sounds \ + /var/lib/asterisk/docs + +# ============================================================================== +# STAGE 3: Final Production Image +# ============================================================================== +FROM asterisk-runtime AS asterisk-production + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX" +LABEL org.opencontainers.image.description="Production Asterisk PBX 20.21.0" +LABEL org.opencontainers.image.version="20.21.0" +LABEL org.opencontainers.image.source="https://github.com/andrius/asterisk" +LABEL org.opencontainers.image.vendor="Andrius Kairiukstis " + +# Copy Asterisk binaries and configurations from builder +COPY --from=asterisk-builder /usr/sbin/asterisk /usr/sbin/asterisk +COPY --from=asterisk-builder /usr/lib/asterisk /usr/lib/asterisk +COPY --from=asterisk-builder /var/lib/asterisk /var/lib/asterisk +COPY --from=asterisk-builder /etc/asterisk /etc/asterisk + +# Copy Asterisk shared libraries +COPY --from=asterisk-builder /usr/lib/libasterisk*.so* /usr/lib/ + +# Copy healthcheck script +COPY healthcheck.sh /usr/local/bin/healthcheck.sh +RUN chmod +x /usr/local/bin/healthcheck.sh + +# Copy entrypoint script (PUID/PGID volume permission handling) +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +# Set proper ownership and permissions +RUN chown -R asterisk:asterisk \ + /etc/asterisk \ + /home/asterisk \ + /var/*/asterisk \ + /usr/lib*/asterisk 2>/dev/null || true \ + && chmod -R 750 /var/spool/asterisk + +# Runtime verification +RUN asterisk -V || (echo "Error: Unable to run asterisk -V" && exit 1) + +# Configure networking +# EXPOSE 5060/udp +# EXPOSE 5060/tcp +# EXPOSE 5061/tcp +# EXPOSE 10000-10099/udp + +# Define volumes for persistent data +VOLUME ["/var/lib/asterisk/sounds", "/var/lib/asterisk/keys", "/var/lib/asterisk/phoneprov", "/var/spool/asterisk", "/var/log/asterisk", "/etc/asterisk"] + +# Add health check +HEALTHCHECK --interval=30s \ + --timeout=10s \ + --start-period=30s \ + --retries=3 \ + CMD /usr/local/bin/healthcheck.sh + +# Entrypoint runs as root, adapts asterisk uid/gid to PUID/PGID, then execs CMD. +# Asterisk drops privileges itself via `-U asterisk -p` in the CMD below. +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] + +# Set working directory +WORKDIR /home/asterisk + +# Default command with production settings +CMD ["/usr/sbin/asterisk", "-vvvdddf", "-T", "-W", "-U", "asterisk", "-p"] diff --git a/asterisk/20.21.0-trixie/build.sh b/asterisk/20.21.0-trixie/build.sh new file mode 100755 index 000000000..725079ad4 --- /dev/null +++ b/asterisk/20.21.0-trixie/build.sh @@ -0,0 +1,145 @@ +#!/bin/bash +# Asterisk build script +# Generated from template for 20.21.0 +# Contains menuselect configuration and build commands + +set -euo pipefail + +# Color output for better readability +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +log() { + echo -e "${GREEN}[BUILD]${NC} $1" +} + +warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +log "Starting Asterisk 20.21.0 build process..." + +# Set build parallelization (use Docker ARG or default) +NPROC=$(nproc) +JOBS=${JOBS:-8} +log "Using $JOBS parallel jobs for compilation (detected $NPROC CPUs)" + +# Configure Asterisk +log "Configuring Asterisk with options..." +./configure --with-pjproject-bundled --with-ssl=ssl --with-crypto + +# Workaround: Asterisk 18.x ships makeopts with a literal '\n' in DOWNLOAD +# that dash echo interprets as a real newline, mangling +# get_sourceable_makeopts output and breaking make_xml_documentation. Flatten +# the line to a plain curl invocation. No-op on versions without the bug. +if [ -f makeopts ]; then + sed -i 's|^DOWNLOAD=.*|DOWNLOAD=/usr/bin/curl -L -O --progress-bar|' makeopts +fi + +# Build menuselect tool +log "Building menuselect tool..." +make menuselect + +# Configure Asterisk modules using menuselect +log "Configuring Asterisk modules..." + +# Disable BUILD_NATIVE optimization for container builds +menuselect/menuselect --disable BUILD_NATIVE menuselect.makeopts + +# Enable better backtraces for debugging +menuselect/menuselect --enable BETTER_BACKTRACES menuselect.makeopts + +# Disable sound packages to reduce image size +menuselect/menuselect --disable-category MENUSELECT_CORE_SOUNDS menuselect.makeopts +menuselect/menuselect --disable-category MENUSELECT_MOH menuselect.makeopts +menuselect/menuselect --disable-category MENUSELECT_EXTRA_SOUNDS menuselect.makeopts + +# Enable core applications +menuselect/menuselect --enable app_voicemail menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_voicemail menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_queue menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_queue menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_confbridge menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_confbridge menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_directory menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_directory menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_dial menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_dial menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_playback menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_playback menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_record menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_record menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_echo menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_echo menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_mixmonitor menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_mixmonitor menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + +# Enable CDR and CEL modules + +# Enable channel drivers +menuselect/menuselect --enable chan_pjsip menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_pjsip menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable chan_iax2 menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_iax2 menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable chan_local menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_local menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable chan_bridge_media menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_bridge_media menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + +# Enable resource modules +menuselect/menuselect --enable res_musiconhold menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_musiconhold menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip_session menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip_session menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip_outbound_registration menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip_outbound_registration menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip_registrar menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip_registrar menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_rtp_asterisk menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_rtp_asterisk menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_timing_timerfd menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_timing_timerfd menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_crypto menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_crypto menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + +# Disable unwanted modules +menuselect/menuselect --disable chan_dahdi menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable chan_dahdi menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --disable chan_misdn menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable chan_misdn menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --disable app_festival menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable app_festival menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + + +log "Module configuration completed" + + +# Pre-build third-party (pjproject) sequentially with verbose output. +# This surfaces real compiler errors that would otherwise be hidden by parallel make. +# Skipped on Asterisk < 13: the 'third-party' target was added with bundled +# pjproject support and does not exist in older trees. +log "Building third-party dependencies (pjproject) with verbose output..." +TMPDIR=${TMPDIR} make NOISY_BUILD=yes -j 1 third-party + +# Build Asterisk +log "Building Asterisk core (this may take several minutes)..." +TMPDIR=${TMPDIR} make -j $JOBS all +log "Installing Asterisk..." +TMPDIR=${TMPDIR} make install +log "Installing sample configurations..." +TMPDIR=${TMPDIR} make samples + +# Download and install Digium Opus codec binary (x86-64 only) +ARCH=$(dpkg --print-architecture 2>/dev/null || echo "unknown") +if [ "$ARCH" = "amd64" ]; then + OPUS_MAJOR="20" + OPUS_URL="https://downloads.digium.com/pub/telephony/codec_opus/asterisk-${OPUS_MAJOR}.0/x86-64/codec_opus-${OPUS_MAJOR}.0-current-x86_64.tar.gz" + log "Downloading Digium Opus codec (Asterisk ${OPUS_MAJOR}.0)..." + OPUS_TMP="/tmp/codec_opus" + mkdir -p "$OPUS_TMP" + if curl -fsSL "$OPUS_URL" | tar -xz -C "$OPUS_TMP"; then + find "$OPUS_TMP" -name "codec_opus*.so" -exec cp -v {} /usr/lib/asterisk/modules/ \; + find "$OPUS_TMP" -name "format_ogg_opus*.so" -exec cp -v {} /usr/lib/asterisk/modules/ \; + mkdir -p /var/lib/asterisk/documentation + find "$OPUS_TMP" -name "codec_opus_config-en_US.xml" -exec cp -v {} /var/lib/asterisk/documentation/ \; + rm -rf "$OPUS_TMP" + log "Opus codec installed successfully" + else + warn "Failed to download Opus codec from $OPUS_URL - Opus transcoding will not be available" + rm -rf "$OPUS_TMP" + fi +else + log "Skipping Digium Opus codec (x86-64 only, detected: $ARCH)" +fi + + +# Strip binaries to reduce size +log "Stripping binaries to reduce image size..." +find /usr/sbin /usr/lib/asterisk -type f -executable \ + -exec strip --strip-unneeded {} + 2>/dev/null || true + +log "Asterisk 20.21.0 build completed successfully!" \ No newline at end of file diff --git a/asterisk/20.21.0-trixie/entrypoint.sh b/asterisk/20.21.0-trixie/entrypoint.sh new file mode 100755 index 000000000..f7deb8c0e --- /dev/null +++ b/asterisk/20.21.0-trixie/entrypoint.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Asterisk container entrypoint +# Generated from template for 20.21.0 +# +# Adapts the in-container `asterisk` user (default uid:gid 1000:1000) to the +# uid/gid supplied via PUID / PGID env vars, then chowns runtime directories +# so bind-mounted volumes are writable. Asterisk drops privileges itself via +# its `-U asterisk -p` CMD flags, so no gosu/su-exec is needed. +# +# When the container is launched with `--user N:M` (compose `user:`), this +# script runs as that user instead of root: the adapt/chown branch is skipped +# and "$@" is exec'd as-is, matching pre-entrypoint behaviour. + +set -e + +PUID="${PUID:-1000}" +PGID="${PGID:-1000}" + +if [ "$(id -u)" = "0" ]; then + current_uid="$(id -u asterisk)" + current_gid="$(id -g asterisk)" + + if [ "$PGID" != "$current_gid" ]; then + groupmod -o -g "$PGID" asterisk + fi + if [ "$PUID" != "$current_uid" ]; then + usermod -o -u "$PUID" -g "$PGID" asterisk + fi + + for path in /etc/asterisk /home/asterisk /var/lib/asterisk \ + /var/log/asterisk /var/spool/asterisk /var/run/asterisk; do + [ -d "$path" ] || continue + if [ "$(stat -c '%u:%g' "$path" 2>/dev/null)" != "$PUID:$PGID" ]; then + chown -R "$PUID:$PGID" "$path" 2>/dev/null || true + fi + done +fi + +# Replace the baked-in -W (light-background adjust) with whatever the user +# supplies via ASTERISK_TERMINAL_OPTS. Use cases (issue #16): +# ASTERISK_TERMINAL_OPTS="" -> drop -W, let the terminal decide +# ASTERISK_TERMINAL_OPTS="-B" -> force black background (dark terminals) +# ASTERISK_TERMINAL_OPTS="-n" -> disable colors entirely (safest in logs) +# (unset) -> keep -W (existing behaviour) +if [ -n "${ASTERISK_TERMINAL_OPTS+x}" ]; then + new_args=() + for arg in "$@"; do + if [ "$arg" = "-W" ]; then + for opt in $ASTERISK_TERMINAL_OPTS; do + new_args+=("$opt") + done + else + new_args+=("$arg") + fi + done + set -- "${new_args[@]}" +fi + +exec "$@" diff --git a/asterisk/20.21.0-trixie/healthcheck.sh b/asterisk/20.21.0-trixie/healthcheck.sh new file mode 100755 index 000000000..938fc209f --- /dev/null +++ b/asterisk/20.21.0-trixie/healthcheck.sh @@ -0,0 +1,159 @@ +#!/bin/bash +# Asterisk health check script +# Generated from template for 20.21.0 + +set -euo pipefail + +# Configuration +ASTERISK_CLI="/usr/sbin/asterisk -rx" +TIMEOUT=10 +VERBOSE=false + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -v|--verbose) + VERBOSE=true + shift + ;; + -t|--timeout) + TIMEOUT="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" >&2 + exit 1 + ;; + esac +done + +# Logging functions +log() { + if [[ "$VERBOSE" == "true" ]]; then + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2 + fi +} + +error() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $*" >&2 +} + +# Health check functions +check_asterisk_running() { + log "Checking if Asterisk is running..." + if ! pgrep -x asterisk >/dev/null; then + error "Asterisk process not found" + return 1 + fi + log "✓ Asterisk process is running" + return 0 +} + +check_asterisk_responsive() { + log "Checking if Asterisk CLI is responsive..." + if ! timeout $TIMEOUT $ASTERISK_CLI "core show version" >/dev/null 2>&1; then + error "Asterisk CLI not responsive" + return 1 + fi + log "✓ Asterisk CLI is responsive" + return 0 +} + +check_pjsip_status() { + log "Checking PJSIP status..." + if ! timeout $TIMEOUT $ASTERISK_CLI "pjsip show version" >/dev/null 2>&1; then + error "PJSIP not available or not responding" + return 1 + fi + log "✓ PJSIP is available" + return 0 +} + +check_database_connectivity() { + log "Checking database connectivity..." + # Check if ODBC is configured and working + if ! timeout $TIMEOUT $ASTERISK_CLI "odbc show all" | grep -q "Connected" 2>/dev/null; then + log "⚠ No ODBC connections found (this may be normal)" + else + log "✓ Database connections available" + fi + return 0 +} + +check_essential_modules() { + log "Checking essential modules..." + local required_modules=( + "res_rtp_asterisk" + "res_timing_timerfd" + "res_crypto" + "res_pjsip" + ) + + for module in "${required_modules[@]}"; do + local module_output + module_output=$(timeout $TIMEOUT $ASTERISK_CLI "module show like $module" 2>&1) + if ! grep -q "$module" <<<"$module_output"; then + error "Required module $module not loaded" + return 1 + fi + done + log "✓ Essential modules are loaded" + return 0 +} + +check_filesystem_access() { + log "Checking filesystem access..." + local required_dirs=( + "/var/log/asterisk" + "/var/spool/asterisk" + "/var/lib/asterisk" + "/etc/asterisk" + ) + + for dir in "${required_dirs[@]}"; do + if [[ ! -d "$dir" ]]; then + error "Required directory $dir not found" + return 1 + fi + if [[ ! -r "$dir" ]]; then + error "Directory $dir not readable" + return 1 + fi + done + log "✓ Filesystem access is working" + return 0 +} + +# Main health check +main() { + log "Starting Asterisk health check..." + + local checks=( + "check_asterisk_running" + "check_asterisk_responsive" + "check_pjsip_status" + "check_database_connectivity" + "check_essential_modules" + "check_filesystem_access" + ) + + local failed=0 + for check in "${checks[@]}"; do + if ! $check; then + failed=$((failed + 1)) + fi + done + + if [[ $failed -eq 0 ]]; then + log "✓ All health checks passed" + exit 0 + else + error "Health check failed: $failed checks failed" + exit 1 + fi +} + +# Handle signals +trap 'error "Health check interrupted"; exit 1' INT TERM + +main "$@" \ No newline at end of file diff --git a/asterisk/22.11.0-trixie/Dockerfile b/asterisk/22.11.0-trixie/Dockerfile new file mode 100644 index 000000000..667379602 --- /dev/null +++ b/asterisk/22.11.0-trixie/Dockerfile @@ -0,0 +1,177 @@ +# Multi-stage optimized Asterisk Docker build +# Asterisk 22.11.0 on Debian trixie +# Generated from YAML configuration - DO NOT EDIT MANUALLY + +# ============================================================================== +# STAGE 1: Build Environment +# ============================================================================== +FROM debian:trixie AS asterisk-builder + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX Builder" +LABEL org.opencontainers.image.description="Build stage for Asterisk 22.11.0" +LABEL org.opencontainers.image.version="22.11.0" +LABEL org.opencontainers.image.source="https://github.com/andrius/asterisk" + +# Build arguments +ARG ASTERISK_VERSION=22.11.0 +ARG JOBS=8 +ARG DEBIAN_FRONTEND=noninteractive +ARG TARGETARCH + +# Environment variables +ENV ASTERISK_VERSION=${ASTERISK_VERSION} +ENV DEBIAN_FRONTEND=${DEBIAN_FRONTEND} +ENV TMPDIR="/tmp/asterisk_build" + +# Create build directories first +RUN mkdir -p \ + /usr/src/asterisk \ + ${TMPDIR} \ + && chmod 777 ${TMPDIR} + +# EOL distribution setup (if needed) +# Update package lists and install ca-certificates first, then build dependencies +RUN apt-get update \ + && apt-get install -y --no-install-recommends ca-certificates \ + && apt-get install -y --no-install-recommends \ + build-essential autoconf binutils-dev curl file libcurl4-openssl-dev \ + libedit-dev libgsm1-dev libicu-dev libjansson-dev libncurses-dev libogg-dev \ + libpopt-dev libpqxx-dev libresample1-dev libspandsp-dev libspeex-dev \ + libspeexdsp-dev libsqlite3-dev libssl-dev libtool libvorbis-dev libxml2-dev \ + libxslt1-dev make odbcinst patch pkg-config portaudio19-dev procps \ + python3-dev unixodbc unixodbc-dev uuid uuid-dev xmlstarlet libsrtp2-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && mkdir -p ${TMPDIR} && chmod 777 ${TMPDIR} + + +WORKDIR /usr/src/asterisk + +# Download and extract Asterisk source. +# When a sha256 checksum is present (plan 002) verify it before extracting; +# otherwise fall back to the historical unverified pipe (legacy tail / +# versions not yet backfilled). sha256sum ships in coreutils on every +# Debian base, including jessie/stretch - no new build dependency. +RUN curl -fsSL -o /tmp/asterisk-src.tar.gz https://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-22.11.0.tar.gz \ + && echo "3bd5ee040509a3d3cd9b1ba9520c18e6ec0a7e7981ca68c457dcd36ba3c54d94 /tmp/asterisk-src.tar.gz" | sha256sum -c - \ + && tar --strip-components=1 -xzf /tmp/asterisk-src.tar.gz \ + && rm /tmp/asterisk-src.tar.gz + +# Configure Asterisk build (skip for very old versions that don't have configure script) +RUN ./configure + +# Generate menuselect configuration +RUN make menuselect/menuselect menuselect-tree menuselect.makeopts + + +# Copy and execute build script +COPY build.sh /usr/src/asterisk/build.sh +RUN chmod +x build.sh && ./build.sh + +# ============================================================================== +# STAGE 2: Runtime Environment +# ============================================================================== +FROM debian:trixie AS asterisk-runtime + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX Runtime" +LABEL org.opencontainers.image.description="Runtime environment for Asterisk 22.11.0" + +ARG DEBIAN_FRONTEND=noninteractive +ARG TARGETARCH +ENV DEBIAN_FRONTEND=${DEBIAN_FRONTEND} + +# Install only runtime dependencies +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + binutils ca-certificates curl gettext-base libedit2 libgsm1 libjansson4 \ + libogg0 libopus0 libpopt0 libresample1 libspandsp2 libspeex1 libspeexdsp1 \ + libsqlite3-0 libvorbis0a libxml2 libxslt1.1 odbcinst portaudio19-dev procps \ + python3 unixodbc uuid libcurl4t64 libssl3t64 libsrtp2-1 libncurses6 \ + libpqxx-7.10 libicu76 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Create asterisk user and required directories +RUN useradd --uid 1000 --system --user-group \ + --home-dir /home/asterisk --create-home \ + asterisk \ + && mkdir -p \ + /var/run/asterisk \ + /var/log/asterisk \ + /var/spool/asterisk/monitor \ + /var/spool/asterisk/outgoing \ + /var/spool/asterisk/tmp \ + /var/spool/asterisk/voicemail \ + /var/spool/asterisk/fax \ + /var/lib/asterisk/keys \ + /var/lib/asterisk/phoneprov \ + /var/lib/asterisk/sounds \ + /var/lib/asterisk/docs + +# ============================================================================== +# STAGE 3: Final Production Image +# ============================================================================== +FROM asterisk-runtime AS asterisk-production + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX" +LABEL org.opencontainers.image.description="Production Asterisk PBX 22.11.0" +LABEL org.opencontainers.image.version="22.11.0" +LABEL org.opencontainers.image.source="https://github.com/andrius/asterisk" +LABEL org.opencontainers.image.vendor="Andrius Kairiukstis " + +# Copy Asterisk binaries and configurations from builder +COPY --from=asterisk-builder /usr/sbin/asterisk /usr/sbin/asterisk +COPY --from=asterisk-builder /usr/lib/asterisk /usr/lib/asterisk +COPY --from=asterisk-builder /var/lib/asterisk /var/lib/asterisk +COPY --from=asterisk-builder /etc/asterisk /etc/asterisk + +# Copy Asterisk shared libraries +COPY --from=asterisk-builder /usr/lib/libasterisk*.so* /usr/lib/ + +# Copy healthcheck script +COPY healthcheck.sh /usr/local/bin/healthcheck.sh +RUN chmod +x /usr/local/bin/healthcheck.sh + +# Copy entrypoint script (PUID/PGID volume permission handling) +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +# Set proper ownership and permissions +RUN chown -R asterisk:asterisk \ + /etc/asterisk \ + /home/asterisk \ + /var/*/asterisk \ + /usr/lib*/asterisk 2>/dev/null || true \ + && chmod -R 750 /var/spool/asterisk + +# Runtime verification +RUN asterisk -V || (echo "Error: Unable to run asterisk -V" && exit 1) + +# Configure networking +# EXPOSE 5060/udp +# EXPOSE 5060/tcp +# EXPOSE 5061/tcp +# EXPOSE 10000-10099/udp + +# Define volumes for persistent data +VOLUME ["/var/lib/asterisk/sounds", "/var/lib/asterisk/keys", "/var/lib/asterisk/phoneprov", "/var/spool/asterisk", "/var/log/asterisk", "/etc/asterisk"] + +# Add health check +HEALTHCHECK --interval=30s \ + --timeout=10s \ + --start-period=30s \ + --retries=3 \ + CMD /usr/local/bin/healthcheck.sh + +# Entrypoint runs as root, adapts asterisk uid/gid to PUID/PGID, then execs CMD. +# Asterisk drops privileges itself via `-U asterisk -p` in the CMD below. +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] + +# Set working directory +WORKDIR /home/asterisk + +# Default command with production settings +CMD ["/usr/sbin/asterisk", "-vvvdddf", "-T", "-W", "-U", "asterisk", "-p"] diff --git a/asterisk/22.11.0-trixie/build.sh b/asterisk/22.11.0-trixie/build.sh new file mode 100755 index 000000000..669e85587 --- /dev/null +++ b/asterisk/22.11.0-trixie/build.sh @@ -0,0 +1,146 @@ +#!/bin/bash +# Asterisk build script +# Generated from template for 22.11.0 +# Contains menuselect configuration and build commands + +set -euo pipefail + +# Color output for better readability +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +log() { + echo -e "${GREEN}[BUILD]${NC} $1" +} + +warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +log "Starting Asterisk 22.11.0 build process..." + +# Set build parallelization (use Docker ARG or default) +NPROC=$(nproc) +JOBS=${JOBS:-8} +log "Using $JOBS parallel jobs for compilation (detected $NPROC CPUs)" + +# Configure Asterisk +log "Configuring Asterisk with options..." +./configure --with-pjproject-bundled --with-ssl=ssl --with-crypto + +# Workaround: Asterisk 18.x ships makeopts with a literal '\n' in DOWNLOAD +# that dash echo interprets as a real newline, mangling +# get_sourceable_makeopts output and breaking make_xml_documentation. Flatten +# the line to a plain curl invocation. No-op on versions without the bug. +if [ -f makeopts ]; then + sed -i 's|^DOWNLOAD=.*|DOWNLOAD=/usr/bin/curl -L -O --progress-bar|' makeopts +fi + +# Build menuselect tool +log "Building menuselect tool..." +make menuselect + +# Configure Asterisk modules using menuselect +log "Configuring Asterisk modules..." + +# Disable BUILD_NATIVE optimization for container builds +menuselect/menuselect --disable BUILD_NATIVE menuselect.makeopts + +# Enable better backtraces for debugging +menuselect/menuselect --enable BETTER_BACKTRACES menuselect.makeopts + +# Disable sound packages to reduce image size +menuselect/menuselect --disable-category MENUSELECT_CORE_SOUNDS menuselect.makeopts +menuselect/menuselect --disable-category MENUSELECT_MOH menuselect.makeopts +menuselect/menuselect --disable-category MENUSELECT_EXTRA_SOUNDS menuselect.makeopts + +# Enable core applications +menuselect/menuselect --enable app_voicemail menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_voicemail menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_queue menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_queue menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_confbridge menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_confbridge menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_directory menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_directory menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_dial menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_dial menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_playback menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_playback menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_record menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_record menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_echo menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_echo menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_mixmonitor menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_mixmonitor menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + +# Enable CDR and CEL modules + +# Enable channel drivers +menuselect/menuselect --enable chan_pjsip menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_pjsip menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable chan_iax2 menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_iax2 menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable chan_local menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_local menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable chan_bridge_media menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_bridge_media menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + +# Enable resource modules +menuselect/menuselect --enable res_musiconhold menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_musiconhold menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip_session menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip_session menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip_outbound_registration menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip_outbound_registration menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip_registrar menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip_registrar menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_rtp_asterisk menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_rtp_asterisk menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_timing_timerfd menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_timing_timerfd menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_crypto menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_crypto menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + +# Disable unwanted modules +menuselect/menuselect --disable chan_dahdi menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable chan_dahdi menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --disable chan_misdn menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable chan_misdn menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --disable app_festival menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable app_festival menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --disable chan_sip menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable chan_sip menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + + +log "Module configuration completed" + + +# Pre-build third-party (pjproject) sequentially with verbose output. +# This surfaces real compiler errors that would otherwise be hidden by parallel make. +# Skipped on Asterisk < 13: the 'third-party' target was added with bundled +# pjproject support and does not exist in older trees. +log "Building third-party dependencies (pjproject) with verbose output..." +TMPDIR=${TMPDIR} make NOISY_BUILD=yes -j 1 third-party + +# Build Asterisk +log "Building Asterisk core (this may take several minutes)..." +TMPDIR=${TMPDIR} make -j $JOBS all +log "Installing Asterisk..." +TMPDIR=${TMPDIR} make install +log "Installing sample configurations..." +TMPDIR=${TMPDIR} make samples + +# Download and install Digium Opus codec binary (x86-64 only) +ARCH=$(dpkg --print-architecture 2>/dev/null || echo "unknown") +if [ "$ARCH" = "amd64" ]; then + OPUS_MAJOR="22" + OPUS_URL="https://downloads.digium.com/pub/telephony/codec_opus/asterisk-${OPUS_MAJOR}.0/x86-64/codec_opus-${OPUS_MAJOR}.0-current-x86_64.tar.gz" + log "Downloading Digium Opus codec (Asterisk ${OPUS_MAJOR}.0)..." + OPUS_TMP="/tmp/codec_opus" + mkdir -p "$OPUS_TMP" + if curl -fsSL "$OPUS_URL" | tar -xz -C "$OPUS_TMP"; then + find "$OPUS_TMP" -name "codec_opus*.so" -exec cp -v {} /usr/lib/asterisk/modules/ \; + find "$OPUS_TMP" -name "format_ogg_opus*.so" -exec cp -v {} /usr/lib/asterisk/modules/ \; + mkdir -p /var/lib/asterisk/documentation + find "$OPUS_TMP" -name "codec_opus_config-en_US.xml" -exec cp -v {} /var/lib/asterisk/documentation/ \; + rm -rf "$OPUS_TMP" + log "Opus codec installed successfully" + else + warn "Failed to download Opus codec from $OPUS_URL - Opus transcoding will not be available" + rm -rf "$OPUS_TMP" + fi +else + log "Skipping Digium Opus codec (x86-64 only, detected: $ARCH)" +fi + + +# Strip binaries to reduce size +log "Stripping binaries to reduce image size..." +find /usr/sbin /usr/lib/asterisk -type f -executable \ + -exec strip --strip-unneeded {} + 2>/dev/null || true + +log "Asterisk 22.11.0 build completed successfully!" \ No newline at end of file diff --git a/asterisk/22.11.0-trixie/entrypoint.sh b/asterisk/22.11.0-trixie/entrypoint.sh new file mode 100755 index 000000000..44b04ff3e --- /dev/null +++ b/asterisk/22.11.0-trixie/entrypoint.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Asterisk container entrypoint +# Generated from template for 22.11.0 +# +# Adapts the in-container `asterisk` user (default uid:gid 1000:1000) to the +# uid/gid supplied via PUID / PGID env vars, then chowns runtime directories +# so bind-mounted volumes are writable. Asterisk drops privileges itself via +# its `-U asterisk -p` CMD flags, so no gosu/su-exec is needed. +# +# When the container is launched with `--user N:M` (compose `user:`), this +# script runs as that user instead of root: the adapt/chown branch is skipped +# and "$@" is exec'd as-is, matching pre-entrypoint behaviour. + +set -e + +PUID="${PUID:-1000}" +PGID="${PGID:-1000}" + +if [ "$(id -u)" = "0" ]; then + current_uid="$(id -u asterisk)" + current_gid="$(id -g asterisk)" + + if [ "$PGID" != "$current_gid" ]; then + groupmod -o -g "$PGID" asterisk + fi + if [ "$PUID" != "$current_uid" ]; then + usermod -o -u "$PUID" -g "$PGID" asterisk + fi + + for path in /etc/asterisk /home/asterisk /var/lib/asterisk \ + /var/log/asterisk /var/spool/asterisk /var/run/asterisk; do + [ -d "$path" ] || continue + if [ "$(stat -c '%u:%g' "$path" 2>/dev/null)" != "$PUID:$PGID" ]; then + chown -R "$PUID:$PGID" "$path" 2>/dev/null || true + fi + done +fi + +# Replace the baked-in -W (light-background adjust) with whatever the user +# supplies via ASTERISK_TERMINAL_OPTS. Use cases (issue #16): +# ASTERISK_TERMINAL_OPTS="" -> drop -W, let the terminal decide +# ASTERISK_TERMINAL_OPTS="-B" -> force black background (dark terminals) +# ASTERISK_TERMINAL_OPTS="-n" -> disable colors entirely (safest in logs) +# (unset) -> keep -W (existing behaviour) +if [ -n "${ASTERISK_TERMINAL_OPTS+x}" ]; then + new_args=() + for arg in "$@"; do + if [ "$arg" = "-W" ]; then + for opt in $ASTERISK_TERMINAL_OPTS; do + new_args+=("$opt") + done + else + new_args+=("$arg") + fi + done + set -- "${new_args[@]}" +fi + +exec "$@" diff --git a/asterisk/22.11.0-trixie/healthcheck.sh b/asterisk/22.11.0-trixie/healthcheck.sh new file mode 100755 index 000000000..330a08e8e --- /dev/null +++ b/asterisk/22.11.0-trixie/healthcheck.sh @@ -0,0 +1,159 @@ +#!/bin/bash +# Asterisk health check script +# Generated from template for 22.11.0 + +set -euo pipefail + +# Configuration +ASTERISK_CLI="/usr/sbin/asterisk -rx" +TIMEOUT=10 +VERBOSE=false + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -v|--verbose) + VERBOSE=true + shift + ;; + -t|--timeout) + TIMEOUT="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" >&2 + exit 1 + ;; + esac +done + +# Logging functions +log() { + if [[ "$VERBOSE" == "true" ]]; then + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2 + fi +} + +error() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $*" >&2 +} + +# Health check functions +check_asterisk_running() { + log "Checking if Asterisk is running..." + if ! pgrep -x asterisk >/dev/null; then + error "Asterisk process not found" + return 1 + fi + log "✓ Asterisk process is running" + return 0 +} + +check_asterisk_responsive() { + log "Checking if Asterisk CLI is responsive..." + if ! timeout $TIMEOUT $ASTERISK_CLI "core show version" >/dev/null 2>&1; then + error "Asterisk CLI not responsive" + return 1 + fi + log "✓ Asterisk CLI is responsive" + return 0 +} + +check_pjsip_status() { + log "Checking PJSIP status..." + if ! timeout $TIMEOUT $ASTERISK_CLI "pjsip show version" >/dev/null 2>&1; then + error "PJSIP not available or not responding" + return 1 + fi + log "✓ PJSIP is available" + return 0 +} + +check_database_connectivity() { + log "Checking database connectivity..." + # Check if ODBC is configured and working + if ! timeout $TIMEOUT $ASTERISK_CLI "odbc show all" | grep -q "Connected" 2>/dev/null; then + log "⚠ No ODBC connections found (this may be normal)" + else + log "✓ Database connections available" + fi + return 0 +} + +check_essential_modules() { + log "Checking essential modules..." + local required_modules=( + "res_rtp_asterisk" + "res_timing_timerfd" + "res_crypto" + "res_pjsip" + ) + + for module in "${required_modules[@]}"; do + local module_output + module_output=$(timeout $TIMEOUT $ASTERISK_CLI "module show like $module" 2>&1) + if ! grep -q "$module" <<<"$module_output"; then + error "Required module $module not loaded" + return 1 + fi + done + log "✓ Essential modules are loaded" + return 0 +} + +check_filesystem_access() { + log "Checking filesystem access..." + local required_dirs=( + "/var/log/asterisk" + "/var/spool/asterisk" + "/var/lib/asterisk" + "/etc/asterisk" + ) + + for dir in "${required_dirs[@]}"; do + if [[ ! -d "$dir" ]]; then + error "Required directory $dir not found" + return 1 + fi + if [[ ! -r "$dir" ]]; then + error "Directory $dir not readable" + return 1 + fi + done + log "✓ Filesystem access is working" + return 0 +} + +# Main health check +main() { + log "Starting Asterisk health check..." + + local checks=( + "check_asterisk_running" + "check_asterisk_responsive" + "check_pjsip_status" + "check_database_connectivity" + "check_essential_modules" + "check_filesystem_access" + ) + + local failed=0 + for check in "${checks[@]}"; do + if ! $check; then + failed=$((failed + 1)) + fi + done + + if [[ $failed -eq 0 ]]; then + log "✓ All health checks passed" + exit 0 + else + error "Health check failed: $failed checks failed" + exit 1 + fi +} + +# Handle signals +trap 'error "Health check interrupted"; exit 1' INT TERM + +main "$@" \ No newline at end of file diff --git a/asterisk/23.5.0-forky/Dockerfile b/asterisk/23.5.0-forky/Dockerfile new file mode 100644 index 000000000..0ee4f9b9c --- /dev/null +++ b/asterisk/23.5.0-forky/Dockerfile @@ -0,0 +1,200 @@ +# Multi-stage optimized Asterisk Docker build +# Asterisk 23.5.0 on Debian forky +# Generated from YAML configuration - DO NOT EDIT MANUALLY + +# ============================================================================== +# STAGE 1: Build Environment +# ============================================================================== +FROM debian:forky AS asterisk-builder + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX Builder" +LABEL org.opencontainers.image.description="Build stage for Asterisk 23.5.0" +LABEL org.opencontainers.image.version="23.5.0" +LABEL org.opencontainers.image.source="https://github.com/andrius/asterisk" + +# Build arguments +ARG ASTERISK_VERSION=23.5.0 +ARG JOBS=8 +ARG DEBIAN_FRONTEND=noninteractive +ARG TARGETARCH + +# Environment variables +ENV ASTERISK_VERSION=${ASTERISK_VERSION} +ENV DEBIAN_FRONTEND=${DEBIAN_FRONTEND} +ENV TMPDIR="/tmp/asterisk_build" + +# Create build directories first +RUN mkdir -p \ + /usr/src/asterisk \ + ${TMPDIR} \ + && chmod 777 ${TMPDIR} + +# EOL distribution setup (if needed) +# Update package lists and install ca-certificates first, then build dependencies +RUN apt-get update \ + && apt-get install -y --no-install-recommends ca-certificates \ + && apt-get install -y --no-install-recommends \ + build-essential autoconf binutils-dev curl file libcurl4-openssl-dev \ + libedit-dev libgsm1-dev libicu-dev libjansson-dev libncurses-dev libogg-dev \ + libpopt-dev libpqxx-dev libresample1-dev libspandsp-dev libspeex-dev \ + libspeexdsp-dev libsqlite3-dev libssl-dev libtool libvorbis-dev libxml2-dev \ + libxslt1-dev make odbcinst patch pkg-config portaudio19-dev procps \ + python3-dev unixodbc unixodbc-dev uuid uuid-dev xmlstarlet libsrtp2-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && mkdir -p ${TMPDIR} && chmod 777 ${TMPDIR} + + +WORKDIR /usr/src/asterisk + +# Download and extract Asterisk source. +# When a sha256 checksum is present (plan 002) verify it before extracting; +# otherwise fall back to the historical unverified pipe (legacy tail / +# versions not yet backfilled). sha256sum ships in coreutils on every +# Debian base, including jessie/stretch - no new build dependency. +RUN curl -fsSL -o /tmp/asterisk-src.tar.gz https://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-23.5.0.tar.gz \ + && echo "8ed3a237e6d8dff94a09527a83143530b5afcc1aee73fa7b85c069bda507adac /tmp/asterisk-src.tar.gz" | sha256sum -c - \ + && tar --strip-components=1 -xzf /tmp/asterisk-src.tar.gz \ + && rm /tmp/asterisk-src.tar.gz + +# Configure Asterisk build (skip for very old versions that don't have configure script) +RUN ./configure + +# Generate menuselect configuration +RUN make menuselect/menuselect menuselect-tree menuselect.makeopts + + +# Copy and execute build script +COPY build.sh /usr/src/asterisk/build.sh +RUN chmod +x build.sh && ./build.sh + +# Derive exact runtime shared-library packages from the freshly built binaries. +# ldd lists the full transitive closure of linked libraries; each resolved .so +# is mapped to its owning Debian package via dpkg-query. This keeps the runtime +# image correct on rolling/experimental suites (e.g. forky) where SONAME- +# versioned package names drift (libicuNN, libpqxx-N.N, the t64 transition, ...). +RUN set -eu; \ + { ldd /usr/sbin/asterisk || true; \ + for f in /usr/lib/libasterisk*.so*; do [ -e "$f" ] && ldd "$f" || true; done; \ + find /usr/lib/asterisk/modules -name '*.so' -exec ldd {} \; 2>/dev/null || true; \ + } 2>/dev/null \ + | awk '/=> \// { print $3 } /^[[:space:]]*\// { print $1 }' \ + | grep -E '^/' \ + | while read -r lib; do readlink -f "$lib" 2>/dev/null || true; done \ + | sort -u \ + | xargs -r dpkg-query -S 2>/dev/null \ + | cut -d: -f1 \ + | tr ',' '\n' \ + | sed 's/^[[:space:]]*//; s/[[:space:]]*$//' \ + | grep -E '^[a-z0-9][a-z0-9+.-]+$' \ + | sort -u > /runtime-lib-deps.txt; \ + echo "== Derived runtime library packages =="; cat /runtime-lib-deps.txt; \ + test -s /runtime-lib-deps.txt +# ============================================================================== +# STAGE 2: Runtime Environment +# ============================================================================== +FROM debian:forky AS asterisk-runtime + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX Runtime" +LABEL org.opencontainers.image.description="Runtime environment for Asterisk 23.5.0" + +ARG DEBIAN_FRONTEND=noninteractive +ARG TARGETARCH +ENV DEBIAN_FRONTEND=${DEBIAN_FRONTEND} + +# Install runtime dependencies: non-library essentials (explicit) plus the +# shared-library packages auto-derived from the built binaries (builder stage). +COPY --from=asterisk-builder /runtime-lib-deps.txt /tmp/runtime-lib-deps.txt +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + binutils ca-certificates curl gettext-base odbcinst portaudio19-dev procps \ + python3 unixodbc uuid \ + $(cat /tmp/runtime-lib-deps.txt) \ + && rm -f /tmp/runtime-lib-deps.txt \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Create asterisk user and required directories +RUN useradd --uid 1000 --system --user-group \ + --home-dir /home/asterisk --create-home \ + asterisk \ + && mkdir -p \ + /var/run/asterisk \ + /var/log/asterisk \ + /var/spool/asterisk/monitor \ + /var/spool/asterisk/outgoing \ + /var/spool/asterisk/tmp \ + /var/spool/asterisk/voicemail \ + /var/spool/asterisk/fax \ + /var/lib/asterisk/keys \ + /var/lib/asterisk/phoneprov \ + /var/lib/asterisk/sounds \ + /var/lib/asterisk/docs + +# ============================================================================== +# STAGE 3: Final Production Image +# ============================================================================== +FROM asterisk-runtime AS asterisk-production + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX" +LABEL org.opencontainers.image.description="Production Asterisk PBX 23.5.0" +LABEL org.opencontainers.image.version="23.5.0" +LABEL org.opencontainers.image.source="https://github.com/andrius/asterisk" +LABEL org.opencontainers.image.vendor="Andrius Kairiukstis " + +# Copy Asterisk binaries and configurations from builder +COPY --from=asterisk-builder /usr/sbin/asterisk /usr/sbin/asterisk +COPY --from=asterisk-builder /usr/lib/asterisk /usr/lib/asterisk +COPY --from=asterisk-builder /var/lib/asterisk /var/lib/asterisk +COPY --from=asterisk-builder /etc/asterisk /etc/asterisk + +# Copy Asterisk shared libraries +COPY --from=asterisk-builder /usr/lib/libasterisk*.so* /usr/lib/ + +# Copy healthcheck script +COPY healthcheck.sh /usr/local/bin/healthcheck.sh +RUN chmod +x /usr/local/bin/healthcheck.sh + +# Copy entrypoint script (PUID/PGID volume permission handling) +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +# Set proper ownership and permissions +RUN chown -R asterisk:asterisk \ + /etc/asterisk \ + /home/asterisk \ + /var/*/asterisk \ + /usr/lib*/asterisk 2>/dev/null || true \ + && chmod -R 750 /var/spool/asterisk + +# Runtime verification +RUN asterisk -V || (echo "Error: Unable to run asterisk -V" && exit 1) + +# Configure networking +# EXPOSE 5060/udp +# EXPOSE 5060/tcp +# EXPOSE 5061/tcp +# EXPOSE 10000-10099/udp + +# Define volumes for persistent data +VOLUME ["/var/lib/asterisk/sounds", "/var/lib/asterisk/keys", "/var/lib/asterisk/phoneprov", "/var/spool/asterisk", "/var/log/asterisk", "/etc/asterisk"] + +# Add health check +HEALTHCHECK --interval=30s \ + --timeout=10s \ + --start-period=30s \ + --retries=3 \ + CMD /usr/local/bin/healthcheck.sh + +# Entrypoint runs as root, adapts asterisk uid/gid to PUID/PGID, then execs CMD. +# Asterisk drops privileges itself via `-U asterisk -p` in the CMD below. +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] + +# Set working directory +WORKDIR /home/asterisk + +# Default command with production settings +CMD ["/usr/sbin/asterisk", "-vvvdddf", "-T", "-W", "-U", "asterisk", "-p"] diff --git a/asterisk/23.5.0-forky/build.sh b/asterisk/23.5.0-forky/build.sh new file mode 100755 index 000000000..001c19dc2 --- /dev/null +++ b/asterisk/23.5.0-forky/build.sh @@ -0,0 +1,150 @@ +#!/bin/bash +# Asterisk build script +# Generated from template for 23.5.0 +# Contains menuselect configuration and build commands + +set -euo pipefail + +# Color output for better readability +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +log() { + echo -e "${GREEN}[BUILD]${NC} $1" +} + +warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +log "Starting Asterisk 23.5.0 build process..." + +# Set build parallelization (use Docker ARG or default) +NPROC=$(nproc) +JOBS=${JOBS:-8} +log "Using $JOBS parallel jobs for compilation (detected $NPROC CPUs)" + +# Configure Asterisk +log "Configuring Asterisk with options..." +./configure --with-pjproject-bundled --with-ssl=ssl --with-crypto + +# Workaround: Asterisk 18.x ships makeopts with a literal '\n' in DOWNLOAD +# that dash echo interprets as a real newline, mangling +# get_sourceable_makeopts output and breaking make_xml_documentation. Flatten +# the line to a plain curl invocation. No-op on versions without the bug. +if [ -f makeopts ]; then + sed -i 's|^DOWNLOAD=.*|DOWNLOAD=/usr/bin/curl -L -O --progress-bar|' makeopts +fi + +# Build menuselect tool +log "Building menuselect tool..." +make menuselect + +# Configure Asterisk modules using menuselect +log "Configuring Asterisk modules..." + +# Disable BUILD_NATIVE optimization for container builds +menuselect/menuselect --disable BUILD_NATIVE menuselect.makeopts + +# ponytail: BETTER_BACKTRACES left off on Debian forky - its binutils removed the +# bfd_boolean type from , so Asterisk's backtrace.c fails to compile. The +# option is off by default, so omitting --enable is enough. Re-enable for all +# distros once Asterisk upstream tracks the binutils >= 2.34 bfd API (also revisit +# when trixie's binutils bumps past 2.33). + +# Disable sound packages to reduce image size +menuselect/menuselect --disable-category MENUSELECT_CORE_SOUNDS menuselect.makeopts +menuselect/menuselect --disable-category MENUSELECT_MOH menuselect.makeopts +menuselect/menuselect --disable-category MENUSELECT_EXTRA_SOUNDS menuselect.makeopts + +# Enable core applications +menuselect/menuselect --enable app_voicemail menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_voicemail menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_queue menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_queue menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_confbridge menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_confbridge menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_directory menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_directory menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_dial menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_dial menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_playback menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_playback menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_record menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_record menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_echo menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_echo menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_mixmonitor menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_mixmonitor menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + +# Enable CDR and CEL modules + +# Enable channel drivers +menuselect/menuselect --enable chan_pjsip menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_pjsip menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable chan_iax2 menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_iax2 menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable chan_local menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_local menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable chan_bridge_media menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_bridge_media menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable chan_websocket menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_websocket menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + +# Enable resource modules +menuselect/menuselect --enable res_musiconhold menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_musiconhold menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip_session menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip_session menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip_outbound_registration menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip_outbound_registration menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip_registrar menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip_registrar menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_rtp_asterisk menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_rtp_asterisk menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_timing_timerfd menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_timing_timerfd menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_crypto menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_crypto menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + +# Disable unwanted modules +menuselect/menuselect --disable chan_dahdi menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable chan_dahdi menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --disable chan_misdn menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable chan_misdn menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --disable app_festival menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable app_festival menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --disable chan_sip menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable chan_sip menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + + +log "Module configuration completed" + + +# Pre-build third-party (pjproject) sequentially with verbose output. +# This surfaces real compiler errors that would otherwise be hidden by parallel make. +# Skipped on Asterisk < 13: the 'third-party' target was added with bundled +# pjproject support and does not exist in older trees. +log "Building third-party dependencies (pjproject) with verbose output..." +TMPDIR=${TMPDIR} make NOISY_BUILD=yes -j 1 third-party + +# Build Asterisk +log "Building Asterisk core (this may take several minutes)..." +TMPDIR=${TMPDIR} make -j $JOBS all +log "Installing Asterisk..." +TMPDIR=${TMPDIR} make install +log "Installing sample configurations..." +TMPDIR=${TMPDIR} make samples + +# Download and install Digium Opus codec binary (x86-64 only) +ARCH=$(dpkg --print-architecture 2>/dev/null || echo "unknown") +if [ "$ARCH" = "amd64" ]; then + OPUS_MAJOR="23" + OPUS_URL="https://downloads.digium.com/pub/telephony/codec_opus/asterisk-${OPUS_MAJOR}.0/x86-64/codec_opus-${OPUS_MAJOR}.0-current-x86_64.tar.gz" + log "Downloading Digium Opus codec (Asterisk ${OPUS_MAJOR}.0)..." + OPUS_TMP="/tmp/codec_opus" + mkdir -p "$OPUS_TMP" + if curl -fsSL "$OPUS_URL" | tar -xz -C "$OPUS_TMP"; then + find "$OPUS_TMP" -name "codec_opus*.so" -exec cp -v {} /usr/lib/asterisk/modules/ \; + find "$OPUS_TMP" -name "format_ogg_opus*.so" -exec cp -v {} /usr/lib/asterisk/modules/ \; + mkdir -p /var/lib/asterisk/documentation + find "$OPUS_TMP" -name "codec_opus_config-en_US.xml" -exec cp -v {} /var/lib/asterisk/documentation/ \; + rm -rf "$OPUS_TMP" + log "Opus codec installed successfully" + else + warn "Failed to download Opus codec from $OPUS_URL - Opus transcoding will not be available" + rm -rf "$OPUS_TMP" + fi +else + log "Skipping Digium Opus codec (x86-64 only, detected: $ARCH)" +fi + + +# Strip binaries to reduce size +log "Stripping binaries to reduce image size..." +find /usr/sbin /usr/lib/asterisk -type f -executable \ + -exec strip --strip-unneeded {} + 2>/dev/null || true + +log "Asterisk 23.5.0 build completed successfully!" \ No newline at end of file diff --git a/asterisk/23.5.0-forky/entrypoint.sh b/asterisk/23.5.0-forky/entrypoint.sh new file mode 100755 index 000000000..4e303a7dc --- /dev/null +++ b/asterisk/23.5.0-forky/entrypoint.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Asterisk container entrypoint +# Generated from template for 23.5.0 +# +# Adapts the in-container `asterisk` user (default uid:gid 1000:1000) to the +# uid/gid supplied via PUID / PGID env vars, then chowns runtime directories +# so bind-mounted volumes are writable. Asterisk drops privileges itself via +# its `-U asterisk -p` CMD flags, so no gosu/su-exec is needed. +# +# When the container is launched with `--user N:M` (compose `user:`), this +# script runs as that user instead of root: the adapt/chown branch is skipped +# and "$@" is exec'd as-is, matching pre-entrypoint behaviour. + +set -e + +PUID="${PUID:-1000}" +PGID="${PGID:-1000}" + +if [ "$(id -u)" = "0" ]; then + current_uid="$(id -u asterisk)" + current_gid="$(id -g asterisk)" + + if [ "$PGID" != "$current_gid" ]; then + groupmod -o -g "$PGID" asterisk + fi + if [ "$PUID" != "$current_uid" ]; then + usermod -o -u "$PUID" -g "$PGID" asterisk + fi + + for path in /etc/asterisk /home/asterisk /var/lib/asterisk \ + /var/log/asterisk /var/spool/asterisk /var/run/asterisk; do + [ -d "$path" ] || continue + if [ "$(stat -c '%u:%g' "$path" 2>/dev/null)" != "$PUID:$PGID" ]; then + chown -R "$PUID:$PGID" "$path" 2>/dev/null || true + fi + done +fi + +# Replace the baked-in -W (light-background adjust) with whatever the user +# supplies via ASTERISK_TERMINAL_OPTS. Use cases (issue #16): +# ASTERISK_TERMINAL_OPTS="" -> drop -W, let the terminal decide +# ASTERISK_TERMINAL_OPTS="-B" -> force black background (dark terminals) +# ASTERISK_TERMINAL_OPTS="-n" -> disable colors entirely (safest in logs) +# (unset) -> keep -W (existing behaviour) +if [ -n "${ASTERISK_TERMINAL_OPTS+x}" ]; then + new_args=() + for arg in "$@"; do + if [ "$arg" = "-W" ]; then + for opt in $ASTERISK_TERMINAL_OPTS; do + new_args+=("$opt") + done + else + new_args+=("$arg") + fi + done + set -- "${new_args[@]}" +fi + +exec "$@" diff --git a/asterisk/23.5.0-forky/healthcheck.sh b/asterisk/23.5.0-forky/healthcheck.sh new file mode 100755 index 000000000..cd8bb32a7 --- /dev/null +++ b/asterisk/23.5.0-forky/healthcheck.sh @@ -0,0 +1,159 @@ +#!/bin/bash +# Asterisk health check script +# Generated from template for 23.5.0 + +set -euo pipefail + +# Configuration +ASTERISK_CLI="/usr/sbin/asterisk -rx" +TIMEOUT=10 +VERBOSE=false + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -v|--verbose) + VERBOSE=true + shift + ;; + -t|--timeout) + TIMEOUT="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" >&2 + exit 1 + ;; + esac +done + +# Logging functions +log() { + if [[ "$VERBOSE" == "true" ]]; then + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2 + fi +} + +error() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $*" >&2 +} + +# Health check functions +check_asterisk_running() { + log "Checking if Asterisk is running..." + if ! pgrep -x asterisk >/dev/null; then + error "Asterisk process not found" + return 1 + fi + log "✓ Asterisk process is running" + return 0 +} + +check_asterisk_responsive() { + log "Checking if Asterisk CLI is responsive..." + if ! timeout $TIMEOUT $ASTERISK_CLI "core show version" >/dev/null 2>&1; then + error "Asterisk CLI not responsive" + return 1 + fi + log "✓ Asterisk CLI is responsive" + return 0 +} + +check_pjsip_status() { + log "Checking PJSIP status..." + if ! timeout $TIMEOUT $ASTERISK_CLI "pjsip show version" >/dev/null 2>&1; then + error "PJSIP not available or not responding" + return 1 + fi + log "✓ PJSIP is available" + return 0 +} + +check_database_connectivity() { + log "Checking database connectivity..." + # Check if ODBC is configured and working + if ! timeout $TIMEOUT $ASTERISK_CLI "odbc show all" | grep -q "Connected" 2>/dev/null; then + log "⚠ No ODBC connections found (this may be normal)" + else + log "✓ Database connections available" + fi + return 0 +} + +check_essential_modules() { + log "Checking essential modules..." + local required_modules=( + "res_rtp_asterisk" + "res_timing_timerfd" + "res_crypto" + "res_pjsip" + ) + + for module in "${required_modules[@]}"; do + local module_output + module_output=$(timeout $TIMEOUT $ASTERISK_CLI "module show like $module" 2>&1) + if ! grep -q "$module" <<<"$module_output"; then + error "Required module $module not loaded" + return 1 + fi + done + log "✓ Essential modules are loaded" + return 0 +} + +check_filesystem_access() { + log "Checking filesystem access..." + local required_dirs=( + "/var/log/asterisk" + "/var/spool/asterisk" + "/var/lib/asterisk" + "/etc/asterisk" + ) + + for dir in "${required_dirs[@]}"; do + if [[ ! -d "$dir" ]]; then + error "Required directory $dir not found" + return 1 + fi + if [[ ! -r "$dir" ]]; then + error "Directory $dir not readable" + return 1 + fi + done + log "✓ Filesystem access is working" + return 0 +} + +# Main health check +main() { + log "Starting Asterisk health check..." + + local checks=( + "check_asterisk_running" + "check_asterisk_responsive" + "check_pjsip_status" + "check_database_connectivity" + "check_essential_modules" + "check_filesystem_access" + ) + + local failed=0 + for check in "${checks[@]}"; do + if ! $check; then + failed=$((failed + 1)) + fi + done + + if [[ $failed -eq 0 ]]; then + log "✓ All health checks passed" + exit 0 + else + error "Health check failed: $failed checks failed" + exit 1 + fi +} + +# Handle signals +trap 'error "Health check interrupted"; exit 1' INT TERM + +main "$@" \ No newline at end of file diff --git a/asterisk/23.5.0-trixie/Dockerfile b/asterisk/23.5.0-trixie/Dockerfile new file mode 100644 index 000000000..855d91900 --- /dev/null +++ b/asterisk/23.5.0-trixie/Dockerfile @@ -0,0 +1,177 @@ +# Multi-stage optimized Asterisk Docker build +# Asterisk 23.5.0 on Debian trixie +# Generated from YAML configuration - DO NOT EDIT MANUALLY + +# ============================================================================== +# STAGE 1: Build Environment +# ============================================================================== +FROM debian:trixie AS asterisk-builder + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX Builder" +LABEL org.opencontainers.image.description="Build stage for Asterisk 23.5.0" +LABEL org.opencontainers.image.version="23.5.0" +LABEL org.opencontainers.image.source="https://github.com/andrius/asterisk" + +# Build arguments +ARG ASTERISK_VERSION=23.5.0 +ARG JOBS=8 +ARG DEBIAN_FRONTEND=noninteractive +ARG TARGETARCH + +# Environment variables +ENV ASTERISK_VERSION=${ASTERISK_VERSION} +ENV DEBIAN_FRONTEND=${DEBIAN_FRONTEND} +ENV TMPDIR="/tmp/asterisk_build" + +# Create build directories first +RUN mkdir -p \ + /usr/src/asterisk \ + ${TMPDIR} \ + && chmod 777 ${TMPDIR} + +# EOL distribution setup (if needed) +# Update package lists and install ca-certificates first, then build dependencies +RUN apt-get update \ + && apt-get install -y --no-install-recommends ca-certificates \ + && apt-get install -y --no-install-recommends \ + build-essential autoconf binutils-dev curl file libcurl4-openssl-dev \ + libedit-dev libgsm1-dev libicu-dev libjansson-dev libncurses-dev libogg-dev \ + libpopt-dev libpqxx-dev libresample1-dev libspandsp-dev libspeex-dev \ + libspeexdsp-dev libsqlite3-dev libssl-dev libtool libvorbis-dev libxml2-dev \ + libxslt1-dev make odbcinst patch pkg-config portaudio19-dev procps \ + python3-dev unixodbc unixodbc-dev uuid uuid-dev xmlstarlet libsrtp2-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && mkdir -p ${TMPDIR} && chmod 777 ${TMPDIR} + + +WORKDIR /usr/src/asterisk + +# Download and extract Asterisk source. +# When a sha256 checksum is present (plan 002) verify it before extracting; +# otherwise fall back to the historical unverified pipe (legacy tail / +# versions not yet backfilled). sha256sum ships in coreutils on every +# Debian base, including jessie/stretch - no new build dependency. +RUN curl -fsSL -o /tmp/asterisk-src.tar.gz https://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-23.5.0.tar.gz \ + && echo "8ed3a237e6d8dff94a09527a83143530b5afcc1aee73fa7b85c069bda507adac /tmp/asterisk-src.tar.gz" | sha256sum -c - \ + && tar --strip-components=1 -xzf /tmp/asterisk-src.tar.gz \ + && rm /tmp/asterisk-src.tar.gz + +# Configure Asterisk build (skip for very old versions that don't have configure script) +RUN ./configure + +# Generate menuselect configuration +RUN make menuselect/menuselect menuselect-tree menuselect.makeopts + + +# Copy and execute build script +COPY build.sh /usr/src/asterisk/build.sh +RUN chmod +x build.sh && ./build.sh + +# ============================================================================== +# STAGE 2: Runtime Environment +# ============================================================================== +FROM debian:trixie AS asterisk-runtime + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX Runtime" +LABEL org.opencontainers.image.description="Runtime environment for Asterisk 23.5.0" + +ARG DEBIAN_FRONTEND=noninteractive +ARG TARGETARCH +ENV DEBIAN_FRONTEND=${DEBIAN_FRONTEND} + +# Install only runtime dependencies +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + binutils ca-certificates curl gettext-base libedit2 libgsm1 libjansson4 \ + libogg0 libopus0 libpopt0 libresample1 libspandsp2 libspeex1 libspeexdsp1 \ + libsqlite3-0 libvorbis0a libxml2 libxslt1.1 odbcinst portaudio19-dev procps \ + python3 unixodbc uuid libcurl4t64 libssl3t64 libsrtp2-1 libncurses6 \ + libpqxx-7.10 libicu76 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Create asterisk user and required directories +RUN useradd --uid 1000 --system --user-group \ + --home-dir /home/asterisk --create-home \ + asterisk \ + && mkdir -p \ + /var/run/asterisk \ + /var/log/asterisk \ + /var/spool/asterisk/monitor \ + /var/spool/asterisk/outgoing \ + /var/spool/asterisk/tmp \ + /var/spool/asterisk/voicemail \ + /var/spool/asterisk/fax \ + /var/lib/asterisk/keys \ + /var/lib/asterisk/phoneprov \ + /var/lib/asterisk/sounds \ + /var/lib/asterisk/docs + +# ============================================================================== +# STAGE 3: Final Production Image +# ============================================================================== +FROM asterisk-runtime AS asterisk-production + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX" +LABEL org.opencontainers.image.description="Production Asterisk PBX 23.5.0" +LABEL org.opencontainers.image.version="23.5.0" +LABEL org.opencontainers.image.source="https://github.com/andrius/asterisk" +LABEL org.opencontainers.image.vendor="Andrius Kairiukstis " + +# Copy Asterisk binaries and configurations from builder +COPY --from=asterisk-builder /usr/sbin/asterisk /usr/sbin/asterisk +COPY --from=asterisk-builder /usr/lib/asterisk /usr/lib/asterisk +COPY --from=asterisk-builder /var/lib/asterisk /var/lib/asterisk +COPY --from=asterisk-builder /etc/asterisk /etc/asterisk + +# Copy Asterisk shared libraries +COPY --from=asterisk-builder /usr/lib/libasterisk*.so* /usr/lib/ + +# Copy healthcheck script +COPY healthcheck.sh /usr/local/bin/healthcheck.sh +RUN chmod +x /usr/local/bin/healthcheck.sh + +# Copy entrypoint script (PUID/PGID volume permission handling) +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/entrypoint.sh + +# Set proper ownership and permissions +RUN chown -R asterisk:asterisk \ + /etc/asterisk \ + /home/asterisk \ + /var/*/asterisk \ + /usr/lib*/asterisk 2>/dev/null || true \ + && chmod -R 750 /var/spool/asterisk + +# Runtime verification +RUN asterisk -V || (echo "Error: Unable to run asterisk -V" && exit 1) + +# Configure networking +# EXPOSE 5060/udp +# EXPOSE 5060/tcp +# EXPOSE 5061/tcp +# EXPOSE 10000-10099/udp + +# Define volumes for persistent data +VOLUME ["/var/lib/asterisk/sounds", "/var/lib/asterisk/keys", "/var/lib/asterisk/phoneprov", "/var/spool/asterisk", "/var/log/asterisk", "/etc/asterisk"] + +# Add health check +HEALTHCHECK --interval=30s \ + --timeout=10s \ + --start-period=30s \ + --retries=3 \ + CMD /usr/local/bin/healthcheck.sh + +# Entrypoint runs as root, adapts asterisk uid/gid to PUID/PGID, then execs CMD. +# Asterisk drops privileges itself via `-U asterisk -p` in the CMD below. +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] + +# Set working directory +WORKDIR /home/asterisk + +# Default command with production settings +CMD ["/usr/sbin/asterisk", "-vvvdddf", "-T", "-W", "-U", "asterisk", "-p"] diff --git a/asterisk/23.5.0-trixie/build.sh b/asterisk/23.5.0-trixie/build.sh new file mode 100755 index 000000000..75d21dfdf --- /dev/null +++ b/asterisk/23.5.0-trixie/build.sh @@ -0,0 +1,147 @@ +#!/bin/bash +# Asterisk build script +# Generated from template for 23.5.0 +# Contains menuselect configuration and build commands + +set -euo pipefail + +# Color output for better readability +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +log() { + echo -e "${GREEN}[BUILD]${NC} $1" +} + +warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +log "Starting Asterisk 23.5.0 build process..." + +# Set build parallelization (use Docker ARG or default) +NPROC=$(nproc) +JOBS=${JOBS:-8} +log "Using $JOBS parallel jobs for compilation (detected $NPROC CPUs)" + +# Configure Asterisk +log "Configuring Asterisk with options..." +./configure --with-pjproject-bundled --with-ssl=ssl --with-crypto + +# Workaround: Asterisk 18.x ships makeopts with a literal '\n' in DOWNLOAD +# that dash echo interprets as a real newline, mangling +# get_sourceable_makeopts output and breaking make_xml_documentation. Flatten +# the line to a plain curl invocation. No-op on versions without the bug. +if [ -f makeopts ]; then + sed -i 's|^DOWNLOAD=.*|DOWNLOAD=/usr/bin/curl -L -O --progress-bar|' makeopts +fi + +# Build menuselect tool +log "Building menuselect tool..." +make menuselect + +# Configure Asterisk modules using menuselect +log "Configuring Asterisk modules..." + +# Disable BUILD_NATIVE optimization for container builds +menuselect/menuselect --disable BUILD_NATIVE menuselect.makeopts + +# Enable better backtraces for debugging +menuselect/menuselect --enable BETTER_BACKTRACES menuselect.makeopts + +# Disable sound packages to reduce image size +menuselect/menuselect --disable-category MENUSELECT_CORE_SOUNDS menuselect.makeopts +menuselect/menuselect --disable-category MENUSELECT_MOH menuselect.makeopts +menuselect/menuselect --disable-category MENUSELECT_EXTRA_SOUNDS menuselect.makeopts + +# Enable core applications +menuselect/menuselect --enable app_voicemail menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_voicemail menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_queue menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_queue menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_confbridge menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_confbridge menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_directory menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_directory menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_dial menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_dial menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_playback menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_playback menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_record menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_record menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_echo menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_echo menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable app_mixmonitor menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable app_mixmonitor menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + +# Enable CDR and CEL modules + +# Enable channel drivers +menuselect/menuselect --enable chan_pjsip menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_pjsip menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable chan_iax2 menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_iax2 menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable chan_local menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_local menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable chan_bridge_media menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_bridge_media menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable chan_websocket menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable chan_websocket menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + +# Enable resource modules +menuselect/menuselect --enable res_musiconhold menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_musiconhold menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip_session menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip_session menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip_outbound_registration menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip_outbound_registration menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_pjsip_registrar menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_pjsip_registrar menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_rtp_asterisk menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_rtp_asterisk menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_timing_timerfd menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_timing_timerfd menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --enable res_crypto menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --enable res_crypto menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + +# Disable unwanted modules +menuselect/menuselect --disable chan_dahdi menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable chan_dahdi menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --disable chan_misdn menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable chan_misdn menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --disable app_festival menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable app_festival menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" +menuselect/menuselect --disable chan_sip menuselect.makeopts || warn "Module not found: $(echo 'menuselect/menuselect --disable chan_sip menuselect.makeopts' | grep -o '[a-z_]*' | tail -1)" + + +log "Module configuration completed" + + +# Pre-build third-party (pjproject) sequentially with verbose output. +# This surfaces real compiler errors that would otherwise be hidden by parallel make. +# Skipped on Asterisk < 13: the 'third-party' target was added with bundled +# pjproject support and does not exist in older trees. +log "Building third-party dependencies (pjproject) with verbose output..." +TMPDIR=${TMPDIR} make NOISY_BUILD=yes -j 1 third-party + +# Build Asterisk +log "Building Asterisk core (this may take several minutes)..." +TMPDIR=${TMPDIR} make -j $JOBS all +log "Installing Asterisk..." +TMPDIR=${TMPDIR} make install +log "Installing sample configurations..." +TMPDIR=${TMPDIR} make samples + +# Download and install Digium Opus codec binary (x86-64 only) +ARCH=$(dpkg --print-architecture 2>/dev/null || echo "unknown") +if [ "$ARCH" = "amd64" ]; then + OPUS_MAJOR="23" + OPUS_URL="https://downloads.digium.com/pub/telephony/codec_opus/asterisk-${OPUS_MAJOR}.0/x86-64/codec_opus-${OPUS_MAJOR}.0-current-x86_64.tar.gz" + log "Downloading Digium Opus codec (Asterisk ${OPUS_MAJOR}.0)..." + OPUS_TMP="/tmp/codec_opus" + mkdir -p "$OPUS_TMP" + if curl -fsSL "$OPUS_URL" | tar -xz -C "$OPUS_TMP"; then + find "$OPUS_TMP" -name "codec_opus*.so" -exec cp -v {} /usr/lib/asterisk/modules/ \; + find "$OPUS_TMP" -name "format_ogg_opus*.so" -exec cp -v {} /usr/lib/asterisk/modules/ \; + mkdir -p /var/lib/asterisk/documentation + find "$OPUS_TMP" -name "codec_opus_config-en_US.xml" -exec cp -v {} /var/lib/asterisk/documentation/ \; + rm -rf "$OPUS_TMP" + log "Opus codec installed successfully" + else + warn "Failed to download Opus codec from $OPUS_URL - Opus transcoding will not be available" + rm -rf "$OPUS_TMP" + fi +else + log "Skipping Digium Opus codec (x86-64 only, detected: $ARCH)" +fi + + +# Strip binaries to reduce size +log "Stripping binaries to reduce image size..." +find /usr/sbin /usr/lib/asterisk -type f -executable \ + -exec strip --strip-unneeded {} + 2>/dev/null || true + +log "Asterisk 23.5.0 build completed successfully!" \ No newline at end of file diff --git a/asterisk/23.5.0-trixie/entrypoint.sh b/asterisk/23.5.0-trixie/entrypoint.sh new file mode 100755 index 000000000..4e303a7dc --- /dev/null +++ b/asterisk/23.5.0-trixie/entrypoint.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Asterisk container entrypoint +# Generated from template for 23.5.0 +# +# Adapts the in-container `asterisk` user (default uid:gid 1000:1000) to the +# uid/gid supplied via PUID / PGID env vars, then chowns runtime directories +# so bind-mounted volumes are writable. Asterisk drops privileges itself via +# its `-U asterisk -p` CMD flags, so no gosu/su-exec is needed. +# +# When the container is launched with `--user N:M` (compose `user:`), this +# script runs as that user instead of root: the adapt/chown branch is skipped +# and "$@" is exec'd as-is, matching pre-entrypoint behaviour. + +set -e + +PUID="${PUID:-1000}" +PGID="${PGID:-1000}" + +if [ "$(id -u)" = "0" ]; then + current_uid="$(id -u asterisk)" + current_gid="$(id -g asterisk)" + + if [ "$PGID" != "$current_gid" ]; then + groupmod -o -g "$PGID" asterisk + fi + if [ "$PUID" != "$current_uid" ]; then + usermod -o -u "$PUID" -g "$PGID" asterisk + fi + + for path in /etc/asterisk /home/asterisk /var/lib/asterisk \ + /var/log/asterisk /var/spool/asterisk /var/run/asterisk; do + [ -d "$path" ] || continue + if [ "$(stat -c '%u:%g' "$path" 2>/dev/null)" != "$PUID:$PGID" ]; then + chown -R "$PUID:$PGID" "$path" 2>/dev/null || true + fi + done +fi + +# Replace the baked-in -W (light-background adjust) with whatever the user +# supplies via ASTERISK_TERMINAL_OPTS. Use cases (issue #16): +# ASTERISK_TERMINAL_OPTS="" -> drop -W, let the terminal decide +# ASTERISK_TERMINAL_OPTS="-B" -> force black background (dark terminals) +# ASTERISK_TERMINAL_OPTS="-n" -> disable colors entirely (safest in logs) +# (unset) -> keep -W (existing behaviour) +if [ -n "${ASTERISK_TERMINAL_OPTS+x}" ]; then + new_args=() + for arg in "$@"; do + if [ "$arg" = "-W" ]; then + for opt in $ASTERISK_TERMINAL_OPTS; do + new_args+=("$opt") + done + else + new_args+=("$arg") + fi + done + set -- "${new_args[@]}" +fi + +exec "$@" diff --git a/asterisk/23.5.0-trixie/healthcheck.sh b/asterisk/23.5.0-trixie/healthcheck.sh new file mode 100755 index 000000000..cd8bb32a7 --- /dev/null +++ b/asterisk/23.5.0-trixie/healthcheck.sh @@ -0,0 +1,159 @@ +#!/bin/bash +# Asterisk health check script +# Generated from template for 23.5.0 + +set -euo pipefail + +# Configuration +ASTERISK_CLI="/usr/sbin/asterisk -rx" +TIMEOUT=10 +VERBOSE=false + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -v|--verbose) + VERBOSE=true + shift + ;; + -t|--timeout) + TIMEOUT="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" >&2 + exit 1 + ;; + esac +done + +# Logging functions +log() { + if [[ "$VERBOSE" == "true" ]]; then + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2 + fi +} + +error() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $*" >&2 +} + +# Health check functions +check_asterisk_running() { + log "Checking if Asterisk is running..." + if ! pgrep -x asterisk >/dev/null; then + error "Asterisk process not found" + return 1 + fi + log "✓ Asterisk process is running" + return 0 +} + +check_asterisk_responsive() { + log "Checking if Asterisk CLI is responsive..." + if ! timeout $TIMEOUT $ASTERISK_CLI "core show version" >/dev/null 2>&1; then + error "Asterisk CLI not responsive" + return 1 + fi + log "✓ Asterisk CLI is responsive" + return 0 +} + +check_pjsip_status() { + log "Checking PJSIP status..." + if ! timeout $TIMEOUT $ASTERISK_CLI "pjsip show version" >/dev/null 2>&1; then + error "PJSIP not available or not responding" + return 1 + fi + log "✓ PJSIP is available" + return 0 +} + +check_database_connectivity() { + log "Checking database connectivity..." + # Check if ODBC is configured and working + if ! timeout $TIMEOUT $ASTERISK_CLI "odbc show all" | grep -q "Connected" 2>/dev/null; then + log "⚠ No ODBC connections found (this may be normal)" + else + log "✓ Database connections available" + fi + return 0 +} + +check_essential_modules() { + log "Checking essential modules..." + local required_modules=( + "res_rtp_asterisk" + "res_timing_timerfd" + "res_crypto" + "res_pjsip" + ) + + for module in "${required_modules[@]}"; do + local module_output + module_output=$(timeout $TIMEOUT $ASTERISK_CLI "module show like $module" 2>&1) + if ! grep -q "$module" <<<"$module_output"; then + error "Required module $module not loaded" + return 1 + fi + done + log "✓ Essential modules are loaded" + return 0 +} + +check_filesystem_access() { + log "Checking filesystem access..." + local required_dirs=( + "/var/log/asterisk" + "/var/spool/asterisk" + "/var/lib/asterisk" + "/etc/asterisk" + ) + + for dir in "${required_dirs[@]}"; do + if [[ ! -d "$dir" ]]; then + error "Required directory $dir not found" + return 1 + fi + if [[ ! -r "$dir" ]]; then + error "Directory $dir not readable" + return 1 + fi + done + log "✓ Filesystem access is working" + return 0 +} + +# Main health check +main() { + log "Starting Asterisk health check..." + + local checks=( + "check_asterisk_running" + "check_asterisk_responsive" + "check_pjsip_status" + "check_database_connectivity" + "check_essential_modules" + "check_filesystem_access" + ) + + local failed=0 + for check in "${checks[@]}"; do + if ! $check; then + failed=$((failed + 1)) + fi + done + + if [[ $failed -eq 0 ]]; then + log "✓ All health checks passed" + exit 0 + else + error "Health check failed: $failed checks failed" + exit 1 + fi +} + +# Handle signals +trap 'error "Health check interrupted"; exit 1' INT TERM + +main "$@" \ No newline at end of file diff --git a/asterisk/asterisk-releases.txt b/asterisk/asterisk-releases.txt index 0662eb56c..af58e68bf 100644 --- a/asterisk/asterisk-releases.txt +++ b/asterisk/asterisk-releases.txt @@ -1127,7 +1127,6 @@ 19.8.0-rc1 19.8.0-rc2 19.8.1 -20-testing 20.0.0 20.0.0-rc1 20.0.0-rc2 @@ -1198,6 +1197,7 @@ 20.20.0 20.20.0-rc1 20.20.1 +20.21.0 20.21.0-rc1 20.21.0-rc2 21.0.0 @@ -1247,7 +1247,6 @@ 21.12.1 21.12.2 21.12.3 -22-testing 22.0.0 22.0.0-rc1 22.0.0-rc2 @@ -1284,9 +1283,9 @@ 22.10.0 22.10.0-rc1 22.10.1 +22.11.0 22.11.0-rc1 22.11.0-rc2 -23-testing 23.0.0 23.0.0-rc1 23.0.0-rc2 @@ -1303,5 +1302,6 @@ 23.4.0 23.4.0-rc1 23.4.1 +23.5.0 23.5.0-rc1 23.5.0-rc2 diff --git a/asterisk/asterisk-releases.yml b/asterisk/asterisk-releases.yml index cd671d0a5..881d09dd9 100644 --- a/asterisk/asterisk-releases.yml +++ b/asterisk/asterisk-releases.yml @@ -1210,6 +1210,7 @@ - 20.20.0 - 20.20.0-rc1 - 20.20.1 + - 20.21.0 - 20.21.0-rc1 - 20.21.0-rc2 21: @@ -1297,6 +1298,7 @@ - 22.10.0 - 22.10.0-rc1 - 22.10.1 + - 22.11.0 - 22.11.0-rc1 - 22.11.0-rc2 23: @@ -1316,5 +1318,6 @@ - 23.4.0 - 23.4.0-rc1 - 23.4.1 + - 23.5.0 - 23.5.0-rc1 - 23.5.0-rc2 diff --git a/asterisk/supported-asterisk-builds.yml b/asterisk/supported-asterisk-builds.yml index df6137d40..057792ce0 100644 --- a/asterisk/supported-asterisk-builds.yml +++ b/asterisk/supported-asterisk-builds.yml @@ -491,8 +491,8 @@ latest_builds: architectures: - "amd64" - "arm64" - additional_tags: "20" tarball_sha256: "32ef7db8e449629128eb5f7e42d3d704f03daacb91d76ee694a9acf7f1fd53e2" + superseded_by: "20.21.0" - version: "20.7-cert11" os_matrix: - os: "debian" @@ -541,8 +541,8 @@ latest_builds: architectures: - "amd64" - "arm64" - additional_tags: "latest,stable,22" tarball_sha256: "0953564c44fa49827f3c9d70ca6e80db83828c9848440852c6be44c961855353" + superseded_by: "22.11.0" - version: "22.8-cert3" os_matrix: - os: "debian" @@ -600,8 +600,8 @@ latest_builds: architectures: - "amd64" - "arm64" - additional_tags: "23" tarball_sha256: "9d90269af187c8437087ba96f569e656a6a4a9a0a2347489c9e81ff1c37d2c51" + superseded_by: "23.5.0" - version: "22.8-cert4" tarball_sha256: "a41a7007d420119255017bbf15759a4204fb45915b1ce5f0dc7622ecaf498c34" os_matrix: @@ -612,8 +612,45 @@ latest_builds: - "arm64" additional_tags: "22-cert" + - version: "20.21.0" + tarball_sha256: "13fd6e8f1fbb19a3174af82a388dd72c87eb2c92d32fca83c4d51bfab03f686a" + os_matrix: + - os: "debian" + distribution: "trixie" + architectures: + - "amd64" + - "arm64" + + additional_tags: "20" + - version: "22.11.0" + tarball_sha256: "3bd5ee040509a3d3cd9b1ba9520c18e6ec0a7e7981ca68c457dcd36ba3c54d94" + os_matrix: + - os: "debian" + distribution: "trixie" + architectures: + - "amd64" + - "arm64" + + additional_tags: "latest,stable,22" + - version: "23.5.0" + tarball_sha256: "8ed3a237e6d8dff94a09527a83143530b5afcc1aee73fa7b85c069bda507adac" + os_matrix: + - os: "debian" + distribution: "trixie" + architectures: + - "amd64" + - "arm64" + + - os: "debian" + distribution: "forky" + architectures: + - "amd64" + - "arm64" + additional_tags: "experimental" + + additional_tags: "23" metadata: - generated_at: "2026-08-10T20:41:17Z" + generated_at: "2026-09-04T22:08:21Z" supported_os: debian: ["stretch", "jessie", "buster", "bullseye", "bookworm", "trixie", "forky"] supported_architectures: ["amd64", "arm64"] diff --git a/configs/generated/asterisk-20.21.0-trixie.yml b/configs/generated/asterisk-20.21.0-trixie.yml new file mode 100644 index 000000000..043dcde90 --- /dev/null +++ b/configs/generated/asterisk-20.21.0-trixie.yml @@ -0,0 +1,146 @@ +asterisk: + addons: + version: null + configure_options: + - --with-pjproject-bundled + - --with-ssl=ssl + - --with-crypto + menuselect: + apps: + - app_voicemail + - app_queue + - app_confbridge + - app_directory + - app_dial + - app_playback + - app_record + - app_echo + - app_mixmonitor + channels: + - chan_pjsip + - chan_iax2 + - chan_local + - chan_bridge_media + drivers: + - res_musiconhold + - res_pjsip + - res_pjsip_session + - res_pjsip_outbound_registration + - res_pjsip_registrar + - res_rtp_asterisk + - res_timing_timerfd + - res_crypto + exclude: + - chan_dahdi + - chan_misdn + - app_festival + opus_codec: + enabled: true + major_version: 20 + source: + checksum: 13fd6e8f1fbb19a3174af82a388dd72c87eb2c92d32fca83c4d51bfab03f686a + url_template: https://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-{version}.tar.gz +base: + distribution: trixie + image: debian:trixie + os: debian +build: + args: + ASTERISK_VERSION: 20.21.0 + DEBIAN_FRONTEND: noninteractive + script: build-asterisk.sh +docker: + expose_ports: + - 5060/udp + - 5060/tcp + - 10000-20000/udp + registry: docker.io + repository: asterisk + tags: + - 20.21.0_debian-trixie + - 20.21.0_debian-trixie-amd64 + volumes: + - /var/lib/asterisk/sounds + - /var/lib/asterisk/keys + - /var/lib/asterisk/phoneprov + - /var/spool/asterisk + - /var/log/asterisk + - /etc/asterisk +features: + hep: false + pjsip: true + recordings: true + tls: true + websockets: false +packages: + build: + - build-essential + - autoconf + - binutils-dev + - ca-certificates + - curl + - file + - libcurl4-openssl-dev + - libedit-dev + - libgsm1-dev + - libicu-dev + - libjansson-dev + - libncurses-dev + - libogg-dev + - libpopt-dev + - libpqxx-dev + - libresample1-dev + - libspandsp-dev + - libspeex-dev + - libspeexdsp-dev + - libsqlite3-dev + - libssl-dev + - libtool + - libvorbis-dev + - libxml2-dev + - libxslt1-dev + - make + - odbcinst + - patch + - pkg-config + - portaudio19-dev + - procps + - python3-dev + - unixodbc + - unixodbc-dev + - uuid + - uuid-dev + - xmlstarlet + - libsrtp2-dev + runtime: + - binutils + - ca-certificates + - curl + - gettext-base + - libedit2 + - libgsm1 + - libjansson4 + - libogg0 + - libopus0 + - libpopt0 + - libresample1 + - libspandsp2 + - libspeex1 + - libspeexdsp1 + - libsqlite3-0 + - libvorbis0a + - libxml2 + - libxslt1.1 + - odbcinst + - portaudio19-dev + - procps + - python3 + - unixodbc + - uuid + - libcurl4t64 + - libssl3t64 + - libsrtp2-1 + - libncurses6 + - libpqxx-7.10 + - libicu76 +version: 20.21.0 diff --git a/configs/generated/asterisk-22.11.0-trixie.yml b/configs/generated/asterisk-22.11.0-trixie.yml new file mode 100644 index 000000000..2f0801c88 --- /dev/null +++ b/configs/generated/asterisk-22.11.0-trixie.yml @@ -0,0 +1,147 @@ +asterisk: + addons: + version: null + configure_options: + - --with-pjproject-bundled + - --with-ssl=ssl + - --with-crypto + menuselect: + apps: + - app_voicemail + - app_queue + - app_confbridge + - app_directory + - app_dial + - app_playback + - app_record + - app_echo + - app_mixmonitor + channels: + - chan_pjsip + - chan_iax2 + - chan_local + - chan_bridge_media + drivers: + - res_musiconhold + - res_pjsip + - res_pjsip_session + - res_pjsip_outbound_registration + - res_pjsip_registrar + - res_rtp_asterisk + - res_timing_timerfd + - res_crypto + exclude: + - chan_dahdi + - chan_misdn + - app_festival + - chan_sip + opus_codec: + enabled: true + major_version: 22 + source: + checksum: 3bd5ee040509a3d3cd9b1ba9520c18e6ec0a7e7981ca68c457dcd36ba3c54d94 + url_template: https://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-{version}.tar.gz +base: + distribution: trixie + image: debian:trixie + os: debian +build: + args: + ASTERISK_VERSION: 22.11.0 + DEBIAN_FRONTEND: noninteractive + script: build-asterisk.sh +docker: + expose_ports: + - 5060/udp + - 5060/tcp + - 10000-20000/udp + registry: docker.io + repository: asterisk + tags: + - 22.11.0_debian-trixie + - 22.11.0_debian-trixie-amd64 + volumes: + - /var/lib/asterisk/sounds + - /var/lib/asterisk/keys + - /var/lib/asterisk/phoneprov + - /var/spool/asterisk + - /var/log/asterisk + - /etc/asterisk +features: + hep: false + pjsip: true + recordings: true + tls: true + websockets: false +packages: + build: + - build-essential + - autoconf + - binutils-dev + - ca-certificates + - curl + - file + - libcurl4-openssl-dev + - libedit-dev + - libgsm1-dev + - libicu-dev + - libjansson-dev + - libncurses-dev + - libogg-dev + - libpopt-dev + - libpqxx-dev + - libresample1-dev + - libspandsp-dev + - libspeex-dev + - libspeexdsp-dev + - libsqlite3-dev + - libssl-dev + - libtool + - libvorbis-dev + - libxml2-dev + - libxslt1-dev + - make + - odbcinst + - patch + - pkg-config + - portaudio19-dev + - procps + - python3-dev + - unixodbc + - unixodbc-dev + - uuid + - uuid-dev + - xmlstarlet + - libsrtp2-dev + runtime: + - binutils + - ca-certificates + - curl + - gettext-base + - libedit2 + - libgsm1 + - libjansson4 + - libogg0 + - libopus0 + - libpopt0 + - libresample1 + - libspandsp2 + - libspeex1 + - libspeexdsp1 + - libsqlite3-0 + - libvorbis0a + - libxml2 + - libxslt1.1 + - odbcinst + - portaudio19-dev + - procps + - python3 + - unixodbc + - uuid + - libcurl4t64 + - libssl3t64 + - libsrtp2-1 + - libncurses6 + - libpqxx-7.10 + - libicu76 +version: 22.11.0 diff --git a/configs/generated/asterisk-23.5.0-forky.yml b/configs/generated/asterisk-23.5.0-forky.yml new file mode 100644 index 000000000..abe9e81bc --- /dev/null +++ b/configs/generated/asterisk-23.5.0-forky.yml @@ -0,0 +1,129 @@ +asterisk: + addons: + version: null + configure_options: + - --with-pjproject-bundled + - --with-ssl=ssl + - --with-crypto + menuselect: + apps: + - app_voicemail + - app_queue + - app_confbridge + - app_directory + - app_dial + - app_playback + - app_record + - app_echo + - app_mixmonitor + channels: + - chan_pjsip + - chan_iax2 + - chan_local + - chan_bridge_media + - chan_websocket + drivers: + - res_musiconhold + - res_pjsip + - res_pjsip_session + - res_pjsip_outbound_registration + - res_pjsip_registrar + - res_rtp_asterisk + - res_timing_timerfd + - res_crypto + exclude: + - chan_dahdi + - chan_misdn + - app_festival + - chan_sip + opus_codec: + enabled: true + major_version: 23 + source: + checksum: 8ed3a237e6d8dff94a09527a83143530b5afcc1aee73fa7b85c069bda507adac + url_template: https://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-{version}.tar.gz +base: + distribution: forky + image: debian:forky + os: debian + runtime_autoderive: true +build: + args: + ASTERISK_VERSION: 23.5.0 + DEBIAN_FRONTEND: noninteractive + script: build-asterisk.sh +docker: + expose_ports: + - 5060/udp + - 5060/tcp + - 10000-20000/udp + registry: docker.io + repository: asterisk + tags: + - 23.5.0_debian-forky + - 23.5.0_debian-forky-amd64 + volumes: + - /var/lib/asterisk/sounds + - /var/lib/asterisk/keys + - /var/lib/asterisk/phoneprov + - /var/spool/asterisk + - /var/log/asterisk + - /etc/asterisk +features: + hep: false + pjsip: true + recordings: true + tls: true + websockets: true +packages: + build: + - build-essential + - autoconf + - binutils-dev + - ca-certificates + - curl + - file + - libcurl4-openssl-dev + - libedit-dev + - libgsm1-dev + - libicu-dev + - libjansson-dev + - libncurses-dev + - libogg-dev + - libpopt-dev + - libpqxx-dev + - libresample1-dev + - libspandsp-dev + - libspeex-dev + - libspeexdsp-dev + - libsqlite3-dev + - libssl-dev + - libtool + - libvorbis-dev + - libxml2-dev + - libxslt1-dev + - make + - odbcinst + - patch + - pkg-config + - portaudio19-dev + - procps + - python3-dev + - unixodbc + - unixodbc-dev + - uuid + - uuid-dev + - xmlstarlet + - libsrtp2-dev + runtime: + - binutils + - ca-certificates + - curl + - gettext-base + - odbcinst + - portaudio19-dev + - procps + - python3 + - unixodbc + - uuid +version: 23.5.0 diff --git a/configs/generated/asterisk-23.5.0-trixie.yml b/configs/generated/asterisk-23.5.0-trixie.yml new file mode 100644 index 000000000..7d263a575 --- /dev/null +++ b/configs/generated/asterisk-23.5.0-trixie.yml @@ -0,0 +1,148 @@ +asterisk: + addons: + version: null + configure_options: + - --with-pjproject-bundled + - --with-ssl=ssl + - --with-crypto + menuselect: + apps: + - app_voicemail + - app_queue + - app_confbridge + - app_directory + - app_dial + - app_playback + - app_record + - app_echo + - app_mixmonitor + channels: + - chan_pjsip + - chan_iax2 + - chan_local + - chan_bridge_media + - chan_websocket + drivers: + - res_musiconhold + - res_pjsip + - res_pjsip_session + - res_pjsip_outbound_registration + - res_pjsip_registrar + - res_rtp_asterisk + - res_timing_timerfd + - res_crypto + exclude: + - chan_dahdi + - chan_misdn + - app_festival + - chan_sip + opus_codec: + enabled: true + major_version: 23 + source: + checksum: 8ed3a237e6d8dff94a09527a83143530b5afcc1aee73fa7b85c069bda507adac + url_template: https://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-{version}.tar.gz +base: + distribution: trixie + image: debian:trixie + os: debian +build: + args: + ASTERISK_VERSION: 23.5.0 + DEBIAN_FRONTEND: noninteractive + script: build-asterisk.sh +docker: + expose_ports: + - 5060/udp + - 5060/tcp + - 10000-20000/udp + registry: docker.io + repository: asterisk + tags: + - 23.5.0_debian-trixie + - 23.5.0_debian-trixie-amd64 + volumes: + - /var/lib/asterisk/sounds + - /var/lib/asterisk/keys + - /var/lib/asterisk/phoneprov + - /var/spool/asterisk + - /var/log/asterisk + - /etc/asterisk +features: + hep: false + pjsip: true + recordings: true + tls: true + websockets: true +packages: + build: + - build-essential + - autoconf + - binutils-dev + - ca-certificates + - curl + - file + - libcurl4-openssl-dev + - libedit-dev + - libgsm1-dev + - libicu-dev + - libjansson-dev + - libncurses-dev + - libogg-dev + - libpopt-dev + - libpqxx-dev + - libresample1-dev + - libspandsp-dev + - libspeex-dev + - libspeexdsp-dev + - libsqlite3-dev + - libssl-dev + - libtool + - libvorbis-dev + - libxml2-dev + - libxslt1-dev + - make + - odbcinst + - patch + - pkg-config + - portaudio19-dev + - procps + - python3-dev + - unixodbc + - unixodbc-dev + - uuid + - uuid-dev + - xmlstarlet + - libsrtp2-dev + runtime: + - binutils + - ca-certificates + - curl + - gettext-base + - libedit2 + - libgsm1 + - libjansson4 + - libogg0 + - libopus0 + - libpopt0 + - libresample1 + - libspandsp2 + - libspeex1 + - libspeexdsp1 + - libsqlite3-0 + - libvorbis0a + - libxml2 + - libxslt1.1 + - odbcinst + - portaudio19-dev + - procps + - python3 + - unixodbc + - uuid + - libcurl4t64 + - libssl3t64 + - libsrtp2-1 + - libncurses6 + - libpqxx-7.10 + - libicu76 +version: 23.5.0