|
| 1 | +#!/bin/sh |
| 2 | + |
| 3 | +set -eu |
| 4 | + |
| 5 | +compose_project() { |
| 6 | + docker inspect --format '{{ index .Config.Labels "com.docker.compose.project" }}' "$(hostname)" |
| 7 | +} |
| 8 | + |
| 9 | +project="$(compose_project)" |
| 10 | +if [ -z "$project" ]; then |
| 11 | + echo 'Could not determine the Compose project from the selector container.' >&2 |
| 12 | + exit 1 |
| 13 | +fi |
| 14 | + |
| 15 | +if [ -z "${PROJECT_DIR:-}" ]; then |
| 16 | + echo 'The host project directory was not provided to the selector.' >&2 |
| 17 | + exit 1 |
| 18 | +fi |
| 19 | + |
| 20 | +compose() { |
| 21 | + docker compose \ |
| 22 | + --project-name "$project" \ |
| 23 | + --project-directory "$PROJECT_DIR" \ |
| 24 | + --file "$PROJECT_DIR/docker-compose.yml" \ |
| 25 | + "$@" |
| 26 | +} |
| 27 | + |
| 28 | +echo "Validating Compose project ${project} at ${PROJECT_DIR}." |
| 29 | +compose config --quiet |
| 30 | + |
| 31 | +cleanup_nginx() { |
| 32 | + compose rm --force --stop nginx || true |
| 33 | +} |
| 34 | + |
| 35 | +trap cleanup_nginx INT TERM |
| 36 | + |
| 37 | +start_nginx() { |
| 38 | + HTTP_PORT="$1" HTTPS_PORT="$2" IP_BIND="${IP_BIND:-127.0.0.1}" \ |
| 39 | + compose up --detach --no-deps --scale nginx=1 nginx |
| 40 | +} |
| 41 | + |
| 42 | +published_port() { |
| 43 | + mapping="$(compose port "$1" "$2" 2>/dev/null || true)" |
| 44 | + [ -n "$mapping" ] || return 0 |
| 45 | + printf '%s\n' "${mapping##*:}" |
| 46 | +} |
| 47 | + |
| 48 | +report_environment_ready() { |
| 49 | + selector_http_port="$1" |
| 50 | + selector_https_port="$2" |
| 51 | + mailpit_port="$(published_port mailpit 8025)" |
| 52 | + eurooffice_port="$(published_port eurooffice 80)" |
| 53 | + playwright_port="$(published_port playwright 9323)" |
| 54 | + signal_port="$(published_port signal-gateway 8080)" |
| 55 | + |
| 56 | + compose exec -T \ |
| 57 | + -e ENV_HTTP_PORT="$selector_http_port" \ |
| 58 | + -e ENV_HTTPS_PORT="$selector_https_port" \ |
| 59 | + -e ENV_MAILPIT_PORT="$mailpit_port" \ |
| 60 | + -e ENV_EUROOFFICE_PORT="$eurooffice_port" \ |
| 61 | + -e ENV_PLAYWRIGHT_PORT="$playwright_port" \ |
| 62 | + -e ENV_SIGNAL_PORT="$signal_port" \ |
| 63 | + -e ENV_ADMIN_USER="$NEXTCLOUD_ADMIN_USER" \ |
| 64 | + -e ENV_ADMIN_PASSWORD="$NEXTCLOUD_ADMIN_PASSWORD" \ |
| 65 | + -e ENV_NEXTCLOUD_BRANCH="$VERSION_NEXTCLOUD" \ |
| 66 | + nextcloud sh /var/www/scripts/report-environment-ready |
| 67 | +} |
| 68 | + |
| 69 | +exit_successfully() { |
| 70 | + echo '✅ Port selection complete. Exiting normally.' |
| 71 | + exit 0 |
| 72 | +} |
| 73 | + |
| 74 | +if [ "${HTTP_PORT+x}" = x ] || [ "${HTTPS_PORT+x}" = x ]; then |
| 75 | + echo "Explicit ports requested: HTTP ${HTTP_PORT:-80}, HTTPS ${HTTPS_PORT:-443}." |
| 76 | + set +e |
| 77 | + output="$(start_nginx "${HTTP_PORT:-80}" "${HTTPS_PORT:-443}" 2>&1)" |
| 78 | + status=$? |
| 79 | + set -e |
| 80 | + printf '%s\n' "$output" |
| 81 | + if [ "$status" -ne 0 ]; then |
| 82 | + cleanup_nginx |
| 83 | + exit "$status" |
| 84 | + fi |
| 85 | + echo 'nginx started with explicit ports.' |
| 86 | + if ! report_environment_ready "${HTTP_PORT:-80}" "${HTTPS_PORT:-443}"; then |
| 87 | + echo 'Could not print environment banner.' >&2 |
| 88 | + fi |
| 89 | + exit_successfully |
| 90 | +fi |
| 91 | + |
| 92 | +offset=0 |
| 93 | +while [ "$offset" -le 19 ]; do |
| 94 | + http_port=$((80 + offset)) |
| 95 | + https_port=$((443 + offset)) |
| 96 | + echo "Trying nginx ports HTTP ${http_port} / HTTPS ${https_port}." |
| 97 | + |
| 98 | + set +e |
| 99 | + output="$(start_nginx "$http_port" "$https_port" 2>&1)" |
| 100 | + status=$? |
| 101 | + set -e |
| 102 | + printf '%s\n' "$output" |
| 103 | + |
| 104 | + if [ "$status" -eq 0 ]; then |
| 105 | + echo "nginx started with HTTP ${http_port} / HTTPS ${https_port}." |
| 106 | + if ! report_environment_ready "$http_port" "$https_port"; then |
| 107 | + echo 'Could not print environment banner.' >&2 |
| 108 | + fi |
| 109 | + exit_successfully |
| 110 | + fi |
| 111 | + |
| 112 | + if ! printf '%s\n' "$output" | grep -Eiq \ |
| 113 | + 'address already in use|port is already allocated|port is already in use|failed to bind host port|cannot bind .* port'; then |
| 114 | + echo 'nginx failed for a reason unrelated to a port conflict; stopping.' >&2 |
| 115 | + cleanup_nginx |
| 116 | + exit "$status" |
| 117 | + fi |
| 118 | + |
| 119 | + echo "Ports ${http_port}/${https_port} are unavailable; trying the next pair." >&2 |
| 120 | + cleanup_nginx |
| 121 | + offset=$((offset + 1)) |
| 122 | +done |
| 123 | + |
| 124 | +echo 'No available nginx port pair found in HTTP 80-99 / HTTPS 443-462.' >&2 |
| 125 | +exit 1 |
0 commit comments