Homarr 2.10.1 常用 CLI 命令与工具详解
Homarr v2.10.1 内置 recovery CLI 全部子命令实测回显与适用场景,沉淀数据类子命令输出后挂起不退出、不解析 _FILE 密钥两大运维怪癖的规避写法,并给出官方自动化正门 REST API(OpenAPI 3.1.0、42 个路径)与 tRPC 调用形态速查。
Homarr 2.10.1 常用 CLI 命令与工具详解
目标:讲清 Homarr v2.10.1 交付形态内置的 recovery CLI(
homarr命令,版本 1.0.0)全部子命令的实测回显与适用场景,沉淀「数据类子命令输出后挂起不退出」「不解析_FILE密钥」两个运维怪癖的规避写法,并给出官方定位的自动化正门——REST API(规范 1.1.0,实测 42 个路径)与 tRPC 调用形态。本文全部回显为 2026-11-02/03 运行实例实测。
一、定位与访问方式
官方对这套 CLI 的定位非常明确(Command line interface 文档页):服务内置的是 recovery CLI,用于 Web 界面无法完成的恢复操作;它不是应用 API,自动化请走 API 或 MCP 端点。使用纪律同样来自官方:改数据的命令前先备份数据库并停止服务;失败的命令会打印错误并返回非零退出码,脚本可安全中断。
访问方式(官方推荐形态):
$ docker exec -it <container-id> /bin/bash
homarr <command>
本文全部实测用一行式写法(免开交互 shell),并处理第七节的密钥坑——必须显式注入 SECRET_ENCRYPTION_KEY。实测前先在宿主导出密钥变量,本文后续命令中的 $KEY 即此值:
$ KEY=$(cat /opt/apps/homarr/secrets/secret_key.txt)
$ docker exec -e SECRET_ENCRYPTION_KEY="$KEY" homarr-2-10-1-server homarr --version
1.0.0
--help 全量回显(实测):
$ docker exec homarr-2-10-1-fresh homarr --help
Usage:
homarr-cli [command]
Available Commands:
users Group of commands to manage users
integrations Group of commands to manage integrations
reset-password Reset password for a user
fix-usernames Changes all credentials usernames to lowercase
recreate-admin Recreate credentials admin user if none exists anymore
harness Build and run a local branch in a browser-ready demo harness
Flags:
-h, --help help for homarr-cli
-v, --version version for homarr-cli
命令族总览(帮助文本实测 + 官方 CLI 文档页逐条对照):
| 命令 | 作用 | 需要数据库连接 | 数据变更 |
|---|---|---|---|
users list | 列出全部用户(id、username、email) | 是 | 否 |
users delete | 按 id 或 username 删除用户 | 是 | 是 |
users update-password | 更新指定用户密码(仅 credentials 提供器) | 是 | 是 |
integrations list | 列出全部集成(id、name) | 是 | 否 |
integrations delete | 按 id 或 name 永久删除集成 | 是 | 是 |
reset-password | 强制重置密码为随机值并终止该用户全部会话 | 是 | 是 |
fix-usernames | 把所有 credentials 用户名转为小写 | 是 | 是 |
recreate-admin | credentials admin 用户不存在时重建 | 是 | 是 |
harness | 开发者工具:构建并运行本地分支 demo | 否(宿主侧) | - |
二、users 命令族
2.1 users list
官方说明:Requires a database connection,输出 id/username/email 三列。实测(主实例,已有 admin 与测试用户 opsuser2):
$ timeout 25 docker exec -e SECRET_ENCRYPTION_KEY="$KEY" homarr-2-10-1-server homarr users list
2026-11-02T18:08:53.452Z debug: Executed SQL query module="db" query="select "id", "name", "email" from "user" "users""
ID Username Email
caduhl49zvdplppzn791z65c admin
q369gs7aou4prb03sq3w16q2 opsuser2 ops2@homarr.local
要点:admin 的 email 列为空属正常(onboarding 写入的邮箱在 account 关联记录,list 取 user 表投影);debug: 行是 LOG_LEVEL=debug 的副作用(CLI 与应用共用环境变量,生产 info 下不出现,见第七节)。空库实例上输出 No users found(实测全新实例回显)。
2.2 users update-password
官方说明:需要数据库连接、需要 --username 或 --id 之一、需要 --password(由 Homarr 加密入库);--help 实测(!string 标记表示必填):
$ timeout 25 docker exec -e SECRET_ENCRYPTION_KEY="$KEY" homarr-2-10-1-server homarr users update-password --help
Update the password for a user (credentials provider only)
Usage:
homarr-cli users update-password [flags]
Flags:
-i, --id string ID of the user
-u, --username string Name of the user
-p, --password !string New password
-h, --help help for users update-password
-v, --version version for homarr-cli
实测(把 opsuser2 密码重置为演示口令 q1w2e3r4):
$ timeout 25 docker exec -e SECRET_ENCRYPTION_KEY="$KEY" homarr-2-10-1-server homarr users update-password -u opsuser2 -p q1w2e3r4
2026-11-02T18:09:43.511Z debug: Executed SQL query module="db" query="update "user" set "password" = ? where "user"."id" = ?"
2026-11-02T18:09:43.514Z debug: Executed SQL query module="db" query="delete from "session" where "session"."user_id" = ?"
All sessions for user opsuser2 have been deleted
Password updated successfully
用户不存在/无 credentials 记录时的回显(实测,退出码仍为 0——脚本不能靠 rc 判断业务结果):
User not found or has no credentials record
2.3 users delete
官方说明:按 id 或 username 删除,flags -i/--id、-u/--username。实测(删除测试用户):
$ timeout 25 docker exec -e SECRET_ENCRYPTION_KEY="$KEY" homarr-2-10-1-server homarr users delete -u opsuser2
2026-11-02T18:10:08.481Z debug: Executed SQL query module="db" query="delete from "user" where "user"."id" = ?"
User opsuser2 (q369gs7aou4prb03sq3w16q2) deleted
回显同时给出被删用户的 id,便于核对;docker exec 交互场景下删除前务必按官方纪律先备份数据库。
三、integrations 命令族
3.1 integrations list:列出集成(id 与 name)。实测空库回显:
$ timeout 25 docker exec homarr-2-10-1-fresh homarr integrations list
No integrations found
3.2 integrations delete:按 id 或 name 永久删除集成(官方措辞 permanently from the database),flags -i/--id、-n/--name。集成凭据由 SECRET_ENCRYPTION_KEY 加密落库,删除不可恢复——这也是官方把它列入 recovery 面而非日常运维面的原因:日常增删改集成走 GUI/API(Management → Integrations)。
四、reset-password(密码找回主场景)
官方语义(Password Recovery 文档页):强制把指定用户密码重置为随机值、更新哈希、终止该用户全部会话并要求重新登录。--help 实测:
Reset password for a user
Usage:
homarr-cli reset-password [flags]
Flags:
-u, --username !string Name of the user
-h, --help help for reset-password
-v, --version version for homarr-cli
实测(对 opsuser2 执行):
$ timeout 25 docker exec -e SECRET_ENCRYPTION_KEY="$KEY" homarr-2-10-1-server homarr reset-password --username opsuser2
2026-11-02T18:09:18.512Z debug: Executed SQL query module="db" query="update "user" set "password" = ? where "user"."id" = ?"
2026-11-02T18:09:18.515Z debug: Executed SQL query module="db" query="delete from "session" where "session"."user_id" = ?"
All sessions for user opsuser2 have been deleted
You can now login with the new password
New password for user opsuser2: ee2d982f1f87e9ebe4116641d63d1fa7484ac5861529fb88
新密码只在 stdout 打印一次,请立即转交用户并建议其登录后改密。用户不存在时回显 User opsuser not found(实测)。典型场景:成员忘记口令且管理员无法从 Web 侧代改 credentials 密码时,用本命令解锁。
五、fix-usernames 与 recreate-admin(账号体系恢复)
5.1 fix-usernames
官方语义(Fix usernames 文档页):当 credentials 用户名含大写字符导致无法登录时,把全部 credentials 用户名转小写并更新数据库。实测回显:
$ timeout 25 docker exec -e SECRET_ENCRYPTION_KEY="$KEY" homarr-2-10-1-server homarr fix-usernames
2026-11-02T18:10:33.474Z debug: Executed SQL query module="db" query="select "id", "name" from "user" "users" where "users"."provider" = ?"
All usernames have been fixed
5.2 recreate-admin
官方语义(Recreate admin 文档页):credentials admin 用户误删后重建。--help 实测:
Recreate credentials admin user if none exists anymore
Usage:
homarr-cli recreate-admin [flags]
Flags:
-u, --username !string Name of the admin
-h, --help help for recreate-admin
-v, --version version for homarr-cli
幂等保护实测(admin 尚存时执行,只报告不重复创建):
$ timeout 25 docker exec -e SECRET_ENCRYPTION_KEY="$KEY" homarr-2-10-1-server homarr recreate-admin -u admin
2026-11-02T18:10:58.507Z debug: Executed SQL query module="db" query="select count(*) from "groupPermission" left join "groupMember" on "groupMember"."group_id" = "groupPermission"."group_id" left join "user" on "user"."id" = "groupMember"."user_id" where ("groupPermission"."permission" = ? and "user"."provider" = ?)"
Credentials admin user exists
六、harness(开发者向,非运维命令)
--help 命令族里的 harness 是仓库宿主侧开发工具(官方 Command line interface 页):bun run cli harness setup feature-board 构建当前 checkout 并以命名 demo 运行、打印分配 URL;配套 harness port/build/run/stop <name>,--env 可重复传环境变量。生产运维用不到,列此备开发同学查阅。
七、两个运维怪癖(必读)
7.1 数据类子命令输出后进程不退出(挂起)
官方文档承诺「失败命令返回非零退出码,脚本可安全停止」,但实测所有访问数据库的子命令(list/delete/update-password/reset-password/fix-usernames/recreate-admin)打印完结果后进程挂起不退出。实证一:连跑六条命令,相邻时间戳间隔恰好都是 timeout 的 25 秒(18:08:53→18:09:18→18:09:43→18:10:08→18:10:33→18:10:58);实证二:超时被杀后服务环境内残留挂起的 CLI 进程:
$ docker exec homarr-2-10-1-server ps aux | grep cli.cjs | grep -v grep
67 root 0:00 {MainThread} node ./cli.cjs users list
104 root 0:00 {MainThread} node ./cli.cjs users delete -u opsuser3
129 root 0:00 {MainThread} node ./cli.cjs users list
153 root 0:00 {MainThread} node ./cli.cjs users list
644 root 0:00 {MainThread} node ./cli.cjs users list
668 root 0:00 {MainThread} node ./cli.cjs reset-password --username opsuser2
693 root 0:00 {MainThread} node ./cli.cjs users update-password -u opsuser2 -p q1w2e3r4
717 root 0:00 {MainThread} node ./cli.cjs users delete -u opsuser2
742 root 0:00 {MainThread} node ./cli.cjs fix-usernames
(homarr 命令本体是 /app/apps/cli/cli.cjs 的 Node 封装,残留进程显示的是真实入口。)
规避纪律:凡脚本化调用 recovery CLI,一律用 timeout 包裹(本文第二至五节实测命令即标准形态:timeout 25 docker exec -e SECRET_ENCRYPTION_KEY="$KEY" homarr-2-10-1-server homarr <命令>),成功与否看 stdout 关键字(如 deleted/Password updated successfully),不要等进程自然退出,也不要用「命令返回=执行完成」做判断。--help/--version 纯本地命令不受影响,实测正常退出。
7.2 不解析 _FILE 密钥(与 Web 进程行为不一致)
《Homarr Docker Compose 部署指南》用 SECRET_ENCRYPTION_KEY_FILE=/run/secrets/secret_key 注入密钥(secrets 通道)。Web 进程会解析 _FILE 后缀,CLI 不会——不带 -e 直接执行,连 --help 都会报环境变量校验错误并抛异常退出(实测完整回显;报错里的建议随机密钥每次不同,属正常):
$ docker exec homarr-2-10-1-server homarr users --help
❌ Invalid environment variables: [
{
expected: 'string',
code: 'invalid_type',
path: [ 'SECRET_ENCRYPTION_KEY' ],
message: 'SECRET_ENCRYPTION_KEY is required, please generate a 64 character secret in hex format or use the following: "d8aec82a396df4ef3a0edeea83d60aa2f0b4694178e1eba6a686f8e0bb640f1f"'
}
]
/app/apps/cli/cli.cjs:22145
throw new Error("Invalid environment variables");
^
Error: Invalid environment variables
at /app/apps/cli/cli.cjs:22145:11
at createEnv (/app/apps/cli/cli.cjs:22150:29)
at createEnv2 (/app/apps/cli/cli.cjs:22187:10)
at createEnv3 (/app/apps/cli/cli.cjs:22264:31)
at ../common/env.ts (/app/apps/cli/cli.cjs:84677:12)
at __init (/app/apps/cli/cli.cjs:11:58)
at ../common/src/encryption.ts (/app/apps/cli/cli.cjs:84710:5)
at __init (/app/apps/cli/cli.cjs:11:58)
at ../common/src/server.ts (/app/apps/cli/cli.cjs:87932:5)
at __init (/app/apps/cli/cli.cjs:11:58)
Node.js v24.22.1
解决:执行时用 -e 显式传入密钥本体(本文第二至五节命令均此写法):
$ docker exec -e SECRET_ENCRYPTION_KEY="$KEY" homarr-2-10-1-server homarr users list
另注意每条命令 stderr 都伴随 DeprecationWarning: The punycode module is deprecated(Node 24 内置库告警,无害),以及 LOG_LEVEL=debug 时 SQL 行混入 stdout——脚本解析输出时按表头/关键字定位,别按行号。
八、REST API:自动化的官方正门
恢复之外的批量操作走 REST(官方 API 页:REST 暴露选定的既有控制,高级操作走 tRPC,两者都接受 ApiKey 头)。运行实例实拉规范元信息:
$ curl -s http://127.0.0.1:8138/api/openapi | python3 -c 'import sys,json;d=json.load(sys.stdin);print(d["openapi"], d["info"]["version"], len(d["paths"]))'
3.1.0 1.1.0 42
$ curl -s -H "ApiKey: a2a9dbf6.6b2e9362728ba1c909ab165fd3aba3e015f7d80c03adc363" http://127.0.0.1:8138/api/info
{"version":"2.10.1"}
即 OpenAPI 3.1.0 规范、API 文档版本 1.1.0、共 42 个路径。认证:API key 在 Management → Tools → API(或 tRPC apiKeys.create)生成,形如 <id>.<token>、只展示一次、以创建者身份行动且不过期。下文 cj.txt 均为 credentials 登录主实例后的 session jar(登录方法见第九节实测样例):
$ curl -s -b cj.txt -X POST http://127.0.0.1:8138/api/trpc/apiKeys.create -H 'Content-Type: application/json' --data '{"json":{"name":"ops-key"}}'
{"result":{"data":{"json":{"apiKey":"913d4a87.76843d60d16afe5c16cb2bdd1eb6931200c34770372035fc"}}}}
42 路径按域分组(实拉规范整理):
| 域 | 路径与方法 |
|---|---|
| apps | GET/POST /api/apps、GET /api/apps/paginated、GET /api/apps/search、GET /api/apps/selectable、GET/PATCH/DELETE /api/apps/{id} |
| boards | GET/POST /api/boards、POST /api/boards/items、PATCH /api/boards/{boardId}/items/{itemId}/layouts/{layoutId}、POST /api/boards/{boardId}/layouts/{layoutId}/reset、DELETE /api/boards/{id}、PUT /api/boards/{id}/content、POST /api/boards/{id}/duplicate、PATCH /api/boards/{id}/home、PUT /api/boards/{id}/layouts、PATCH /api/boards/{id}/mobile-home、PATCH /api/boards/{id}/name、GET/PATCH /api/boards/{id}/settings、PATCH /api/boards/{id}/visibility |
| certificates | POST /api/certificates/root、GET /api/certificates/{fileName} |
| integrations | POST /api/integrations/request、GET /api/integrations/{id}/test-connection |
| invites | GET/POST /api/invites、DELETE /api/invites/{id} |
| settings | GET/PATCH /api/settings/board |
| users | GET/POST /api/users、DELETE/GET /api/users/{userId}、PATCH /api/users/{userId}/changePassword、PUT /api/users/profile、PUT /api/users/profileImage、GET/PATCH /api/users/preferences、PATCH /api/users/changeHome、PATCH /api/users/changeScheme、PATCH /api/users/changeSearchEngine、PATCH /api/users/ddg-bangs、PATCH /api/users/firstDayOfWeek、PATCH /api/users/header-preferences、PATCH /api/users/right-click-widgets、PATCH /api/users/search-preferences、POST /api/users/search、GET /api/users/selectable |
| 其他 | GET /api/health/live、GET /api/info、GET /api/openapi |
实测样例。列用户:
$ curl -s -H "ApiKey: a2a9dbf6.6b2e9362728ba1c909ab165fd3aba3e015f7d80c03adc363" http://127.0.0.1:8138/api/users
[{"id":"caduhl49zvdplppzn791z65c","name":"admin","email":null,"emailVerified":null,"image":null}]
admin 的 id 与 2.1 节 users list 一致,email 为 null 亦与「user 表投影不含向导邮箱」的解释吻合。
建用户——必填字段是 username/confirmPassword/groupIds(漏传时 400 逐字段点名,实测完整回显;校验失败无副作用):
$ curl -s -H "ApiKey: a2a9dbf6.6b2e9362728ba1c909ab165fd3aba3e015f7d80c03adc363" -H 'Content-Type: application/json' --data '{"name":"opsuser","email":"ops@homarr.local","password":"q1w2e3r4"}' -w '\nHTTP %{http_code}\n' http://127.0.0.1:8138/api/users
{"message":"Input validation failed","code":"BAD_REQUEST","data":{"code":"BAD_REQUEST","httpStatus":400,"path":"userRouter.create","zodError":{"formErrors":[],"fieldErrors":{"username":["Invalid input: expected string, received undefined"],"confirmPassword":["Invalid input: expected string, received undefined"],"groupIds":["Invalid input: expected array, received undefined"]}},"error":null,"isBoardLayoutBoundsError":false},"issues":[{"expected":"string","code":"invalid_type","path":["username"],"message":"Invalid input: expected string, received undefined"},{"expected":"string","code":"invalid_type","path":["confirmPassword"],"message":"Invalid input: expected string, received undefined"},{"expected":"array","code":"invalid_type","path":["groupIds"],"message":"Invalid input: expected array, received undefined"}]}
HTTP 400
备份导出 GET /api/backup/export(session 通道实测,zip 含数据库与配置快照):
$ curl -s -m 30 -b cj.txt -o backup-8138.zip -w 'export GET: %{http_code} %{size_download}B\n' http://127.0.0.1:8138/api/backup/export
export GET: 200 2457662B
$ curl -s -b cj.txt -o /dev/null -X POST -w 'export POST: %{http_code} %{size_download}B\n' http://127.0.0.1:8138/api/backup/export
export POST: 405 0B
$ curl -s -o /dev/null -w 'export noauth: %{http_code} %{size_download}B\n' http://127.0.0.1:8138/api/backup/export
export noauth: 403 24B
方法探测实证:只认 GET(POST 返回 405 空响应体)、只认 session(无认证 403,body 为 {"error":"Unauthorized"}——API key 通道不覆盖该端点)。看板/偏好/服务器设置的读写样例与逐键语义见《Homarr 2.10.1 配置参数详解》第四至六节(含 PATCH 空响应体 200 实测)。官方约束摘录:分页与共享搜索上限 100 条;PUT /api/boards/{id}/content 是全量覆盖(未列条目会被删,改前先 board.getBoardByName 读现状);跨域浏览器请求必须用 ApiKey(session cookie 仅限同源)。
九、tRPC 调用形态速查
REST 未覆盖的操作走 tRPC(应用内部全量接口,接受同一 ApiKey 头或 session cookie)。实测形态:
- 查询:
GET /api/trpc/<过程名>?input={"json":…};无参查询可直接 GET 过程名(《Homarr 2.10.1 配置参数详解》的serverSettings.getAll即此形态); - 变更:
POST /api/trpc/<过程名>,请求体{"json":…}; - 响应统一包在
result.data.json;错误在error.json,含code/httpStatus/path(如 onboarding 未 claim 时FORBIDDEN 403 "This onboarding session is not claimed.",向导链完整实测见《Homarr Docker Compose 部署指南》 4.6 节)。
实测两例。credentials 登录表单字段是 name 而非 username(传错即 CredentialsSignin 回跳,《Homarr Docker Compose 部署指南》 4.6 节同坑)。主实例登录实测(先取 CSRF token 再回调):
$ CSRF=$(curl -s -c cj.txt http://127.0.0.1:8138/api/auth/csrf | python3 -c 'import sys,json;print(json.load(sys.stdin)["csrfToken"])')
$ curl -s -o /dev/null -w 'login: %{http_code} -> %{redirect_url}\n' -b cj.txt -c cj.txt -X POST http://127.0.0.1:8138/api/auth/callback/credentials --data-urlencode "csrfToken=$CSRF" --data-urlencode "name=admin" --data-urlencode "password=q1w2e3r4" --data-urlencode "callbackUrl=http://127.0.0.1:8138/"
login: 302 -> http://localhost:8138/
回跳地址显示 localhost:8138 是服务端按自身 URL 配置规范化的结果(实测请求发往 127.0.0.1:8138,$CSRF 由上一条命令赋值)。
集成创建 integration.create 的 secrets 必填(实测 400 完整回显——集成凭据以数组形式传入、加密落库;校验失败无副作用):
$ curl -s -b cj.txt -X POST http://127.0.0.1:8138/api/trpc/integration.create -H 'Content-Type: application/json' --data '{"json":{"name":"mock-svc","url":"http://127.0.0.1:9999","kind":"mock","attemptSearchEngineCreation":false}}'
{"error":{"json":{"message":"[\n {\n \"expected\": \"array\",\n \"code\": \"invalid_type\",\n \"path\": [\n \"secrets\"\n ],\n \"message\": \"Invalid input: expected array, received undefined\"\n }\n]","code":-32600,"data":{"code":"BAD_REQUEST","httpStatus":400,"path":"integration.create","zodError":{"formErrors":[],"fieldErrors":{"secrets":["Invalid input: expected array, received undefined"]}},"error":null,"isBoardLayoutBoundsError":false}}}}
十、官方文档对照与选型提醒
| 本文内容 | 官方文档页 |
|---|---|
| recovery CLI 定位/访问方式/harness | Command line interface(https://homarr.dev/docs/develop-and-automate/command-line-interface) |
| users 三子命令参数 | CLI → Users |
| integrations 两子命令参数 | CLI → Integrations |
| reset-password 语义 | CLI → Password Recovery |
| fix-usernames 语义 | CLI → Fix usernames |
| REST/tRPC 契约细节 | API(https://homarr.dev/docs/management/api) |
选型提醒:账号恢复(忘密、误删 admin、大写用户名锁死)用 recovery CLI;一切批量/自动化(建板、建应用、建集成、导出备份)用 REST/tRPC/MCP——这是官方原文分工,且 CLI 的挂起怪癖(7.1)本就不适合编排进脚本流水线。
十一、参考链接
- CLI 官方文档:https://homarr.dev/docs/develop-and-automate/command-line-interface
- API 官方文档:https://homarr.dev/docs/management/api
- 在线 API 引用(实例自取):
GET /api/openapi?format=scalar - GitHub 仓库:https://github.com/homarr-labs/homarr
- 站内相关:《Homarr 介绍与选型指南》、《Homarr Docker Compose 部署指南》、《Homarr 2.10.1 配置参数详解》