- edge: 容器化 nginx 接管 80/443,逐字移植现网 vhost(blog/jiu/marzban/pay)+ stream SNI 分流 - singbox: Hysteria2(host 网络,UDP 443) - certbot: DNS-01(Cloudflare)续期,容器化 - xray: REALITY 仅 profile newnode(本台沿用 Marzban) - deploy.sh 幂等且切换感知;cutover.sh 一次性停宿主 nginx 切容器(可秒级回滚) - 弃用方案A 的 host nginx-apply/sudoers/root-setup - 部署目录改 ~/pangolin(免 root);CI 注入 CF_API_TOKEN EC2 实测:edge nginx -t 通过(真实证书)、compose 校验通过 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+32
-47
@@ -1,61 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
# deploy.sh —— 在 EC2 上幂等编排 pangolin 数据面。
|
||||
# 由 CI(NAS runner via ssh)调用,也可手动 `ssh ec2 'cd /opt/pangolin && ./scripts/deploy.sh'`。
|
||||
#
|
||||
# 步骤:生成密钥 -> 渲染配置 -> docker-compose up -> (幂等)加 nginx 路由 -> 健康检查 -> 输出客户端信息
|
||||
# 全程不触碰 marzban/blog/jiu;唯一特权动作是 sudo 调用受限的 nginx-apply 脚本。
|
||||
# deploy.sh —— 幂等部署(免 root)。CI 与手动均可。
|
||||
# - 总是确保 singbox(Hy2)在跑;
|
||||
# - edge:若宿主 nginx 仍在(未切换)则只校验配置、不启动(避免抢 80/443);
|
||||
# 宿主 nginx 已停(已切换)则正常拉起。
|
||||
# 首次 nginx 切换由 cutover.sh(需 root 一次)完成。
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.." # -> deploy/
|
||||
|
||||
COMPOSE="docker-compose -p pangolin"
|
||||
NGINX_APPLY="/usr/local/sbin/pangolin-nginx-apply.sh"
|
||||
EDGE_IMAGE="nginx:1.27-alpine"
|
||||
|
||||
echo "==> [1/5] 生成/复用密钥与证书"
|
||||
echo "==> [1/4] 生成/复用密钥与证书"
|
||||
./scripts/gen-secrets.sh
|
||||
|
||||
echo "==> [2/5] 渲染配置(模板 -> config.json)"
|
||||
echo "==> [2/4] 渲染配置"
|
||||
# shellcheck disable=SC1091
|
||||
source ./secrets/pangolin.env
|
||||
render() { # render <tmpl> <out>
|
||||
sed -e "s|__UUID__|${UUID}|g" \
|
||||
-e "s|__REALITY_PRIVATE_KEY__|${REALITY_PRIVATE_KEY}|g" \
|
||||
-e "s|__REALITY_SHORT_ID__|${REALITY_SHORT_ID}|g" \
|
||||
-e "s|__HY2_PASSWORD__|${HY2_PASSWORD}|g" \
|
||||
"$1" > "$2"
|
||||
sed "s|__HY2_PASSWORD__|${HY2_PASSWORD}|g" ./singbox/config.tmpl.json > ./singbox/config.json
|
||||
|
||||
echo "==> [3/4] 拉起 singbox(Hy2)"
|
||||
docker-compose -p pangolin up -d singbox
|
||||
docker-compose -p pangolin ps singbox
|
||||
|
||||
echo "==> [4/4] edge(分发层)"
|
||||
edge_validate() {
|
||||
docker run --rm \
|
||||
-v "$PWD/edge/nginx.conf:/etc/nginx/nginx.conf:ro" \
|
||||
-v "$PWD/edge/stream.conf:/etc/nginx/stream.conf:ro" \
|
||||
-v "$PWD/edge/conf.d:/etc/nginx/conf.d:ro" \
|
||||
-v /etc/letsencrypt:/etc/letsencrypt:ro \
|
||||
-v /opt/jiu:/opt/jiu:ro \
|
||||
-v /var/www/pay:/var/www/pay:ro \
|
||||
"$EDGE_IMAGE" nginx -t
|
||||
}
|
||||
render ./xray/config.tmpl.json ./xray/config.json
|
||||
render ./singbox/config.tmpl.json ./singbox/config.json
|
||||
|
||||
echo "==> [3/5] 拉起容器(docker-compose up -d)"
|
||||
$COMPOSE pull --quiet || true
|
||||
$COMPOSE up -d
|
||||
$COMPOSE ps
|
||||
|
||||
echo "==> [4/5] nginx SNI 路由(幂等)"
|
||||
if grep -qF "127.0.0.1:11443" /etc/nginx/stream.conf 2>/dev/null; then
|
||||
echo " 路由已存在,跳过"
|
||||
elif [[ -x "$NGINX_APPLY" ]]; then
|
||||
sudo "$NGINX_APPLY"
|
||||
if systemctl is-active --quiet nginx 2>/dev/null; then
|
||||
echo " 宿主 nginx 仍在运行 → 仅校验 edge 配置,不启动(切换请跑 cutover.sh)"
|
||||
edge_validate && echo " edge 配置校验通过 ✅"
|
||||
else
|
||||
echo " !! 未找到 $NGINX_APPLY(需先执行一次性 root 前置 setup/root-setup.sh)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "==> [5/5] 健康检查"
|
||||
ok=1
|
||||
# REALITY:经宿主 nginx 用 www.apple.com 做 TLS 握手应成功
|
||||
if echo | timeout 10 openssl s_client -connect 127.0.0.1:443 -servername www.apple.com >/dev/null 2>&1; then
|
||||
echo " [REALITY] 443/www.apple.com 握手 OK"
|
||||
else
|
||||
echo " [REALITY] 握手失败"; ok=0
|
||||
fi
|
||||
# Hy2:UDP 443 应有 sing-box 在监听
|
||||
if ss -uln 2>/dev/null | grep -q ":443 "; then
|
||||
echo " [Hy2] UDP 443 监听 OK"
|
||||
else
|
||||
echo " [Hy2] UDP 443 未监听"; ok=0
|
||||
echo " 宿主 nginx 未运行 → 拉起 edge"
|
||||
edge_validate
|
||||
docker-compose -p pangolin up -d edge
|
||||
docker-compose -p pangolin ps edge
|
||||
fi
|
||||
|
||||
./scripts/print-clients.sh
|
||||
|
||||
[[ "$ok" == "1" ]] && echo "==> 部署完成 ✅" || { echo "==> 健康检查未通过 ❌"; exit 1; }
|
||||
echo "==> 完成 ✅"
|
||||
|
||||
Reference in New Issue
Block a user