ERPNext v16 配置参数详解
ERPNext v16.52.1 三层配置体系实测详解:common_site_config/site_config 两层 JSON、bench set-config 读写删全流程、Redis 三连接与 socketio、邮件与超时参数、apps.json 版本锁定、公司默认科目与库存/会计/销售默认值,附单站点生产配置模板。
ERPNext v16 配置参数详解
目标:本篇系统梳理 ERPNext v16.52.1 的三层配置体系——bench 工程层(common_site_config.json / apps.json)、站点层(site_config.json)与业务层(System Settings / Company 默认科目 / 库存与销售默认值),所有参数值与修改命令均在 v16.52.1 实测环境验证通过,并给出单站点自托管的推荐配置模板。
一、环境信息
本篇所有参数读取、写入与回显均来自以下实测环境(实测日期 2026-10-27):
- 操作系统:Ubuntu 22.04(x86_64)
- ERPNext:v16.52.1(应用锁定 commit ade850b,详见 5.7 节 apps.json 实测)
- Frappe 框架:16.53.0(与应用同镜像分发)
- 数据库:MariaDB 11.8
- 缓存/队列:Redis 6.2 双实例
- 默认站点:frontend(已装 frappe + erpnext 两应用)
- 部署形态:官方 frappe_docker pwd.yml 多服务栈(部署过程见《ERPNext v16 Docker Compose 部署实战》)
- bench 工程路径:/home/frappe/frappe-bench
二、前置条件
本篇的配置命令都通过 bench 工具链执行。bench 是 Frappe 体系的工程管理 CLI,所有站点配置命令需满足两个前提:
- 工作目录:命令在 bench 工程根目录执行(官方编排内为 /home/frappe/frappe-bench),bench 靠目录内的 sites/ 与 apps/ 定位工程;
- 站点指定:多站点工程中,站点级命令必须用
--site <站点名>指定目标;不带 --site 的bench set-config -g操作的是工程级共享配置。
验证环境就绪(实测回显):
cd /home/frappe/frappe-bench && ls sites/
apps.json
apps.txt
assets
common_site_config.json
frontend
cat sites/apps.txt
erpnext
frappe
解读:sites/ 下的 frontend 目录即站点本体(site_config.json、备份、上传文件都在其中),apps.txt 是已装应用清单(configurator 与建站流程会维护它),两文件与两份 JSON 配置共同构成配置体系。
三、参数查看与修改方式
3.1 配置文件体系:两层 JSON + 合并视图
ERPNext 的配置分布在两层 JSON 文件里,运行时框架把两者叠加成合并视图 frappe.conf 供程序读取:
| 文件 | 作用域 | 产生方式 | 典型内容 |
|---|---|---|---|
| sites/common_site_config.json | 整个 bench 工程(全部站点共享) | 部署初始化(configurator)或 bench set-config -g 写入 | db_host、redis 三连接、socketio_port、default_site |
| sites/<站点>/site_config.json | 单个站点 | 建站自动生成,bench --site <站点> set-config 写入 | db_name/db_password、installed_apps、站点级开关 |
| sites/apps.json | 整个工程 | bench get-app / 更新流程维护 | 各应用版本与 commit 锁定 |
叠加规则:同名键时站点级覆盖工程级。工程级放「所有站点一致的连接信息」(数据库地址、Redis 地址),站点级放「每站点不同的事实」(库名、密码、已装应用),这是两层设计的核心分工。
工程级文件实测内容(frontend 单站点环境):
cat sites/common_site_config.json
{
"db_host": "db",
"db_port": 3306,
"default_site": "frontend",
"redis_cache": "redis://redis-cache:6379",
"redis_queue": "redis://redis-queue:6379",
"redis_socketio": "redis://redis-queue:6379",
"socketio_port": 9000
}
站点级文件实测内容:
cat sites/frontend/site_config.json
{
"db_name": "_b014443fe3d53c1a",
"db_password": "ujHrvgH2Q6Axb6R2",
"db_type": "mariadb",
"db_user": "_b014443fe3d53c1a",
"installed_apps": [
"frappe",
"erpnext"
],
"maintenance_mode": 0
}
(maintenance_mode 为本文 3.2 实测 set-config 写入后保留的显式值,默认建站产物中不含该键。)
3.2 bench set-config:写入与删除的标准姿势
改配置的正规途径是 bench 命令而非手工编辑 JSON(避免格式手误与进程内缓存不一致)。命令帮助(bench set-config --help 实测回显):
Usage: bench set-config [OPTIONS] KEY VALUE
Insert/Update a value in site_config.json
Options:
-g, --global Set value in bench config
-p, --parse Evaluate as Python Object
--help Show this message and exit.
① 站点级写入与读回(maintenance_mode 实测:设 1 验证 → 改回 0):
cd /home/frappe/frappe-bench
bench --site frontend set-config maintenance_mode 1
grep maintenance_mode sites/frontend/site_config.json
"maintenance_mode": 1
bench --site frontend set-config maintenance_mode 0
② 工程级写入与删除(临时键实测全过程):
bench set-config -g c1_test_key hello
grep c1_test_key sites/common_site_config.json
"c1_test_key": "hello",
删除工程级键用 bench config remove-common-config(bench config remove-common-config --help 实测回显):
Usage: bench config remove-common-config [OPTIONS] [KEYS]...
Remove specific keys from current bench's common config
Options:
--help Show this message and exit.
bench config remove-common-config c1_test_key
grep -c c1_test_key sites/common_site_config.json
0
③ 值类型陷阱(实测踩坑):set-config 默认把 VALUE 当字符串写盘。实测给站点配 mail_port:
bench --site frontend set-config mail_port 465
grep mail_port sites/frontend/site_config.json
"mail_port": "465",
写进文件的是字符串 "465"。需要数字/布尔等原生类型时追加 -p 让 bench 按 Python 字面量解析(如 bench --site frontend set-config -p mail_port 465)。字符串型的端口多数场景仍能用(框架读取后转换),但与程序做严格比较时会踩坑,建议写入时就用对类型。
④ 站点级键的删除:没有对应的 site 级 remove 命令,正规做法是编辑该站点的 site_config.json 删掉键行(保持 JSON 合法),随后重启相关进程生效。本文演示键清理即用此法(实测回显):
python3 -c "
import json
p = 'sites/frontend/site_config.json'
d = json.load(open(p))
for k in ('mail_server', 'mail_port', 'use_tls'):
d.pop(k, None)
json.dump(d, open(p, 'w'), indent=1)
"
grep -cE 'mail_|use_tls' sites/frontend/site_config.json
0
3.3 通过 API/界面查看业务设置
业务层设置(第六章)不以 JSON 文件存在,而是存在数据库中的「单一对象文档」(Single DocType),如 System Settings、Stock Settings。查看方式:
curl -s -b /tmp/erpcookie.txt -X POST http://127.0.0.1:8135/api/method/frappe.client.get_value \
-H "Content-Type: application/json" \
-d '{"doctype":"System Settings","fieldname":["language","time_zone","session_expiry"]}'
{"message":{"language":"en","time_zone":"Asia/Shanghai","session_expiry":"170:00"}}
(cookie 获取方式见《ERPNext v16 Docker Compose 部署实战》4.5 节;也可在 Desk 界面经「设置」入口查看同名表单。)
四、参数总览
两份 JSON 配置文件的常用键总表(实测环境实际生效的值):
common_site_config.json(工程级):
| 键 | 实测值 | 说明 |
|---|---|---|
| db_host | db | 数据库主机 |
| db_port | 3306 | 数据库端口 |
| default_site | frontend | 不带站点标识请求的默认站点 |
| redis_cache | redis://redis-cache:6379 | 缓存实例连接串 |
| redis_queue | redis://redis-queue:6379 | 任务队列实例连接串 |
| redis_socketio | redis://redis-queue:6379 | 实时推送所用 Redis(官方单栈复用队列实例) |
| socketio_port | 9000 | 推送进程监听端口 |
frontend/site_config.json(站点级):
| 键 | 实测值 | 说明 |
|---|---|---|
| db_name | _b014443fe3d53c1a | 站点数据库库名(建站随机生成) |
| db_user | _b014443fe3d53c1a | 库用户(与库名同名) |
| db_password | ujHrvgH2Q6Axb6R2 | 库用户密码(建站随机生成) |
| db_type | mariadb | 数据库类型 |
| installed_apps | [frappe, erpnext] | 已装应用清单 |
| maintenance_mode | 0 | 维护模式开关(1 时站点只读) |
解读:工程级 7 个键全部由部署编排生成,日常运维基本不动;站点级前 5 个键是建站产物(数据库凭据类),真正高频操作的是 maintenance_mode 这类运行开关与第六章的业务默认值。
五、核心参数分类详解
5.1 数据库连接参数
工程级:db_host / db_port 指向数据库服务地址,官方编排由环境变量 DB_HOST/DB_PORT 注入 configurator 写入。迁移数据库服务器时改这两处(bench set-config -g db_host 新地址),全部站点一并生效。
站点级:db_name / db_user / db_password / db_type 由 bench new-site 建站时自动生成——库名自动加下划线前缀(_ + 随机串)避免与其他站点/业务库重名,用户与库名同名,密码随机。三个运维要点:
- db_password 与数据库实际密码必须一致:在数据库侧手工改了库用户密码而不同步 site_config.json,站点立即连库失败(报 OperationalError 1045 Access denied);
- db_type 可选 postgresql(框架支持),但官方编排与社区回归主线是 mariadb,切换前需充分验证;
- 这几个键是站点备份/恢复的关联点:
bench restore恢复他人备份时会同步改写本地 site_config.json 的库凭据。
5.2 Redis 三连接与 socketio 端口
框架把 Redis 用途拆成三个逻辑连接,由 common_site_config.json 的三个键分别指定:
| 键 | 用途 | 官方编排实测 |
|---|---|---|
| redis_cache | 页面/文档缓存(可丢,重建即可) | 独立实例 redis-cache:6379,不挂持久化卷 |
| redis_queue | 后台任务队列(不可丢,含未执行任务) | 独立实例 redis-queue:6379,挂持久化卷 |
| redis_socketio | 实时推送的事件通道 | 复用 redis-queue:6379 |
socketio_port: 9000 是推送进程(Node.js)的监听端口,入口层把 WebSocket 流量转发到它。三个键的拆分逻辑:
💡 技术拓展:Redis 的「按用途分实例」是性能与可靠性的经典取舍——
形态 取舍 单实例混用 部署最简;队列重任务刷内存会挤掉热缓存 缓存/队列双实例 官方编排采用;缓存可随时 FLUSH,队列独立持久化互不拖累 三实例(socketio 独立) 推送流量大时进一步隔离;小规模场景收益有限 官方单栈取双实例 + socketio 复用队列实例:推送事件量级远小于任务队列,复用是合理的省资源设计;大型部署可把 redis_socketio 指向第三个实例做隔离。
5.3 站点运行开关
maintenance_mode(实测验证过 1↔0 切换):置 1 后站点进入维护状态,普通用户请求被拒、管理员仍可登录处理。发布迁移、大版本升级前后常用。写盘与恢复:
bench --site frontend set-config maintenance_mode 1 # 开启维护
bench --site frontend set-config maintenance_mode 0 # 恢复
⚠️ 注意:该键为站点级。若写到了工程级 common_site_config.json,合并视图下它同样生效且会影响所有站点——排查「全站莫名维护」时先看工程级是否有同名键。
default_site(工程级):请求未携带站点标识(如直接用 IP 访问入口)时服务的默认站点。单站点部署建站命令 --set-default frontend 已自动写入。
session_expiry(System Settings,业务层):登录会话有效期,实测环境为 170:00(HH:MM 格式,即 170 小时)。安全要求高的环境建议调短(如 12:00)。
5.4 邮件参数
站点外发邮件(密码找回、通知、发票送达)的 SMTP 参数写入站点级 site_config.json。写入实测:
bench --site frontend set-config mail_server smtp.example.com
bench --site frontend set-config -p mail_port 465
bench --site frontend set-config use_tls 1
grep -E 'mail_|use_tls' sites/frontend/site_config.json
"mail_port": 465,
"mail_server": "smtp.example.com",
"use_tls": 1
(mail_port 用 -p 写入了数字类型,对比 3.2 ③ 的字符串坑。)
常用邮件参数一览(写入方式均为站点级 set-config):
| 键 | 示例值 | 说明 |
|---|---|---|
| mail_server | smtp.example.com | SMTP 服务器地址 |
| mail_port | 465 | SMTP 端口(465=SSL,587=STARTTLS) |
| use_tls | 1 | STARTTLS 加密(587 端口配 1,465 端口配 use_ssl) |
| use_ssl | 1 | SSL/TLS 直连(465 端口场景) |
| mail_login | erp@example.com | SMTP 认证账号 |
| mail_password | ${MAIL_PASSWORD} | SMTP 认证口令——敏感值不落明文,用环境变量注入或写入后收紧文件权限 |
| always_use_account_name_as_sender | 0 | 发件人规范策略(0/1 二选一使用) |
⚠️ 注意:mail_password 属于凭据类敏感值,演示环境不落真实口令;生产注入方式为导出变量后由部署工具渲染,或写入后执行
chmod 600 sites/frontend/site_config.json收紧权限。
更图形化的邮件发件账号(Email Account 文档)在 Desk 界面配置,底层同样落在这套站点参数体系。
5.5 超时与代理层参数
http_timeout(工程级):框架处理单请求的超时上限,默认 120 秒。跑长报表/大数据导入时按需调大(实测 300 写盘与还原全程):
bench config http_timeout 300
grep http_timeout sites/common_site_config.json
"http_timeout": 300,
bench config remove-common-config http_timeout
grep -c http_timeout sites/common_site_config.json
0
配套的入口层超时:入口 Nginx 的 PROXY_READ_TIMEOUT(实测编排取值 120)必须 ≥ http_timeout,否则长请求先被入口掐断(表现为 504);上传体积上限 CLIENT_MAX_BODY_SIZE(实测 50m)同理需与业务匹配。这两项在部署篇环境变量表中配置(见《ERPNext v16 Docker Compose 部署实战》第六章)。
5.6 开发者模式
developer_mode(站点级,实测写盘 1 后清理还原):开启后 Desk 界面开放 DocType 定义编辑、自定义脚本等开发能力。生产站点保持 0(或删除该键)——开发者模式放宽了元数据改动入口,误操作会直接影响业务表结构:
bench --site frontend set-config developer_mode 1 # 仅开发环境使用
grep developer_mode sites/frontend/site_config.json
"developer_mode": 1,
5.7 应用版本锁定:apps.txt 与 apps.json
sites/apps.txt 是已装应用清单(建站与 configurator 维护,实测内容 erpnext、frappe 两行);sites/apps.json 是各应用的版本与 commit 锁定(升级流程读写),实测内容:
{
"frappe": {
"resolution": {"commit_hash": null, "branch": null},
"idx": 1,
"version": "16.53.0"
},
"erpnext": {
"is_repo": true,
"resolution": {
"commit_hash": "ade850bbd6a7412e9994a9637d2c5c713771632a",
"branch": "v16.52.1"
},
"required": [],
"idx": 2,
"version": "16.52.1"
}
}
解读:应用镜像内 frappe 框架 16.53.0 独立发版(高于 erpnext 的 16.52.1 属正常),erpnext 锁定 v16.52.1 分支与 commit。排查「镜像 tag 与实际代码版本」时以 apps.json 为准;升级前后核对该文件可确认迁移是否真实生效。
六、公司级与业务默认设置
ERPNext 的业务配置不落在 JSON 文件,而是数据库中的设置文档。本节各值均为实测环境(公司 Quzuo Trading,币种 CNY)的真实读数。
6.1 公司默认科目
Company 文档保存全公司默认科目与币种,是单据自动过账的依据。实测读数(frappe.client.get_value):
{"default_currency":"CNY",
"default_cash_account":"Cash - QT",
"default_receivable_account":"Debtors - QT",
"default_payable_account":"Creditors - QT",
"default_income_account":"Sales - QT",
"default_expense_account":"Cost of Goods Sold - QT",
"default_inventory_account":"Stock In Hand - QT",
"stock_received_but_not_billed":"Stock Received But Not Billed - QT",
"enable_perpetual_inventory":1}
逐项解读:
- 科目名后缀
- QT是公司缩写自动后缀(Quzuo Trading 建司时按名称生成),多公司场景靠后缀区分同名科目; - default_receivable_account(Debtors)/default_payable_account(Creditors)是应收应付挂账科目,销售发票与采购发票自动过账到它们;
- enable_perpetual_inventory=1 为永续盘存制:收发货即同步生成库存科目与暂估科目的会计分录,库存账与总账实时一致(0 则是定期盘点制,靠期末凭证调整)。生产环境保持 1;
- default_bank_account 实测为 null(建司未配银行账户),收款对账前应在公司表单补配。
💡 技术拓展:永续盘存 vs 定期盘点两种库存核算制——
制度 记账时机 特点 永续盘存(Perpetual) 每笔收发存单据即时生成分录 库存价值实时可查,ERPNext 默认启用 定期盘点(Periodic) 期末盘点后一次调整 记账轻,但期间内账面与实物脱节 ERPNext 公司级 enable_perpetual_inventory 即两制的开关,默认永续盘存,与其实时库存台账(Bin)设计配套。
6.2 库存默认值(Stock Settings)
实测读数与解读:
| 字段 | 实测值 | 说明 |
|---|---|---|
| allow_negative_stock | 0 | 禁止负库存出库(0=超额发货直接报错) |
| auto_insert_price_list_rate_if_missing | 1 | 物料定价缺失时自动按 standard_rate 建价格记录(4.7 建物料时自动生成 Item Price 即此开关的作用) |
| stock_uom | Nos | 新物料默认库存单位 |
| allow_existing_serial_no | 1 | 允许直接使用已存在的序列号 |
allow_negative_stock 建议保持 0:负库存掩盖出入库差错,月结时集中暴露。确有先出后入的业务(如调拨在途),优先用物料需求单/转移单流程而非放开负库存。
6.3 会计与销售默认值
Accounts Settings 实测读数:
| 字段 | 实测值 | 说明 |
|---|---|---|
| unlink_payment_on_cancellation_of_invoice | 1 | 取消发票时自动解除付款关联(1=一并冲销,避免悬挂预收) |
| book_deferred_entries_via_journal_entry | 0 | 递延收入/支出经日记账处理(0=自动开票) |
| allow_multi_currency_invoices_against_single_party_account | 0 | 多币种发票挂单币种应收(0=禁止混挂) |
Selling Settings 实测读数:
| 字段 | 实测值 | 说明 |
|---|---|---|
| allow_multiple_items | 1 | 订单允许一次录多行物料 |
| maintain_same_sales_rate | 0 | 不强制订单价与上次一致(0=允许浮动报价) |
| editable_price_list_rate | 0 | 销售员不可改价格表价(0=价格管制收紧) |
解读:默认值整体偏「严管」——价格表主导定价、禁负库存、取消发票连带冲销。初创团队想放开销售侧灵活度时改 Selling Settings 两项即可,会计侧默认值不建议动。
七、生产配置模板
适用场景:单站点自托管、4 GB 内存 / 40 GB SSD、20 人以下并发使用。在官方编排产出的默认配置之上追加/确认以下键:
工程级 common_site_config.json(在官方生成的 7 键基础上追加):
{
"db_host": "db",
"db_port": 3306,
"default_site": "frontend",
"redis_cache": "redis://redis-cache:6379",
"redis_queue": "redis://redis-queue:6379",
"redis_socketio": "redis://redis-queue:6379",
"socketio_port": 9000,
"http_timeout": 300,
"restart_supervisor_on_update": 0,
"maintenance_mode": 0
}
站点级 frontend/site_config.json(在建站产物基础上追加):
{
"db_name": "_b014443fe3d53c1a",
"db_user": "_b014443fe3d53c1a",
"db_password": "ujHrvgH2Q6Axb6R2",
"db_type": "mariadb",
"installed_apps": ["frappe", "erpnext"],
"maintenance_mode": 0,
"developer_mode": 0,
"mail_server": "smtp.example.com",
"mail_port": 465,
"use_ssl": 1,
"mail_login": "erp@example.com"
}
模板逐项说明:
- http_timeout: 300——低配机器跑报表慢,放宽单请求超时;入口层 PROXY_READ_TIMEOUT 同步 ≥300;
- restart_supervisor_on_update: 0——容器化编排下进程由编排守护,避免 bench update 时重复拉起;裸机 supervisor 托管形态则置 1;
- maintenance_mode/developer_mode 显式写 0:状态一眼可查,避免「隐式默认」引发歧义;
- 邮件四键:mail_password 不落文件明文(凭据注入方式见 5.4 ⚠️);
- 数据库凭据保持建站随机值(db_name/db_user/db_password),不要改成简单口令——它只被框架进程读取。
⚠️ 注意:模板仅列键值含义与默认值;每键的写入命令统一用 3.2 节的 set-config 流程,改完工程级键需重启 backend/websocket/worker 组进程生效。
八、常见问题(FAQ)
Q1:set-config 写数字,读出来是字符串?
默认按字符串写盘(实测 mail_port 写成 "465")。追加 -p 参数让 bench 按 Python 字面量解析:bench --site frontend set-config -p mail_port 465。
Q2:站点级键怎么删除?
工程级键有 bench config remove-common-config;站点级没有专用 CLI——编辑该站点 site_config.json 删键行(保持 JSON 合法)后重启相关进程(本文 3.2 ④ 实测全流程)。
Q3:改完配置需要重启什么?
工程级连接类键(db_host/redis_*/http_timeout)被 backend/websocket/worker/scheduler 全部进程读取:改完执行全栈重启(编排形态 docker compose -f pwd.yml restart backend websocket scheduler queue-short queue-long)。站点级开关类(maintenance_mode/developer_mode)即时读库生效,无需重启。
Q4:站点连不上数据库,报 Access denied?
site_config.json 的 db_password 与数据库侧库用户密码不一致(常见于在数据库侧手工改密)。把新密码同步回站点配置:bench --site frontend set-config db_password 新密码。
Q5:科目的 - QT 后缀是什么?
公司缩写自动后缀(Quzuo Trading → QT),建司时按公司名生成,用于多公司场景区分同名科目。它在 Company 表单的 company_abbr 字段,建司后不建议修改(历史单据已引用后缀名)。
Q6:邮件参数配好了但发信失败怎么排查?
先确认端口与加密方式匹配(465 配 use_ssl=1;587 配 use_tls=1,实测中 465+use_tls 组合会对不上握手),再在 Desk 界面 Email Account 测试连接;站点配置层参数正确后,发信走后台队列,失败记录见 Email Queue 文档列表。
九、参考链接
- Frappe 框架站点配置文档:https://docs.frappe.io/framework/user/en/bench/resources/bench-yaml
- Frappe 官方文档首页:https://docs.frappe.io
- ERPNext 官方文档:https://docs.frappe.io/erpnext
- ERPNext GitHub 仓库:https://github.com/frappe/erpnext
- 官方部署仓库 frappe_docker:https://github.com/frappe/frappe_docker
- 本专栏背景认知:《ERPNext 介绍与选型指南》
- 本专栏部署实战:《ERPNext v16 Docker Compose 部署实战》