forked from wangbo/easyai
fix(deploy): 明确提示初始管理员密码
This commit is contained in:
+3
-2
@@ -144,8 +144,9 @@ CONFIG_TRUSTED_PROXY=
|
||||
# 完成身份冲突扫描和人工处置后才能启用手机号、邮箱和微信身份唯一索引。
|
||||
CONFIG_AUTH_UNIQUE_INDEXES_ENABLED=false
|
||||
|
||||
# 仅在首次创建 admin 账号时使用;启动脚本会生成 20 位字母数字随机值并持久化到 .env。
|
||||
# 已存在 admin 的升级环境不会使用或修改现有管理员密码。
|
||||
# 仅在数据库首次创建 admin 账号时使用;启动脚本会生成 20 位字母数字随机值并持久化到 .env。
|
||||
# 首次部署完成页会明确显示登录账号和密码;初始密码没有独立过期时间,首次登录后请立即修改。
|
||||
# admin 创建后不再使用该值;修改 .env 或执行升级不会重置现有管理员密码。
|
||||
CONFIG_INITIAL_ADMIN_PASSWORD=
|
||||
|
||||
CONFIG_TOKEN_SIGN_SK=easyai2025easyai
|
||||
|
||||
@@ -12,6 +12,7 @@ on:
|
||||
- 'scripts/test-public-api-base-url.sh'
|
||||
- 'scripts/init-server-http-bind-ip.sh'
|
||||
- 'scripts/test-server-http-bind-ip.sh'
|
||||
- 'scripts/init-security-env.sh'
|
||||
- 'scripts/test-deployment-public-url.sh'
|
||||
- '.github/workflows/test-deployment-public-url.yml'
|
||||
pull_request:
|
||||
@@ -25,6 +26,7 @@ on:
|
||||
- 'scripts/test-public-api-base-url.sh'
|
||||
- 'scripts/init-server-http-bind-ip.sh'
|
||||
- 'scripts/test-server-http-bind-ip.sh'
|
||||
- 'scripts/init-security-env.sh'
|
||||
- 'scripts/test-deployment-public-url.sh'
|
||||
- '.github/workflows/test-deployment-public-url.yml'
|
||||
workflow_dispatch:
|
||||
@@ -37,7 +39,7 @@ jobs:
|
||||
|
||||
- name: Check shell syntax
|
||||
run: |
|
||||
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
|
||||
bash -n start.sh update.sh scripts/init-security-env.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
|
||||
|
||||
@@ -36,7 +36,17 @@ jobs:
|
||||
DEPLOY_IP: "192.168.1.100"
|
||||
run: |
|
||||
(Get-Content .env.sample) -replace '^SERVER_HTTP_PORT=.*$', 'SERVER_HTTP_PORT=4100' | Set-Content .env.sample -Encoding UTF8
|
||||
powershell -ExecutionPolicy Bypass -File .\start.ps1
|
||||
$output = powershell -ExecutionPolicy Bypass -File .\start.ps1 2>&1 | Out-String
|
||||
if ($LASTEXITCODE -ne 0) { Write-Host $output; exit $LASTEXITCODE }
|
||||
$adminPassword = (Select-String -Path .env -Pattern '^CONFIG_INITIAL_ADMIN_PASSWORD=' | ForEach-Object { $_.Line.Substring('CONFIG_INITIAL_ADMIN_PASSWORD='.Length) })
|
||||
if ([string]::IsNullOrWhiteSpace($adminPassword)) { throw 'Initial admin password was not generated' }
|
||||
if (-not $output.Contains('登录账号: admin')) { throw 'Deployment output does not show the admin username' }
|
||||
if (-not $output.Contains("登录密码: $adminPassword")) { throw 'Deployment output does not show the generated admin password' }
|
||||
if (-not $output.Contains('初始密码没有独立过期时间')) { throw 'Deployment output does not explain the initial password lifetime' }
|
||||
$existingOutput = powershell -ExecutionPolicy Bypass -File .\start.ps1 2>&1 | Out-String
|
||||
if ($LASTEXITCODE -ne 0) { Write-Host $existingOutput; exit $LASTEXITCODE }
|
||||
if (-not $existingOutput.Contains('本次部署不会生成或重置已有密码')) { throw 'Existing-env output does not explain password preservation' }
|
||||
if ($existingOutput.Contains("登录密码: $adminPassword")) { throw 'Existing-env output must not report the env value as the current password' }
|
||||
|
||||
- name: Verify .env
|
||||
run: |
|
||||
|
||||
@@ -38,7 +38,20 @@ DEPLOY_ACCESS=domain DEPLOY_DOMAIN=demo.example.com DEPLOY_HTTPS=true CERTBOT_EM
|
||||
|
||||
`start.sh` / `start.ps1` 和 `update.sh` / `update.ps1` 会自动初始化并持久化鉴权安全密钥。首次安装或存量升级发现 `WS_AUTH_WS_TICKET_SECRET` 缺失、过短时,会生成新的高强度随机值,并确保 `WS_AUTH_METHODS` 包含 `ws_ticket`;Compose 会把同一密钥同时注入 `easyai-server` 与 `ws-gateway`。已有合格密钥会原样保留,重复启动或升级不会轮换,用户无需手动填写或复制密钥。
|
||||
|
||||
生成结果仅保存在本机 `.env`,脚本日志只显示变量名而不会输出密钥内容。不要把 `.env` 提交到 Git;集群部署时,各 `easyai-server` / `ws-gateway` 实例必须使用同一份持久化配置。
|
||||
生成结果仅保存在本机 `.env`。除首次安装完成页会明确显示登录用的初始管理员密码外,脚本日志对其他安全密钥只显示变量名,不输出密钥内容。不要把 `.env` 提交到 Git;集群部署时,各 `easyai-server` / `ws-gateway` 实例必须使用同一份持久化配置。
|
||||
|
||||
#### 初始管理员密码生命周期
|
||||
|
||||
首次安装时,部署脚本会生成 20 位随机密码,写入 `.env` 的 `CONFIG_INITIAL_ADMIN_PASSWORD`,并在部署完成页直接显示:
|
||||
|
||||
```text
|
||||
登录账号: admin
|
||||
登录密码: <本次部署生成的随机密码>
|
||||
```
|
||||
|
||||
后端只在数据库中不存在 `admin` 时读取该值并创建管理员。创建成功后,`.env` 中的值不再用于登录校验,修改该变量或执行升级都不会重置现有管理员密码。初始密码没有独立的自动过期时间,在管理员主动修改前持续有效,因此首次登录后应立即修改密码。
|
||||
|
||||
如果部署脚本检测到已有 `.env`,完成页不会把其中的值误报成当前密码:数据库已有 `admin` 时继续使用现有密码;数据库尚未创建 `admin` 时,可查看 `.env -> CONFIG_INITIAL_ADMIN_PASSWORD`。
|
||||
|
||||
#### 后端公开 API 地址
|
||||
|
||||
|
||||
@@ -156,6 +156,15 @@ powershell -ExecutionPolicy Bypass -File .\start.ps1
|
||||
- 本地访问:`http://127.0.0.1:3010`
|
||||
- 局域网访问:`http://<LAN_IP>:3010`
|
||||
|
||||
首次安装还会在完成页直接显示管理员登录信息:
|
||||
|
||||
```text
|
||||
登录账号: admin
|
||||
登录密码: <本次部署生成的 20 位随机密码>
|
||||
```
|
||||
|
||||
该密码只在数据库首次创建 `admin` 时使用,创建后修改 `.env` 不会重置现有密码。初始密码没有独立过期时间,首次登录后应立即修改。已有 `.env` 的部署只提示密码沿用规则,不会把可能已经失效的环境变量值显示成当前登录密码。
|
||||
|
||||
---
|
||||
|
||||
## 7. 实现清单
|
||||
|
||||
@@ -98,10 +98,29 @@ DEPLOY_NON_INTERACTIVE=1 \
|
||||
DEPLOY_DRY_RUN=1 \
|
||||
DEPLOY_ACCESS=ip \
|
||||
DEPLOY_IP=10.0.0.8 \
|
||||
bash start.sh >/dev/null
|
||||
bash start.sh > "$TMP_DIR/first-install.log"
|
||||
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
|
||||
initial_admin_password="$(awk -F= '$1 == "CONFIG_INITIAL_ADMIN_PASSWORD" { print $2; exit }' .env)"
|
||||
[ "${#initial_admin_password}" -ge 12 ] || {
|
||||
echo "Initial admin password was not generated" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -Fq '登录账号: admin' "$TMP_DIR/first-install.log"
|
||||
grep -Fq "登录密码: ${initial_admin_password}" "$TMP_DIR/first-install.log"
|
||||
grep -Fq '生命周期: 仅在数据库首次创建 admin 时使用;创建后修改 .env 不会重置密码。' "$TMP_DIR/first-install.log"
|
||||
grep -Fq '有效期: 初始密码没有独立过期时间,在管理员修改密码前持续有效。' "$TMP_DIR/first-install.log"
|
||||
DEPLOY_NON_INTERACTIVE=1 \
|
||||
DEPLOY_DRY_RUN=1 \
|
||||
DEPLOY_ACCESS=ip \
|
||||
DEPLOY_IP=10.0.0.8 \
|
||||
bash start.sh > "$TMP_DIR/existing-env.log"
|
||||
grep -Fq '管理员账号: admin(本次部署不会生成或重置已有密码)' "$TMP_DIR/existing-env.log"
|
||||
if grep -Fq "登录密码: ${initial_admin_password}" "$TMP_DIR/existing-env.log"; then
|
||||
echo "Existing-env deployment must not report CONFIG_INITIAL_ADMIN_PASSWORD as the current login password" >&2
|
||||
exit 1
|
||||
fi
|
||||
if command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then
|
||||
assert_compose_exposure 0.0.0.0
|
||||
assert_canvas_ws_auth_config
|
||||
|
||||
@@ -358,6 +358,32 @@ function Start-Services {
|
||||
Ok "EasyAI started"
|
||||
}
|
||||
|
||||
function Show-AdminLoginInfo {
|
||||
Write-Host ""
|
||||
if ($script:SecurityEnvMode -ne "new") {
|
||||
Write-Host " 管理员账号: admin(本次部署不会生成或重置已有密码)" -ForegroundColor Yellow
|
||||
Write-Host " 登录提示: 若数据库尚未创建 admin,请查看 .env -> CONFIG_INITIAL_ADMIN_PASSWORD;若 admin 已存在,请使用当前密码。" -ForegroundColor DarkGray
|
||||
return
|
||||
}
|
||||
|
||||
$content = Get-Content (Join-Path $script:Root ".env") -Raw -Encoding UTF8
|
||||
$initialAdminPassword = Get-EnvValue $content "CONFIG_INITIAL_ADMIN_PASSWORD"
|
||||
if ([string]::IsNullOrWhiteSpace($initialAdminPassword)) {
|
||||
Fail "Cannot read initial admin password from .env -> CONFIG_INITIAL_ADMIN_PASSWORD"
|
||||
}
|
||||
|
||||
$heading = if ($script:DeployDryRun) {
|
||||
" -------- 初始管理员(Docker 首次启动后生效)--------"
|
||||
} else {
|
||||
" -------- 初始管理员(首次登录后请立即修改密码)--------"
|
||||
}
|
||||
Write-Host $heading -ForegroundColor Yellow
|
||||
Write-Host " 登录账号: " -NoNewline; Write-Host "admin" -ForegroundColor White
|
||||
Write-Host " 登录密码: " -NoNewline; Write-Host $initialAdminPassword -ForegroundColor White
|
||||
Write-Host " 生命周期: 仅在数据库首次创建 admin 时使用;创建后修改 .env 不会重置密码。" -ForegroundColor DarkGray
|
||||
Write-Host " 有效期: 初始密码没有独立过期时间,在管理员修改密码前持续有效。" -ForegroundColor DarkGray
|
||||
}
|
||||
|
||||
function Main {
|
||||
Init-ProjectDir
|
||||
|
||||
@@ -425,19 +451,14 @@ function Main {
|
||||
Write-Host "================================" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
Write-Host " 预期访问: " -NoNewline; Write-Host "http://${ip}:3010" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host " 初始管理员: admin;随机密码保存在 .env 的 CONFIG_INITIAL_ADMIN_PASSWORD" -ForegroundColor DarkGray
|
||||
} else {
|
||||
Write-Host "================================" -ForegroundColor Green
|
||||
Write-Host " 部署成功" -ForegroundColor Green
|
||||
Write-Host "================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host " 访问地址: " -NoNewline; Write-Host "http://${ip}:3010" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Write-Host " -------- 初始管理员(首次登录后请修改密码)--------" -ForegroundColor Yellow
|
||||
Write-Host " 账号: " -NoNewline; Write-Host "admin" -ForegroundColor White
|
||||
Write-Host " 密码位置: " -NoNewline; Write-Host ".env -> CONFIG_INITIAL_ADMIN_PASSWORD" -ForegroundColor White
|
||||
}
|
||||
Show-AdminLoginInfo
|
||||
Write-Host ""
|
||||
Wait-ForExit
|
||||
}
|
||||
|
||||
@@ -457,6 +457,32 @@ run_https_setup() {
|
||||
fi
|
||||
}
|
||||
|
||||
show_admin_login_info() {
|
||||
echo ""
|
||||
if [ "$SECURITY_ENV_MODE" != "new" ]; then
|
||||
echo "管理员账号: admin(本次部署不会生成或重置已有密码)"
|
||||
echo "登录提示: 若数据库尚未创建 admin,请查看 .env -> CONFIG_INITIAL_ADMIN_PASSWORD;若 admin 已存在,请使用当前密码。"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local initial_admin_password
|
||||
initial_admin_password="$(read_env_value .env "CONFIG_INITIAL_ADMIN_PASSWORD")"
|
||||
if [ -z "$initial_admin_password" ]; then
|
||||
echo "❌ 未能读取初始管理员密码: .env -> CONFIG_INITIAL_ADMIN_PASSWORD" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$DEPLOY_DRY_RUN" = "1" ]; then
|
||||
echo "-------- 初始管理员(Docker 首次启动后生效)--------"
|
||||
else
|
||||
echo "-------- 初始管理员(首次登录后请立即修改密码)--------"
|
||||
fi
|
||||
echo "登录账号: admin"
|
||||
echo "登录密码: ${initial_admin_password}"
|
||||
echo "生命周期: 仅在数据库首次创建 admin 时使用;创建后修改 .env 不会重置密码。"
|
||||
echo "有效期: 初始密码没有独立过期时间,在管理员修改密码前持续有效。"
|
||||
}
|
||||
|
||||
# ==================== 主流程 ====================
|
||||
main() {
|
||||
init_project_dir
|
||||
@@ -551,6 +577,7 @@ main() {
|
||||
echo "HTTPS 已启用"
|
||||
fi
|
||||
fi
|
||||
show_admin_login_info
|
||||
echo ""
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user