Files
visit.waterschurch.org/deploy/deploy.sh
T

149 lines
6.9 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# =============================================================================
# Deploy visit.waterschurch.org to the cPanel host over SSH.
#
# deploy/deploy.sh # build + upload + configure (goes live)
# deploy/deploy.sh --no-build # upload the existing ./out
# deploy/deploy.sh --keep-redirect # deploy but keep sending visitors to
# # the Church Center form (pre-launch)
#
# Requires: the SSH alias "waterschurch" from ~/.ssh/config, rsync, node, npm.
# Idempotent: safe to re-run for every content update.
#
# On the server (as the cPanel user) it:
# 1. ensures the subdomain exists with document root ~/visit.waterschurch.org
# 2. creates ~/visit-private/{data,logs} and a .env from .env.example if missing
# 3. rsyncs ./out → ~/visit.waterschurch.org, preserving cPanel's own files
# (.user.ini, php.ini, .well-known/) and rebuilding .htaccess from:
# cPanel-generated PHP blocks + [pre-launch redirect] + deploy/htaccess.root
# 4. installs the 5-minute retry cron job if absent
# 5. requests an AutoSSL check and prints the health endpoint
# It never touches DNS, the main site, or an existing .env.
# =============================================================================
set -euo pipefail
SSH_HOST="${SSH_HOST:-waterschurch}"
SUBDOMAIN="visit"
ROOTDOMAIN="waterschurch.org"
FQDN="$SUBDOMAIN.$ROOTDOMAIN"
REMOTE_DOCROOT="visit.waterschurch.org" # relative to $HOME on the server
REMOTE_PRIVATE="visit-private" # relative to $HOME on the server
BUILD=1
KEEP_REDIRECT=0
for arg in "$@"; do
case "$arg" in
--no-build) BUILD=0 ;;
--keep-redirect) KEEP_REDIRECT=1 ;;
*) echo "unknown option: $arg"; exit 2 ;;
esac
done
cd "$(dirname "$0")/.."
if [[ $BUILD -eq 1 ]]; then
echo "▶ building"
npm run build
fi
[[ -f out/index.html && -f out/.htaccess && -f out/api/plan-visit.php ]] || { echo "out/ is incomplete — run npm run build"; exit 1; }
echo "▶ preparing server"
ssh "$SSH_HOST" bash -s -- "$SUBDOMAIN" "$ROOTDOMAIN" "$REMOTE_DOCROOT" "$REMOTE_PRIVATE" <<'REMOTE'
set -euo pipefail
SUB="$1"; ROOT="$2"; DOCROOT="$HOME/$3"; PRIV="$HOME/$4"; FQDN="$SUB.$ROOT"
if uapi --output=json DomainInfo list_domains 2>/dev/null | grep -q "\"$FQDN\""; then
CUR=$(uapi --output=json DomainInfo single_domain_data domain="$FQDN" 2>/dev/null | python3 -c 'import json,sys; print(json.load(sys.stdin)["result"]["data"].get("documentroot",""))' 2>/dev/null || true)
echo " subdomain $FQDN exists (docroot: ${CUR:-unknown})"
if [[ -n "$CUR" && "$CUR" != "$DOCROOT" ]]; then
echo " ⚠ document root differs — pointing it at $DOCROOT"
uapi --output=json SubDomain changedocroot subdomain="$SUB" rootdomain="$ROOT" dir="$DOCROOT" >/dev/null
fi
else
echo " creating subdomain $FQDN → $DOCROOT"
uapi --output=json SubDomain addsubdomain domain="$SUB" rootdomain="$ROOT" dir="$DOCROOT" | python3 -c 'import json,sys; r=json.load(sys.stdin)["result"]; print(" ", "ok" if r["status"] else r["errors"])'
fi
mkdir -p "$DOCROOT"
# Preserve cPanel-generated .htaccess blocks (PHP ini directives + PHP handler) before we replace the file.
if [[ -f "$DOCROOT/.htaccess" ]]; then
awk '/^# BEGIN cPanel-generated/,/^# END cPanel-generated/ {print} /^# php -- BEGIN cPanel-generated/,/^# php -- END cPanel-generated/ {print}' "$DOCROOT/.htaccess" > "$DOCROOT/.htaccess.cpanel-blocks"
echo " preserved $(grep -c . "$DOCROOT/.htaccess.cpanel-blocks") lines of cPanel-generated .htaccess directives"
fi
mkdir -p "$PRIV/data" "$PRIV/logs"
chmod 750 "$PRIV" "$PRIV/data" "$PRIV/logs"
echo " private dir: $PRIV"
REMOTE
echo "▶ uploading build"
rsync -az --delete \
--exclude '/.htaccess' --exclude '/.htaccess.*' \
--exclude '/.user.ini' --exclude '/php.ini' --exclude '/.well-known/' \
--exclude 'api/data/' \
--chmod=Du=rwx,Dgo=rx,Fu=rw,Fgo=r \
out/ "$SSH_HOST:$REMOTE_DOCROOT/"
scp -q out/.htaccess "$SSH_HOST:$REMOTE_DOCROOT/.htaccess.visit"
scp -q deploy/htaccess.prelaunch-redirect "$SSH_HOST:$REMOTE_DOCROOT/.htaccess.prelaunch"
scp -q .env.example "$SSH_HOST:$REMOTE_PRIVATE/.env.example"
echo "▶ configuring"
ssh "$SSH_HOST" bash -s -- "$REMOTE_DOCROOT" "$REMOTE_PRIVATE" "$FQDN" "$KEEP_REDIRECT" <<'REMOTE'
set -euo pipefail
DOCROOT="$HOME/$1"; PRIV="$HOME/$2"; FQDN="$3"; KEEP="$4"
# --- .env (never overwritten)
if [[ ! -f "$PRIV/.env" ]]; then
cp "$PRIV/.env.example" "$PRIV/.env"
SALT=$(head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n')
sed -i "s|^HASH_SALT=.*|HASH_SALT=$SALT|; s|^ALLOWED_ORIGINS=.*|ALLOWED_ORIGINS=|; s|^DEBUG_GEO=.*|DEBUG_GEO=false|" "$PRIV/.env"
echo " created $PRIV/.env (INTEGRATION_MODE=mock — add API keys, then set live)"
else
echo " kept existing $PRIV/.env"
fi
chmod 640 "$PRIV/.env"
# --- assemble .htaccess: cPanel blocks + [pre-launch redirect] + site config
{
[[ -f "$DOCROOT/.htaccess.cpanel-blocks" ]] && cat "$DOCROOT/.htaccess.cpanel-blocks" && echo
if [[ "$KEEP" == "1" ]]; then cat "$DOCROOT/.htaccess.prelaunch"; fi
sed "s|^# SetEnv VISIT_PRIVATE_DIR .*|SetEnv VISIT_PRIVATE_DIR $PRIV|" "$DOCROOT/.htaccess.visit"
} > "$DOCROOT/.htaccess.new"
mv -f "$DOCROOT/.htaccess.new" "$DOCROOT/.htaccess"
rm -f "$DOCROOT/.htaccess.visit" "$DOCROOT/.htaccess.prelaunch" "$DOCROOT/.htaccess.cpanel-blocks"
chmod 644 "$DOCROOT/.htaccess"
if [[ "$KEEP" == "1" ]]; then echo " .htaccess: PRE-LAUNCH redirect to Church Center is ACTIVE"; else echo " .htaccess: site is LIVE (no redirect)"; fi
# --- PHP binary for cron
PHP_BIN=$(command -v php || true)
for c in /usr/local/bin/php /opt/cpanel/ea-php83/root/usr/bin/php /opt/cpanel/ea-php82/root/usr/bin/php; do
[[ -z "$PHP_BIN" && -x "$c" ]] && PHP_BIN="$c"
done
echo " php: ${PHP_BIN:-NOT FOUND} $($PHP_BIN -r 'echo PHP_VERSION;' 2>/dev/null || true)"
# --- cron (idempotent)
CRON="*/5 * * * * VISIT_PRIVATE_DIR=$PRIV $PHP_BIN $DOCROOT/api/cron/retry-integrations.php >> $PRIV/logs/cron.log 2>&1"
if ! crontab -l 2>/dev/null | grep -qF "retry-integrations.php"; then
( crontab -l 2>/dev/null || true; echo "$CRON" ) | crontab -
echo " cron installed (every 5 minutes)"
else
echo " cron already present"
fi
# --- SSL
if uapi --output=json SSL start_autossl_check >/dev/null 2>&1; then echo " AutoSSL check requested"; else echo " (AutoSSL check not available via UAPI; use cPanel → SSL/TLS Status if needed)"; fi
echo " build: $(head -1 "$DOCROOT/BUILD.txt")"
REMOTE
echo "▶ verifying"
sleep 2
printf " https://%s/ → " "$FQDN"; curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" --max-time 20 "https://$FQDN/" || true
printf " /api/health.php → "; curl -s --max-time 20 "https://$FQDN/api/health.php" | head -c 600 || true
echo
if [[ $KEEP_REDIRECT -eq 1 ]]; then
echo "Deployed behind the pre-launch redirect. To go live: deploy/deploy.sh --no-build"
else
echo "Live. Next: fill in $REMOTE_PRIVATE/.env on the server, set INTEGRATION_MODE=live, and run docs/LAUNCH-CHECKLIST.md."
fi