fix(deploy): 默认关闭沙箱公网访问

This commit is contained in:
2026-08-17 10:19:10 +08:00
parent 919a797510
commit ee52bcf34f
15 changed files with 332 additions and 33 deletions
+5 -5
View File
@@ -30,6 +30,9 @@ WEB_PORT=3010
SERVER_HTTP_PORT=3001
# easyai-server 后端 HTTP 端口
SERVER_HTTP_BIND_IP=127.0.0.1
# easyai-server 宿主机绑定地址。域名/本机部署保持 127.0.0.1;仅 IP/LAN 直连模式使用 0.0.0.0
NODE_MAX_OLD_SPACE_SIZE=8192
# easyai-server 的 Node.js V8 old-space 堆上限,单位 MiB
@@ -66,14 +69,11 @@ MEMORY_TCP_PORT=4004
# 记忆整理相关参数在 .env.AMS 中配置(MEMORY_MAINTENANCE_*
# ========== 4. 沙箱环境 ==========
SANDBOX_PORT=8081
# 不建议对外暴露
SANDBOX_JUPYTERLAB_PORT=8888
SANDBOX_JUPYTER_TOKEN=easyaiisbest
# 建议设置 token
# Sandbox API 与 JupyterLab 默认不映射宿主机端口;token 仅用于容器内 Jupyter 认证
SANDBOX_SERVICE_BASE_URL=
# 留空时 easyai-server 通过 Docker 内网 http://sandbox:8000 访问
# ========== 5. Redis ==========
REDIS_PORT=
@@ -10,6 +10,8 @@ on:
- '.env.sample'
- 'scripts/init-public-api-base-url.sh'
- 'scripts/test-public-api-base-url.sh'
- 'scripts/init-server-http-bind-ip.sh'
- 'scripts/test-server-http-bind-ip.sh'
- 'scripts/test-deployment-public-url.sh'
- '.github/workflows/test-deployment-public-url.yml'
pull_request:
@@ -21,6 +23,8 @@ on:
- '.env.sample'
- 'scripts/init-public-api-base-url.sh'
- 'scripts/test-public-api-base-url.sh'
- 'scripts/init-server-http-bind-ip.sh'
- 'scripts/test-server-http-bind-ip.sh'
- 'scripts/test-deployment-public-url.sh'
- '.github/workflows/test-deployment-public-url.yml'
workflow_dispatch:
@@ -33,10 +37,13 @@ jobs:
- name: Check shell syntax
run: |
bash -n start.sh update.sh scripts/init-public-api-base-url.sh scripts/test-public-api-base-url.sh scripts/test-deployment-public-url.sh
bash -n start.sh update.sh scripts/init-public-api-base-url.sh scripts/init-server-http-bind-ip.sh scripts/test-public-api-base-url.sh scripts/test-server-http-bind-ip.sh scripts/test-deployment-public-url.sh
- name: Test migration helper
run: bash scripts/test-public-api-base-url.sh
- name: Test server HTTP bind migration
run: bash scripts/test-server-http-bind-ip.sh
- name: Test deployment dry-run matrix
run: bash scripts/test-deployment-public-url.sh
+10
View File
@@ -8,6 +8,8 @@ on:
- 'update.ps1'
- 'scripts/Initialize-PublicApiBaseUrl.ps1'
- 'scripts/Test-PublicApiBaseUrl.ps1'
- 'scripts/Initialize-ServerHttpBindIp.ps1'
- 'scripts/Test-ServerHttpBindIp.ps1'
- '.env.sample'
- '.github/workflows/test-start-ps1.yml'
pull_request:
@@ -16,6 +18,8 @@ on:
- 'update.ps1'
- 'scripts/Initialize-PublicApiBaseUrl.ps1'
- 'scripts/Test-PublicApiBaseUrl.ps1'
- 'scripts/Initialize-ServerHttpBindIp.ps1'
- 'scripts/Test-ServerHttpBindIp.ps1'
- '.env.sample'
- '.github/workflows/test-start-ps1.yml'
workflow_dispatch:
@@ -40,12 +44,18 @@ jobs:
$socket = Select-String -Path .env -Pattern '^NUXT_PUBLIC_BASE_SOCKETURL=' | ForEach-Object { $_.Line }
$sg = Select-String -Path .env -Pattern '^NUXT_PUBLIC_SG_APIURL=' | ForEach-Object { $_.Line }
$publicApi = Select-String -Path .env -Pattern '^CONFIG_PUBLIC_API_BASE_URL=' | ForEach-Object { $_.Line }
$serverBindIp = Select-String -Path .env -Pattern '^SERVER_HTTP_BIND_IP=' | ForEach-Object { $_.Line }
if ($api -ne 'NUXT_PUBLIC_BASE_APIURL=http://192.168.1.100:4100') { exit 1 }
if ($socket -ne 'NUXT_PUBLIC_BASE_SOCKETURL=ws://192.168.1.100:3002') { exit 1 }
if ($sg -ne 'NUXT_PUBLIC_SG_APIURL=http://192.168.1.100:3003') { exit 1 }
if ($publicApi -ne 'CONFIG_PUBLIC_API_BASE_URL=http://192.168.1.100:4100') { exit 1 }
if ($serverBindIp -ne 'SERVER_HTTP_BIND_IP=0.0.0.0') { exit 1 }
Write-Host "OK: .env 配置正确"
- name: Test public API URL migration helper
run: |
powershell -ExecutionPolicy Bypass -File .\scripts\Test-PublicApiBaseUrl.ps1
- name: Test server HTTP bind migration helper
run: |
powershell -ExecutionPolicy Bypass -File .\scripts\Test-ServerHttpBindIp.ps1
+5 -2
View File
@@ -455,10 +455,11 @@ curl https://<你的域名>/asg-api/health
1. 增加脚本沙箱环境容器,需要更新`docker-compose.yml`,用以支持SKILL中的脚本运行
2. 增加环境变量配置
```dotenv
SANDBOX_PORT=8081 #对外暴露沙箱环境的端口,不建议暴露,权限较高
SANDBOX_SERVICE_BASE_URL= #脚本运行环境使用的服务地址,默认为通过内网直接访问http://sandbox:8000,不需要配置。当将sandbox部署在其他外部网络才需要配置
SANDBOX_SERVICE_BASE_URL= #脚本运行环境使用的服务地址,默认通过 Docker 内网访问 http://sandbox:8000,不需要配置
```
> 安全默认值:Sandbox API 与 JupyterLab 不映射宿主机端口,Nginx 模板对 `/api/sandbox`、`/sandbox`、`/jupyterlab` 返回 404。不要在公网重新开放这些高权限入口。
### 2025.1.29
@@ -582,6 +583,7 @@ cd easyai
```bash
NUXT_PUBLIC_BASE_APIURL=http://<你的服务器公网IP或者局域网地址>:3001
NUXT_PUBLIC_BASE_SOCKETURL=ws://<你的服务器公网IP或者局域网地址>:3002
SERVER_HTTP_BIND_IP=0.0.0.0
```
3. 开放服务器的3001、3002和3010端口
4. [首次执行,后续无需重复执行]添加脚本的执行权限,命令:
@@ -619,6 +621,7 @@ powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\start.ps1"
```bash
NUXT_PUBLIC_BASE_APIURL=/api
NUXT_PUBLIC_BASE_SOCKETURL=wss://<你的域名>/socket.io
SERVER_HTTP_BIND_IP=127.0.0.1
```
3. [首次执行,后续无需重复执行]添加执行权限,命令:
```bash
+2 -5
View File
@@ -55,7 +55,7 @@ services:
labels:
- "com.centurylinklabs.watchtower.enable=true"
ports:
- "${SERVER_HTTP_PORT}:3001" #http端口
- "${SERVER_HTTP_BIND_IP:-127.0.0.1}:${SERVER_HTTP_PORT}:3001" # 域名/本机部署默认仅回环;IP/LAN 模式由启动脚本显式设为 0.0.0.0
# read_only: true
networks:
easyai:
@@ -341,10 +341,7 @@ services:
container_name: sandbox
networks:
- easyai
#沙箱环境默认不对外暴露
ports:
# - "${SANDBOX_PORT}:8000"
- "${SANDBOX_JUPYTERLAB_PORT:-8888}:8888"
# 不映射宿主机端口,仅允许 Docker 内网中的 easyai-server 访问
labels:
- "com.centurylinklabs.watchtower.enable=true"
volumes:
+21 -19
View File
@@ -95,6 +95,15 @@ server {
return 308 /api/;
}
# Sandbox 只能由 easyai-server 通过 Docker 内网访问,禁止从公网 API 入口绕过。
location = /api/sandbox {
return 404;
}
location ^~ /api/sandbox/ {
return 404;
}
location /api/ {
proxy_pass http://127.0.0.1:3001/;
proxy_read_timeout 1200s; # 您已设置,适合长连接
@@ -160,14 +169,12 @@ server {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
}
location /jupyterlab/ {
proxy_pass http://127.0.0.1:8888/lab/;
proxy_redirect off;
proxy_set_header X-Original-Prefix '/lab';
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 Host $host;
location = /jupyterlab {
return 404;
}
location ^~ /jupyterlab/ {
return 404;
}
location /socket.io {
proxy_pass http://127.0.0.1:3002;
@@ -197,17 +204,12 @@ server {
proxy_buffering off; # 对于 WebSocket 连接禁用缓冲
}
# 沙箱环境 API(脚本执行、下载、安装依赖等),需在 docker-compose 中取消 SANDBOX_PORT 映射
location /sandbox/ {
proxy_pass http://127.0.0.1:8081/;
proxy_read_timeout 300s;
client_max_body_size 50M;
proxy_redirect off;
proxy_set_header X-Original-Prefix '/sandbox';
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 Host $host;
location = /sandbox {
return 404;
}
location ^~ /sandbox/ {
return 404;
}
}
+47
View File
@@ -0,0 +1,47 @@
function Get-ServerHttpBindEnvValue {
param([string]$Content, [string]$Key)
$match = [regex]::Match($Content, "(?m)^$([regex]::Escape($Key))=([^\r\n]*)$")
if ($match.Success) { return $match.Groups[1].Value.Trim() }
return ""
}
function Set-ServerHttpBindEnvValue {
param([string]$Content, [string]$Key, [string]$Value)
$line = "$Key=$Value"
$pattern = "(?m)^$([regex]::Escape($Key))=.*$"
if ($Content -match $pattern) { return ($Content -replace $pattern, $line) }
if ($Content -and -not $Content.EndsWith("`n")) { $Content += "`n" }
return ($Content + $line + "`n")
}
function Initialize-ServerHttpBindIp {
param(
[Parameter(Mandatory = $true)][string]$Path,
[string]$Override = ""
)
if (-not (Test-Path $Path)) { throw "Environment file not found: $Path" }
$content = Get-Content $Path -Raw -Encoding UTF8
if (-not $content) { $content = "" }
$current = Get-ServerHttpBindEnvValue $content "SERVER_HTTP_BIND_IP"
$target = if (-not [string]::IsNullOrWhiteSpace($Override)) { $Override.Trim() } else { $current }
if ([string]::IsNullOrWhiteSpace($target)) {
$publicApiUrl = Get-ServerHttpBindEnvValue $content "NUXT_PUBLIC_BASE_APIURL"
$target = if (
$publicApiUrl -eq "/api" -or
$publicApiUrl.StartsWith("/api/") -or
$publicApiUrl -match '^https?://(127\.0\.0\.1|localhost)(:\d+)?(?:/|$)'
) { "127.0.0.1" } elseif ($publicApiUrl -match '^https?://') { "0.0.0.0" } else { "127.0.0.1" }
}
if ($target -notin @("127.0.0.1", "0.0.0.0")) {
throw "SERVER_HTTP_BIND_IP only supports 127.0.0.1 or 0.0.0.0, current value: $target"
}
if ($current -ne $target) {
$content = Set-ServerHttpBindEnvValue $content "SERVER_HTTP_BIND_IP" $target
[System.IO.File]::WriteAllText($Path, $content, [System.Text.UTF8Encoding]::new($false))
Write-Host " ✓ SERVER_HTTP_BIND_IP=$target"
}
}
+40
View File
@@ -0,0 +1,40 @@
$ErrorActionPreference = "Stop"
. (Join-Path $PSScriptRoot "Initialize-ServerHttpBindIp.ps1")
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ("easyai-bind-test-" + [guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Path $tempDir | Out-Null
$envPath = Join-Path $tempDir ".env"
function Assert-BindIp {
param([string]$PublicApiUrl, [string]$Expected)
[System.IO.File]::WriteAllText($envPath, "NUXT_PUBLIC_BASE_APIURL=$PublicApiUrl`n", [System.Text.UTF8Encoding]::new($false))
Initialize-ServerHttpBindIp -Path $envPath
$content = Get-Content $envPath -Raw -Encoding UTF8
if ($content -notmatch "(?m)^SERVER_HTTP_BIND_IP=$([regex]::Escape($Expected))$") {
throw "Expected SERVER_HTTP_BIND_IP=$Expected for $PublicApiUrl"
}
}
try {
Assert-BindIp "/api" "127.0.0.1"
Assert-BindIp "http://10.0.0.8:3001" "0.0.0.0"
Assert-BindIp "http://127.0.0.1:3001" "127.0.0.1"
[System.IO.File]::WriteAllText($envPath, "NUXT_PUBLIC_BASE_APIURL=/api`nSERVER_HTTP_BIND_IP=0.0.0.0`n", [System.Text.UTF8Encoding]::new($false))
Initialize-ServerHttpBindIp -Path $envPath
if ((Get-Content $envPath -Raw -Encoding UTF8) -notmatch '(?m)^SERVER_HTTP_BIND_IP=0\.0\.0\.0$') {
throw "Existing explicit bind value was not preserved"
}
$invalidAccepted = $false
try {
Initialize-ServerHttpBindIp -Path $envPath -Override "192.168.1.8"
$invalidAccepted = $true
} catch { }
if ($invalidAccepted) { throw "Invalid SERVER_HTTP_BIND_IP unexpectedly accepted" }
Write-Host "Server HTTP bind IP PowerShell tests passed"
} finally {
Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue
}
+83
View File
@@ -0,0 +1,83 @@
#!/bin/bash
server_bind_read_env_value() {
local file="$1"
local key="$2"
awk -F= -v key="$key" '$1 == key { sub(/^[^=]*=/, ""); print; exit }' "$file" | tr -d '\r'
}
server_bind_write_env_value() {
local file="$1"
local key="$2"
local value="$3"
local tmp_file
tmp_file="$(mktemp "${file}.XXXXXX")"
awk -v key="$key" -v value="$value" '
BEGIN { replaced = 0 }
$0 ~ "^" key "=" {
if (!replaced) {
print key "=" value
replaced = 1
}
next
}
{ print }
END {
if (!replaced) print key "=" value
}
' "$file" > "$tmp_file"
chmod --reference="$file" "$tmp_file" 2>/dev/null || true
mv "$tmp_file" "$file"
}
infer_server_http_bind_ip() {
local file="$1"
local public_api_url
public_api_url="$(server_bind_read_env_value "$file" "NUXT_PUBLIC_BASE_APIURL")"
case "$public_api_url" in
/api|/api/*|http://127.0.0.1:*|https://127.0.0.1:*|http://localhost:*|https://localhost:*)
printf '%s\n' "127.0.0.1"
;;
http://*|https://*)
printf '%s\n' "0.0.0.0"
;;
*)
printf '%s\n' "127.0.0.1"
;;
esac
}
init_server_http_bind_ip() {
local file="${1:-.env}"
local override="${2:-}"
local current target
if [ ! -f "$file" ]; then
echo "❌ 未找到环境文件: $file" >&2
return 1
fi
current="$(server_bind_read_env_value "$file" "SERVER_HTTP_BIND_IP")"
target="${override:-$current}"
if [ -z "$target" ]; then
target="$(infer_server_http_bind_ip "$file")"
fi
case "$target" in
127.0.0.1|0.0.0.0) ;;
*)
echo "❌ SERVER_HTTP_BIND_IP 仅支持 127.0.0.1 或 0.0.0.0,当前为: $target" >&2
return 1
;;
esac
if [ "$current" != "$target" ]; then
server_bind_write_env_value "$file" "SERVER_HTTP_BIND_IP" "$target"
echo " ✓ SERVER_HTTP_BIND_IP=$target"
fi
}
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
init_server_http_bind_ip "${1:-.env}" "${2:-}"
fi
+37 -1
View File
@@ -20,6 +20,7 @@ mkdir -p "$TMP_DIR/scripts"
cp \
"$REPO_ROOT/scripts/init-security-env.sh" \
"$REPO_ROOT/scripts/init-public-api-base-url.sh" \
"$REPO_ROOT/scripts/init-server-http-bind-ip.sh" \
"$TMP_DIR/scripts/"
cd "$TMP_DIR"
@@ -48,6 +49,34 @@ assert_compression_config() {
fi
}
assert_sandbox_public_access_disabled() {
local config_file="$1"
grep -q '^ location = /api/sandbox {' "$config_file"
grep -q '^ location \^~ /api/sandbox/ {' "$config_file"
grep -q '^ location = /jupyterlab {' "$config_file"
grep -q '^ location \^~ /jupyterlab/ {' "$config_file"
grep -q '^ location = /sandbox {' "$config_file"
grep -q '^ location \^~ /sandbox/ {' "$config_file"
if grep -Eq 'proxy_pass http://127\.0\.0\.1:(8081|8888)' "$config_file"; then
echo "Unexpected public Sandbox/Jupyter proxy in $config_file" >&2
return 1
fi
}
assert_compose_exposure() {
local expected_server_host_ip="$1"
docker compose config --format json | python3 -c '
import json, sys
expected = sys.argv[1]
config = json.load(sys.stdin)
sandbox_ports = config["services"]["sandbox"].get("ports") or []
assert sandbox_ports == [], f"sandbox ports published: {sandbox_ports}"
server_ports = config["services"]["easyai-server"].get("ports") or []
assert len(server_ports) == 1, server_ports
assert server_ports[0].get("host_ip") == expected, server_ports
' "$expected_server_host_ip"
}
sed -i.bak 's/^SERVER_HTTP_PORT=.*/SERVER_HTTP_PORT=4100/' .env.sample
rm -f .env.sample.bak
DEPLOY_NON_INTERACTIVE=1 \
@@ -57,8 +86,9 @@ DEPLOY_NON_INTERACTIVE=1 \
bash start.sh >/dev/null
grep -qx 'NUXT_PUBLIC_BASE_APIURL=http://10.0.0.8:4100' .env
grep -qx 'CONFIG_PUBLIC_API_BASE_URL=http://10.0.0.8:4100' .env
grep -qx 'SERVER_HTTP_BIND_IP=0.0.0.0' .env
if command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then
docker compose config --quiet
assert_compose_exposure 0.0.0.0
fi
reset_case
@@ -75,6 +105,11 @@ grep -q 'proxy_set_header X-Forwarded-Port $server_port;' demo.example.com.conf
grep -q "proxy_set_header X-Original-Prefix '/api';" demo.example.com.conf
grep -q 'location = /api {' demo.example.com.conf
assert_compression_config demo.example.com.conf
assert_sandbox_public_access_disabled demo.example.com.conf
grep -qx 'SERVER_HTTP_BIND_IP=127.0.0.1' .env
if command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then
assert_compose_exposure 127.0.0.1
fi
# 直接验证 https.sh 的缺省配置生成函数会采用完整模板,而不是只代理 3010。
eval "$(awk '
@@ -90,6 +125,7 @@ grep -q 'proxy_pass http://127.0.0.1:3001/;' easyai-proxy.conf
grep -q 'location /socket.io {' easyai-proxy.conf
grep -q 'proxy_set_header X-Forwarded-Host $easyai_forwarded_host;' easyai-proxy.conf
assert_compression_config easyai-proxy.conf
assert_sandbox_public_access_disabled easyai-proxy.conf
reset_case
DEPLOY_NON_INTERACTIVE=1 \
+37
View File
@@ -0,0 +1,37 @@
#!/bin/bash
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT
# shellcheck source=init-server-http-bind-ip.sh
. "$REPO_ROOT/scripts/init-server-http-bind-ip.sh"
write_env() {
printf '%s\n' "$1" > "$TMP_DIR/.env"
}
write_env 'NUXT_PUBLIC_BASE_APIURL=/api'
init_server_http_bind_ip "$TMP_DIR/.env" >/dev/null
grep -qx 'SERVER_HTTP_BIND_IP=127.0.0.1' "$TMP_DIR/.env"
write_env 'NUXT_PUBLIC_BASE_APIURL=http://10.0.0.8:3001'
init_server_http_bind_ip "$TMP_DIR/.env" >/dev/null
grep -qx 'SERVER_HTTP_BIND_IP=0.0.0.0' "$TMP_DIR/.env"
write_env 'NUXT_PUBLIC_BASE_APIURL=http://127.0.0.1:3001'
init_server_http_bind_ip "$TMP_DIR/.env" >/dev/null
grep -qx 'SERVER_HTTP_BIND_IP=127.0.0.1' "$TMP_DIR/.env"
write_env $'NUXT_PUBLIC_BASE_APIURL=/api\nSERVER_HTTP_BIND_IP=0.0.0.0'
init_server_http_bind_ip "$TMP_DIR/.env" >/dev/null
grep -qx 'SERVER_HTTP_BIND_IP=0.0.0.0' "$TMP_DIR/.env"
if init_server_http_bind_ip "$TMP_DIR/.env" '192.168.1.8' >/dev/null 2>&1; then
echo 'Invalid SERVER_HTTP_BIND_IP unexpectedly accepted' >&2
exit 1
fi
echo 'Server HTTP bind IP shell tests passed'
+14
View File
@@ -173,6 +173,8 @@ function Setup-EnvFiles {
$content = Upsert-Env $content "NUXT_PUBLIC_BASE_APIURL" $publicApiBaseUrl
$content = Upsert-Env $content "NUXT_PUBLIC_BASE_SOCKETURL" "ws://$($script:DeployIP):3002"
$content = Upsert-Env $content "NUXT_PUBLIC_SG_APIURL" "http://$($script:DeployIP):3003"
$serverBindIp = if ($script:DeployIP -eq "127.0.0.1" -or $script:DeployIP -eq "localhost") { "127.0.0.1" } else { "0.0.0.0" }
$content = Upsert-Env $content "SERVER_HTTP_BIND_IP" $serverBindIp
$webPortMatch = [regex]::Match($content, '(?m)^WEB_PORT=(\d+)$')
$webPort = if ($webPortMatch.Success) { $webPortMatch.Groups[1].Value } else { "3010" }
$content = Upsert-Env $content "CONFIG_SECURITY_ORIGIN" "http://$($script:DeployIP):$webPort"
@@ -386,6 +388,18 @@ function Main {
Ensure-FileFromSample ".env.AMS" ".env.AMS.sample"
}
. (Join-Path $script:Root "scripts\Initialize-ServerHttpBindIp.ps1")
$serverBindOverride = if ($script:SkipDeployQuestions) {
""
} elseif ($script:DeployIP -eq "127.0.0.1" -or $script:DeployIP -eq "localhost") {
"127.0.0.1"
} else {
"0.0.0.0"
}
Initialize-ServerHttpBindIp `
-Path (Join-Path $script:Root ".env") `
-Override $serverBindOverride
. (Join-Path $script:Root "scripts\Initialize-SecurityEnv.ps1")
Initialize-SecurityEnv -Path (Join-Path $script:Root ".env") -Mode $script:SecurityEnvMode
+14
View File
@@ -495,6 +495,20 @@ main() {
fi
fi
# 域名和本机部署默认仅绑定回环;只有明确的 IP/LAN 直连模式才开放后端宿主机端口。
# shellcheck source=scripts/init-server-http-bind-ip.sh
. ./scripts/init-server-http-bind-ip.sh
local server_bind_override=""
if [ "$DEPLOY_MODE" = "domain" ]; then
server_bind_override="127.0.0.1"
elif [ "$DEPLOY_MODE" = "ip" ]; then
case "$DEPLOY_IP" in
127.0.0.1|localhost) server_bind_override="127.0.0.1" ;;
*) server_bind_override="0.0.0.0" ;;
esac
fi
init_server_http_bind_ip .env "$server_bind_override"
# 空值或历史默认值只在首次发现时生成并写回 .env,后续启动保持稳定。
# 数据库中的后台 JWT 轮转配置由后端优先使用,不受此处影响。
# shellcheck source=scripts/init-security-env.sh
+3
View File
@@ -174,6 +174,9 @@ if (-not $skipRepoUpdate) {
# 空值或历史默认值只初始化一次并写回 .env;已有自定义值及数据库轮转配置不受影响。
if (-not (Test-Path ".env")) { Write-Err "未找到 .env,请先执行 start.ps1 完成初始化" }
. (Join-Path $scriptDir "scripts\Initialize-ServerHttpBindIp.ps1")
Initialize-ServerHttpBindIp -Path (Join-Path $scriptDir ".env")
. (Join-Path $scriptDir "scripts\Initialize-SecurityEnv.ps1")
Initialize-SecurityEnv -Path (Join-Path $scriptDir ".env") -Mode "upgrade"
+6
View File
@@ -128,6 +128,12 @@ if [ ! -f .env ]; then
echo "❌ 未找到 .env,请先执行 start.sh 完成初始化"
exit 1
fi
# 老部署缺少绑定配置时,根据现有公开 API 地址迁移:域名/本机保持回环,IP 直连保持可用。
# shellcheck source=scripts/init-server-http-bind-ip.sh
. ./scripts/init-server-http-bind-ip.sh
init_server_http_bind_ip .env
# shellcheck source=scripts/init-security-env.sh
. ./scripts/init-security-env.sh
init_security_env .env upgrade