Nginx auth_request plus MaxMind City lookup blocks non-Shanghai mainland CN with a fixed notice page for sparkmessenger/sparkmsg (and deploy helpers for the shared Singapore host). Co-authored-by: Cursor <cursoragent@cursor.com>
144 lines
4.3 KiB
Bash
144 lines
4.3 KiB
Bash
#!/usr/bin/env bash
|
|
# Deploy Spark Messenger website to the Singapore ECS host.
|
|
# Layout on host:
|
|
# /var/www/sparkmessenger.wyrs365.com static site
|
|
# /etc/nginx/conf.d/sparkmessenger.conf TLS vhost (loopback :8443)
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
HOST="${SPARK_SSH_HOST:-root@47.236.66.9}"
|
|
KEY="${SPARK_SSH_KEY:-$HOME/.ssh/wyrs_shanghai_deploy.pem}"
|
|
SITE_SRC="$ROOT/website"
|
|
SITE_DST="/var/www/sparkmessenger.wyrs365.com"
|
|
DOMAINS=(sparkmessenger.wyrs365.com sparkmsg.wyrs365.com)
|
|
PRIMARY="${DOMAINS[0]}"
|
|
SSH=(ssh -i "$KEY" -o BatchMode=yes -o StrictHostKeyChecking=accept-new "$HOST")
|
|
SCP=(scp -i "$KEY" -o BatchMode=yes -o StrictHostKeyChecking=accept-new)
|
|
|
|
need() {
|
|
command -v "$1" >/dev/null || {
|
|
echo "need $1 on this machine" >&2
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
need ssh
|
|
need scp
|
|
need rsync
|
|
|
|
if [[ ! -f "$KEY" ]]; then
|
|
echo "missing SSH key: $KEY" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -f "$SITE_SRC/index.html" ]]; then
|
|
echo "missing $SITE_SRC/index.html" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "==> upload site + nginx conf + geo-guard"
|
|
"${SSH[@]}" "mkdir -p '$SITE_DST' /var/www/certbot /tmp/spark-nginx-host /tmp/spark-geo-guard"
|
|
rsync -az --delete -e "ssh -i $KEY -o BatchMode=yes -o StrictHostKeyChecking=accept-new" \
|
|
"$SITE_SRC/" "$HOST:$SITE_DST/"
|
|
"${SCP[@]}" "$ROOT/deploy/nginx/host/sparkmessenger.conf" "$HOST:/tmp/spark-nginx-host/sparkmessenger.conf"
|
|
"${SCP[@]}" \
|
|
"$ROOT/deploy/geo-guard/wyrs_geo_guard.py" \
|
|
"$ROOT/deploy/geo-guard/wyrs-geo-guard.service" \
|
|
"$ROOT/deploy/geo-guard/install-host.sh" \
|
|
"$ROOT/deploy/nginx/snippets/wyrs-cn-geo-access.conf" \
|
|
"$ROOT/deploy/nginx/static/cn-mainland-denied.html" \
|
|
"$HOST:/tmp/spark-geo-guard/"
|
|
"${SSH[@]}" bash -s <<'GEO'
|
|
set -euo pipefail
|
|
mkdir -p /opt/wyrs-geo-guard /etc/nginx/snippets /var/www/wyrs-geo-deny
|
|
# install-host.sh expects repo-relative paths; invoke pieces here
|
|
if ! rpm -q python3-geoip2 >/dev/null 2>&1; then
|
|
dnf install -y python3-geoip2
|
|
fi
|
|
install -m 0755 /tmp/spark-geo-guard/wyrs_geo_guard.py /opt/wyrs-geo-guard/wyrs_geo_guard.py
|
|
install -m 0644 /tmp/spark-geo-guard/wyrs-geo-guard.service /etc/systemd/system/wyrs-geo-guard.service
|
|
install -m 0644 /tmp/spark-geo-guard/wyrs-cn-geo-access.conf /etc/nginx/snippets/wyrs-cn-geo-access.conf
|
|
install -m 0644 /tmp/spark-geo-guard/cn-mainland-denied.html /var/www/wyrs-geo-deny/index.html
|
|
systemctl daemon-reload
|
|
systemctl enable --now wyrs-geo-guard.service
|
|
systemctl restart wyrs-geo-guard.service
|
|
curl -fsS http://127.0.0.1:18099/healthz >/dev/null
|
|
GEO
|
|
|
|
echo "==> ensure TLS certificates"
|
|
"${SSH[@]}" bash -s -- "$PRIMARY" "${DOMAINS[@]}" <<'REMOTE'
|
|
set -euo pipefail
|
|
PRIMARY=$1
|
|
shift
|
|
DOMAINS=("$@")
|
|
|
|
cert_ok() {
|
|
[[ -f "/etc/letsencrypt/live/$1/fullchain.pem" ]]
|
|
}
|
|
|
|
need_issue=0
|
|
if ! cert_ok "$PRIMARY"; then
|
|
need_issue=1
|
|
else
|
|
# Ensure SAN covers all website domains; re-issue if missing.
|
|
for d in "${DOMAINS[@]}"; do
|
|
if ! openssl x509 -in "/etc/letsencrypt/live/$PRIMARY/fullchain.pem" -noout -text 2>/dev/null | grep -q "$d"; then
|
|
need_issue=1
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [[ "$need_issue" -eq 1 ]]; then
|
|
mkdir -p /var/www/certbot
|
|
cat > /etc/nginx/conf.d/sparkmessenger-acme.conf <<EOF
|
|
server {
|
|
listen 80;
|
|
listen [::]:80;
|
|
server_name ${DOMAINS[*]};
|
|
|
|
location /.well-known/acme-challenge/ {
|
|
root /var/www/certbot;
|
|
}
|
|
|
|
location / {
|
|
return 404;
|
|
}
|
|
}
|
|
EOF
|
|
nginx -t
|
|
systemctl reload nginx
|
|
|
|
certbot_args=(certonly --webroot -w /var/www/certbot --non-interactive --agree-tos --keep-until-expiring --cert-name "$PRIMARY")
|
|
# Use a placeholder email if register is needed; prefer existing account.
|
|
if [[ -n "${CERTBOT_EMAIL:-}" ]]; then
|
|
certbot_args+=(--email "$CERTBOT_EMAIL")
|
|
else
|
|
certbot_args+=(--register-unsafely-without-email)
|
|
fi
|
|
for d in "${DOMAINS[@]}"; do
|
|
certbot_args+=(-d "$d")
|
|
done
|
|
certbot "${certbot_args[@]}"
|
|
rm -f /etc/nginx/conf.d/sparkmessenger-acme.conf
|
|
fi
|
|
|
|
if ! cert_ok "$PRIMARY"; then
|
|
echo "certificate missing for $PRIMARY" >&2
|
|
exit 1
|
|
fi
|
|
|
|
cp /tmp/spark-nginx-host/sparkmessenger.conf /etc/nginx/conf.d/sparkmessenger.conf
|
|
nginx -t
|
|
systemctl reload nginx
|
|
echo "website nginx ready"
|
|
REMOTE
|
|
|
|
echo "==> verify"
|
|
for d in "${DOMAINS[@]}"; do
|
|
code=$("${SSH[@]}" "curl -fsS -o /dev/null -w '%{http_code}' --resolve ${d}:443:127.0.0.1 https://${d}/" || true)
|
|
echo "$d -> HTTP $code"
|
|
done
|
|
|
|
echo "done"
|