#!/bin/sh set -eu origin="${APP_PUBLIC_BASE_URL:-}" case "$origin" in http://*|https://*) ;; *) echo "APP_PUBLIC_BASE_URL must be an HTTP(S) origin." >&2; exit 1 ;; esac authority="${origin#*://}" authority="${authority%/}" case "$authority" in ""|*/*|*\?*|*\#*|*@*) echo "APP_PUBLIC_BASE_URL must not contain credentials, a path, query, or fragment." >&2; exit 1 ;; esac external_host="${authority%%:*}" port="${authority#"$external_host"}" case "$external_host" in ""|*[!A-Za-z0-9.-]*) echo "APP_PUBLIC_BASE_URL contains an unsupported host." >&2; exit 1 ;; esac if [ -n "$port" ]; then port="${port#:}" case "$port" in ""|*[!0-9]*) echo "APP_PUBLIC_BASE_URL contains an invalid port." >&2; exit 1 ;; esac fi scheme="${origin%%:*}" http_config="$(mktemp)" checks="$(mktemp)" trap 'rm -f "$http_config" "$checks"' EXIT case "${INGRESS_MODE:-proxy}" in proxy) [ "$scheme" = https ] || { echo "Proxy ingress requires the canonical HTTPS origin." >&2; exit 1; } [ -n "${INGRESS_PROXY_CIDRS:-}" ] || { echo "INGRESS_PROXY_CIDRS must identify the observed Traefik socket peers." >&2; exit 1; } printf 'geo $realip_remote_addr $ingress_peer_trusted {\n default 0;\n' > "$http_config" for cidr in $INGRESS_PROXY_CIDRS; do case "$cidr" in *[!0-9A-Fa-f:./]*|*/0|*/*/*) echo "Invalid ingress proxy CIDR." >&2; exit 1 ;; */*) ;; *) echo "Ingress proxy peers must use explicit CIDR notation." >&2; exit 1 ;; esac prefix="${cidr##*/}" case "$prefix" in ''|*[!0-9]*) echo "Invalid ingress prefix." >&2; exit 1 ;; esac # Only RFC1918/ULA ranges may group peers; all other addresses must be individual. # This also rejects IPv6 prefixes covering every IPv4-mapped address. case "$cidr" in [fF][cCdD]*:*) minimum=64; maximum=128 ;; *:*) minimum=128; maximum=128 ;; 10.*|192.168.*|172.1[6-9].*|172.2[0-9].*|172.3[01].*) minimum=24; maximum=32 ;; *) minimum=32; maximum=32 ;; esac [ "$prefix" -ge "$minimum" ] && [ "$prefix" -le "$maximum" ] || { echo "Ingress proxy CIDR is too broad or invalid." >&2; exit 1; } printf ' %s 1;\n' "$cidr" >> "$http_config" done printf '}\nreal_ip_header X-Forwarded-For;\nreal_ip_recursive off;\n' >> "$http_config" for cidr in $INGRESS_PROXY_CIDRS; do printf 'set_real_ip_from %s;\n' "$cidr" >> "$http_config"; done cat > "$checks" <<'CHECKS' if ($ingress_peer_trusted = 0) { return 403; } if ($http_x_forwarded_proto != "https") { return 400; } if ($http_x_forwarded_for = "") { return 400; } if ($http_x_forwarded_for ~ ",") { return 400; } # A malformed address is not forwarded verbatim: realip leaves the socket IP intact. CHECKS ;; direct) [ "$scheme" = http ] || { echo "Direct ingress is only supported for HTTP development." >&2; exit 1; } ;; *) echo "INGRESS_MODE must be proxy or direct." >&2; exit 1 ;; esac sed -e "s/__APP_EXTERNAL_HOST__/$external_host/g" \ -e "s/__APP_EXTERNAL_AUTHORITY__/$authority/g" \ -e "s/__APP_EXTERNAL_SCHEME__/$scheme/g" \ -e "/__APP_INGRESS_HTTP__/r $http_config" -e '/__APP_INGRESS_HTTP__/d' \ -e "/__APP_INGRESS_CHECK__/r $checks" -e '/__APP_INGRESS_CHECK__/d' \ /etc/nginx/jobtracker.conf.template > /etc/nginx/conf.d/default.conf # Validate addresses and the generated configuration before the entrypoint starts serving. nginx -t