| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- #!/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" <<STAGE
- $begin_marker
- server {
- listen 80;
- server_name $domain;
- location / {
- proxy_pass http://$site_container:80;
- proxy_set_header Host \$host;
- proxy_set_header X-Real-IP \$remote_addr;
- proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto \$scheme;
- }
- }
- $end_marker
- STAGE
- head -n -1 "$clean_config" > "$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 <<HOOK
- #!/bin/sh
- docker exec $proxy_container nginx -s reload
- HOOK
- chmod 755 /etc/letsencrypt/renewal-hooks/deploy/reload-lessncosmos-nginx.sh
- rm -f /tmp/lessncosmos-nginx.conf "$clean_config" "$stage_block" "$final_block"
- echo "Provisioned: https://$domain"
- REMOTE
- rm -f "$ARCHIVE"
|