From a498cc4799d7dd10add266f553e411ee5e9a8180 Mon Sep 17 00:00:00 2001 From: david_bai Date: Thu, 2 Oct 2025 22:45:42 +0800 Subject: [PATCH] chore(deploy): public output polish and public/full config fixes - deploy.sh: show public endpoints (domain/public IP only); add TURN info (domain/public IP); prepend logs chmod 777; append HTTPS+Nginx quick-test tips. - generate-config.sh: fix public/full CORS and NEXT_PUBLIC_API_URL; prefer PUBLIC_IP for TURN host when no domain; update help text. --- deploy.sh | 101 +++++++++++++++++++++++++----- docker/scripts/generate-config.sh | 20 +++--- 2 files changed, 99 insertions(+), 22 deletions(-) diff --git a/deploy.sh b/deploy.sh index 2324d71..b59e94e 100644 --- a/deploy.sh +++ b/deploy.sh @@ -210,7 +210,12 @@ setup_environment() { # 构建和启动服务 deploy_services() { log_info "构建和启动服务..." - + + # 确保日志目录存在并放宽权限,避免容器无法写日志(coturn/nginx 等) + mkdir -p logs logs/nginx logs/backend logs/frontend logs/coturn 2>/dev/null || true + chmod 777 -R logs 2>/dev/null || true + log_info "日志目录已准备并授权: ./logs (权限 777)" + # 停止现有服务 if docker compose ps | grep -q "Up"; then log_info "停止现有服务..." @@ -312,31 +317,76 @@ show_deployment_info() { # 读取配置信息 local local_ip="" + local public_ip="" local frontend_port="" local backend_port="" + local deployment_mode="" + local network_mode="" + local domain_name="" + local turn_enabled_env="" if [[ -f ".env" ]]; then local_ip=$(grep "LOCAL_IP=" .env | cut -d'=' -f2) + public_ip=$(grep "PUBLIC_IP=" .env | cut -d'=' -f2) frontend_port=$(grep "FRONTEND_PORT=" .env | cut -d'=' -f2) backend_port=$(grep "BACKEND_PORT=" .env | cut -d'=' -f2) + deployment_mode=$(grep "DEPLOYMENT_MODE=" .env | cut -d'=' -f2) + network_mode=$(grep "NETWORK_MODE=" .env | cut -d'=' -f2) + domain_name=$(grep "DOMAIN_NAME=" .env | cut -d'=' -f2) + turn_enabled_env=$(grep "TURN_ENABLED=" .env | cut -d'=' -f2) fi echo -e "${BLUE}📋 访问信息:${NC}" - echo " 前端应用: http://localhost:${frontend_port:-3002}" - echo " 后端API: http://localhost:${backend_port:-3001}" - - if [[ -n "$local_ip" ]] && [[ "$local_ip" != "127.0.0.1" ]]; then - echo "" - echo -e "${BLUE}🌐 局域网访问:${NC}" - echo " 前端应用: http://$local_ip:${frontend_port:-3002}" - echo " 后端API: http://$local_ip:${backend_port:-3001}" + + # 判定是否公网场景(public/full) + local is_public="false" + if [[ "$deployment_mode" == "public" || "$deployment_mode" == "full" || "$network_mode" == "public" ]]; then + is_public="true" + fi + + if [[ "$is_public" == "true" ]]; then + # 公网展示优先域名,其次公网IP + if [[ -n "$domain_name" ]]; then + if [[ "$WITH_NGINX" == "true" || "$deployment_mode" == "full" ]]; then + echo " 公网访问: https://$domain_name" + echo " API 地址: https://$domain_name" + else + echo " 公网访问: http://$domain_name:${frontend_port:-3002}" + echo " API 地址: http://$domain_name:${backend_port:-3001}" + fi + elif [[ -n "$public_ip" ]]; then + echo " 公网访问: http://$public_ip:${frontend_port:-3002}" + echo " API 地址: http://$public_ip:${backend_port:-3001}" + else + # 回退:无法获取公网IP时给出局域网与本机 + echo " 前端应用: http://localhost:${frontend_port:-3002}" + echo " 后端API: http://localhost:${backend_port:-3001}" + fi + else + # 内网/基础模式:本机+局域网 + echo " 前端应用: http://localhost:${frontend_port:-3002}" + echo " 后端API: http://localhost:${backend_port:-3001}" + if [[ -n "$local_ip" ]] && [[ "$local_ip" != "127.0.0.1" ]]; then + echo "" + echo -e "${BLUE}🌐 局域网访问:${NC}" + echo " 前端应用: http://$local_ip:${frontend_port:-3002}" + echo " 后端API: http://$local_ip:${backend_port:-3001}" + fi fi if [[ "$WITH_NGINX" == "true" ]]; then echo "" echo -e "${BLUE}🔀 Nginx代理:${NC}" - echo " HTTP: http://localhost" - [[ -f "docker/ssl/server-cert.pem" ]] && echo " HTTPS: https://localhost" + if [[ -n "$domain_name" ]]; then + echo " HTTP: http://$domain_name" + [[ -f "docker/ssl/server-cert.pem" ]] && echo " HTTPS: https://$domain_name" + elif [[ -n "$public_ip" ]]; then + echo " HTTP: http://$public_ip" + [[ -f "docker/ssl/server-cert.pem" ]] && echo " HTTPS: https://$public_ip" + else + echo " HTTP: http://localhost" + [[ -f "docker/ssl/server-cert.pem" ]] && echo " HTTPS: https://localhost" + fi fi echo "" @@ -354,7 +404,7 @@ show_deployment_info() { echo " 要信任HTTPS连接,请将CA证书导入浏览器" fi - if [[ "$WITH_TURN" == "true" ]]; then + if [[ "$WITH_TURN" == "true" || "$turn_enabled_env" == "true" ]]; then local turn_username="" local turn_realm="" if [[ -f ".env" ]]; then @@ -364,8 +414,18 @@ show_deployment_info() { echo "" echo -e "${BLUE}🔄 TURN服务器:${NC}" - echo " STUN: stun:$local_ip:3478" - echo " TURN: turn:$local_ip:3478" + # 展示优先域名的 TURN 信息,否则展示公网IP + if [[ -n "$domain_name" ]]; then + echo " STUN: stun:${domain_name}:3478" + echo " TURN (UDP): turn:${domain_name}:3478" + echo " TURN (TLS): turns:turn.${domain_name}:443 (如已配置 443 SNI 分流)" + elif [[ -n "$public_ip" ]]; then + echo " STUN: stun:${public_ip}:3478" + echo " TURN: turn:${public_ip}:3478" + else + echo " STUN: stun:${local_ip}:3478" + echo " TURN: turn:${local_ip}:3478" + fi echo " 用户名: ${turn_username:-privydrop}" echo " 密码: (保存在.env文件中)" fi @@ -376,6 +436,19 @@ show_deployment_info() { echo " - 如遇问题,请查看日志: docker compose logs -f" echo " - 更多帮助: $0 --help" echo "" + + # 公网场景追加:如何测试域名(HTTPS+Nginx) + if [[ "$is_public" == "true" && -z "$domain_name" ]]; then + echo -e "${BLUE}🌍 公网域名部署(HTTPS + Nginx)快速测试:${NC}" + echo " 1) 将你的域名 A 记录解析到 ${public_ip:-}" + echo " 可选:将 turn. 也解析到同一IP,用于 TURN 主机名" + echo " 2) 运行: ./deploy.sh --mode full --domain --with-nginx --with-turn" + echo " 3) 放行端口: 80, 443, 3478/udp, 5349/tcp, 5349/udp" + echo " 4) 验证: https:// 正常打开,/api/health 返回 200" + echo " WebRTC: 打开 webrtc-internals,观察是否出现 relay 候选 (TURN)" + echo " 注: 目前 Docker 版本未启用 443 SNI 转发至 coturn,如需 turns:443 请后续启用 stream 分流。" + echo "" + fi } # 主函数 diff --git a/docker/scripts/generate-config.sh b/docker/scripts/generate-config.sh index bf258da..5cd5bb7 100755 --- a/docker/scripts/generate-config.sh +++ b/docker/scripts/generate-config.sh @@ -74,8 +74,8 @@ PrivyDrop 配置生成脚本(Docker 版) 选项: --mode MODE 生成模式: private|basic|public|full private/basic: 内网HTTP;默认不启用TURN,前端直连后端 - public: 公网HTTP + 启用TURN(无域名也可,TURN host=本机IP) - full: 完整HTTPS + 启用TURN(建议配合域名) + public: 公网HTTP + 启用TURN(无域名也可,TURN host=公网IP优先) + full: 完整HTTPS + 启用TURN(建议配合域名,前端走域名HTTPS) --with-turn 在任意模式下启用TURN(含private/basic)。默认 external-ip=LOCAL_IP --turn-external-ip IP 显式指定TURN external-ip;不指定则使用 PUBLIC_IP,否则回退 LOCAL_IP --turn-port-range R 指定TURN端口段(UDP),格式 MIN-MAX;默认 49152-49252 @@ -88,7 +88,7 @@ PrivyDrop 配置生成脚本(Docker 版) TURN external-ip 写入优先使用 PUBLIC_IP, 留空则回退为 LOCAL_IP(仅同局域网可用,穿透受限)。 -生成内容: +生成内容(自动写入关键变量): - .env 核心环境变量(含 NEXT_PUBLIC_API_URL/CORS 等) - docker/nginx/* Nginx 反向代理配置(private/basic 也会生成 HTTP 配置) - docker/ssl/* 自签证书(private/basic/public 生成;full 可替换为正式证书) @@ -112,7 +112,7 @@ PrivyDrop 配置生成脚本(Docker 版) --turn-port-range 56000-56100 --turn-external-ip 192.168.0.113 \ [--local-ip 192.168.0.113] - # 4) 公网HTTP + TURN(自动探测公网IP,不带域名也可) + # 4) 公网HTTP + TURN(自动探测公网IP,不带域名也可;自动注入 NEXT_PUBLIC_API_URL) bash docker/scripts/generate-config.sh --mode public --local-ip 192.168.0.113 # 5) 公网HTTP + TURN(指定公网IP,避免外网探测) @@ -170,12 +170,15 @@ generate_env_file() { local next_public_turn_password="" if [[ "$DEPLOYMENT_MODE" == "public" ]]; then - cors_origin="http://${DOMAIN_NAME:-$LOCAL_IP},http://localhost" - api_url="$cors_origin" + # 公网无域名:前端直连后端,自动写入基于 PUBLIC_IP(无则回退 LOCAL_IP) + local effective_public_host="${PUBLIC_IP:-$LOCAL_IP}" + cors_origin="http://${effective_public_host}:3002,http://localhost:3002" + api_url="http://${effective_public_host}:3001" turn_enabled="true" elif [[ "$DEPLOYMENT_MODE" == "full" ]]; then + # 有域名HTTPS:前端与后端都走域名,由 Nginx /api 转发 cors_origin="https://${DOMAIN_NAME:-$LOCAL_IP}" - api_url="$cors_origin" + api_url="https://${DOMAIN_NAME:-$LOCAL_IP}" ssl_mode="letsencrypt" turn_enabled="true" fi @@ -190,7 +193,8 @@ generate_env_file() { turn_host_value="turn.${DOMAIN_NAME}" turn_realm_value="turn.${DOMAIN_NAME}" else - turn_host_value="$LOCAL_IP" + # 无域名时:主机优先使用 PUBLIC_IP,其次回退 LOCAL_IP + turn_host_value="${PUBLIC_IP:-$LOCAL_IP}" turn_realm_value="turn.local" fi