#!/usr/bin/env bash set -euo pipefail cd "$(dirname "$0")" source ./deploy.config KEY_PATH="${KEY_FILE/#\~/$HOME}" RELEASE_ID="$(date -u +%Y%m%d%H%M%S)" ARCHIVE="${TMPDIR:-/tmp}/lessncosmos-initial-${RELEASE_ID}.tar.gz" REMOTE_ARCHIVE="/tmp/lessncosmos-initial-${RELEASE_ID}.tar.gz" chmod 600 "$KEY_PATH" npm run build COPYFILE_DISABLE=1 tar -C dist -czf "$ARCHIVE" . SSH=(ssh -i "$KEY_PATH" -o BatchMode=yes -o StrictHostKeyChecking=accept-new "$SERVER_USER@$SERVER_HOST") SCP=(scp -i "$KEY_PATH" -o BatchMode=yes -o StrictHostKeyChecking=accept-new) "${SCP[@]}" "$ARCHIVE" "$SERVER_USER@$SERVER_HOST:$REMOTE_ARCHIVE" "${SCP[@]}" nginx.conf "$SERVER_USER@$SERVER_HOST:/tmp/lessncosmos-nginx.conf" "${SSH[@]}" bash -s -- \ "$REMOTE_ARCHIVE" "$REMOTE_ROOT" "$RELEASE_ID" \ "$SITE_CONTAINER" "$DOCKER_NETWORK" "$PROXY_CONTAINER" "$DOMAIN" <<'REMOTE' set -euo pipefail archive="$1" remote_root="$2" release_id="$3" site_container="$4" docker_network="$5" proxy_container="$6" domain="$7" gateway_config="/opt/meishi_ccdw_life/nginx.conf" release_dir="$remote_root/releases/$release_id" begin_marker="# BEGIN MANAGED $domain" end_marker="# END MANAGED $domain" if grep -q "server_name $domain" "$gateway_config" && ! grep -qF "$begin_marker" "$gateway_config"; then echo "Refusing to continue: $domain is already configured outside the managed block." >&2 exit 1 fi mkdir -p "$release_dir" tar -xzf "$archive" -C "$release_dir" ln -sfn "$release_dir" "$remote_root/current" rm -f "$archive" if docker inspect "$site_container" >/dev/null 2>&1; then docker rm -f "$site_container" >/dev/null fi docker run -d \ --name "$site_container" \ --restart unless-stopped \ --network "$docker_network" \ -v "$remote_root/current:/usr/share/nginx/html:ro" \ docker.m.daocloud.io/library/nginx:alpine >/dev/null backup="$gateway_config.backup-$(date -u +%Y%m%d%H%M%S)" cp "$gateway_config" "$backup" clean_config="$(mktemp)" awk -v begin="$begin_marker" -v end="$end_marker" ' $0 == begin { skip=1; next } $0 == end { skip=0; next } !skip { print } ' "$gateway_config" > "$clean_config" stage_block="$(mktemp)" cat > "$stage_block" < "$gateway_config" cat "$stage_block" >> "$gateway_config" printf '}\n' >> "$gateway_config" if ! docker exec "$proxy_container" nginx -t; then cp "$backup" "$gateway_config" exit 1 fi docker exec "$proxy_container" nginx -s reload mkdir -p "$remote_root/current/.well-known/acme-challenge" printf 'ready' > "$remote_root/current/.well-known/acme-challenge/deployment-check" challenge="" for _ in 1 2 3 4 5 6 7 8 9 10; do challenge="$(curl -fsS -H "Host: $domain" http://127.0.0.1/.well-known/acme-challenge/deployment-check 2>/dev/null || true)" [[ "$challenge" == "ready" ]] && break sleep 1 done test "$challenge" = "ready" certbot certonly --webroot \ --webroot-path "$remote_root/current" \ --domain "$domain" \ --non-interactive --agree-tos --register-unsafely-without-email final_block="$(mktemp)" { printf '%s\n' "$begin_marker" sed 's/^/ /' /tmp/lessncosmos-nginx.conf printf '%s\n' "$end_marker" } > "$final_block" head -n -1 "$clean_config" > "$gateway_config" cat "$final_block" >> "$gateway_config" printf '}\n' >> "$gateway_config" if ! docker exec "$proxy_container" nginx -t; then cp "$backup" "$gateway_config" docker exec "$proxy_container" nginx -s reload exit 1 fi docker exec "$proxy_container" nginx -s reload cat > /etc/letsencrypt/renewal-hooks/deploy/reload-lessncosmos-nginx.sh <