# AI 安装执行手册(统一入口 / 中文) [中文(本页)](/agent-install.md) · [English](/agent-install.en.md) ## 语言选择 / Language selection - 用户明确指定的语言优先;否则按当前请求/对话的语言选择。中文使用本页,英文使用 [English runbook](/agent-install.en.md)。不要从操作系统、shell、时区、用户名或所在地推断语言。 - 偏好不明确或使用其他语言时,先简短询问“中文还是 English? / Chinese or English?”,不要默默选择尚未提供的翻译。 - 执行计划、授权确认、进度、错误解释、下一步与交付报告均使用所选语言;切换语言不代表授权重新执行已完成步骤。 - 命令、路径、配置键、API 字段、模型 ID 及 `PASS` / `FAIL` / `SKIPPED` / `BLOCKED` 状态标识保持原样。原始错误脱敏后,用所选语言解释,不改变技术含义。 - 中英文是同一流程的两种语言版本,授权边界和验收条件一致;语言与平台、安装目标独立选择。若两版执行步骤或安全规则冲突,停止并报告,不挑选更宽松的一版。 **For English-speaking assistants:** Follow the user’s explicit language preference first, otherwise the current request/conversation language. For English, read [agent-install.en.md](/agent-install.en.md) and conduct the entire installation interaction in English. For Chinese, continue below. If unclear or another language is requested, ask which supported language to use. Keep commands and identifiers unchanged. 本文件是 Claude、Codex 等 AI 助手安装或恢复 Mendry **源码评估环境**的统一执行入口。其他文档提供接口与功能参考,不构成另一套 AI 安装流程。命令以当前 checkout 为准;发现文档与实现不一致时停止并报告,不猜测接口或修改应用代码来绕过安装问题。 **状态:Preview。** 提供从源码构建的 Docker Compose 评估配套;尚无受支持的生产镜像、生产安装包、升级或回滚方案。不要将本流程报告为生产部署成功。本手册也不意味着 Windows 全功能、SSH 探针或 Docker 验证已完成跨平台认证。 ## 0. 执行约定与授权 开始前一次性确认以下信息(已知的无需重复询问): - 目标:**事故控制台**(默认建议,包含 API 和前端),还是 **Local Harness 离线体验**? - 控制台部署方式:**Docker Compose 容器化评估**(无需宿主机 Go/Node,进入第 10 节),还是 **本机源码运行**(第 1–5 节)?两者与体验目标独立选择,不默认替用户选择。Docker 还需选择配套 PostgreSQL/Redis 或已有依赖;Local Harness 仍按第 8 节源码运行。 - 系统及 shell:Linux/macOS Bash、Windows PowerShell,还是 WSL?不要混用 Windows 和 WSL 的工具、路径、数据库地址。 - 仓库绝对路径及目标版本;新环境还是已有环境?已有配置、账号、数据库不得覆盖。 - 本机源码或 Docker 已有依赖路径:是否已有专用 PostgreSQL 数据库和 Redis、连接权限,以及该数据库原有的加密密钥? - 是否允许下载 Go/npm 依赖或容器镜像、构建镜像、创建容器/网络/持久化卷、执行数据库迁移并启动所选服务? - 是否只验收服务启动,还是继续配置模型并进行可能收费、向提供方发送数据的验证? 先给出执行计划和会写入的资源,再按授权执行。缺少必要信息时报告 `BLOCKED` 并询问,不自行安装系统服务、创建云资源或改防火墙。 ### 不可违反的安全边界 1. 不覆盖已有 `.env`;不为已有数据库重新生成 `MENDRY_ENCRYPTION_KEY`。缺失旧密钥时停止,不能靠新密钥恢复原凭据。 2. 不删除数据库、Redis 数据、卷、迁移历史或运行快照;不执行 `seed`、破坏性集成测试或重置账号来“修好安装”。 3. 不把密码、连接串、模型 API Key、Cookie、完整 Webhook URL 放入聊天、命令历史、共享日志或提交。用户通过私有编辑器/本地隐藏输入提供凭据;AI 只检查存在性与合法性,不能输出原值。 4. 不打印 `.env`、完整环境变量或带凭据的请求。保持 `MENDRY_HTTP_REQUEST_DEBUG=false`、`MENDRY_POSTGRES_QUERY_DEBUG=false`。 5. 默认只绑定回环地址,保持 `analysis_only`。公网访问、外部模型调用、SSH 安装、写仓库、自动修复和 Enhanced 验证分别需要明确授权。 6. 不自动 `git pull`、切分支、重置用户修改或终止未知进程。安装应用依赖会执行第三方构建/安装逻辑,应仅在用户信任的源码评估环境中进行。 7. 每条短命令执行后检查退出码,失败即停。Bash 用 `$?`,PowerShell 对原生命令用 `$LASTEXITCODE`;不要把整篇代码块不加检查地批量执行。 ## 1. 只读预检 工作目录:用户确认的仓库根目录。没有 checkout 时,先让用户确认目录和版本,再从 `https://github.com/Funovate/Mendry` 克隆;不要覆盖现有目录。 两种 shell 均可逐条执行: ```text git status --short git rev-parse --short HEAD go version ``` 控制台路径另执行: ```text node --version npm --version ``` 通过条件: - 能找到 `backend/go.mod`、`backend/.env.example`、`frontend/package-lock.json`。 - Go 1.25+;控制台需要 Node.js `^20.19.0 || >=22.12.0` 及 npm(取自 `frontend/package-lock.json` 中 Vite 的 `engines`;`frontend/` 本身未固定 Node 版本)。 - 已记录原有工作区修改,后续不得覆盖。 - 本手册直接调用 Go 命令,不要求 Make。Bash 首次生成密钥需要 OpenSSL;PowerShell 使用 .NET 安全随机数。 - PostgreSQL、Redis 已由用户或运维准备好,且是获准使用的评估资源。**本手册不提供未经验证的数据库自动安装包**;没有依赖时停止,列出需要准备的数据库、账号、连接地址和 TLS 要求。Local Harness 不需要这些依赖。 发现版本不符或命令不存在:说明缺项,让用户批准安装或切换工具链后重新预检。不要静默升级全局工具。 选择 Local Harness 的用户跳到第 8 节,其余继续。 ## 2. 准备私有配置(控制台) 工作目录:仓库根目录下的 `backend/`。只进入一次,后续后端命令都在此目录运行。 ```text cd backend ``` ### 2.1 仅在 `.env` 不存在时创建 **Bash:** ```bash if [ -e .env ]; then printf '%s\n' 'Reuse existing .env; do not overwrite.' else (umask 077; set -C; cat .env.example > .env) fi ``` **PowerShell:** ```powershell if (Test-Path .env) { Write-Output 'Reuse existing .env; do not overwrite.' } else { [System.IO.File]::Copy((Join-Path $PWD '.env.example'), (Join-Path $PWD '.env'), $false) } ``` 将文件保存在仅当前用户和获准管理员可读的目录。Unix 核查权限;Windows 核查文件与父目录 ACL,不要假设复制后的文件天然私密。 ### 2.2 首次生成加密密钥(仅新数据库) 下面命令只替换示例占位密钥,直接保存到 `.env`,不显示密钥。仅在已确认新数据库、文件权限安全后执行一种。已有环境跳过,保留原值。 **Bash:** ```bash # 在用户本地私有终端执行;关闭 shell 命令追踪。 ( set +x set -e key=$(openssl rand -base64 32) MENDRY_NEW_KEY="$key" node -e 'const fs=require("fs"); const p=".env"; const s=fs.readFileSync(p,"utf8"); const old="MENDRY_ENCRYPTION_KEY=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; if(s.split(old).length!==2) throw Error("Expected exactly one placeholder; stop without changes"); fs.writeFileSync(p,s.replace(old,"MENDRY_ENCRYPTION_KEY="+process.env.MENDRY_NEW_KEY));' ) ``` 检查整个子 shell 的退出码;非零时停止。临时变量不会留在父 shell 中。 **PowerShell:** ```powershell $path = Join-Path $PWD '.env' $content = [System.IO.File]::ReadAllText($path) $placeholder = 'MENDRY_ENCRYPTION_KEY=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=' if (($content.Split([string[]]@($placeholder), [System.StringSplitOptions]::None)).Count -ne 2) { throw 'Expected exactly one placeholder; stop without changes' } $bytes = New-Object byte[] 32 $rng = [System.Security.Cryptography.RandomNumberGenerator]::Create() try { $rng.GetBytes($bytes) $content = $content.Replace($placeholder, 'MENDRY_ENCRYPTION_KEY=' + [Convert]::ToBase64String($bytes)) [System.IO.File]::WriteAllText($path, $content, (New-Object System.Text.UTF8Encoding($false))) } finally { $rng.Dispose() [Array]::Clear($bytes, 0, $bytes.Length) Remove-Variable content, bytes -ErrorAction SilentlyContinue } ``` 通过条件:密钥是 32 随机字节的标准 base64,已持久保存且不是示例值;用户知道备份位置。不要在交付报告里附上密钥。 ### 2.3 用户私下填写连接配置 使用私有编辑器修改 `backend/.env`: | 配置项 | 要求 | | ----------------------- | --------------------------------------------------------------------------------- | | `MENDRY_POSTGRES_URL` | 用户授权的数据库;用户名/密码的 URL 保留字符要百分号编码;远程 TLS 遵循服务商要求 | | `MENDRY_REDIS_URL` | 按密码/ACL/TLS 情况配置;URL 不带 `/0` 等数据库路径 | | `MENDRY_REDIS_DB` | 单独指定 Redis 逻辑库;不通过清空 Redis 来解决冲突 | | `MENDRY_ENCRYPTION_KEY` | 新环境使用上一步生成值;已有数据库必须使用原密钥 | | `MENDRY_HTTP_ADDR` | 本地评估保持 `127.0.0.1:8080` | | `MENDRY_PUBLIC_URL` | 本地评估保持 `http://127.0.0.1:8080` | 其他配置保留示例默认值。具体格式见 [配置模板](https://github.com/Funovate/Mendry/blob/a60d47164f602d692cd56edecdb19315c37b830a/backend/.env.example)。 后端从 `backend/` 加载 `.env`;已有进程环境变量优先于文件,`MENDRY_*` 优先于兼容的 `FIXTHE_*`,包括显式空值。遇到配置不符时只检查变量名称和是否设置,不能转储值;清除或修改现有环境变量前取得用户同意。不要 `source .env` / `Invoke-Expression` 执行配置文件。 确认 `.env` 不被 Git 跟踪: ```text git check-ignore .env git ls-files --error-unmatch .env ``` 预期前一条显示被忽略;后一条因未跟踪而非零退出(这是本手册明确允许的预期非零结果)。若被跟踪或未忽略,停止处理,不提交凭据。 ## 3. 数据库迁移与登录账号 工作目录:`backend/`。 ### 3.1 迁移 迁移会修改数据库 schema。已有数据库先由用户确认备份可用和迁移授权;不是受支持的生产升级流程。 ```text go run ./cmd/migrate ``` 通过条件:命令退出码为 0。API 不会自动迁移。重复执行由迁移历史决定待执行项,不需要手工删除历史;锁超时、校验和冲突或旧版 schema 不兼容都应停止并报告,不删库重来。 ### 3.2 首次账号 已有账号且用户能登录:跳过。忘记密码不是重跑 bootstrap 可以解决的问题。 首次运行时,由用户在私有编辑器中临时添加 `MENDRY_BOOTSTRAP_ADMIN_PASSWORD` 到 `.env`(12–72 字节,建议密码管理器生成的随机 ASCII 密码)。该项只供初始化命令读取,不在聊天中传递。确认没有同名导出环境变量覆盖它。 ```text go run ./cmd/bootstrap-admin --username admin ``` 需要其他用户名时先由用户确认,再替换 `admin`。通过条件:命令退出码为 0。随后从 `.env` 删除临时密码项,保留密码管理器中的记录;失败时也应清理临时项。 相同已启用账号重复运行不会替换密码哈希。数据库最多一个账号;不得换用户名尝试创建第二个身份。 ## 4. 启动并验收 API 工作目录:`backend/`,在专用终端前台运行: ```text go run ./cmd/api ``` 这是长驻进程,不等待其正常退出再执行下一步。记录启动终端和工作目录;不要使用不受管理的后台进程。端口被占用时先确认归属,不杀未知进程。 在另一个终端检查,最多等待 120 秒(编译/下载超时可经用户同意延长);失败时只检查脱敏启动错误,不无限重试。 **Bash:** ```bash curl --fail --silent --show-error --max-time 10 http://127.0.0.1:8080/livez curl --fail --silent --show-error --max-time 10 http://127.0.0.1:8080/readyz ``` **PowerShell:** ```powershell (Invoke-WebRequest -UseBasicParsing -TimeoutSec 10 http://127.0.0.1:8080/livez).StatusCode (Invoke-WebRequest -UseBasicParsing -TimeoutSec 10 http://127.0.0.1:8080/readyz).StatusCode ``` 通过条件:两个端点均返回 HTTP 200,且确认响应来自本次目标实例。`livez` 只说明进程存活;`readyz` 才包含 PostgreSQL 与 Redis 就绪情况。它们都不代表模型或 Git 配置可用。 ## 5. 启动并验收控制台 另开专用终端,从仓库根目录进入 `frontend/`: ```text cd frontend npm ci npm run dev -- --host 127.0.0.1 --port 5173 --strictPort ``` 先确认 `npm ci` 退出码为 0,再启动开发服务器。`npm ci` 会重建该包的 `node_modules`;不要改用 `npm install` 或自动修复审计结果来改写锁文件。 这里显式覆盖包脚本中的 `0.0.0.0`,只监听回环地址;`--strictPort` 防止端口冲突时偷偷换端口。 通过条件: 1. 浏览器能打开 `http://127.0.0.1:5173`。 2. 用户使用初始化账号成功登录;不要抓取或展示 Session Cookie。 3. `/api` 请求由 Vite 代理至 `127.0.0.1:8080`,没有持续认证或服务端错误。 无浏览器能力时只能报告“API 就绪、前端启动,登录待用户验证”,不能宣称控制台完整验收。 Vite 是评估用开发服务器,不是生产部署方式。需要更改 API 端口时,必须同步核查 `frontend/vite.config.ts` 的代理配置;不要只改 `.env` 然后忽略控制台失败。 ## 6. 可选:从服务启动到 AI 可用 本节需用户授权项目配置、外部请求及可能发生的模型费用。没有授权时跳过,交付状态为“服务可用,AI 未验收”。没有浏览器/对应 API 操作能力时,明确让用户完成以下操作,不猜测请求格式。 1. 在控制台创建专用评估项目;复用同名项目前确认归属,不覆盖已有项目配置。 2. 保存环境、用户授权的只读 Git 基线及选定证据来源。各配置步骤独立保存。参考 [首个项目](/zh-cn/docs/get-started/first-project/) 与 [配置参考](/zh-cn/docs/reference/configuration/)。首个项目的 Webhook 示例仅保证摄取所需配置,不等于 Git/模型已就绪。 3. 创建模型凭据并配置 provider、HTTPS base URL、API 模式、model。OpenAI-compatible 选择 `chat_completions` 或 `responses`;Anthropic 使用 `messages`。凭据通过控制台私下输入。获取模型列表、选择返回的 ID、执行连接测试并保存。参考 [LLM 提供方](/zh-cn/docs/guides/llm-providers/),不要硬编码猜测模型 ID。 4. 保持 `analysis_only`。不为通过测试启用 `auto_hotfix`、安装远程 SSH 探针或授予 Git 写权限。 5. 用户批准后,仅发送不含真实业务数据的测试信号。参考 [首个事故](/zh-cn/docs/get-started/first-incident/),在私有终端使用实际入站 URL,不能将 token 复制进对话或日志。 6. 验收事件流中的记录、对应事故以及最终分析结果。Webhook 的 `202 accepted` 只是同步接收成功;模型故障时也可能走确定性降级,因此“出现事故”不是模型分析通过的证据。 只有连接测试通过,且事故中有可审阅的模型分析结果,才能报告端到端 AI 验证通过。证据不足、模型失败或仅有确定性归一化,应如实分别记录,不能绕过限制。 远程信号需要可达的 `MENDRY_PUBLIC_URL`;远程机器不能使用本机回环地址。Vite 仅代理 `/api`,不代理 `/hooks`;SSH 探针回传要求 HTTPS。需要这些能力时停止本地安装流程,另行确认网络/TLS与主机权限方案。 ## 7. 停止、重启与失败处置 - 停止:在本次创建的 API、前端终端分别按 Ctrl+C,等待正常退出;不删除数据与配置。 - 同版本重启:复用 `backend/.env`,从 `backend/` 运行 `go run ./cmd/api`,从 `frontend/` 运行第 5 节的开发服务器命令,再做健康及登录检查。无依赖变化时不必重复 `npm ci`。 - 版本变化:不要自动更新。用户批准、确认备份与版本要求后才重新安装相应依赖、应用待执行迁移;没有经过验证的自动回滚承诺。 | 失败现象 | 下一步;禁止动作 | | -------------------------- | ----------------------------------------------------------------- | | Go/npm 下载失败 | 检查版本、网络、代理;不自动禁用 TLS 或改不可信镜像 | | PostgreSQL 连接或迁移失败 | 核查目标库、权限、URL 编码、TLS、锁和历史;不删除库/迁移记录 | | Redis 失败或 readyz 非 200 | 核查 URL、ACL、TLS、逻辑库及脱敏错误;不 `FLUSHALL` | | 加密密钥缺失/解密失败 | 找回同一数据库的原密钥;不重新生成替代 | | 登录失败 | 核查账号、Redis、浏览器请求及代理;不重复建账号或改数据库密码哈希 | | 8080/5173 被占用 | 确認端口归属,询问用户;不杀未知进程 | | 模型连接失败 | 核查提供方、API 模式、模型权限、网络;不展示 Key,不把降级当成功 | | 事件已接收但无分析 | 区分异步摄取、确定性降级、Git/证据缺失与模型失败;不放宽修复策略 | 更多诊断见 [故障排查](/zh-cn/docs/guides/troubleshooting/)。达到约定超时后报告 `BLOCKED`,包含失败步骤、脱敏错误、已完成步骤、保留资源和需要用户决定的事项。 ## 8. 独立分支:Local Harness 离线体验 只执行第 0、1 节与本节,不执行数据库、账号、API、前端安装。需要 Go;首次编译可能下载模块,但 fixture 本身不需要外部模型网络访问或 API Key。 工作目录:`backend/`。两种 shell 均可逐条运行: ```text go run ./cmd/agentcore-local run --config examples/agentcore-local/fixture-report.config.json --event examples/agentcore-local/report.event.json --state-dir .agentcore/runs ``` 通过条件:退出码为 0,输出包含 run ID。将实际 ID 替换下面的 `RUN_ID` 后执行(不能原样复制占位符): ```text go run ./cmd/agentcore-local inspect --state-dir .agentcore/runs --run-id RUN_ID ``` 检查持久 snapshot 中的状态、完成原因及产物。已有 run 不删除;需要继续时使用相同配置/event 和 `run --resume`,具体见 [Local Harness](/zh-cn/docs/get-started/local-harness/)。未知写入结果不能自动重放或自行 `resolve`。 报告“Local Harness fixture 验证通过”,不要报告“事故控制台已安装”或“真实模型验证通过”。 ## 9. 交付报告(必须填写) 不包含任何凭据;使用 `PASS`、`FAIL`、`SKIPPED`、`BLOCKED` 区分已验证与未执行。 ```text 目标:事故控制台 / Local Harness 部署方式:本机源码 / Docker Compose Compose 文件组合、项目名、镜像 ID、持久化卷(如适用): 源码版本、系统与 shell: 仓库绝对路径: 预检: 配置保存:路径与权限确认(不附内容) 数据库迁移 / 账号初始化: API livez / readyz: 前端访问 / 用户登录: 模型连接 / 端到端分析: Local fixture / snapshot: 新建或复用的资源、运行终端: 停止与重启方式: 未完成项、失败原因与下一步: 结论:源码评估服务就绪 / AI 端到端验证通过 / Local fixture 通过 / BLOCKED ``` ## 10. Docker Compose 分支(容器化评估) 选择 Docker 后执行第 0 节、本节、第 6 节(可选)及第 9 节;不执行第 1–5 节的宿主机 Go/npm 流程。宿主机不需要 Go/Node。此分支从当前 checkout 构建镜像,尚未完成容器端到端验收,不是生产安装包。 ### 10.1 预检与资源授权 在仓库根目录逐条检查 `git status --short`、`git rev-parse --short HEAD`、`docker version`、`docker compose version`。需要可用的 Linux 容器引擎和 Compose **2.30.0+**(使用 raw env_file);Windows 使用 Docker Desktop Linux containers 或明确选定的 WSL 引擎,不混用路径。确认 Docker context 指向用户批准的本机引擎,不操作未知远端引擎。 确认端口 8080、Compose 项目名、镜像下载/构建、创建网络/容器/卷、数据库迁移权限。选择: - **配套依赖**:仅新建专用评估库时使用 `compose.yaml + compose.local.yaml`。创建 PostgreSQL 17、Redis 7 及持久化卷;数据库不发布宿主机端口。Redis 无密码,仅限可信本机 Docker 环境,不能把此网络当成多租户安全隔离。 - **已有依赖**:仅使用 `compose.yaml`,不启动配套数据库。确认容器内可达地址、ACL/TLS、备份和原加密密钥。容器里的 `127.0.0.1` 不是宿主机;不要猜测宿主机网关或关闭 TLS。 缺少 Docker 时报告 `BLOCKED`,经批准安装后再继续,不静默安装。默认不开放公网,不挂载 Docker socket;本镜像不提供 Enhanced Docker 验证或自动修复运行环境。 ### 10.2 私有配置 进入仓库的 `deploy/`,下列所有 Compose 命令均在此运行。仅当 `.env` 不存在时,采用第 2.1 节的安全复制命令,从此目录的 `.env.example` 创建;检查权限、Git 忽略和未跟踪状态。不得复用示例空密钥启动。 用户用密码管理器/私有编辑器填写,不在聊天、命令参数或日志中传递秘密: - 新数据库:生成并保存 **32 随机字节的标准 base64** 作为 `MENDRY_ENCRYPTION_KEY`;已有数据库保留原值。Docker 路径不要求安装 Node 来生成密钥,可使用密码管理器或本地 .NET/OpenSSL,输出只能写入私有文件。 - 配套依赖:生成随机十六进制数据库密码,写入 `POSTGRES_PASSWORD`,并将相同值私下填写到 `MENDRY_POSTGRES_URL=postgres://mendry:PASSWORD@postgres:5432/mendry?sslmode=disable`。替换 PASSWORD,不能保留占位符。保持 `MENDRY_REDIS_URL=redis://redis:6379`。 - 已有依赖:填写实际 PostgreSQL / Redis URL,按第 2.3 节的编码与 TLS 规则处理;不需要 `POSTGRES_PASSWORD`。证书文件若有需要,先确认只读挂载方案。 - 保持 `COMPOSE_PROJECT_NAME` 稳定且与用户确认一致;已有同名资源先确认归属。更名会选用另一组卷,不能用来绕过已有数据。 - 容器内 API 监听 `0.0.0.0:8080`,但宿主机只发布 `127.0.0.1:8080` 的 Nginx;`MENDRY_PUBLIC_URL` 默认保持 `http://127.0.0.1:8080`。 `env_file` 使用 raw 格式:值不加引号,不添加行尾注释,美元符号保持原样。Compose 自身仍会解析项目名和 POSTGRES_PASSWORD,因此配套密码限定为随机十六进制。检查同名 shell 变量是否存在以防覆盖(只检查名称,不打印值)。不要运行会展开秘密的 `docker compose config`(无 `--quiet`)或 `docker inspect`;Docker 管理员仍能访问容器环境,须信任引擎管理员。 ### 10.3 构建、迁移与账号 以下是**配套依赖**命令。若选择**已有依赖**,从每条命令删除 `-f compose.local.yaml`,并跳过启动 postgres/redis 的命令;所有后续停止/重启命令也保持相同文件组合。每条短命令检查退出码,失败即停。 ```text docker compose --env-file .env -f compose.yaml -f compose.local.yaml config --quiet docker compose --env-file .env -f compose.yaml -f compose.local.yaml build api web docker compose --env-file .env -f compose.yaml -f compose.local.yaml up -d --wait --wait-timeout 120 postgres redis docker compose --env-file .env -f compose.yaml -f compose.local.yaml run --rm --no-deps migrate ``` 迁移前确认数据库目标与备份,退出码必须为 0。API 不自动迁移。镜像标签是评估用可变标签;记录源码版本和实际镜像 ID,不宣称可复现生产发行。 已有可登录账号跳过初始化。首次账号:用户临时在 `deploy/.env` 添加 `MENDRY_BOOTSTRAP_ADMIN_PASSWORD`(12–72 字节),执行: ```text docker compose --env-file .env -f compose.yaml -f compose.local.yaml run --rm --no-deps bootstrap-admin ``` 默认用户名 `admin`;其他用户名经确认后在命令末尾加 `bootstrap-admin --username NAME`。无论成功或失败均删除临时密码项,再启动 API,避免将密码留在长驻容器环境。不得重置已有账号或尝试创建第二个账号。 ### 10.4 启动与验收 ```text docker compose --env-file .env -f compose.yaml -f compose.local.yaml up -d --wait --wait-timeout 120 api web docker compose --env-file .env -f compose.yaml -f compose.local.yaml ps ``` 退出码为 0、服务 healthy 后,执行第 4 节的两个 HTTP 健康检查(地址不变,此时经 Nginx 代理),浏览器打开 `http://127.0.0.1:8080` 并验证登录及页面刷新。Nginx 提供构建后的静态资源,支持 SPA 回退以及同源 `/api`、`/hooks` 代理,不使用 Vite 开发服务器。无浏览器能力时登录标记待验证;容器 healthy 不代表模型可用。模型验证继续第 6 节,仍需单独授权;远程 Webhook/SSH 需要另行确认 HTTPS 和网络方案。 ### 10.5 停止、重启与保留数据 ```text docker compose --env-file .env -f compose.yaml -f compose.local.yaml stop docker compose --env-file .env -f compose.yaml -f compose.local.yaml up -d --wait --wait-timeout 120 api web ``` 上述第二条为同版本重启;配套依赖由 depends_on 启动。保留 `deploy/.env`、原加密密钥、项目名、PostgreSQL/Redis/runtime 卷。runtime 存储 artifacts/workspaces;备份需同时覆盖数据库、运行数据和加密密钥。禁止 `down -v`、卷 prune、删库或重生成密钥。版本变化先确认备份及授权,再构建、迁移、启动;不承诺自动回滚。 健康超时先检查 `ps` 和用户私下审阅的脱敏日志:数据库就绪、连接地址、原密钥、卷写权限、端口冲突。不要输出完整容器环境或带凭据日志。保留失败资源并报告 `BLOCKED`,不无限重试或自动清理。交付按第 9 节记录 Compose 文件组合、项目名、镜像 ID、卷及验收结果。 ## 维护依据 中英文版本必须同步维护:章节编号、命令、安全边界与验收条件保持一致,仅翻译说明和交付模板,不翻译可执行标识。英文版见 [agent-install.en.md](/agent-install.en.md)。修改第 10 节时同步检查 Docker Compose 配套:[compose.yaml](https://github.com/Funovate/Mendry/blob/a60d47164f602d692cd56edecdb19315c37b830a/deploy/compose.yaml)、[compose.local.yaml](https://github.com/Funovate/Mendry/blob/a60d47164f602d692cd56edecdb19315c37b830a/deploy/compose.local.yaml)、[deploy/.env.example](https://github.com/Funovate/Mendry/blob/a60d47164f602d692cd56edecdb19315c37b830a/deploy/.env.example)、[后端 Dockerfile](https://github.com/Funovate/Mendry/blob/a60d47164f602d692cd56edecdb19315c37b830a/backend/Dockerfile)、[前端 Dockerfile](https://github.com/Funovate/Mendry/blob/a60d47164f602d692cd56edecdb19315c37b830a/frontend/Dockerfile)、[nginx.conf](https://github.com/Funovate/Mendry/blob/a60d47164f602d692cd56edecdb19315c37b830a/frontend/nginx.conf);修改后在 `frontend/` 运行 `npm run test:deploy`([deploy/check.test.cjs](https://github.com/Funovate/Mendry/blob/a60d47164f602d692cd56edecdb19315c37b830a/deploy/check.test.cjs))。 更改安装步骤时核对 [根 README](https://github.com/Funovate/Mendry/blob/a60d47164f602d692cd56edecdb19315c37b830a/README.md)、[后端说明](https://github.com/Funovate/Mendry/blob/a60d47164f602d692cd56edecdb19315c37b830a/backend/README.md)、[配置模板](https://github.com/Funovate/Mendry/blob/a60d47164f602d692cd56edecdb19315c37b830a/backend/.env.example)、[Makefile](https://github.com/Funovate/Mendry/blob/a60d47164f602d692cd56edecdb19315c37b830a/backend/Makefile)、[前端脚本](https://github.com/Funovate/Mendry/blob/a60d47164f602d692cd56edecdb19315c37b830a/frontend/package.json) 及上面的专题参考。入口文件只链接本手册,不复制其执行流程;不能用文档修改宣称尚未验证的生产分发能力。