ERPNext v16 配置参数详解

ERPNext v16.52.1 三层配置体系实测详解:common_site_config/site_config 两层 JSON、bench set-config 读写删全流程、Redis 三连接与 socketio、邮件与超时参数、apps.json 版本锁定、公司默认科目与库存/会计/销售默认值,附单站点生产配置模板。

ERPNextERPNext项目管理2026/10/28

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,所有站点配置命令需满足两个前提:

  1. 工作目录:命令在 bench 工程根目录执行(官方编排内为 /home/frappe/frappe-bench),bench 靠目录内的 sites/ 与 apps/ 定位工程;
  2. 站点指定:多站点工程中,站点级命令必须用 --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_hostdb数据库主机
db_port3306数据库端口
default_sitefrontend不带站点标识请求的默认站点
redis_cacheredis://redis-cache:6379缓存实例连接串
redis_queueredis://redis-queue:6379任务队列实例连接串
redis_socketioredis://redis-queue:6379实时推送所用 Redis(官方单栈复用队列实例)
socketio_port9000推送进程监听端口

frontend/site_config.json(站点级):

键实测值说明
db_name_b014443fe3d53c1a站点数据库库名(建站随机生成)
db_user_b014443fe3d53c1a库用户(与库名同名)
db_passwordujHrvgH2Q6Axb6R2库用户密码(建站随机生成)
db_typemariadb数据库类型
installed_apps[frappe, erpnext]已装应用清单
maintenance_mode0维护模式开关(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 建站时自动生成——库名自动加下划线前缀(_ + 随机串)避免与其他站点/业务库重名,用户与库名同名,密码随机。三个运维要点:

  1. db_password 与数据库实际密码必须一致:在数据库侧手工改了库用户密码而不同步 site_config.json,站点立即连库失败(报 OperationalError 1045 Access denied);
  2. db_type 可选 postgresql(框架支持),但官方编排与社区回归主线是 mariadb,切换前需充分验证;
  3. 这几个键是站点备份/恢复的关联点: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_serversmtp.example.comSMTP 服务器地址
mail_port465SMTP 端口(465=SSL,587=STARTTLS)
use_tls1STARTTLS 加密(587 端口配 1,465 端口配 use_ssl)
use_ssl1SSL/TLS 直连(465 端口场景)
mail_loginerp@example.comSMTP 认证账号
mail_password${MAIL_PASSWORD}SMTP 认证口令——敏感值不落明文,用环境变量注入或写入后收紧文件权限
always_use_account_name_as_sender0发件人规范策略(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_stock0禁止负库存出库(0=超额发货直接报错)
auto_insert_price_list_rate_if_missing1物料定价缺失时自动按 standard_rate 建价格记录(4.7 建物料时自动生成 Item Price 即此开关的作用)
stock_uomNos新物料默认库存单位
allow_existing_serial_no1允许直接使用已存在的序列号

allow_negative_stock 建议保持 0:负库存掩盖出入库差错,月结时集中暴露。确有先出后入的业务(如调拨在途),优先用物料需求单/转移单流程而非放开负库存。

6.3 会计与销售默认值

Accounts Settings 实测读数:

字段实测值说明
unlink_payment_on_cancellation_of_invoice1取消发票时自动解除付款关联(1=一并冲销,避免悬挂预收)
book_deferred_entries_via_journal_entry0递延收入/支出经日记账处理(0=自动开票)
allow_multi_currency_invoices_against_single_party_account0多币种发票挂单币种应收(0=禁止混挂)

Selling Settings 实测读数:

字段实测值说明
allow_multiple_items1订单允许一次录多行物料
maintain_same_sales_rate0不强制订单价与上次一致(0=允许浮动报价)
editable_price_list_rate0销售员不可改价格表价(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 文档列表。

九、参考链接

  1. Frappe 框架站点配置文档:https://docs.frappe.io/framework/user/en/bench/resources/bench-yaml
  2. Frappe 官方文档首页:https://docs.frappe.io
  3. ERPNext 官方文档:https://docs.frappe.io/erpnext
  4. ERPNext GitHub 仓库:https://github.com/frappe/erpnext
  5. 官方部署仓库 frappe_docker:https://github.com/frappe/frappe_docker
  6. 本专栏背景认知:《ERPNext 介绍与选型指南》
  7. 本专栏部署实战:《ERPNext v16 Docker Compose 部署实战》