diff --git a/asterisk/14.7.8-alpine-3.24/Dockerfile b/asterisk/14.7.8-alpine-3.24/Dockerfile new file mode 100644 index 000000000..a5c6ccd59 --- /dev/null +++ b/asterisk/14.7.8-alpine-3.24/Dockerfile @@ -0,0 +1,92 @@ +# Alpine Asterisk image - installs prebuilt, signed apks from the sibling +# project's Cloudsmith repository (andrius/asterisk-alpine). There is no build +# stage: the .apk already contains the compiled, module-selected Asterisk. +# Generated from YAML configuration - DO NOT EDIT MANUALLY +FROM alpine:3.24 + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX" +LABEL org.opencontainers.image.description="Asterisk PBX 14.7.8 on Alpine (apk)" +LABEL org.opencontainers.image.version="14.7.8" +LABEL org.opencontainers.image.source="https://github.com/andrius/asterisk" +LABEL org.opencontainers.image.vendor="Andrius Kairiukstis " + +# Trust the Cloudsmith repository signing key (vendored; copied into the build +# context alongside this Dockerfile). +COPY cloudsmith-asterisk-alpine.rsa.pub /etc/apk/keys/alpine@asterisk-25B0C9A992BE0CEF.rsa.pub + +# Add the pinned apk repository and install Asterisk + the selected subpackages +# at an exact version, plus the runtime tools the entrypoint/healthcheck need. +# The @andrius-asterisk tag keeps these from clashing with Alpine's own +# asterisk in the main repo; the exact "=version-rN" pin makes rebuilds +# reproducible (or fail loudly if the apk was pruned). +RUN echo "@andrius-asterisk https://dl.cloudsmith.io/public/asterisk/alpine/alpine/v3.24/main" >>/etc/apk/repositories \ + && apk add --no-cache \ + "asterisk@andrius-asterisk=14.7.8-r0" \ + "asterisk-sample-config@andrius-asterisk=14.7.8-r0" \ + "asterisk-opus@andrius-asterisk=14.7.8-r0" \ + "asterisk-srtp@andrius-asterisk=14.7.8-r0" \ + "asterisk-curl@andrius-asterisk=14.7.8-r0" \ + "asterisk-speex@andrius-asterisk=14.7.8-r0" \ + "asterisk-fax@andrius-asterisk=14.7.8-r0" \ + "asterisk-odbc@andrius-asterisk=14.7.8-r0" \ + "asterisk-mobile@andrius-asterisk=14.7.8-r0" \ + "asterisk-tds@andrius-asterisk=14.7.8-r0" \ + bash \ + shadow \ + gettext \ + procps \ + ca-certificates \ + curl \ + tzdata \ + && asterisk -V + +# The asterisk apk creates the asterisk user (uid 100, home /var/lib/asterisk). +# Normalize it to the Debian image's identity (uid/gid 1000, home +# /home/asterisk, bash shell) so both image families behave identically and +# cloud/orchestration setups see a consistent uid. The entrypoint's PUID/PGID +# remap then no-ops on the default, exactly as on Debian. +RUN groupmod -g 1000 asterisk \ + && usermod -u 1000 -g 1000 -d /home/asterisk -s /bin/bash asterisk \ + && mkdir -p \ + /home/asterisk \ + /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 + +# Healthcheck + entrypoint (the shared bash partials; bash + shadow are +# installed above so usermod/groupmod PUID/PGID remap works unchanged). +COPY healthcheck.sh /usr/local/bin/healthcheck.sh +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/healthcheck.sh /usr/local/bin/entrypoint.sh \ + && chown -R asterisk:asterisk \ + /etc/asterisk \ + /home/asterisk \ + /var/lib/asterisk \ + /var/log/asterisk \ + /var/spool/asterisk \ + /var/run/asterisk \ + && chmod -R 750 /var/spool/asterisk + +# Networking (documented; publish explicitly at run time). +# EXPOSE 5060/udp +# EXPOSE 5060/tcp +# EXPOSE 10000-20000/udp +VOLUME ["/var/lib/asterisk/sounds", "/var/lib/asterisk/keys", "/var/lib/asterisk/phoneprov", "/var/spool/asterisk", "/var/log/asterisk", "/etc/asterisk"] +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ + CMD /usr/local/bin/healthcheck.sh + +# Entrypoint runs as root, remaps the asterisk uid/gid to PUID/PGID, then execs +# CMD. Asterisk drops privileges itself via the -U/-p flags below. +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] +WORKDIR /home/asterisk +CMD ["/usr/sbin/asterisk", "-vvvdddf", "-T", "-W", "-U", "asterisk", "-p"] diff --git a/asterisk/14.7.8-alpine-3.24/cloudsmith-asterisk-alpine.rsa.pub b/asterisk/14.7.8-alpine-3.24/cloudsmith-asterisk-alpine.rsa.pub new file mode 100644 index 000000000..c34e63730 --- /dev/null +++ b/asterisk/14.7.8-alpine-3.24/cloudsmith-asterisk-alpine.rsa.pub @@ -0,0 +1,11 @@ +-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAu5GYPGV/b1+giz7rgDN6 +bkeFqT8zMHBzJ051SdVT4MbF/A6ap0hyhHDKc3o2T06Ete/vde2DjZj+RUKP1bP+ +Ywamb6waQqAJsGDJ86tSsJ6eklX8N88j9Mggyx3WXu6JGrigY6i0u/7QUMXV9KAL +E2r902YoqZHn6F8FITD2VXB9NwIyMfiLsGnTmLkehhrVPupx9Qdo3URtCagYbYMh +hIScUGr1i1LKQaTSgyOCCF9sdReJuj2OT8BUuBWmIxWg4nxmx8rndllUMseYEG/q +M7dYMjLNShL6u4WNMb0hwKaYKHy69PtVBSUnLu0Y3rrH2oLo/B4XGyyX7jGw3pjx +rq1bHE2nkgGV3OjXE/ZT7oLDYZtriZHYEEdBJwFr1SHyevOlcsNqdkiskwpE/TH4 +dxnIhMYJ8LYw1o5OQV6oSGpV/Mk3aYvMKyc00hZ8PjfWQkgxrkpQ4HRymp74bB1Z +M6AAzp1WcmZ3lR5ZLhAClXbwSetLrXACavIS07clOoNXAgMBAAE= +-----END PUBLIC KEY----- diff --git a/asterisk/14.7.8-alpine-3.24/entrypoint.sh b/asterisk/14.7.8-alpine-3.24/entrypoint.sh new file mode 100755 index 000000000..7a46e26d8 --- /dev/null +++ b/asterisk/14.7.8-alpine-3.24/entrypoint.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Asterisk container entrypoint +# Generated from template for 14.7.8 +# +# 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/14.7.8-alpine-3.24/healthcheck.sh b/asterisk/14.7.8-alpine-3.24/healthcheck.sh new file mode 100755 index 000000000..659867ea0 --- /dev/null +++ b/asterisk/14.7.8-alpine-3.24/healthcheck.sh @@ -0,0 +1,159 @@ +#!/bin/bash +# Asterisk health check script +# Generated from template for 14.7.8 + +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/16.30.1-alpine-3.24/Dockerfile b/asterisk/16.30.1-alpine-3.24/Dockerfile new file mode 100644 index 000000000..6e3ebe5c8 --- /dev/null +++ b/asterisk/16.30.1-alpine-3.24/Dockerfile @@ -0,0 +1,92 @@ +# Alpine Asterisk image - installs prebuilt, signed apks from the sibling +# project's Cloudsmith repository (andrius/asterisk-alpine). There is no build +# stage: the .apk already contains the compiled, module-selected Asterisk. +# Generated from YAML configuration - DO NOT EDIT MANUALLY +FROM alpine:3.24 + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX" +LABEL org.opencontainers.image.description="Asterisk PBX 16.30.1 on Alpine (apk)" +LABEL org.opencontainers.image.version="16.30.1" +LABEL org.opencontainers.image.source="https://github.com/andrius/asterisk" +LABEL org.opencontainers.image.vendor="Andrius Kairiukstis " + +# Trust the Cloudsmith repository signing key (vendored; copied into the build +# context alongside this Dockerfile). +COPY cloudsmith-asterisk-alpine.rsa.pub /etc/apk/keys/alpine@asterisk-25B0C9A992BE0CEF.rsa.pub + +# Add the pinned apk repository and install Asterisk + the selected subpackages +# at an exact version, plus the runtime tools the entrypoint/healthcheck need. +# The @andrius-asterisk tag keeps these from clashing with Alpine's own +# asterisk in the main repo; the exact "=version-rN" pin makes rebuilds +# reproducible (or fail loudly if the apk was pruned). +RUN echo "@andrius-asterisk https://dl.cloudsmith.io/public/asterisk/alpine/alpine/v3.24/main" >>/etc/apk/repositories \ + && apk add --no-cache \ + "asterisk@andrius-asterisk=16.30.1-r0" \ + "asterisk-sample-config@andrius-asterisk=16.30.1-r0" \ + "asterisk-opus@andrius-asterisk=16.30.1-r0" \ + "asterisk-srtp@andrius-asterisk=16.30.1-r0" \ + "asterisk-curl@andrius-asterisk=16.30.1-r0" \ + "asterisk-speex@andrius-asterisk=16.30.1-r0" \ + "asterisk-fax@andrius-asterisk=16.30.1-r0" \ + "asterisk-odbc@andrius-asterisk=16.30.1-r0" \ + "asterisk-mobile@andrius-asterisk=16.30.1-r0" \ + "asterisk-tds@andrius-asterisk=16.30.1-r0" \ + bash \ + shadow \ + gettext \ + procps \ + ca-certificates \ + curl \ + tzdata \ + && asterisk -V + +# The asterisk apk creates the asterisk user (uid 100, home /var/lib/asterisk). +# Normalize it to the Debian image's identity (uid/gid 1000, home +# /home/asterisk, bash shell) so both image families behave identically and +# cloud/orchestration setups see a consistent uid. The entrypoint's PUID/PGID +# remap then no-ops on the default, exactly as on Debian. +RUN groupmod -g 1000 asterisk \ + && usermod -u 1000 -g 1000 -d /home/asterisk -s /bin/bash asterisk \ + && mkdir -p \ + /home/asterisk \ + /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 + +# Healthcheck + entrypoint (the shared bash partials; bash + shadow are +# installed above so usermod/groupmod PUID/PGID remap works unchanged). +COPY healthcheck.sh /usr/local/bin/healthcheck.sh +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/healthcheck.sh /usr/local/bin/entrypoint.sh \ + && chown -R asterisk:asterisk \ + /etc/asterisk \ + /home/asterisk \ + /var/lib/asterisk \ + /var/log/asterisk \ + /var/spool/asterisk \ + /var/run/asterisk \ + && chmod -R 750 /var/spool/asterisk + +# Networking (documented; publish explicitly at run time). +# EXPOSE 5060/udp +# EXPOSE 5060/tcp +# EXPOSE 10000-20000/udp +VOLUME ["/var/lib/asterisk/sounds", "/var/lib/asterisk/keys", "/var/lib/asterisk/phoneprov", "/var/spool/asterisk", "/var/log/asterisk", "/etc/asterisk"] +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ + CMD /usr/local/bin/healthcheck.sh + +# Entrypoint runs as root, remaps the asterisk uid/gid to PUID/PGID, then execs +# CMD. Asterisk drops privileges itself via the -U/-p flags below. +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] +WORKDIR /home/asterisk +CMD ["/usr/sbin/asterisk", "-vvvdddf", "-T", "-W", "-U", "asterisk", "-p"] diff --git a/asterisk/16.30.1-alpine-3.24/cloudsmith-asterisk-alpine.rsa.pub b/asterisk/16.30.1-alpine-3.24/cloudsmith-asterisk-alpine.rsa.pub new file mode 100644 index 000000000..c34e63730 --- /dev/null +++ b/asterisk/16.30.1-alpine-3.24/cloudsmith-asterisk-alpine.rsa.pub @@ -0,0 +1,11 @@ +-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAu5GYPGV/b1+giz7rgDN6 +bkeFqT8zMHBzJ051SdVT4MbF/A6ap0hyhHDKc3o2T06Ete/vde2DjZj+RUKP1bP+ +Ywamb6waQqAJsGDJ86tSsJ6eklX8N88j9Mggyx3WXu6JGrigY6i0u/7QUMXV9KAL +E2r902YoqZHn6F8FITD2VXB9NwIyMfiLsGnTmLkehhrVPupx9Qdo3URtCagYbYMh +hIScUGr1i1LKQaTSgyOCCF9sdReJuj2OT8BUuBWmIxWg4nxmx8rndllUMseYEG/q +M7dYMjLNShL6u4WNMb0hwKaYKHy69PtVBSUnLu0Y3rrH2oLo/B4XGyyX7jGw3pjx +rq1bHE2nkgGV3OjXE/ZT7oLDYZtriZHYEEdBJwFr1SHyevOlcsNqdkiskwpE/TH4 +dxnIhMYJ8LYw1o5OQV6oSGpV/Mk3aYvMKyc00hZ8PjfWQkgxrkpQ4HRymp74bB1Z +M6AAzp1WcmZ3lR5ZLhAClXbwSetLrXACavIS07clOoNXAgMBAAE= +-----END PUBLIC KEY----- diff --git a/asterisk/16.30.1-alpine-3.24/entrypoint.sh b/asterisk/16.30.1-alpine-3.24/entrypoint.sh new file mode 100755 index 000000000..bf517cf42 --- /dev/null +++ b/asterisk/16.30.1-alpine-3.24/entrypoint.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Asterisk container entrypoint +# Generated from template for 16.30.1 +# +# 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/16.30.1-alpine-3.24/healthcheck.sh b/asterisk/16.30.1-alpine-3.24/healthcheck.sh new file mode 100755 index 000000000..afd879fe3 --- /dev/null +++ b/asterisk/16.30.1-alpine-3.24/healthcheck.sh @@ -0,0 +1,159 @@ +#!/bin/bash +# Asterisk health check script +# Generated from template for 16.30.1 + +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/18.26.4-alpine-3.24/Dockerfile b/asterisk/18.26.4-alpine-3.24/Dockerfile new file mode 100644 index 000000000..da6d562f1 --- /dev/null +++ b/asterisk/18.26.4-alpine-3.24/Dockerfile @@ -0,0 +1,92 @@ +# Alpine Asterisk image - installs prebuilt, signed apks from the sibling +# project's Cloudsmith repository (andrius/asterisk-alpine). There is no build +# stage: the .apk already contains the compiled, module-selected Asterisk. +# Generated from YAML configuration - DO NOT EDIT MANUALLY +FROM alpine:3.24 + +LABEL maintainer="Andrius Kairiukstis " +LABEL org.opencontainers.image.title="Asterisk PBX" +LABEL org.opencontainers.image.description="Asterisk PBX 18.26.4 on Alpine (apk)" +LABEL org.opencontainers.image.version="18.26.4" +LABEL org.opencontainers.image.source="https://github.com/andrius/asterisk" +LABEL org.opencontainers.image.vendor="Andrius Kairiukstis " + +# Trust the Cloudsmith repository signing key (vendored; copied into the build +# context alongside this Dockerfile). +COPY cloudsmith-asterisk-alpine.rsa.pub /etc/apk/keys/alpine@asterisk-25B0C9A992BE0CEF.rsa.pub + +# Add the pinned apk repository and install Asterisk + the selected subpackages +# at an exact version, plus the runtime tools the entrypoint/healthcheck need. +# The @andrius-asterisk tag keeps these from clashing with Alpine's own +# asterisk in the main repo; the exact "=version-rN" pin makes rebuilds +# reproducible (or fail loudly if the apk was pruned). +RUN echo "@andrius-asterisk https://dl.cloudsmith.io/public/asterisk/alpine/alpine/v3.24/main" >>/etc/apk/repositories \ + && apk add --no-cache \ + "asterisk@andrius-asterisk=18.26.4-r0" \ + "asterisk-sample-config@andrius-asterisk=18.26.4-r0" \ + "asterisk-opus@andrius-asterisk=18.26.4-r0" \ + "asterisk-srtp@andrius-asterisk=18.26.4-r0" \ + "asterisk-curl@andrius-asterisk=18.26.4-r0" \ + "asterisk-speex@andrius-asterisk=18.26.4-r0" \ + "asterisk-fax@andrius-asterisk=18.26.4-r0" \ + "asterisk-odbc@andrius-asterisk=18.26.4-r0" \ + "asterisk-mobile@andrius-asterisk=18.26.4-r0" \ + "asterisk-tds@andrius-asterisk=18.26.4-r0" \ + bash \ + shadow \ + gettext \ + procps \ + ca-certificates \ + curl \ + tzdata \ + && asterisk -V + +# The asterisk apk creates the asterisk user (uid 100, home /var/lib/asterisk). +# Normalize it to the Debian image's identity (uid/gid 1000, home +# /home/asterisk, bash shell) so both image families behave identically and +# cloud/orchestration setups see a consistent uid. The entrypoint's PUID/PGID +# remap then no-ops on the default, exactly as on Debian. +RUN groupmod -g 1000 asterisk \ + && usermod -u 1000 -g 1000 -d /home/asterisk -s /bin/bash asterisk \ + && mkdir -p \ + /home/asterisk \ + /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 + +# Healthcheck + entrypoint (the shared bash partials; bash + shadow are +# installed above so usermod/groupmod PUID/PGID remap works unchanged). +COPY healthcheck.sh /usr/local/bin/healthcheck.sh +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod +x /usr/local/bin/healthcheck.sh /usr/local/bin/entrypoint.sh \ + && chown -R asterisk:asterisk \ + /etc/asterisk \ + /home/asterisk \ + /var/lib/asterisk \ + /var/log/asterisk \ + /var/spool/asterisk \ + /var/run/asterisk \ + && chmod -R 750 /var/spool/asterisk + +# Networking (documented; publish explicitly at run time). +# EXPOSE 5060/udp +# EXPOSE 5060/tcp +# EXPOSE 10000-20000/udp +VOLUME ["/var/lib/asterisk/sounds", "/var/lib/asterisk/keys", "/var/lib/asterisk/phoneprov", "/var/spool/asterisk", "/var/log/asterisk", "/etc/asterisk"] +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ + CMD /usr/local/bin/healthcheck.sh + +# Entrypoint runs as root, remaps the asterisk uid/gid to PUID/PGID, then execs +# CMD. Asterisk drops privileges itself via the -U/-p flags below. +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] +WORKDIR /home/asterisk +CMD ["/usr/sbin/asterisk", "-vvvdddf", "-T", "-W", "-U", "asterisk", "-p"] diff --git a/asterisk/18.26.4-alpine-3.24/cloudsmith-asterisk-alpine.rsa.pub b/asterisk/18.26.4-alpine-3.24/cloudsmith-asterisk-alpine.rsa.pub new file mode 100644 index 000000000..c34e63730 --- /dev/null +++ b/asterisk/18.26.4-alpine-3.24/cloudsmith-asterisk-alpine.rsa.pub @@ -0,0 +1,11 @@ +-----BEGIN PUBLIC KEY----- +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAu5GYPGV/b1+giz7rgDN6 +bkeFqT8zMHBzJ051SdVT4MbF/A6ap0hyhHDKc3o2T06Ete/vde2DjZj+RUKP1bP+ +Ywamb6waQqAJsGDJ86tSsJ6eklX8N88j9Mggyx3WXu6JGrigY6i0u/7QUMXV9KAL +E2r902YoqZHn6F8FITD2VXB9NwIyMfiLsGnTmLkehhrVPupx9Qdo3URtCagYbYMh +hIScUGr1i1LKQaTSgyOCCF9sdReJuj2OT8BUuBWmIxWg4nxmx8rndllUMseYEG/q +M7dYMjLNShL6u4WNMb0hwKaYKHy69PtVBSUnLu0Y3rrH2oLo/B4XGyyX7jGw3pjx +rq1bHE2nkgGV3OjXE/ZT7oLDYZtriZHYEEdBJwFr1SHyevOlcsNqdkiskwpE/TH4 +dxnIhMYJ8LYw1o5OQV6oSGpV/Mk3aYvMKyc00hZ8PjfWQkgxrkpQ4HRymp74bB1Z +M6AAzp1WcmZ3lR5ZLhAClXbwSetLrXACavIS07clOoNXAgMBAAE= +-----END PUBLIC KEY----- diff --git a/asterisk/18.26.4-alpine-3.24/entrypoint.sh b/asterisk/18.26.4-alpine-3.24/entrypoint.sh new file mode 100755 index 000000000..886beecdf --- /dev/null +++ b/asterisk/18.26.4-alpine-3.24/entrypoint.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Asterisk container entrypoint +# Generated from template for 18.26.4 +# +# 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/18.26.4-alpine-3.24/healthcheck.sh b/asterisk/18.26.4-alpine-3.24/healthcheck.sh new file mode 100755 index 000000000..68a01c4a0 --- /dev/null +++ b/asterisk/18.26.4-alpine-3.24/healthcheck.sh @@ -0,0 +1,159 @@ +#!/bin/bash +# Asterisk health check script +# Generated from template for 18.26.4 + +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/supported-asterisk-builds.yml b/asterisk/supported-asterisk-builds.yml index b9088aeef..96b6ed43e 100644 --- a/asterisk/supported-asterisk-builds.yml +++ b/asterisk/supported-asterisk-builds.yml @@ -23,7 +23,7 @@ latest_builds: distribution: "edge" alpine_tree: "edge" alpine_role: "edge" - apk_version: "24.0.0_git20260716-r0" + apk_version: "24.0.0_git20260720-r0" apk_packages: ["srtp", "curl", "speex", "fax", "odbc", "ldap", "pgsql", "prometheus", "mobile", "tds"] architectures: - "amd64" @@ -151,6 +151,14 @@ latest_builds: architectures: - "amd64" + - os: "alpine" + distribution: "3.24" + alpine_tree: "v3.24" + alpine_role: "stable" + apk_version: "14.7.8-r0" + apk_packages: ["opus", "srtp", "curl", "speex", "fax", "odbc", "mobile", "tds"] + architectures: + - "amd64" tarball_sha256: "3de8b119c3acacc4b54a1fe6cd7b49929394187f19288c684f9ca510826839a1" - version: "15.7.4" additional_tags: "15" @@ -169,6 +177,15 @@ latest_builds: architectures: - "amd64" + - os: "alpine" + distribution: "3.24" + alpine_tree: "v3.24" + alpine_role: "stable" + apk_version: "16.30.1-r0" + apk_packages: ["opus", "srtp", "curl", "speex", "fax", "odbc", "mobile", "tds"] + architectures: + - "amd64" + - "arm64" tarball_sha256: "8a91b0f8412d8e3dbd7172c118c52ba4ed4e016696f2778a466db094ec4b8b22" - version: "16.8-cert14" additional_tags: "16-cert" @@ -208,6 +225,15 @@ latest_builds: architectures: - "amd64" + - os: "alpine" + distribution: "3.24" + alpine_tree: "v3.24" + alpine_role: "stable" + apk_version: "18.26.4-r0" + apk_packages: ["opus", "srtp", "curl", "speex", "fax", "odbc", "mobile", "tds"] + architectures: + - "amd64" + - "arm64" tarball_sha256: "a17f511bfa092c8fa9eccd3a5ecf5f728ccdcf2b1a04d2c06e7177d96c3c9ee1" - version: "19.8.1" additional_tags: "19" @@ -504,6 +530,8 @@ latest_builds: architectures: - "amd64" - "arm64" + - "armv7" + - "armhf" - os: "alpine" distribution: "edge" alpine_tree: "edge" @@ -532,6 +560,8 @@ latest_builds: architectures: - "amd64" - "arm64" + - "armv7" + - "armhf" additional_tags: "22-cert" tarball_sha256: "061a4fd3ddd67a553d67c3cf4c2027cec640dd44f2a4e3f1a1765dc8269fcdd2" - version: "23.4.1" @@ -558,6 +588,8 @@ latest_builds: architectures: - "amd64" - "arm64" + - "armv7" + - "armhf" - os: "alpine" distribution: "edge" alpine_tree: "edge" diff --git a/configs/generated/asterisk-14.7.8-alpine-3.24.yml b/configs/generated/asterisk-14.7.8-alpine-3.24.yml new file mode 100644 index 000000000..5744bf0fd --- /dev/null +++ b/configs/generated/asterisk-14.7.8-alpine-3.24.yml @@ -0,0 +1,52 @@ +asterisk: {} +base: + distribution: '3.24' + image: alpine:3.24 + os: alpine +build: + type: single-stage +docker: + expose_ports: + - 5060/udp + - 5060/tcp + - 10000-20000/udp + registry: docker.io + repository: asterisk + tags: + - 14.7.8_alpine-3.24 + - 14.7.8_alpine-3.24-amd64 + volumes: + - /var/lib/asterisk/sounds + - /var/lib/asterisk/keys + - /var/lib/asterisk/phoneprov + - /var/spool/asterisk + - /var/log/asterisk + - /etc/asterisk +packages: + build: [] + runtime: [] +version: 14.7.8 +alpine: + tree: v3.24 + repo_url: https://dl.cloudsmith.io/public/asterisk/alpine/alpine/v3.24/main + pin_tag: andrius-asterisk + signing_key_file: cloudsmith-asterisk-alpine.rsa.pub + signing_key_dest: /etc/apk/keys/alpine@asterisk-25B0C9A992BE0CEF.rsa.pub + runtime_packages: + - bash + - shadow + - gettext + - procps + - ca-certificates + - curl + - tzdata + apk_packages: + - opus + - srtp + - curl + - speex + - fax + - odbc + - mobile + - tds + apk_version: 14.7.8-r0 diff --git a/configs/generated/asterisk-16.30.1-alpine-3.24.yml b/configs/generated/asterisk-16.30.1-alpine-3.24.yml new file mode 100644 index 000000000..5602dcfd9 --- /dev/null +++ b/configs/generated/asterisk-16.30.1-alpine-3.24.yml @@ -0,0 +1,52 @@ +asterisk: {} +base: + distribution: '3.24' + image: alpine:3.24 + os: alpine +build: + type: single-stage +docker: + expose_ports: + - 5060/udp + - 5060/tcp + - 10000-20000/udp + registry: docker.io + repository: asterisk + tags: + - 16.30.1_alpine-3.24 + - 16.30.1_alpine-3.24-amd64 + volumes: + - /var/lib/asterisk/sounds + - /var/lib/asterisk/keys + - /var/lib/asterisk/phoneprov + - /var/spool/asterisk + - /var/log/asterisk + - /etc/asterisk +packages: + build: [] + runtime: [] +version: 16.30.1 +alpine: + tree: v3.24 + repo_url: https://dl.cloudsmith.io/public/asterisk/alpine/alpine/v3.24/main + pin_tag: andrius-asterisk + signing_key_file: cloudsmith-asterisk-alpine.rsa.pub + signing_key_dest: /etc/apk/keys/alpine@asterisk-25B0C9A992BE0CEF.rsa.pub + runtime_packages: + - bash + - shadow + - gettext + - procps + - ca-certificates + - curl + - tzdata + apk_packages: + - opus + - srtp + - curl + - speex + - fax + - odbc + - mobile + - tds + apk_version: 16.30.1-r0 diff --git a/configs/generated/asterisk-18.26.4-alpine-3.24.yml b/configs/generated/asterisk-18.26.4-alpine-3.24.yml new file mode 100644 index 000000000..122a30c09 --- /dev/null +++ b/configs/generated/asterisk-18.26.4-alpine-3.24.yml @@ -0,0 +1,52 @@ +asterisk: {} +base: + distribution: '3.24' + image: alpine:3.24 + os: alpine +build: + type: single-stage +docker: + expose_ports: + - 5060/udp + - 5060/tcp + - 10000-20000/udp + registry: docker.io + repository: asterisk + tags: + - 18.26.4_alpine-3.24 + - 18.26.4_alpine-3.24-amd64 + volumes: + - /var/lib/asterisk/sounds + - /var/lib/asterisk/keys + - /var/lib/asterisk/phoneprov + - /var/spool/asterisk + - /var/log/asterisk + - /etc/asterisk +packages: + build: [] + runtime: [] +version: 18.26.4 +alpine: + tree: v3.24 + repo_url: https://dl.cloudsmith.io/public/asterisk/alpine/alpine/v3.24/main + pin_tag: andrius-asterisk + signing_key_file: cloudsmith-asterisk-alpine.rsa.pub + signing_key_dest: /etc/apk/keys/alpine@asterisk-25B0C9A992BE0CEF.rsa.pub + runtime_packages: + - bash + - shadow + - gettext + - procps + - ca-certificates + - curl + - tzdata + apk_packages: + - opus + - srtp + - curl + - speex + - fax + - odbc + - mobile + - tds + apk_version: 18.26.4-r0