关于 nocobase-app-installer
nocobase-app-installer 技能通过已构建的部署归档安装和运行 NocoBase 3,面向生产部署场景。它管理版本发布、pm2 进程以及升级和回滚流程,不负责开发应用。
主要功能
- 01从部署归档安装
- 02使用 pm2 运行应用
- 03检查安装状态与健康情况
- 04升级并在失败时回滚
- 05支持本地或 SSH 部署
适用场景
- 01在服务器部署 NocoBase 应用
- 02检查现有安装和运行状态
- 03升级生产环境并处理失败回滚
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nocobase/ skills-v3 --skill nocobase-app-installer安装后在 Claude Code 中输入/nocobase-app-installer确认已加载。
附带文件references/remote-deployment.md
详细介绍
使用 app-installer 安装并运行 NocoBase 3
此 Skill 安装的是已经构建好的 NocoBase——机器上不会进行任何开发,只负责运行。@nocobase/app-installer 会将每个版本安装在 releases/<version>_<build time>/app 下,并通过 pm2 运行;config.yml、app.env、storage/、backups/ 和 logs/ 位于 releases 旁边,每次升级都会保留。它从 --archive 安装,该归档由应用项目构建。本 Skill 会判断何时使用它,以及如何处理它报告的情况;每个标志的参考说明请查看 --help。
运行
在 Agent 工作所在的机器上运行安装程序,并指定 registry 和 --json。对于 SSH 部署,这里指本地机器,而不是服务器:
npx --yes --registry="${NOCOBASE_REGISTRY:-https://registry.npmjs.org}" @nocobase/app-installer@beta <command> … --json
发布的安装程序使用 @beta;不要退回到不带标签的调用或 @latest。如果现有安装需要明确版本,或用户指定了明确版本,请保留该版本;测试未发布的本地 registry 时,使用 snapshot 标签。
NocoBase 3 会发布到公共 npm registry。只有当有人将 shell 指向其他 registry(例如未发布的 snapshot)时,才会设置 NOCOBASE_REGISTRY;安装程序会将 registry 记录在 installer.json 中,并从该 registry 提供命令建议。软件包前面的 --yes 是 npx 自身的参数:它会在不询问的情况下下载安装程序。命令后面的安装程序 --yes 是另一个独立的确认选项,只能由用户提供。
除非用户指定了确切版本,否则使用已发布的 beta 渠道。未发布的 snapshot registry 会将其软件包标记为 latest;仅在测试此类 registry 时使用该标签。部署前请查看 --help,确认所选版本支持 deploy 和 --ssh。
--json 会在 stdout 上打印一个文档,并在 stderr 上输出进度,其封装格式与 pnpm nocobase … --json 相同。请读取文档,而不能只看退出代码:ok、status(success、success-noop 或 failure)、result;失败时还包括 error.code、error.message、error.suggestions 和 error.details。每条建议都包含 message;如果有可运行命令,还会包含 run,格式为 { command, args }:一个可执行文件及其参数,应原样运行,不经过 shell。app-installer 0.1.0-beta.1 及更早版本(固定到该版本的建议命令仍会运行这些版本)会将 status 输出为 error,并将 run 输出为一行 shell 命令;该命令应按输出内容原样运行,因此请通过 ok 判断成功或失败。
| 退出代码 | 含义 |
|---|---|
0 | 已完成,或无事可做(success-noop)。 |
1 | 失败;未触及已经在运行的应用。 |
2 | 用法无效、预检查失败,或仍需确认;未写入任何内容。 |
3 | 切换后升级失败并已回滚;先前版本正在运行。 |
4 | 回滚也失败;应用已停止运行。 |
选择部署路径
项目是由 nocobase-create-app 创建并在本地开发的源代码,用户会对其进行修改;安装则是由此 Skill 构建、仅用于运行的 NocoBase,通常用于生产环境。开始安装前,先确定部署路径:
| 用户要求 | 部署路径 |
|---|---|
| 安装、创建或试用 NocoBase,以便进行开发 | nocobase-create-app Skill |
| 将应用部署到生产环境或服务器 | 此 Skill,使用 --archive 和应用的部署归档 |
| 使用 Docker 运行 | 应用的 nocobase-deployment Skill 和 Docker 配置 |
- 如果用户只说“在此服务器上安装 NocoBase”,但没有项目或归档,则尚未确定部署路径。要运行用户自己的应用,应先使用
nocobase-create-app在本地创建应用、构建其归档,再使用--archive将其安装到此处。不要在服务器上创建项目并用pnpm dev运行:那是开发模式,不是部署。 installer.json中的source.kind为template,表示该安装由较早版本的 app-installer 从已发布的 Hub 模板安装。当前版本会以STATE_UNSUPPORTED拒绝处理;请交由安装该模板的 app-installer 版本处理。- 如果当前工作目录中已有
installer.json,则表示安装已存在:从status开始。
选择安装程序的运行位置
当用户提供 SSH 服务器时,请将 Agent、此 Skill 和安装程序保留在本地计算机上。继续操作前,请阅读远程部署:其中介绍了本地编排、离线执行和恢复。服务器不需要 Agent、Skill 或 npm 访问权限。以下关于 install、status、upgrade 和 rollback 的说明仍定义了生命周期;执行远程操作时,请使用相同的 SSH 选项和绝对路径的远程 --dir。
当 Agent 已在应用服务器上时,请使用以下本地命令。归档应在源代码所在的位置构建,而不是在生产环境的安装目录中构建。如果源项目在本地可用,请遵循其 AGENTS.md 和 nocobase-deployment Skill 进行构建;否则,请向用户或 CI 获取归档。不要在生产服务器上构建或运行开发项目。
构建归档
在应用项目中构建;构建方式以项目自身的 AGENTS.md 和 nocobase-deployment Skill 为准:
APP_BASE_PATH=/crm pnpm build --target linux-x64 --node-version 24 --tar
--target和--node-version描述的是运行应用的机器,而不是构建机器:在运行应用的机器上执行node -p "process.platform + '-' + process.arch"和node --version获取对应值;Alpine 使用带-musl的 target。安装程序会拒绝为其他机器构建的归档,并指出适用的命令。APP_BASE_PATH会编译进客户端,未设置时为/main。应用会在此路径下提供服务,之后构建的每个归档都必须使用相同路径。- SQLite 以外的数据库需要在构建前将驱动添加到项目中,例如
pnpm add @nocobase/db-postgres@beta:归档只包含构建时使用的驱动。
归档路径为 storage/exports/dist.tar.gz;用户需将其复制到运行 NocoBase 的机器上,例如 scp storage/exports/dist.tar.gz user@server:/tmp/crm.tar.gz。ARCHIVE_TOO_OLD 或 STORAGE_IN_RELEASE 表示项目中的 NocoBase 软件包版本低于安装程序所需版本:请升级这些软件包,重新构建,然后重试。
安装
所有安装方式
- 检查机器:运行
node --version(24 或更高版本)和command -v pm2,后者可以在不启动守护进程的情况下查找 pm2。必须全局安装 pm2 4.3 或更高版本:npm install -g pm2;通过npx获取的副本会导致pm2 startup无法正常工作。指出缺少的内容及其安装命令,除非用户要求,否则不要全局安装任何内容。在 Windows 上,请使用 WSL。 - 与用户确认:目标目录(必须是新目录或空目录,例如
/srv/nocobase/crm);不含基本路径的公共源站,例如https://apps.example.com,如果机器只能通过http://127.0.0.1:<port>访问,则可不提供;前面是否有反向代理;端口(默认为 13000,且机器上的每个安装都必须使用不同端口);以及数据库(默认为 SQLite)。 - 服务监听
127.0.0.1,适合由同一台机器上的反向代理访问;如果用户要通过http://<address>:<port>直接访问,则添加--host 0.0.0.0,并将该地址用作源站。要使用其他数据库,请添加--dialect <dialect>,通过--set database.connections.main.host=…等参数提供连接信息,并在用户导出密码后,使用--set-from-env database.connections.main.password=<VARIABLE>提供密码;绝不要将密码放在命令行中。 PORT_IN_USE会在error.details.freePort中给出一个可用端口;请向用户提供该端口,而不是默默地自行选择。
运行
install <dir> --archive <file> --origin <origin> --json。无需 pnpm,整个过程只需一两分钟。如果归档文件未包含 --dialect 所需的驱动程序,安装将以 DRIVER_MISSING 错误停止,并给出用于修复问题的构建命令。
成功时
当 result.started 为 true 时,表示安装已通过健康检查。请告知用户:
result.url,以及首次登录信息:result.initialAdmin.username或其email,密码位于config.yml中的users.initialAdmin下。如果result.initialAdmin.defaultPassword为 true,则密码仍是config.example.yml中的admin123,用户必须在登录后更改;否则,密码就是用户设置的密码。结果中绝不包含密码,且不会读取config.yml;result.nextCommands中的每条命令:pm2 startup会输出一条命令,用户只需通过 sudo 运行一次,之后 pm2 会恢复安装程序保存的进程列表,因此重启后安装也会恢复运行;- 如果使用了反向代理:代理应将请求转发到安装所用的端口,并设置 WebSocket 升级标头。多个安装共用一个源站时,将根据各自的基本路径进行路由;
warnings中的所有内容。
切换前安装失败时,目标目录会保持原样。失败步骤的相关信息位于 error.details 中:解压发行版时查看 output;发行版自带的 CLI 未打印结果时查看 stderr 和 stdout。如果是该 CLI 自行报告的失败,则保留 CLI 自身的错误代码(例如 CONFIG_INVALID),并通过 error.message 和 error.suggestions 说明问题所在。START_FAILED 表示已完成安装,但未运行:请显示 error.details.log。
在一台机器上安装多个实例
每个应用只安装一次,且各自使用独立目录和 --port。pm2 进程名称默认为 nocobase-<directory name>,因此目录名称不同就不会冲突;如果两个目录名称相同,则会在写入任何内容前报告 PM2_NAME_IN_USE,此时可通过 --name 为第二个实例指定不同名称。
状态
status --dir <root> --json 不会更改任何内容。请报告应用及其 version、current(发行版 ID)、endpoints.url、health.ok、process,以及 warnings 中的所有内容。node.matches: false 表示自构建发行版以来,机器上的 Node 主版本发生了变化;在为这台机器构建的发行版替换它之前,该发行版将无法加载其原生模块:警告会列出所需步骤——重新构建归档文件,然后运行 upgrade --archive;这些步骤与任何升级一样,都会经过停止、备份和确认流程。pending 非空表示某个操作已中断;请参阅下文。
升级和回滚
升级现有数据库前,请阅读目标应用及已注册插件针对该版本的升级说明。在恢复计划中纳入文档中提及的校验和变更、数据前置条件和不可逆迁移。安装程序停止应用前,请使用目标应用支持的 CLI 和部署配置检查 db repair --dry-run --json 输出,即使没有记录过往修正也应如此。这是一项只读校验和检查:安装程序自身的 db apply --dry-run 会发现待处理任务,但不会验证校验和,即使采用严格校验和策略也是如此。如果所选安装程序无法执行所需检查或准备工作,请先确定受支持的维护流程,再继续升级。
如果校验和预览建议进行变更,请在实际修复前说明每项迁移或种子校验和差异;如果没有建议变更,则跳过修复。安装程序会应用迁移,但不会自动确认已变更的历史校验和。修复只会更新历史记录中的校验和;不会更改架构、修复不完整的表,也不能替代向前迁移。不要通过更改迁移策略或反复重试同一归档来掩盖漂移。
普通安装程序升级前不要执行实际修复。SQLite 备份是在停止应用后创建的,其中已经包含新校验和;如果升级回滚,旧运行时在 onChecksumMismatch: error 下可能无法接受这些校验和。修复流程必须先停止写入、备份原始历史记录,再执行经过审核的修复和迁移;如果失败,重启旧运行时前必须恢复同一份修复前备份。额外手动备份本身并不会改变自动回滚所恢复的备份。如果所选安装程序无法协调这一流程,只完成只读检查,并先确定受支持的维护流程。
两种操作都会停止应用,因此由用户决定:
- 升级会获取新归档:
upgrade --dir <root> --archive <file> --json。它必须是针对相同基本路径构建的同一应用,且不能是较旧版本;重新构建的相同版本也属于新发布版本,会正常部署。 - 不要使用
--yes运行。它会返回CONFIRMATION_REQUIRED,并附带error.details.notes:将停止哪些内容、会备份哪些内容,以及 Node 主版本是否变更。将这些说明转告用户,并等用户明确同意后,再使用--yes重新运行。success-noop表示该发布版本已在运行。 - 安装程序会备份
config.yml中声明的所有 SQLite 数据库,以及config.yml和app.env,但不会备份其他数据库:BACKUP_REQUIRED会列出这些连接;请让用户先备份,然后添加--backup-done。 - 升级会保留三个发布版本,始终包括新版本和升级前的版本;成功后会清理更旧的版本。如果用户希望保留更多版本以便回滚,请传入
--keep <n>。 - 查看结果:
- 退出码为 0:新版本已通过运行状况检查。报告
result.fromVersion、result.toVersion、发布 IDresult.to、result.migrations和result.backup,并指出result.pruned中的任何发布版本,因为这些版本已无法回滚到。 - 退出码为 3:已重新运行先前的版本。报告
error.message、error.details.log,并说明数据库是否已恢复;外部数据库可能仍包含失败升级造成的变更。确认原因后,将下一次尝试留给用户决定。 - 退出码为 4:应用已停止运行。与用户逐步处理
error.suggestions。rollback --dir <root> --json会返回到上次升级前的版本,或返回到--to <release id or version>指定的版本。如果该次升级迁移了 SQLite 数据库,且安装程序保留了数据库备份,回滚时会恢复备份,并丢失此后存储的所有内容;确认提示会说明这一点,并且同样需要转发确认步骤。外部数据库需要单独执行恢复流程:--backup-done不会让安装程序恢复这些数据库。如果不可逆迁移导致架构与先前的运行时不兼容,要返回该运行时,也必须有兼容的数据库备份。--no-restore会保留当前数据库;只有在确认数据库与所选运行时兼容时才使用此选项。
- 退出码为 0:新版本已通过运行状况检查。报告
恢复中断的操作
upgrade 返回 OPERATION_INTERRUPTED,或 status 中显示 pending,表示先前的运行在应用停止期间中断。直接运行 rollback 即可通过相同的确认步骤恢复:撤销中断的升级并恢复数据库,或完成中断的回滚。
更改源地址或端口
app-installer 没有用于此操作的命令。源地址、主机地址和端口在 app.env 中,分别对应 APP_PUBLIC_ORIGIN、APP_SERVER_HOST 和 APP_SERVER_PORT。更改前,请告知用户:
- 应用的新访问地址将由新源地址和基础路径组成;
- 应用重启时会短暂停止运行;
- 新端口必须未被占用,否则应用重启后会陷入崩溃循环,且只有
logs/app.err.log能说明原因;此外,前置反向代理必须将请求转发到该端口; - 无法通过这种方式更改
APP_BASE_PATH:它已编译到客户端中。
在用户同意后,只编辑这三行,不要更改其他内容,然后运行 pm2 restart <name>,其中 <name> 是 status 中的 name。pm2 会通过 launcher.mjs 启动应用,该文件每次启动时都会读取 app.env,因此无需重新注册任何内容。之后,status 会报告新的 endpoints,并检查 app.env 中地址的运行状况;如果源地址变了,请让用户打开 endpoints.url。
保持数据完整
根目录中存放着应用配置、密钥和数据的唯一副本。除上述 app.env 中的三行外,所有更改都通过 app-installer 进行;是否删除任何内容,应由用户决定。不要在对话中透露 config.yml 的内容,该文件包含密钥。