diff --git a/.env.sample b/.env.sample index 68032c6..d4b188c 100644 --- a/.env.sample +++ b/.env.sample @@ -9,3 +9,18 @@ ICECAST_SOURCE_PASSWORD=changeme ICECAST_ADMIN_PASSWORD=changeme ICECAST_LOCATION=Cyberspace + +##################################################################### +# Icecast mounts # +##################################################################### + +# One mount per line: mount|username|password|max-listeners +# Example: + +# ICECAST_MOUNTS=" +# /radio1|alias1|changeme|100 +# /radio2|alias2|changeme|150 +# /radio3|alias3|changeme|200 +# " + +ICECAST_MOUNTS="" diff --git a/abra.sh b/abra.sh new file mode 100644 index 0000000..a0b4598 --- /dev/null +++ b/abra.sh @@ -0,0 +1 @@ +export ICECAST_ENTRYPOINT_VERSION=v1 diff --git a/compose.yml b/compose.yml index 45bef8b..4ef729b 100644 --- a/compose.yml +++ b/compose.yml @@ -4,6 +4,12 @@ version: "3.8" services: app: image: libretime/icecast:2.5-beta3 + entrypoint: /coopcloud-entrypoint.sh + command: ["icecast", "-c", "/etc/icecast.xml"] + configs: + - source: icecast_entrypoint + target: /coopcloud-entrypoint.sh + mode: 0555 networks: - proxy environment: @@ -11,6 +17,7 @@ services: - ICECAST_SOURCE_PASSWORD - ICECAST_ADMIN_PASSWORD - ICECAST_LOCATION + - ICECAST_MOUNTS deploy: restart_policy: condition: on-failure @@ -43,3 +50,8 @@ services: networks: proxy: external: true + +configs: + icecast_entrypoint: + name: ${STACK_NAME}_icecast_entrypoint_${ICECAST_ENTRYPOINT_VERSION} + file: entrypoint.sh diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..0267768 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,94 @@ +#!/bin/sh + +set -eu + +CONFIG=/etc/icecast.xml +BEGIN_MARKER="" +END_MARKER="" + +xml_escape() { + printf '%s' "$1" | sed \ + -e 's/&/\&/g' \ + -e 's//\>/g' \ + -e 's/"/\"/g' \ + -e "s/'/\'/g" +} + +# Remove mounts generated by a previous run. +awk ' + // { skip=1; next } + // { skip=0; next } + !skip { print } +' "$CONFIG" > /tmp/icecast.xml + +cat /tmp/icecast.xml > "$CONFIG" + +if [ -n "${ICECAST_MOUNTS:-}" ]; then + MOUNTS=/tmp/icecast-mounts.xml + + printf '%s\n' "$BEGIN_MARKER" > "$MOUNTS" + + printf '%s\n' "$ICECAST_MOUNTS" | + while IFS='|' read -r mount username password max_listeners; do + [ -z "$mount" ] && continue + + case "$mount" in + \#*) continue ;; + /*) ;; + *) + echo "Invalid Icecast mount: $mount must start with /" >&2 + exit 1 + ;; + esac + + if [ -z "$username" ]; then + echo "Invalid Icecast mount $mount: username is required" >&2 + exit 1 + fi + + if [ -z "$password" ]; then + echo "Invalid Icecast mount $mount: password is required" >&2 + exit 1 + fi + + case "$max_listeners" in + ''|*[!0-9]*) + echo "Invalid max-listeners for $mount: $max_listeners" >&2 + exit 1 + ;; + esac + + mount=$(xml_escape "$mount") + username=$(xml_escape "$username") + password=$(xml_escape "$password") + max_listeners=$(xml_escape "$max_listeners") + + cat >> "$MOUNTS" < + ${mount} + ${username} + ${password} + ${max_listeners} + + + + +MOUNT + done + + printf '%s\n' "$END_MARKER" >> "$MOUNTS" + + awk ' + /<\/icecast>/ { + while ((getline line < "/tmp/icecast-mounts.xml") > 0) + print line + close("/tmp/icecast-mounts.xml") + } + { print } + ' "$CONFIG" > /tmp/icecast.xml + + cat /tmp/icecast.xml > "$CONFIG" +fi + +exec /usr/local/bin/docker-entrypoint "$@"