diff --git a/deploy/enable-runxian-dukang-ssl.sh b/deploy/enable-runxian-dukang-ssl.sh new file mode 100644 index 0000000..4240266 --- /dev/null +++ b/deploy/enable-runxian-dukang-ssl.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# 为杜康 runxian.top 五域名申请 Let's Encrypt 并切换 HTTPS 配置 +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +DOMAINS=( + user.runxian.top + shop.runxian.top + partner.runxian.top + webadmin.runxian.top + dkapi.runxian.top +) + +echo "==> 检查 DNS 解析到本机..." +for d in "${DOMAINS[@]}"; do + ip="$(dig +short "$d" @223.5.5.5 | tail -1)" + if [[ -z "$ip" ]]; then + echo "ERROR: $d 无 A 记录,请先在 DNS 添加指向本机公网 IP" + exit 1 + fi + echo " $d -> $ip" +done + +mkdir -p /var/www/certbot /var/log/nginx/dukang + +echo "==> 申请证书..." +certbot certonly --webroot -w /var/www/certbot \ + --cert-name user.runxian.top \ + -d user.runxian.top \ + -d shop.runxian.top \ + -d partner.runxian.top \ + -d webadmin.runxian.top \ + -d dkapi.runxian.top \ + --non-interactive --agree-tos -m admin@runxian.top || { + echo "certbot 失败,请确认 DNS 已生效且 80 端口可从公网访问" + exit 1 +} + +echo "==> 切换 nginx HTTPS 配置..." +install -m 644 "$SCRIPT_DIR/nginx-runxian-dukang-ssl.conf" /etc/nginx/conf.d/dukang-runxian.conf +nginx -t +systemctl reload nginx + +echo "==> 验证..." +for url in \ + https://user.runxian.top/ \ + https://shop.runxian.top/ \ + https://partner.runxian.top/ \ + https://webadmin.runxian.top/ \ + https://dkapi.runxian.top/api/v1/health; do + code="$(curl -sf -o /dev/null -w '%{http_code}' "$url" || echo fail)" + echo " $url -> $code" +done + +echo "==> runxian.top 杜康域名 HTTPS 已启用" diff --git a/deploy/nginx-runxian-dukang-ssl.conf b/deploy/nginx-runxian-dukang-ssl.conf new file mode 100644 index 0000000..b240a5c --- /dev/null +++ b/deploy/nginx-runxian-dukang-ssl.conf @@ -0,0 +1,150 @@ +# 杜康好客 — runxian.top HTTPS(证书申请后启用) +# 执行: deploy/enable-runxian-dukang-ssl.sh + +map $host $dukang_runxian_port { + user.runxian.top 8091; + shop.runxian.top 8092; + partner.runxian.top 8093; + webadmin.runxian.top 8094; +} + +server { + listen 80; + server_name user.runxian.top shop.runxian.top partner.runxian.top; + + location ^~ /.well-known/acme-challenge/ { + root /var/www/certbot; + default_type "text/plain"; + } + + location ~ ^/MP_verify_.*\.txt$ { + root /opt/dukang-haoke/apps/h5-user/dist; + default_type text/plain; + access_log off; + } + + location / { + return 301 https://$host$request_uri; + } +} + +server { + listen 443 ssl; + server_name user.runxian.top shop.runxian.top partner.runxian.top; + + access_log /var/log/nginx/dukang/runxian-h5.access.log main; + error_log /var/log/nginx/dukang/runxian-h5.error.log warn; + + ssl_certificate /etc/letsencrypt/live/user.runxian.top/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/user.runxian.top/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + + client_max_body_size 20m; + + location /api/ { + proxy_pass http://127.0.0.1:8090; + proxy_http_version 1.1; + 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; + proxy_set_header Connection ""; + } + + location / { + proxy_pass http://127.0.0.1:$dukang_runxian_port; + proxy_http_version 1.1; + 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; + } +} + +server { + listen 80; + server_name dkapi.runxian.top; + + location ^~ /.well-known/acme-challenge/ { + root /var/www/certbot; + default_type "text/plain"; + } + + location / { + return 301 https://$host$request_uri; + } +} + +server { + listen 443 ssl; + server_name dkapi.runxian.top; + + access_log /var/log/nginx/dukang/runxian-api.access.log main; + error_log /var/log/nginx/dukang/runxian-api.error.log warn; + + ssl_certificate /etc/letsencrypt/live/user.runxian.top/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/user.runxian.top/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + + client_max_body_size 20m; + + location / { + proxy_pass http://127.0.0.1:8090; + proxy_http_version 1.1; + 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; + proxy_set_header Connection ""; + } +} + +server { + listen 80; + server_name webadmin.runxian.top; + + location ^~ /.well-known/acme-challenge/ { + root /var/www/certbot; + default_type "text/plain"; + } + + location / { + return 301 https://$host$request_uri; + } +} + +server { + listen 443 ssl; + server_name webadmin.runxian.top; + + access_log /var/log/nginx/dukang/runxian-admin.access.log main; + error_log /var/log/nginx/dukang/runxian-admin.error.log warn; + + ssl_certificate /etc/letsencrypt/live/user.runxian.top/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/user.runxian.top/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + + client_max_body_size 20m; + + location /api/ { + proxy_pass http://127.0.0.1:8090; + proxy_http_version 1.1; + 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; + proxy_set_header Connection ""; + } + + location / { + proxy_pass http://127.0.0.1:8094; + proxy_http_version 1.1; + 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; + } +} diff --git a/deploy/nginx-runxian-dukang.conf b/deploy/nginx-runxian-dukang.conf new file mode 100644 index 0000000..7247625 --- /dev/null +++ b/deploy/nginx-runxian-dukang.conf @@ -0,0 +1,110 @@ +# 杜康好客 — runxian.top 别名域名(与 lingshivip.cn 同后端) +# user/shop/partner → 8091/8092/8093;webadmin → 8094;dkapi → 8090 +# 证书:certbot --cert-name user.runxian.top -d user.runxian.top -d shop.runxian.top ... + +map $host $dukang_runxian_port { + user.runxian.top 8091; + shop.runxian.top 8092; + partner.runxian.top 8093; + webadmin.runxian.top 8094; +} + +# --- HTTP: H5 三端(校验文件 + API;证书就绪后见 dukang-runxian-ssl.conf)--- +server { + listen 80; + server_name user.runxian.top shop.runxian.top partner.runxian.top; + + access_log /var/log/nginx/dukang/runxian-h5.access.log main; + error_log /var/log/nginx/dukang/runxian-h5.error.log warn; + + location ^~ /.well-known/acme-challenge/ { + root /var/www/certbot; + default_type "text/plain"; + } + + location ~ ^/MP_verify_.*\.txt$ { + root /opt/dukang-haoke/apps/h5-user/dist; + default_type text/plain; + access_log off; + } + + location /api/ { + proxy_pass http://127.0.0.1:8090; + proxy_http_version 1.1; + 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; + proxy_set_header Connection ""; + } + + location / { + proxy_pass http://127.0.0.1:$dukang_runxian_port; + proxy_http_version 1.1; + 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; + } +} + +# --- HTTP: API --- +server { + listen 80; + server_name dkapi.runxian.top; + + access_log /var/log/nginx/dukang/runxian-api.access.log main; + error_log /var/log/nginx/dukang/runxian-api.error.log warn; + + client_max_body_size 20m; + + location ^~ /.well-known/acme-challenge/ { + root /var/www/certbot; + default_type "text/plain"; + } + + location / { + proxy_pass http://127.0.0.1:8090; + proxy_http_version 1.1; + 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; + proxy_set_header Connection ""; + } +} + +# --- HTTP: admin-web --- +server { + listen 80; + server_name webadmin.runxian.top; + + access_log /var/log/nginx/dukang/runxian-admin.access.log main; + error_log /var/log/nginx/dukang/runxian-admin.error.log warn; + + client_max_body_size 20m; + + location ^~ /.well-known/acme-challenge/ { + root /var/www/certbot; + default_type "text/plain"; + } + + location /api/ { + proxy_pass http://127.0.0.1:8090; + proxy_http_version 1.1; + 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; + proxy_set_header Connection ""; + } + + location / { + proxy_pass http://127.0.0.1:8094; + proxy_http_version 1.1; + 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; + } +} diff --git a/deploy/remote-release.sh b/deploy/remote-release.sh index b574373..b0f24ff 100644 --- a/deploy/remote-release.sh +++ b/deploy/remote-release.sh @@ -70,7 +70,8 @@ fi echo "==> 5. 重启 PM2" if pm2 describe dukang-api &>/dev/null; then - pm2 restart dukang-api dukang-h5-user dukang-h5-shop dukang-h5-partner + pm2 restart dukang-api dukang-h5-user dukang-h5-shop dukang-h5-partner dukang-admin-web 2>/dev/null \ + || pm2 restart dukang-api dukang-h5-user dukang-h5-shop dukang-h5-partner else pm2 start "$DEPLOY_DIR/ecosystem.config.cjs" fi