devops: 备案通过回切 https 域名 + 流水线 Ali 单轨
- nginx-jiu-ali.conf:443 ssl+http2 正式入口(HSTS/XFO/nosniff 安全头、 ACME webroot 续期通道、80→443 跳转);8443 明文过渡口拆除 - 客户端构建 URL 全量回切 https://jiu.51yanmei.com(compile×5/local_test/ release-client/notify) - 流水线去 EC2:deploy-client/site 单轨 Ali、manual 回滚与每日备份切 ali、 seed/reset/debug-db 改容器内取密码(SEC-003,退役 DB_PASSWORD secret) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
This commit is contained in:
@@ -18,9 +18,10 @@ jobs:
|
||||
|
||||
- name: Dump MySQL to local backup dir
|
||||
env:
|
||||
EC2_SSH_KEY: ${{ secrets.EC2_SSH_KEY }}
|
||||
EC2_HOST: ${{ secrets.EC2_HOST }}
|
||||
EC2_USER: ${{ secrets.EC2_USER }}
|
||||
# 2026-07-03 割接后备份源=阿里机主库
|
||||
DEPLOY_SSH_KEY: ${{ secrets.ALI_SSH_KEY }}
|
||||
DEPLOY_HOST: ${{ secrets.ALI_HOST }}
|
||||
DEPLOY_USER: ${{ secrets.ALI_USER }}
|
||||
run: sh scripts/ci/backup-db.sh
|
||||
|
||||
- name: Notify (Telegram)
|
||||
|
||||
@@ -10,15 +10,14 @@ jobs:
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
printf '%s' "${{ secrets.EC2_SSH_KEY }}" > ~/.ssh/ec2_deploy.pem
|
||||
printf '%s' "${{ secrets.ALI_SSH_KEY }}" > ~/.ssh/ec2_deploy.pem
|
||||
chmod 600 ~/.ssh/ec2_deploy.pem
|
||||
ssh-keyscan -H ${{ secrets.EC2_HOST }} >> ~/.ssh/known_hosts
|
||||
ssh-keyscan -H ${{ secrets.ALI_HOST }} >> ~/.ssh/known_hosts
|
||||
|
||||
- name: Query DB
|
||||
env:
|
||||
EC2_HOST: ${{ secrets.EC2_HOST }}
|
||||
EC2_USER: ${{ secrets.EC2_USER }}
|
||||
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
|
||||
EC2_HOST: ${{ secrets.ALI_HOST }}
|
||||
EC2_USER: ${{ secrets.ALI_USER }}
|
||||
run: |
|
||||
ssh -i ~/.ssh/ec2_deploy.pem ${EC2_USER}@${EC2_HOST} bash << EOF
|
||||
echo "=== Docker containers ==="
|
||||
@@ -26,20 +25,20 @@ jobs:
|
||||
|
||||
echo ""
|
||||
echo "=== Databases ==="
|
||||
docker exec jiu_mysql mysql -uroot -p${DB_PASSWORD} -e "SHOW DATABASES;" 2>/dev/null \
|
||||
|| echo "jiu_mysql container not found or DB_PASSWORD wrong"
|
||||
docker exec jiu_mysql sh -c 'exec mysql -uroot -p\$MYSQL_ROOT_PASSWORD -e "SHOW DATABASES;"' 2>/dev/null \
|
||||
|| echo "jiu_mysql container not found or MYSQL_ROOT_PASSWORD wrong"
|
||||
|
||||
echo ""
|
||||
echo "=== Tables in jiu_db ==="
|
||||
docker exec jiu_mysql mysql -uroot -p${DB_PASSWORD} jiu_db -e "SHOW TABLES;" 2>/dev/null
|
||||
docker exec jiu_mysql sh -c 'exec mysql -uroot -p\$MYSQL_ROOT_PASSWORD jiu_db -e "SHOW TABLES;"' 2>/dev/null
|
||||
|
||||
echo ""
|
||||
echo "=== shops ==="
|
||||
docker exec jiu_mysql mysql -uroot -p${DB_PASSWORD} jiu_db -e "SELECT id, name, code FROM shops;" 2>/dev/null
|
||||
docker exec jiu_mysql sh -c 'exec mysql -uroot -p\$MYSQL_ROOT_PASSWORD jiu_db -e "SELECT id, name, code FROM shops;"' 2>/dev/null
|
||||
|
||||
echo ""
|
||||
echo "=== users ==="
|
||||
docker exec jiu_mysql mysql -uroot -p${DB_PASSWORD} jiu_db -e "SELECT id, shop_id, username, role, is_active FROM users;" 2>/dev/null
|
||||
docker exec jiu_mysql sh -c 'exec mysql -uroot -p\$MYSQL_ROOT_PASSWORD jiu_db -e "SELECT id, shop_id, username, role, is_active FROM users;"' 2>/dev/null
|
||||
EOF
|
||||
|
||||
- name: Cleanup SSH key
|
||||
|
||||
@@ -180,20 +180,9 @@ jobs:
|
||||
GITEA_REPOSITORY: ${{ gitea.repository }}
|
||||
run: sh scripts/ci/release-client.sh "${{ gitea.ref_name }}"
|
||||
|
||||
- name: Deploy → EC2
|
||||
env:
|
||||
FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }}
|
||||
FORGEJO_URL: ${{ secrets.FORGEJO_URL }}
|
||||
GITEA_REPOSITORY: ${{ gitea.repository }}
|
||||
EC2_SSH_KEY: ${{ secrets.EC2_SSH_KEY }}
|
||||
EC2_HOST: ${{ secrets.EC2_HOST }}
|
||||
EC2_USER: ${{ secrets.EC2_USER }}
|
||||
run: sh scripts/ci/deploy-client.sh "${{ gitea.ref_name }}"
|
||||
|
||||
# 迁移期影子目标:同步 Flutter web + version.yaml + 安装包到阿里机。失败不挡 EC2。
|
||||
- name: Deploy → Ali (migration shadow)
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
# 2026-07-03 割接后阿里机即唯一发布目标(EC2 轨移除;EC2 仅保留
|
||||
# jiu.51yanmei.com 反代桥接到 ali,见 baize 台账)。
|
||||
- name: Deploy → Ali
|
||||
env:
|
||||
FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }}
|
||||
FORGEJO_URL: ${{ secrets.FORGEJO_URL }}
|
||||
|
||||
@@ -32,20 +32,9 @@ jobs:
|
||||
GITEA_REPOSITORY: ${{ gitea.repository }}
|
||||
run: sh scripts/ci/release-site.sh "${{ gitea.ref_name }}"
|
||||
|
||||
- name: Deploy → EC2
|
||||
env:
|
||||
FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }}
|
||||
FORGEJO_URL: ${{ secrets.FORGEJO_URL }}
|
||||
GITEA_REPOSITORY: ${{ gitea.repository }}
|
||||
EC2_SSH_KEY: ${{ secrets.EC2_SSH_KEY }}
|
||||
EC2_HOST: ${{ secrets.EC2_HOST }}
|
||||
EC2_USER: ${{ secrets.EC2_USER }}
|
||||
run: sh scripts/ci/deploy-site.sh "${{ gitea.ref_name }}"
|
||||
|
||||
# 迁移期影子目标:同步官网到阿里机。失败不挡 EC2。
|
||||
- name: Deploy → Ali (migration shadow)
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
# 2026-07-03 割接后阿里机即唯一发布目标(EC2 轨移除;EC2 仅保留
|
||||
# jiu.51yanmei.com 反代桥接到 ali,见 baize 台账)。
|
||||
- name: Deploy → Ali
|
||||
env:
|
||||
FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }}
|
||||
FORGEJO_URL: ${{ secrets.FORGEJO_URL }}
|
||||
|
||||
@@ -28,9 +28,16 @@ jobs:
|
||||
FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }}
|
||||
FORGEJO_URL: ${{ secrets.FORGEJO_URL }}
|
||||
GITEA_REPOSITORY: ${{ gitea.repository }}
|
||||
EC2_SSH_KEY: ${{ secrets.EC2_SSH_KEY }}
|
||||
EC2_HOST: ${{ secrets.EC2_HOST }}
|
||||
EC2_USER: ${{ secrets.EC2_USER }}
|
||||
# 2026-07-03 割接后回滚目标统一为阿里机
|
||||
DEPLOY_TARGET: ali
|
||||
DEPLOY_SSH_KEY: ${{ secrets.ALI_SSH_KEY }}
|
||||
DEPLOY_HOST: ${{ secrets.ALI_HOST }}
|
||||
DEPLOY_USER: ${{ secrets.ALI_USER }}
|
||||
# 兼容:回滚割接前旧 tag 时,旧脚本直接引用 EC2_*(set -u 下缺失即炸)——
|
||||
# 同值指向阿里,旧脚本也会部署到阿里而不是复活 EC2
|
||||
EC2_SSH_KEY: ${{ secrets.ALI_SSH_KEY }}
|
||||
EC2_HOST: ${{ secrets.ALI_HOST }}
|
||||
EC2_USER: ${{ secrets.ALI_USER }}
|
||||
run: |
|
||||
TAG="${{ inputs.version }}"
|
||||
case "$TAG" in
|
||||
|
||||
@@ -17,20 +17,19 @@ jobs:
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
printf '%s' "${{ secrets.EC2_SSH_KEY }}" > ~/.ssh/ec2_deploy.pem
|
||||
printf '%s' "${{ secrets.ALI_SSH_KEY }}" > ~/.ssh/ec2_deploy.pem
|
||||
chmod 600 ~/.ssh/ec2_deploy.pem
|
||||
ssh-keyscan -H ${{ secrets.EC2_HOST }} >> ~/.ssh/known_hosts
|
||||
ssh-keyscan -H ${{ secrets.ALI_HOST }} >> ~/.ssh/known_hosts
|
||||
|
||||
- name: Reset database & reseed
|
||||
env:
|
||||
EC2_HOST: ${{ secrets.EC2_HOST }}
|
||||
EC2_USER: ${{ secrets.EC2_USER }}
|
||||
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
|
||||
EC2_HOST: ${{ secrets.ALI_HOST }}
|
||||
EC2_USER: ${{ secrets.ALI_USER }}
|
||||
SHOPS: ${{ github.event.inputs.shops }}
|
||||
run: |
|
||||
# 1. 清库重建
|
||||
ssh -i ~/.ssh/ec2_deploy.pem ${EC2_USER}@${EC2_HOST} \
|
||||
"docker exec jiu_mysql mysql -uroot -p${DB_PASSWORD} -e 'DROP DATABASE IF EXISTS jiu_db; CREATE DATABASE jiu_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'"
|
||||
"docker exec jiu_mysql sh -c 'exec mysql -uroot -p\$MYSQL_ROOT_PASSWORD -e \"DROP DATABASE IF EXISTS jiu_db; CREATE DATABASE jiu_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\"'"
|
||||
echo "✓ Database reset"
|
||||
|
||||
# 2. 重启 jiu-server,AutoMigrate 重建表结构
|
||||
@@ -57,13 +56,13 @@ jobs:
|
||||
echo "→ Seeding $SHOP ..."
|
||||
if [ "$FIRST" = "true" ]; then
|
||||
ssh -i ~/.ssh/ec2_deploy.pem ${EC2_USER}@${EC2_HOST} \
|
||||
"docker exec -i jiu_mysql mysql -uroot -p${DB_PASSWORD} --default-character-set=utf8mb4 jiu_db" \
|
||||
"docker exec -i jiu_mysql sh -c 'exec mysql -uroot -p\$MYSQL_ROOT_PASSWORD --default-character-set=utf8mb4 jiu_db'" \
|
||||
< "$FILE"
|
||||
FIRST=false
|
||||
else
|
||||
grep -v "^TRUNCATE" "$FILE" | \
|
||||
ssh -i ~/.ssh/ec2_deploy.pem ${EC2_USER}@${EC2_HOST} \
|
||||
"docker exec -i jiu_mysql mysql -uroot -p${DB_PASSWORD} --default-character-set=utf8mb4 jiu_db"
|
||||
"docker exec -i jiu_mysql sh -c 'exec mysql -uroot -p\$MYSQL_ROOT_PASSWORD --default-character-set=utf8mb4 jiu_db'"
|
||||
fi
|
||||
echo "✓ $SHOP done"
|
||||
done
|
||||
|
||||
@@ -21,15 +21,14 @@ jobs:
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
printf '%s' "${{ secrets.EC2_SSH_KEY }}" > ~/.ssh/ec2_deploy.pem
|
||||
printf '%s' "${{ secrets.ALI_SSH_KEY }}" > ~/.ssh/ec2_deploy.pem
|
||||
chmod 600 ~/.ssh/ec2_deploy.pem
|
||||
ssh-keyscan -H ${{ secrets.EC2_HOST }} >> ~/.ssh/known_hosts
|
||||
ssh-keyscan -H ${{ secrets.ALI_HOST }} >> ~/.ssh/known_hosts
|
||||
|
||||
- name: Seed databases
|
||||
env:
|
||||
EC2_HOST: ${{ secrets.EC2_HOST }}
|
||||
EC2_USER: ${{ secrets.EC2_USER }}
|
||||
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
|
||||
EC2_HOST: ${{ secrets.ALI_HOST }}
|
||||
EC2_USER: ${{ secrets.ALI_USER }}
|
||||
SHOPS: ${{ github.event.inputs.shops }}
|
||||
CLEAR: ${{ github.event.inputs.clear }}
|
||||
run: |
|
||||
@@ -41,7 +40,7 @@ jobs:
|
||||
echo " 清空 ${SHOP}..."
|
||||
printf "SET @shop_code='%s';\n" "$SHOP" | cat - backend/seeds/clear_shop.sql | \
|
||||
ssh -i ~/.ssh/ec2_deploy.pem ${EC2_USER}@${EC2_HOST} \
|
||||
"docker exec -i jiu_mysql mysql -uroot -p${DB_PASSWORD} --default-character-set=utf8mb4 jiu_db"
|
||||
"docker exec -i jiu_mysql sh -c 'exec mysql -uroot -p\$MYSQL_ROOT_PASSWORD --default-character-set=utf8mb4 jiu_db'"
|
||||
done
|
||||
echo "✓ 清空完成"
|
||||
fi
|
||||
@@ -56,7 +55,7 @@ jobs:
|
||||
fi
|
||||
echo "→ Seeding $SHOP ..."
|
||||
ssh -i ~/.ssh/ec2_deploy.pem ${EC2_USER}@${EC2_HOST} \
|
||||
"docker exec -i jiu_mysql mysql -uroot -p${DB_PASSWORD} --default-character-set=utf8mb4 jiu_db" \
|
||||
"docker exec -i jiu_mysql sh -c 'exec mysql -uroot -p\$MYSQL_ROOT_PASSWORD --default-character-set=utf8mb4 jiu_db'" \
|
||||
< "$FILE"
|
||||
echo "✓ $SHOP done"
|
||||
done
|
||||
|
||||
+46
-19
@@ -2,34 +2,51 @@
|
||||
# 与 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 跳转块)。
|
||||
# 2026-07-03 备案通过回切:443 ssl(jiu.51yanmei.com)为唯一正式入口 + 80→443 跳转。
|
||||
# 8443 明文过渡口已拆(用户拍板:裸 IP 版 client 从未发过,存量客户端都是 https
|
||||
# 域名 BASE_URL,DNS 回切后自动恢复,8443 无人使用)。
|
||||
# 证书:/etc/nginx/ssl/jiu.51yanmei.com/(2026-07-03 从 EC2 letsencrypt 同步,
|
||||
# 2026-08-28 到期;续期方案=DNS 已指 ali 后 certbot HTTP-01 webroot,见 baize)。
|
||||
# 后端上游 = 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 8443 default_server;
|
||||
server_name _;
|
||||
# ali nginx 1.24 无 `http2 on;`(1.25.1+),用 listen 参数旧语法
|
||||
listen 443 ssl http2 default_server; # 正式入口(备案后回切 2026-07-03)
|
||||
server_name jiu.51yanmei.com _;
|
||||
|
||||
# 备案通过切回 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;
|
||||
# 证书现为 EC2 同步副本(2026-08-28 到期)。ACME 通道已就绪:待批准后在 ali 跑
|
||||
# `certbot certonly --webroot -w /var/www/acme -d jiu.51yanmei.com` 签新证,
|
||||
# 然后把这两行换成 /etc/letsencrypt/live/jiu.51yanmei.com/ 并配 reload 部署钩子。
|
||||
ssl_certificate /etc/nginx/ssl/jiu.51yanmei.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/nginx/ssl/jiu.51yanmei.com/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
# 安全响应头(SEC-P02)。注意 nginx add_header 继承规则:location 内有自己的
|
||||
# add_header 时会整体覆盖 server 级——故 /images、/app/index.html、/downloads
|
||||
# 三处各自补了 HSTS。
|
||||
add_header Strict-Transport-Security "max-age=31536000" always;
|
||||
add_header X-Frame-Options SAMEORIGIN always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
|
||||
client_max_body_size 20m;
|
||||
|
||||
# certbot HTTP-01 续期通道(webroot 独立目录,不放 marketing——
|
||||
# deploy-site 的 rsync --delete 会清掉站点目录里的挑战文件)
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
root /var/www/acme;
|
||||
}
|
||||
|
||||
# 商品图片静态文件
|
||||
location ^~ /images/ {
|
||||
alias /opt/jiu/images/;
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
add_header Strict-Transport-Security "max-age=31536000" always;
|
||||
}
|
||||
|
||||
# 文件导入接口(超时更长)
|
||||
@@ -68,6 +85,7 @@ server {
|
||||
alias /opt/jiu/web/index.html;
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
add_header Pragma "no-cache";
|
||||
add_header Strict-Transport-Security "max-age=31536000" always;
|
||||
expires 0;
|
||||
}
|
||||
|
||||
@@ -95,6 +113,7 @@ server {
|
||||
alias /opt/jiu/downloads/;
|
||||
add_header Content-Disposition "attachment";
|
||||
add_header Cache-Control "no-cache";
|
||||
add_header Strict-Transport-Security "max-age=31536000" always;
|
||||
autoindex off;
|
||||
}
|
||||
|
||||
@@ -105,9 +124,17 @@ server {
|
||||
}
|
||||
}
|
||||
|
||||
# 备案通过、入口切回 443 后再恢复此跳转块(80 未备案期间被拦截,挂了也无意义):
|
||||
# server {
|
||||
# listen 80;
|
||||
# server_name jiu.51yanmei.com;
|
||||
# return 301 https://$host$request_uri;
|
||||
# }
|
||||
# 80 → 443 跳转(仅 jiu 域名;51yanmei.com 门户 80 在 51yanmei.conf 自管)。
|
||||
# ACME 挑战必须在跳转前放行(HTTP-01 走 80)。
|
||||
server {
|
||||
listen 80;
|
||||
server_name jiu.51yanmei.com;
|
||||
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
root /var/www/acme;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
+14
-9
@@ -1,10 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
# backup-db.sh — dump the production MySQL (jiu_db) from EC2 and keep a gzip
|
||||
# snapshot on the mac (host) runner's local disk (~/jiu-db-backups), retaining
|
||||
# the last 30 days. The DB password is read on EC2 from production.env's
|
||||
# DATABASE_DSN, so no DB-password secret is needed.
|
||||
# backup-db.sh — dump the production MySQL (jiu_db) from the production host
|
||||
# and keep a gzip snapshot on the mac (host) runner's local disk
|
||||
# (~/jiu-db-backups), retaining the last 30 days. The DB password is read on
|
||||
# the host from production.env's DATABASE_DSN, so no DB-password secret is
|
||||
# needed.
|
||||
#
|
||||
# Requires env (same as deploy-server): EC2_SSH_KEY, EC2_HOST, EC2_USER.
|
||||
# Target host (post-cutover 2026-07-03: Ali is the primary): pass
|
||||
# DEPLOY_SSH_KEY / DEPLOY_HOST / DEPLOY_USER (falls back to EC2_* legacy vars).
|
||||
set -euo pipefail
|
||||
|
||||
# shellcheck source=scripts/ci/lib-forgejo.sh
|
||||
@@ -15,15 +17,18 @@ mkdir -p "${BACKUP_DIR}"
|
||||
FILENAME="jiu_db_$(date +%Y%m%d_%H%M%S).sql.gz"
|
||||
DEST="${BACKUP_DIR}/${FILENAME}"
|
||||
|
||||
TARGET_HOST="${DEPLOY_HOST:-$EC2_HOST}"
|
||||
TARGET_USER="${DEPLOY_USER:-$EC2_USER}"
|
||||
|
||||
setup_ssh
|
||||
trap teardown_ssh EXIT
|
||||
|
||||
echo "==> backup-db: dumping jiu_db from ${EC2_HOST}"
|
||||
# On EC2: parse the DSN password from production.env, then mysqldump the
|
||||
echo "==> backup-db: dumping jiu_db from ${TARGET_HOST}"
|
||||
# On the host: parse the DSN password from production.env, then mysqldump the
|
||||
# container to stdout; stream back over ssh and gzip locally. The heredoc is
|
||||
# single-quoted, so it runs verbatim on EC2 (no local expansion). ${SSH} carries
|
||||
# single-quoted, so it runs verbatim on the host (no local expansion). ${SSH} carries
|
||||
# no -t, keeping stdout a clean dump stream.
|
||||
${SSH} "${EC2_USER}@${EC2_HOST}" 'bash -s' <<'ENDSSH' | gzip > "${DEST}"
|
||||
${SSH} "${TARGET_USER}@${TARGET_HOST}" 'bash -s' <<'ENDSSH' | gzip > "${DEST}"
|
||||
set -euo pipefail
|
||||
PW=$(python3 -c 'import re;e=open("/opt/jiu/config/production.env").read();d=re.search(r"DATABASE_DSN=(.*)",e).group(1).strip().strip(chr(34)).strip(chr(39));print(re.match(r"[^:]+:([^@]+)@",d).group(1))')
|
||||
exec docker exec -e MYSQL_PWD="${PW}" jiu_mysql mysqldump -uroot --single-transaction --no-tablespaces jiu_db
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
# 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).
|
||||
# reload the host nginx (443 ssl jiu.51yanmei.com, 备案回切 2026-07-03).
|
||||
# - 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.
|
||||
@@ -56,7 +56,7 @@ fi
|
||||
if [ "$DEPLOY_TARGET" = "ali" ]; then
|
||||
# --- 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.
|
||||
# DB on :8081; nginx serves 443 ssl (jiu.51yanmei.com, 备案回切 2026-07-03).
|
||||
${SSH} "${TARGET_USER}@${TARGET_HOST}" << 'ENDSSH'
|
||||
set -e
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ else
|
||||
fi
|
||||
|
||||
MSG="${ICON} 岩美 ${TAG} ${LABEL}
|
||||
https://jiu.51yanmei.com"
|
||||
https://jiu.51yanmei.com" # 2026-07-03 备案通过,正式域名入口
|
||||
|
||||
curl -f -X POST "https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage" \
|
||||
-d "chat_id=${TELEGRAM_CHAT_ID}" \
|
||||
|
||||
@@ -28,7 +28,7 @@ ver = sys.argv[1]
|
||||
notes = sys.argv[2]
|
||||
changelog_file = sys.argv[3]
|
||||
|
||||
base = "https://jiu.51yanmei.com/downloads"
|
||||
base = "https://jiu.51yanmei.com/downloads" # 2026-07-03 备案通过回切 https 域名
|
||||
mac_url = f"{base}/jiu-macos-x64.zip"
|
||||
win_url = f"{base}/jiu-windows-x64-setup.exe"
|
||||
android_url = f"{base}/jiu-android.apk"
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
# sh scripts/local_test.sh # 编译 + 启动
|
||||
# sh scripts/local_test.sh --no-open # 只编译不启动
|
||||
#
|
||||
# 后端固定指向生产 https://jiu.51yanmei.com(与 CI compile-macos.sh 一致)。
|
||||
# 后端固定指向生产 https://jiu.51yanmei.com(与 CI compile-macos.sh 一致;
|
||||
# 2026-07-03 备案通过已回切 https 域名)。
|
||||
set -euo pipefail
|
||||
|
||||
export PATH="/opt/homebrew/bin:$PATH"
|
||||
|
||||
Reference in New Issue
Block a user