Lowdefy 配置参数详解
以可运行工单看板为例,逐项拆解 lowdefy.yaml 的应用级参数、pages/blocks、connections/requests、auth 与 global/menus,附 build/dev/start 与请求 API 实测回显。
Lowdefy 配置参数详解
目标:以一份可运行的低代码工单看板为样本,逐项拆解
lowdefy.yaml的应用级参数、pages/blocks、connections/requests、auth与global/menus,并给出每项参数修改后的实测结果。文中配置与回显均来自 Ubuntu 22.04.5 + Lowdefy 7.1.0 实测(2026-10-27)。
一、环境信息
| 项目 | 取值 |
|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS(x86_64) |
| Node.js | v24.22.1 |
| Lowdefy CLI | 7.1.0 |
| MongoDB | 7.0.45 |
| 实验应用目录 | /opt/lowdefy/c1 |
| 生产服务端口 | 3005/tcp |
| 开发服务端口 | 3006/tcp(页面预览实际监听 3007/tcp) |
| 认证方式 | Better Auth + 邮箱密码 |
| 实测日期 | 2026-10-27 |
应用名称在日志中显示为 Lowdefy C1 Lab,版本 0.1.0。本文所有“实测回显”均取自该应用的 build、dev、start 日志与 HTTP 请求结果。
二、前置条件
阅读并复现本文前,确认以下条件已满足:
- 已按 《Ubuntu 22.04 安装 Lowdefy 指南》 完成 Node.js 24、pnpm 与 Lowdefy CLI 安装。
- 已初始化应用目录,根目录存在
lowdefy.yaml。 - MongoDB 已运行,本文使用
mongodb://127.0.0.1:27017,业务库为lowdefy_c1。 - 已准备两个运行时密钥,通过环境变量注入,不写进配置文件:
LOWDEFY_SECRET_MONGODB_URI:MongoDB 连接串。LOWDEFY_SECRET_AUTH_SECRET:认证签名密钥,长度不少于 32 个字符。
- 3005、3006、3007 端口未被占用。
启动生产服务前的环境变量注入方式如下,后续章节直接复用:
export LOWDEFY_SECRET_MONGODB_URI="mongodb://127.0.0.1:27017"
export LOWDEFY_SECRET_AUTH_SECRET="c1-auth-secret-0123456789"
三、参数查看与修改方式
3.1 配置文件与加载顺序
Lowdefy 只要求根目录存在一个 lowdefy.yaml,其余配置都从它出发按 _ref 引用加载:
lowdefy.yaml:应用入口,声明版本、应用级参数、connections、auth,以及pages数组。pages/*.yaml:页面文件,通过- _ref: pages/home.yaml挂载,避免单文件膨胀。- 被引用的文件可以是 YAML,也可以是 JSON;根文件本身必须是 YAML。
_secret运算符在构建和运行时求值,用于从LOWDEFY_SECRET_<名称>环境变量读取敏感值。
本文实验应用的根配置如下(节选,完整版见第六章):
lowdefy: 7.1.0
name: Lowdefy C1 Lab
version: 0.1.0
slug: lowdefy-c1
description: Lowdefy 配置参数实测
license: Apache-2.0
cli:
port: 3000
disableTelemetry: true
config:
homePageId: home
global:
appTitle: 低代码工单看板
pages:
- _ref: pages/home.yaml
- _ref: pages/admin.yaml
pages 下的两个条目不是内联页面,而是引用外部文件;构建时会把引用展开成完整页面树。这一结构在本文实验中构建成功,两个页面均可访问。
3.2 用 build 校验参数
改完配置后,先用 build 做一次全量校验。它会检查 YAML 语法、引用是否存在、必填参数是否齐全,以及认证等模块的配置约束:
cd /opt/lowdefy/c1
lowdefy build
实测回显(已去除终端颜色控制符):
17:05:56 ∙ Running 'lowdefy build'. Lowdefy app version 7.1.0.
17:05:56 ∙ Starting build.
17:05:56 ∙ Dependencies unchanged.
- Running Lowdefy build.
17:05:56 ∙ $ node lowdefy/build.mjs
17:05:57 ∙ /bin/sh: 1: git: not found
17:05:57 ∙ Lowdefy build successful.
- Installing dependencies.
17:05:58 ∙ Dependencies install successfully.
- Running client build.
17:05:59 ∙ Client bundle size (gzip): 329.72 kB.
17:05:59 ∙ Client build successful.
17:05:59 ✔ Build successful.
回显中的 git: not found 是构建过程调用 git 获取版本信息时的提示,不影响构建结果,最终仍输出 Build successful。若参数有误,构建会直接失败并给出带文件行号的错误,例如第五章 5.5 节的认证配置错误。
3.3 dev 模式查看改动结果
开发模式会监听配置文件变化并自动重建配置,适合逐项调参:
cd /opt/lowdefy/c1
lowdefy dev --port 3006 --no-open
实测回显(已去除终端颜色控制符):
17:06:27 ∙ Running 'lowdefy dev'. Lowdefy app version 7.1.0.
17:06:27 ∙ Starting development server.
- Fetching @lowdefy/server-dev from npm.
17:06:29 ∙ Fetched @lowdefy/server-dev from npm.
- Installing dependencies.
17:06:30 ∙ Dependencies install successfully.
- Building config...
17:06:30 ∙ /bin/sh: 1: git: not found
17:06:31 ✔ Built config in 629ms.
17:06:31 ⚠ Mock user active - login bypassed
17:06:32 ∙ VITE v8.0.16 ready in 180 ms
17:06:32 ∙ ➜ Local: http://127.0.0.1:3007/
注意两点:--port 3006 是 CLI 服务端口,页面预览由 Vite 在 3007 提供;Mock user active - login bypassed 表示配置中的 auth.dev.mockUser 已生效,开发模式下跳过登录。
3.4 用请求 API 验证配置
配置是否真正生效,最终要看服务端行为。Lowdefy 为每个页面请求暴露固定路径:
POST /api/request/{pageId}/{requestId}
请求体必须是合法 JSON,且业务数据要放在 payload 键下。下面以读取工单为例,服务运行在 3005:
curl -s -X POST -H "Content-Type: application/json" \
-d '{}' \
http://localhost:3005/api/request/home/get_tickets
实测回显:
{"id":"request:home:get_tickets","success":true,"type":"MongoDBFind","response":[{"_id":{"_oid":"6ae0dd011367051a24439f78"},"title":"网络故障","status":"open","created_at":{"~d":1793121537195}},{"_id":{"_oid":"6ae0dc441367051a24439f77"},"title":null,"status":"open","created_at":{"~d":1793121348888}}]}
返回结构固定包含 id、success、type、response 四个字段。MongoDB 的 ObjectId 序列化为 {"_oid":"..."},Date 序列化为 {"~d":毫秒时间戳},调用方需要按此结构解析。
四、参数总览
lowdefy.yaml 的顶层键及其作用如下:
| 参数 | 是否必需 | 作用 | 本文是否实测 |
|---|---|---|---|
lowdefy | 必需 | 声明应用使用的 Lowdefy 版本 | 是 |
name | 可选 | 应用名称,出现在服务端日志 | 是 |
version | 可选 | 应用版本,日志中显示为 app_version | 是 |
slug | 可选 | 应用标识 | 是(构建通过) |
description | 可选 | 应用描述 | 是(构建通过) |
license | 可选 | 许可证标识 | 是(构建通过) |
cli | 可选 | CLI 行为,如默认端口、遥测开关 | 是 |
config | 可选 | 运行配置,如首页 id、超时、安全策略 | 是 |
global | 可选 | 全局变量,供 _global 运算符读取 | 是 |
menus | 可选 | 导航菜单定义 | 是(构建通过) |
auth | 条件必需 | 启用登录、角色与页面保护时必须配置 | 是 |
connections | 条件必需 | 使用数据库或外部 API 时必须配置 | 是 |
pages | 必需 | 页面定义,可用 _ref 拆分 | 是 |
auth 的“条件必需”含义是:只要声明了除 auth.dev 之外的认证键,就必须同时提供登录机制、secret 和 database,否则构建失败。
五、核心参数分类详解
5.1 应用级参数
应用级参数决定“这是什么应用、默认怎么跑”。本文实验值如下:
lowdefy: 7.1.0
name: Lowdefy C1 Lab
version: 0.1.0
cli:
port: 3000
disableTelemetry: true
config:
homePageId: home
各参数含义与实测结论:
lowdefy:配置语法与运行时版本。CLI 会读取该值判断是否需要升级,本文构建日志中的版本提示即来自此处与 CLI 版本的比对。name/version:只影响日志与展示,不改变路由。启动日志中显示为app_name: Lowdefy C1 Lab、app_version: 0.1.0。cli.port:默认端口。本文设为 3000,但启动时用--port 3005覆盖,服务最终监听 3005,说明命令行参数的优先级高于cli.port。cli.disableTelemetry:关闭遥测上报,适合内网部署。config.homePageId:访问根路径/时加载的页面 id。本文设为home,匿名访问/返回 200,服务端日志记录pageId: home。
验证首页参数:
curl -s -o /dev/null -w "status=%{http_code}\n" http://localhost:3005/
实测回显:
status=200
服务端对应日志:
17:06:18 ∙ event: page_view
17:06:18 ∙ pageId: home
17:06:18 ∙ path: home
5.2 pages 与 blocks
pages 是应用的主体,每一项至少要有 id 与 type。type 决定页面外壳,本文使用 PageHeaderMenu,自带页头与菜单区域。
页面级字段如下:
| 字段 | 作用 |
|---|---|
id | 页面唯一标识,也是路由与权限判断的依据 |
type | 页面块类型,如 PageHeaderMenu |
properties | 页面属性,如标题 |
requests | 页面内可调用的请求定义 |
events | 页面生命周期事件,如 onMount |
blocks | 页面内容块数组 |
首页配置(节选):
id: home
type: PageHeaderMenu
properties:
title: 工单看板
requests:
- id: get_tickets
type: MongoDBFind
connectionId: tickets_connection
properties:
query: {}
events:
onMount:
- id: load_tickets
type: Request
params: get_tickets
blocks:
- id: page_title
type: Title
properties:
content:
_global: appTitle
blocks 中每个块同样以 id 与 type 为必需字段,可嵌套 blocks 形成布局树:
- id: list_card
type: Card
properties:
title: 工单列表
blocks:
- id: tickets_table
type: TableLight
properties:
rowKey: _id
columns:
- key: title
title: 标题
- key: status
title: 状态
data:
_request: get_tickets
实测结论:把页面拆到 pages/home.yaml 与 pages/admin.yaml 再由根配置 _ref 挂载后,构建成功;TableLight 通过 _request: get_tickets 绑定请求结果,返回的数组可直接作为表格数据源。块 id 只要求在同一页面内唯一,跨页面可复用。
5.3 connections
connections 定义与外部服务的连接,位于配置根部。每个连接必须有 id、type、properties。本文使用 MongoDB 集合连接:
connections:
- id: tickets_connection
type: MongoDBCollection
properties:
databaseUri:
_secret: MONGODB_URI
databaseName: lowdefy_c1
collection: tickets
write: true
参数说明:
databaseUri:连接串,用_secret: MONGODB_URI读取LOWDEFY_SECRET_MONGODB_URI,避免明文入库。databaseName/collection:定位到具体库与集合,本文为lowdefy_c1.tickets。write: true:允许该连接执行写入类请求。本文的写入请求执行成功,说明该参数已放开写操作。
连接属性中的运算符在每次请求调用时重新求值,因此可以在 properties 中引用会变化的上下文,而不必为每次调用重建连接。
5.4 requests
requests 是连接的具体用法,必须声明 id、type、connectionId,并按请求类型提供 properties。本文定义一读一写两个请求:
requests:
- id: get_tickets
type: MongoDBFind
connectionId: tickets_connection
properties:
query: {}
options:
sort:
- - created_at
- -1
- id: insert_ticket
type: MongoDBInsertOne
connectionId: tickets_connection
payload:
ticket_title:
_state: ticket_title
properties:
doc:
title:
_payload: ticket_title
status: open
created_at:
_date: now
关键字段与求值位置:
| 字段 | 求值位置 | 说明 |
|---|---|---|
payload | 客户端 | 可用 _state 读取输入框等客户端状态 |
properties | 服务端 | 用 _payload 读取上一步 payload 的值 |
connectionId | 构建时校验 | 必须指向已定义的连接 id |
type | 构建时校验 | 必须是连接支持的类型 |
写入请求的实测调用需要把业务值放进 payload 键:
curl -s -X POST -H "Content-Type: application/json" \
-d '{"payload":{"ticket_title":"网络故障"}}' \
http://localhost:3005/api/request/home/insert_ticket
实测回显:
{"id":"request:home:insert_ticket","success":true,"type":"MongoDBInsertOne","response":{"acknowledged":true,"insertedId":{"_oid":"6ae0dd011367051a24439f78"}}}
再次读取可看到标题已正确写入:
{"id":"request:home:get_tickets","success":true,"type":"MongoDBFind","response":[{"_id":{"_oid":"6ae0dd011367051a24439f78"},"title":"网络故障","status":"open","created_at":{"~d":1793121537195}},{"_id":{"_oid":"6ae0dc441367051a24439f77"},"title":null,"status":"open","created_at":{"~d":1793121348888}}]}
这里有一个容易踩坑的实测细节:payload 在客户端求值,直接调用 HTTP API 时并没有浏览器状态,若不按 {"payload":{...}} 传值,_state: ticket_title 会解析为空,写入的 title 就是 null。要让接口调用拿到值,必须显式提供 payload。
请求体不合法时服务端返回 400,而不是 500:
curl -s -o /dev/null -w "status=%{http_code}\n" -X POST http://localhost:3005/api/request/home/get_tickets
实测回显:
status=400
响应体:
{"name":"UserError","message":"Request body is not valid JSON."}
用 GET 访问同一路径则返回 405:
{"error":"Method not allowed."}
5.5 auth
auth 是参数最多、约束最严的一块。本文目标有三项:启用邮箱密码登录、声明 admin/viewer 两个角色、只允许 admin 访问管理页。
先看约束。只写 roles 与 pages.roles 而不给登录机制时,构建直接失败:
17:05:32 ∙ /opt/lowdefy/c1/lowdefy.yaml:32
17:05:32 ✖ [ConfigError] Auth is configured without an authentication mechanism. Configure a login method ("emailAndPassword.enabled: true", "magicLink.enabled: true", "emailOTP.enabled: true" or "phoneNumber.enabled: true"), or an OAuth provider in "providers", or an API auth strategy in "strategies".
17:05:32 ∙ Build failed with 1 error(s). See above for details.
补齐登录机制、secret 与 database 后构建通过:
auth:
secret:
_secret: AUTH_SECRET
database:
id: auth_db
type: MongoDBAuthAdapter
properties:
uri:
_secret: MONGODB_URI
emailAndPassword:
enabled: true
roles:
- id: admin
- id: viewer
pages:
roles:
admin:
- admin_page
dev:
mockUser:
id: admin
email: admin@example.com
name: 管理员
roles:
- admin
各参数作用:
secret:Better Auth 的签名密钥,建议至少 32 个字符。本文用短密钥启动,服务端给出两条警告:
17:06:10 ⚠ Auth "secret" is shorter than 32 characters. Use a long random value, e.g. `openssl rand -base64 32`.
17:06:10 ⚠ [better-auth] Warning: your BETTER_AUTH_SECRET should be at least 32 characters long for adequate security. Generate one with `npx auth secret` or `openssl rand -base64 32`.
database:认证数据存储,MongoDBAuthAdapter把用户、会话写入 MongoDB;properties.uri同样走_secret。emailAndPassword.enabled:启用邮箱密码登录。未配置auth.email时无法发送重置邮件,启动日志会提示:
17:06:10 ⚠ Auth "email" is not configured - password reset emails cannot be sent, so the reset flow is unavailable.
roles:声明应用使用的角色名,供页面与接口授权引用。pages.roles:角色到页面 id 数组的映射,本文把admin_page绑定到admin。dev.mockUser:仅开发模式使用的模拟用户,注入后跳过登录流程。
页面保护的实测对比:
# 公开页:匿名可访问
curl -s -o /dev/null -w "home status=%{http_code}\n" http://localhost:3005/
# 受保护页:匿名被重定向到登录页
curl -s -o /dev/null -w "admin status=%{http_code} redirect=%{redirect_url}\n" http://localhost:3005/admin_page
实测回显:
home status=200
admin status=302 redirect=http://localhost:3005/login?callbackUrl=%2Fadmin_page
同一受保护页在开发模式下由 dev.mockUser(角色 admin)访问,返回 200:
dev admin status=200
对应开发日志:
17:06:31 ⚠ Mock user active - login bypassed
需要强调:dev.mockUser 是绕过认证引擎的模拟身份,只用于开发调试;生产环境的页面拦截以上面的 302 重定向为准。这也是为什么生产验证要单独用匿名请求做一次。
5.6 global 与 menus
global 存放跨页面共享的变量,通过 _global 运算符读取:
global:
appTitle: 低代码工单看板
页面标题块直接引用:
- id: page_title
type: Title
properties:
content:
_global: appTitle
修改 global.appTitle 后,所有引用 _global: appTitle 的块会同步变化,不需要逐页改动。
menus 定义导航结构,每项包含菜单 id 与 links 数组,链接用 MenuLink 指向页面 id:
menus:
- id: main_menu
links:
- id: home_link
type: MenuLink
pageId: home
properties:
title: 首页
- id: admin_link
type: MenuLink
pageId: admin_page
properties:
title: 管理页
pageId 必须是已定义的页面 id,否则构建阶段会报引用错误。本文两个链接均指向实际页面,构建通过。
六、生产配置模板
以下模板把本文验证过的参数组合成一份可直接改用的生产配置。密钥全部走环境变量,不落盘。
根配置 lowdefy.yaml:
lowdefy: 7.1.0
name: Lowdefy C1 Lab
version: 0.1.0
slug: lowdefy-c1
description: Lowdefy 配置参数实测
license: Apache-2.0
cli:
port: 3000
disableTelemetry: true
config:
homePageId: home
global:
appTitle: 低代码工单看板
menus:
- id: main_menu
links:
- id: home_link
type: MenuLink
pageId: home
properties:
title: 首页
- id: admin_link
type: MenuLink
pageId: admin_page
properties:
title: 管理页
auth:
secret:
_secret: AUTH_SECRET
database:
id: auth_db
type: MongoDBAuthAdapter
properties:
uri:
_secret: MONGODB_URI
emailAndPassword:
enabled: true
roles:
- id: admin
- id: viewer
pages:
roles:
admin:
- admin_page
connections:
- id: tickets_connection
type: MongoDBCollection
properties:
databaseUri:
_secret: MONGODB_URI
databaseName: lowdefy_c1
collection: tickets
write: true
pages:
- _ref: pages/home.yaml
- _ref: pages/admin.yaml
页面文件 pages/home.yaml(节选):
id: home
type: PageHeaderMenu
properties:
title: 工单看板
requests:
- id: get_tickets
type: MongoDBFind
connectionId: tickets_connection
properties:
query: {}
options:
sort:
- - created_at
- -1
- id: insert_ticket
type: MongoDBInsertOne
connectionId: tickets_connection
payload:
ticket_title:
_state: ticket_title
properties:
doc:
title:
_payload: ticket_title
status: open
created_at:
_date: now
events:
onMount:
- id: load_tickets
type: Request
params: get_tickets
运行时密钥清单:
| 环境变量 | 用途 | 要求 |
|---|---|---|
LOWDEFY_SECRET_MONGODB_URI | 业务库与认证库连接串 | 可被 MongoDB 客户端直接使用 |
LOWDEFY_SECRET_AUTH_SECRET | 认证签名密钥 | 至少 32 个字符的随机值 |
启动与实测回显:
cd /opt/lowdefy/c1
lowdefy start --port 3005
17:06:09 ∙ Running 'lowdefy start'. Lowdefy app version 7.1.0.
17:06:09 ✔ Started server.
17:06:10 ∙ Lowdefy server listening on http://localhost:3005
17:06:10 ∙ app_name: Lowdefy C1 Lab
17:06:10 ∙ app_version: 0.1.0
17:06:10 ∙ server: lowdefy
17:06:10 ∙ port: 3005
17:06:10 ∙ lowdefy_version: 7.1.0
服务启动后即可用第三章的请求 API 逐项验证。生产部署建议把上述环境变量写入 EnvironmentFile,由 systemd 托管,具体步骤见 《Ubuntu 22.04 安装 Lowdefy 指南》。
七、常见问题
7.1 构建报 Auth is configured without an authentication mechanism
现象:只配置 auth.roles、auth.pages.roles 时构建失败,退出码 1。
✖ [ConfigError] Auth is configured without an authentication mechanism. Configure a login method ("emailAndPassword.enabled: true", "magicLink.enabled: true", "emailOTP.enabled: true" or "phoneNumber.enabled: true"), or an OAuth provider in "providers", or an API auth strategy in "strategies".
原因:auth 一旦声明为真实认证栈,就必须有登录机制、secret 和 database。
处理:补齐三件套。本文补上 auth.secret、MongoDBAuthAdapter 与 emailAndPassword.enabled: true 后构建成功。
7.2 认证密钥过短的警告
现象:服务能启动,但日志连续输出警告,提示 secret 短于 32 个字符、熵不足。
原因:Better Auth 对签名密钥长度有安全要求,短密钥不会被拒绝启动,但会削弱会话安全。
处理:用 openssl rand -base64 32 生成随机值,写入 LOWDEFY_SECRET_AUTH_SECRET 后重启。本文为复现警告特意使用了短值,生产环境不要沿用。
7.3 Request body is not valid JSON
现象:POST 请求返回 400。
{"name":"UserError","message":"Request body is not valid JSON."}
原因:没有发送请求体,或请求体不是合法 JSON。
处理:始终带 Content-Type: application/json,并至少发送 {}。需要向请求传值时,按 {"payload":{"字段名":"值"}} 的格式发送。
7.4 受保护页面返回 302
现象:访问 /admin_page 得到 302,跳转到 /login?callbackUrl=%2Fadmin_page。
原因:该页面已通过 auth.pages.roles 绑定到 admin 角色,而当前请求没有登录会话。
处理:这是预期的保护行为。开发阶段可用 auth.dev.mockUser 或 lowdefy dev --mock-user 注入模拟身份,生产环境应完成真实登录后再访问。
7.5 修改配置后页面没有变化
现象:改了 lowdefy.yaml,运行中的生产服务没有反映新配置。
原因:lowdefy start 读取的是 .lowdefy/server 下的构建产物,不是源配置。
处理:先停止服务,重新执行 lowdefy build,再执行 lowdefy start。开发模式 lowdefy dev 会自动重建,不需要手动 build。
7.6 配置端口与实际监听端口不一致
现象:cli.port 写的是 3000,服务却监听 3005。
原因:启动命令带了 --port 3005,命令行参数优先。
处理:二者取其一即可。需要固定端口时,删掉命令行的 --port,只保留 cli.port;需要临时换端口时,用命令行覆盖。
八、参考链接
站内文档:
官方资料:
- Lowdefy 官方文档:
https://docs.lowdefy.com - 应用配置 Schema:
https://docs.lowdefy.com/lowdefy-schema - 连接与请求:
https://docs.lowdefy.com/connections-and-requests - 认证配置:
https://docs.lowdefy.com/auth-configuration - 角色与页面权限:
https://docs.lowdefy.com/roles - 部署到 Node.js:
https://docs.lowdefy.com/node-server