spark-server/deploy/website/deploy.sh
DESKTOP-L8OUL9F\gfl0034 5b53dd906c Add Spark Messenger marketing site for Singapore host.
Serve sparkmessenger/sparkmsg on shared Nginx SNI with deploy script and Let's Encrypt.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-22 15:06:37 +08:00

121 lines
3.1 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"
"${SSH[@]}" "mkdir -p '$SITE_DST' /var/www/certbot /tmp/spark-nginx-host"
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"
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"