#!/usr/bin/env bash set -euo pipefail # load env (prefer absolute ENV_FILE injected by Python CLI; fallback to ./env.sh) if [[ -n "${ENV_FILE:-}" && -f "${ENV_FILE}" ]]; then set -a; . "${ENV_FILE}"; set +a elif [[ -f "./env.sh" ]]; then set -a; . ./env.sh; set +a fi : "${HOSTNAME:?HOSTNAME not set in env.sh}" : "${EMAIL:?EMAIL not set in env.sh}" export SYSTEMD_PAGER="" export SYSTEMD_COLORS="0" DEBIAN_FRONTEND=noninteractive # sanity check if [[ "${HOSTNAME}" == "localhost" || "${HOSTNAME}" == "127.0.0.1" || "${HOSTNAME}" == "ubuntu" ]]; then echo "ERROR: HOSTNAME cannot be 'localhost'. Use a public FQDN." >&2 exit 1 fi echo -e "\n* * * Starting nginx configuration for landing page, reverse proxy and WSS * * *" # set paths & ports vars WEBROOT="/var/www/${HOSTNAME}" LE_ACME_DIR="/var/www/letsencrypt" SITES_AVAIL="/etc/nginx/sites-available" SITES_EN="/etc/nginx/sites-enabled" BASE_HTTP="${SITES_AVAIL}/${HOSTNAME}" # :80 vhost BASE_HTTPS="${SITES_AVAIL}/${HOSTNAME}-ssl" # :443 vhost (we’ll write it ourselves) WSS_AVAIL="${SITES_AVAIL}/wss-config-nym" BACKUP_DIR="/etc/nginx/sites-backups" NYM_PORT_HTTP="${NYM_PORT_HTTP:-8080}" NYM_PORT_WSS="${NYM_PORT_WSS:-9000}" WSS_LISTEN_PORT="${WSS_LISTEN_PORT:-9001}" mkdir -p "${WEBROOT}" "${LE_ACME_DIR}" "${BACKUP_DIR}" "${SITES_AVAIL}" "${SITES_EN}" # helpers neat_backup() { local file="$1"; [[ -f "$file" ]] || return 0 local sha_now; sha_now="$(sha256sum "$file" | awk '{print $1}')" || return 0 local tag; tag="$(basename "$file")" local latest="${BACKUP_DIR}/${tag}.latest" if [[ -f "$latest" ]]; then local sha_prev; sha_prev="$(awk '{print $1}' "$latest")" [[ "$sha_now" == "$sha_prev" ]] && return 0 fi cp -a "$file" "${BACKUP_DIR}/${tag}.bak.$(date +%s)" echo "$sha_now ${tag}" > "$latest" ls -1t "${BACKUP_DIR}/${tag}.bak."* 2>/dev/null | tail -n +6 | xargs -r rm -f } ensure_enabled() { local src="$1"; local name; name="$(basename "$src")" ln -sf "$src" "${SITES_EN}/${name}" } cert_ok() { [[ -s "/etc/letsencrypt/live/${HOSTNAME}/fullchain.pem" && -s "/etc/letsencrypt/live/${HOSTNAME}/privkey.pem" ]] } fetch_landing_html() { local url="https://raw.githubusercontent.com/nymtech/nym/refs/heads/develop/scripts/nym-node-setup/landing-page.html" mkdir -p "${WEBROOT}" if command -v curl >/dev/null 2>&1; then curl -fsSL "$url" -o "${WEBROOT}/index.html" || true else wget -qO "${WEBROOT}/index.html" "$url" || true fi if [[ ! -s "${WEBROOT}/index.html" ]]; then cat > "${WEBROOT}/index.html" <<'HTML'
This is a Nym Exit Gateway. The operator of this router has no access to any of the data routing through that due to encryption design.
HTML fi } inject_email() { local file="${WEBROOT}/index.html" [[ -n "${EMAIL:-}" && -s "$file" ]] || return 0 # Escape characters that would break sed replacement local esc_email esc_email="$(printf '%s' "$EMAIL" | sed -e 's/[&/\]/\\&/g')" # try to update existing meta (case-insensitive on the name attr) if grep -qiE ']+name=["'"'"']contact:email["'"'"']' "$file"; then sed -i -E \ "s|(]+name=[\"']contact:email[\"'][^>]*content=\")[^\"]*(\"[^>]*>)|\1${esc_email}\2|I" \ "$file" || true return 0 fi # insert before if present (case-insensitive) if grep -qi '' "$file"; then awk -v email="$EMAIL" ' BEGIN{IGNORECASE=1} /<\/head>/ && !done { print " " done=1 } { print } ' "$file" > "${file}.tmp" && mv "${file}.tmp" "$file" return 0 fi # fallback: append at end printf '\n\n' "$EMAIL" >> "$file" || true } fetch_logo() { local logo_url="https://raw.githubusercontent.com/nymtech/websites/refs/heads/main/www/nym.com/public/images/Nym_meta_Image.png?token=GHSAT0AAAAAACEERII7URYRTFACZ4F2OWZ42GMCPBQ" mkdir -p "${WEBROOT}/images" if [[ ! -s "${WEBROOT}/images/nym_logo.png" ]]; then if command -v curl >/dev/null 2>&1; then curl -fsSL "$logo_url" -o "${WEBROOT}/images/nym_logo.png" || true else wget -qO "${WEBROOT}/images/nym_logo.png" "$logo_url" || true fi fi } reload_nginx() { nginx -t && systemctl reload nginx; } # landing page (idempotent) fetch_landing_html inject_email fetch_logo echo "Landing page at ${WEBROOT}/index.html" # disable default and stale SSL configs [[ -L "${SITES_EN}/default" ]] && unlink "${SITES_EN}/default" || true for f in "${SITES_EN}"/*; do [[ -L "$f" ]] || continue if grep -q "/etc/letsencrypt/live/localhost" "$f"; then echo "Disabling vhost referencing localhost cert: $f"; unlink "$f" fi done for f in "${SITES_EN}"/*; do [[ -L "$f" ]] || continue if grep -qE 'listen\s+.*443' "$f"; then cert=$(awk '/ssl_certificate[ \t]+/ {print $2}' "$f" | tr -d ';' | head -n1) key=$(awk '/ssl_certificate_key[ \t]+/ {print $2}' "$f" | tr -d ';' | head -n1) if [[ -n "${cert:-}" && ! -s "$cert" ]] || [[ -n "${key:-}" && ! -s "$key" ]]; then echo "Disabling SSL vhost with missing cert/key: $f"; unlink "$f" fi fi done # HTTP :80 vhost (ACME-safe, proxy to :8080) neat_backup "${BASE_HTTP}" cat > "${BASE_HTTP}" <