deploy.sh 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #!/usr/bin/env bash
  2. # CelestiaTrace frontend deployment.
  3. # This updates only the frontend service and never runs docker compose down.
  4. set -Eeuo pipefail
  5. SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
  6. REPO_DIR="$(dirname "$SCRIPT_DIR")"
  7. SERVER_IP="47.93.193.127"
  8. PEM_KEY="$REPO_DIR/ccdw-meishi-1.pem"
  9. REMOTE_DIR="/opt/celestia-trace-frontend"
  10. SSH_USER="root"
  11. COMPOSE_PROJECT="celestia-trace-frontend"
  12. PROXY_DIR="/opt/meishi_ccdw_life"
  13. PROXY_CONTAINER="meishi_ccdw_life-proxy-1"
  14. PROXY_CONFIG="$REPO_DIR/remote_nginx.conf"
  15. API_BASE_URL="https://api.ccdw.life/celestia-trace/v1"
  16. PUBLIC_URL="http://c.lessncosmos.com"
  17. SSH_OPTS=(-i "$PEM_KEY" -o BatchMode=yes -o StrictHostKeyChecking=accept-new)
  18. if [[ ! -f "$PEM_KEY" ]]; then
  19. echo "SSH key not found: $PEM_KEY" >&2
  20. exit 1
  21. fi
  22. if [[ ! -f "$PROXY_CONFIG" ]]; then
  23. echo "Nginx config not found: $PROXY_CONFIG" >&2
  24. exit 1
  25. fi
  26. chmod 400 "$PEM_KEY"
  27. ssh "${SSH_OPTS[@]}" "$SSH_USER@$SERVER_IP" "mkdir -p '$REMOTE_DIR'"
  28. rsync -avz --delete \
  29. --exclude '.git' \
  30. --exclude '.env' \
  31. --exclude 'node_modules' \
  32. --exclude 'dist' \
  33. -e "ssh -i $PEM_KEY -o BatchMode=yes -o StrictHostKeyChecking=accept-new" \
  34. "$SCRIPT_DIR/" "$SSH_USER@$SERVER_IP:$REMOTE_DIR/"
  35. ssh "${SSH_OPTS[@]}" "$SSH_USER@$SERVER_IP" << REMOTE_CMDS
  36. set -Eeuo pipefail
  37. cd "$REMOTE_DIR"
  38. export VITE_API_BASE_URL="$API_BASE_URL"
  39. docker compose -p "$COMPOSE_PROJECT" config --quiet
  40. docker compose -p "$COMPOSE_PROJECT" up -d --build --no-deps frontend
  41. for attempt in \$(seq 1 30); do
  42. health=\$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' celestia-frontend)
  43. if [[ "\$health" == "healthy" ]]; then
  44. docker compose -p "$COMPOSE_PROJECT" ps frontend
  45. exit 0
  46. fi
  47. if [[ "\$health" == "unhealthy" || "\$health" == "exited" ]]; then
  48. docker logs --tail 100 celestia-frontend
  49. exit 1
  50. fi
  51. sleep 2
  52. done
  53. echo "Frontend health check timed out" >&2
  54. docker logs --tail 100 celestia-frontend
  55. exit 1
  56. REMOTE_CMDS
  57. scp "${SSH_OPTS[@]}" "$PROXY_CONFIG" "$SSH_USER@$SERVER_IP:$PROXY_DIR/nginx.conf.next"
  58. ssh "${SSH_OPTS[@]}" "$SSH_USER@$SERVER_IP" << REMOTE_CMDS
  59. set -Eeuo pipefail
  60. cd "$PROXY_DIR"
  61. docker run --rm \
  62. --network meishi_ccdw_life_default \
  63. -v "$PROXY_DIR/nginx.conf.next:/etc/nginx/nginx.conf:ro" \
  64. -v /etc/letsencrypt:/etc/letsencrypt:ro \
  65. docker.m.daocloud.io/library/nginx:alpine nginx -t
  66. cp nginx.conf.next nginx.conf
  67. chmod 644 nginx.conf
  68. rm -f nginx.conf.next
  69. docker exec "$PROXY_CONTAINER" nginx -s reload
  70. for attempt in \$(seq 1 15); do
  71. if curl --fail --silent --show-error \
  72. --resolve c.lessncosmos.com:80:127.0.0.1 \
  73. "$PUBLIC_URL/healthz" >/dev/null; then
  74. exit 0
  75. fi
  76. sleep 2
  77. done
  78. echo "Public HTTP health check failed: $PUBLIC_URL/healthz" >&2
  79. exit 1
  80. REMOTE_CMDS
  81. echo "Frontend deployed: $PUBLIC_URL"