From 493e9b45b3d0a503667f298a119b543605fe9a71 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Thu, 2 Jul 2026 22:27:13 +0800 Subject: [PATCH] =?UTF-8?q?devops:=20=E5=89=B2=E6=8E=A5=E5=90=8E=20server?= =?UTF-8?q?=20=E9=83=A8=E7=BD=B2=E8=BD=A8=E9=81=93=E5=88=87=E4=B8=BA?= =?UTF-8?q?=E4=BB=85=20Ali=20=E4=B8=BB=E8=BD=A8=EF=BC=88=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=20EC2=20=E8=BD=A8=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o --- .gitea/workflows/deploy-server.yml | 19 ++---------- deploy/nginx-jiu-ali.conf | 48 ++++++++++++++++++------------ scripts/ci/deploy-server.sh | 37 +++++++++++++++-------- 3 files changed, 56 insertions(+), 48 deletions(-) diff --git a/.gitea/workflows/deploy-server.yml b/.gitea/workflows/deploy-server.yml index 8da1932..c2af391 100644 --- a/.gitea/workflows/deploy-server.yml +++ b/.gitea/workflows/deploy-server.yml @@ -36,22 +36,9 @@ jobs: GITEA_REPOSITORY: ${{ gitea.repository }} run: sh scripts/ci/release-server.sh "${{ gitea.ref_name }}" - - name: Deploy → EC2 - env: - FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }} - FORGEJO_URL: ${{ secrets.FORGEJO_URL }} - GITEA_REPOSITORY: ${{ gitea.repository }} - DEPLOY_TARGET: ec2 - EC2_SSH_KEY: ${{ secrets.EC2_SSH_KEY }} - EC2_HOST: ${{ secrets.EC2_HOST }} - EC2_USER: ${{ secrets.EC2_USER }} - run: sh scripts/ci/deploy-server.sh "${{ gitea.ref_name }}" - - # 迁移期影子目标:部署到阿里机(只换二进制 + reload 独立 nginx,jiu 保持 stopped)。 - # if: always() → EC2 失败也照样尝试;continue-on-error → 阿里失败不让流水线变红。 - - name: Deploy → Ali (migration shadow) - if: always() - continue-on-error: true + # 2026-07-02 割接后阿里机即线上主轨(EC2 jiu 已停用,Deploy→EC2 轨已移除, + # 绝不能再部署 EC2——那会把停用的后端对着过时旧库重新拉起)。 + - name: Deploy → Ali env: FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }} FORGEJO_URL: ${{ secrets.FORGEJO_URL }} diff --git a/deploy/nginx-jiu-ali.conf b/deploy/nginx-jiu-ali.conf index 73c61ee..5459cee 100644 --- a/deploy/nginx-jiu-ali.conf +++ b/deploy/nginx-jiu-ali.conf @@ -1,18 +1,27 @@ # 阿里云独立 nginx 版(宿主机直接终结 TLS,不经 pangolin)。 -# 与 nginx-jiu.conf(EC2 pangolin 容器版,listen 127.0.0.1:8445)等价, -# 仅入口监听改为对公网 443 直连。CI deploy-server.sh 的 ali 分支落到 -# /etc/nginx/conf.d/jiu.conf。 +# 与 nginx-jiu.conf(EC2 pangolin 容器版,listen 127.0.0.1:8445)等价。 +# CI deploy-server.sh 的 ali 分支落到 /etc/nginx/conf.d/jiu.conf。 +# +# 过渡期入口 = 8443 明文 HTTP,裸 IP 直连 http://182.92.213.171:8443 +#(备案未通过前 80/443/8080 被阿里云拦截,走非标端口;不建过渡子域, +# 证书签给域名对不上 IP,故过渡期不做 TLS——登录口令/JWT 明文传输,仅限过渡; +# 备案通过后改回 listen 443 ssl + 域名 + 80→443 跳转块)。 +# 后端上游 = 127.0.0.1:8081(非 8080!ali 上 8080 已被 pay 项目 payd 占用; +# 对应 /opt/jiu/config/production.env 的 SERVER_PORT=8081)。 limit_req_zone $binary_remote_addr zone=jiu_pub:10m rate=10r/s; limit_req_status 429; server { - listen 443 ssl http2; - server_name jiu.51yanmei.com; + listen 8443 default_server; + server_name _; - ssl_certificate /etc/letsencrypt/live/jiu.51yanmei.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/jiu.51yanmei.com/privkey.pem; - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; + # 备案通过切回 443 时恢复(证书路径仍有效,jiu.51yanmei.com,2026-09-21 到期): + # listen 443 ssl http2; + # server_name jiu.51yanmei.com; + # ssl_certificate /etc/letsencrypt/live/jiu.51yanmei.com/fullchain.pem; + # ssl_certificate_key /etc/letsencrypt/live/jiu.51yanmei.com/privkey.pem; + # ssl_protocols TLSv1.2 TLSv1.3; + # ssl_ciphers HIGH:!aNULL:!MD5; client_max_body_size 20m; @@ -25,7 +34,7 @@ server { # 文件导入接口(超时更长) location ~ ^/api/v1/import/ { - proxy_pass http://127.0.0.1:8080; + proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 300s; @@ -34,7 +43,7 @@ server { # 未鉴权公开/登录接口:加最外层 per-IP 限流 location ~ ^/api/v1/(public|auth)/ { limit_req zone=jiu_pub burst=20 nodelay; - proxy_pass http://127.0.0.1:8080; + proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 30s; @@ -42,7 +51,7 @@ server { # API 反向代理 location ~ ^/(api|health|version) { - proxy_pass http://127.0.0.1:8080; + proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 30s; @@ -65,7 +74,7 @@ server { # 公开商品详情页(扫码跳转)→ 后端注入 OG 标签 location ~ ^/product/ { limit_req zone=jiu_pub burst=20 nodelay; - proxy_pass http://127.0.0.1:8080; + proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 30s; @@ -75,7 +84,7 @@ server { location ~ ^/app/product/ { limit_req zone=jiu_pub burst=20 nodelay; rewrite ^/app(/product/.+)$ $1 break; - proxy_pass http://127.0.0.1:8080; + proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 30s; @@ -96,8 +105,9 @@ server { } } -server { - listen 80; - server_name jiu.51yanmei.com; - return 301 https://$host$request_uri; -} +# 备案通过、入口切回 443 后再恢复此跳转块(80 未备案期间被拦截,挂了也无意义): +# server { +# listen 80; +# server_name jiu.51yanmei.com; +# return 301 https://$host$request_uri; +# } diff --git a/scripts/ci/deploy-server.sh b/scripts/ci/deploy-server.sh index bf9c9d2..99406bd 100644 --- a/scripts/ci/deploy-server.sh +++ b/scripts/ci/deploy-server.sh @@ -4,13 +4,14 @@ # assets by tag (manual rollback). Does NOT touch the web app, marketing site, # or version.yaml. # -# Target is EC2 by default. During the EC2→Ali migration, set DEPLOY_TARGET=ali -# plus DEPLOY_HOST/DEPLOY_USER/DEPLOY_SSH_KEY to deploy to the Alibaba Cloud box. -# - ec2 (default): stop jiu → swap binary → start jiu → health check → -# reload nginx inside the pangolin-edge container. -# - ali: swap binary only (jiu.service stays stopped — the Ali DB is a -# read-only replica until cutover; backend is started at cutover) → -# reload the host nginx with the standalone (listen 443) config. +# Targets (post-cutover 2026-07-02: Ali is the live primary; the EC2 jiu stack +# is decommissioned — deploying there would resurrect a backend against a stale +# database, so the workflow no longer calls the ec2 branch): +# - ali: stop jiu → swap binary → start jiu → health check (:8081) → +# reload the host nginx (transition listen-8443 config). +# - ec2 (legacy default, kept for manual rollback of pre-cutover tags only): +# stop jiu → swap binary → start jiu → health check → reload nginx +# inside the pangolin-edge container. set -euo pipefail # shellcheck source=scripts/ci/lib-forgejo.sh @@ -53,14 +54,13 @@ if [ -f dist/jiu-gencode ]; then fi if [ "$DEPLOY_TARGET" = "ali" ]; then - # --- Alibaba Cloud (shadow target, pre-cutover) --- - # Swap the binary but DO NOT start jiu: the Ali DB is a read-only replica, so - # the backend's startup AutoMigrate/backfill would fail. jiu.service is started - # only at cutover (after the replica is promoted to primary). Reload the host - # nginx with the standalone listen-443 config. + # --- Alibaba Cloud (live primary since the 2026-07-02 cutover) --- + # Full swap-and-restart: jiu.service runs against the promoted local primary + # DB on :8081; nginx serves the transition listen-8443 config. ${SSH} "${TARGET_USER}@${TARGET_HOST}" << 'ENDSSH' set -e +systemctl stop jiu cp /tmp/jiu-server /opt/jiu/backend/jiu-server chmod +x /opt/jiu/backend/jiu-server @@ -73,10 +73,21 @@ if [ -f /tmp/jiu-gencode ]; then fi fi +systemctl start jiu +echo "Waiting for health check..." +for i in $(seq 1 30); do + if curl -f http://localhost:8081/health > /dev/null 2>&1; then + echo "Health check passed" + break + fi + sleep 2 +done +curl -f http://localhost:8081/health > /dev/null || { echo "Health check failed!"; exit 1; } + cp /tmp/nginx-jiu.conf /etc/nginx/conf.d/jiu.conf nginx -t && systemctl reload nginx -echo "Ali server staged (binary swapped, jiu.service left stopped, nginx reloaded)" +echo "Ali server deploy complete!" ENDSSH else # --- EC2 (live primary) ---