Family Accounting Tool v4.29 配置参数详解

Family Accounting Tool v4.29 全量配置参数详解:application.conf 与 accounting-config.yml 每个参数的默认值、作用与实测行为,附家庭生产配置模板与排障 FAQ。

Family Accounting Tool财务记账配置2026/10/23

Family Accounting Tool v4.29 配置参数详解

目标:系统梳理 Family Accounting Tool(facto)v4.29 的全部配置入口——conf/application.conf(Play/HOCON)与 conf/accounting-config.yml(家庭记账建模 YAML)的每个参数,给出默认值、作用、取值约束与修改方法,并提供可直接套用的家庭生产配置模板。所有行为均基于 v4.29 发行包实测(Ubuntu 22.04 / Java 11 / MariaDB 10.6)。

一、环境信息

  • 应用版本:Family Accounting Tool v4.29(官方发行包 release-v4.29.tar.gz)
  • 实测环境:Ubuntu 22.04.5 LTS、OpenJDK 11.0.32.1、MariaDB 10.6.23、应用目录 /opt/facto
  • 配置文件清单(发行包内 conf/ 目录实测内容):
accounting-config.yml   # 家庭记账建模:科目/账户/支付方式/模板/图表/常量
application.conf        # Play 框架与应用核心配置(HOCON 格式)
messages                # 英文语言包
messages.nl             # 荷兰语语言包
routes                  # HTTP 路由表(一般不改)
  • 参数来源说明:默认值逐条对照发行包内原始配置文件与源码 app/jvm/src/main/scala/app/models/accounting/config/Parsable.scala(v4.29 标签,查询日期 2026-10-23);错误行为均为实测回显。

二、前置条件

  • 已按发行包方式安装并初始化好 facto(安装全过程见 《Ubuntu 22.04 安装 Family Accounting Tool v4.29 指南》);尚未安装时,本文示例中的文件路径与命令按 /opt/facto 安装目录书写;
  • 熟悉 YML 基本语法与 HOCON 格式(HOCON 是 Play 框架使用的 JSON 超集:支持花括号层级、= 或 : 赋值、# 注释);
  • 修改配置前建议备份:cp -a /opt/facto/conf /root/facto-conf-backup。

三、参数查看与修改方式

facto 的参数分三个层次,查看与修改方式各不相同:

  1. 配置文件层(本文主体):/opt/facto/conf/application.conf 与 /opt/facto/conf/accounting-config.yml,用任意文本编辑器修改;
  2. JVM 系统属性层:启动命令行以 -D<key>=<value> 传入,优先级高于配置文件,常用的一次性动作(建表 -DdropAndCreateNewDb、建管理员 -DcreateAdminUser)与覆盖项(如 -Dhttp.port=9001)都走这里;
  3. 环境变量层:仅 Docker 镜像内置(APPLICATION_SECRET 覆盖会话密钥、DATABASE_URL 覆盖数据库连接,机制为镜像内配置的 ${?VAR} 可选替换),发行包方式一般不用。

生效方式:v4.29 生产模式(Prod)下所有配置在启动时一次性加载,修改配置文件后必须重启进程(systemd 方式 systemctl restart facto,SysV 方式 service facto restart)才生效,无热加载。

校验行为(实测):配置在启动阶段解析,任何解析错误都会让应用拒绝启动。例如把 accounting-config.yml 的时区改成不存在的值后启动,实测报错:

com.google.inject.CreationException: Unable to create injector, see the following errors:
1) Error in custom provider, java.time.zone.ZoneRulesException: Unknown time-zone ID: Mars/Olympus
Caused by: java.time.zone.ZoneRulesException: Unknown time-zone ID: Mars/Olympus

因此每次改完配置,先在前台跑 bin/server 观察启动日志,确认出现 Application started (Prod) 再切回服务托管。

四、参数总览

4.1 application.conf 参数总览

参数默认值作用改动风险
play.http.secret.key"changeme"会话签名密钥,兼作外部 API 的 appSecret必改,泄露等于交出 API 写权限
play.i18n.langs["en"]界面语言,仅支持 en/nl低
play.server.websocket.frame.maxLength100MWebSocket 单帧上限(决定附件上传通道容量)低
play.http.session.maxAge60d登录会话有效期低
db.default.drivercom.mysql.jdbc.DriverJDBC 驱动类随数据库选型
db.default.urljdbc:mysql://localhost/facto?user=mysqluser&password=mysqlpassword数据库连接串必改
db.default.slick.profileslick.jdbc.MySQLProfile$Slick 方言随数据库选型
app.accounting.configYamlFilePath"conf/accounting-config.yml"记账建模 YAML 的路径一般不改
app.accounting.attachmentsFolder"/changeme/path/to/attachments/folder"附件落盘目录必改(原值是占位符)
app.setup.defaultPassword"changeme"初始 admin 用户密码(仅 -DcreateAdminUser 时使用)建议改

4.2 accounting-config.yml 顶层键总览

顶层键作用必填
categories消费/收入科目定义是
accounts成员与共同账户定义是
moneyReservoirs支付方式(钱包/银行卡/储蓄账户)定义是
templates重复记账模板是(可为空列表)
predefinedCharts预定义统计图表是(可为空列表)
constants全局常量(共同账户、特殊科目、时区、财年等)是

4.3 JVM 与启动参数总览

参数默认值作用
-Dhttp.port9000HTTP 监听端口
JAVA_OPTS(环境变量)JVM 默认堆透传 JVM 参数(堆限制等)
-DdropAndCreateNewDb无启动时清空并重建全部数据表(危险,仅首次安装)
-DcreateAdminUser无创建/重置 admin 用户后退出

五、核心参数分类详解

5.1 会话与安全参数

play.http.secret.key 是 facto 最重要的安全参数,实测它有双重身份:既是 Play 框架给浏览器会话 Cookie(PLAY_SESSION)签名的密钥,也是外部 API 每个请求 URL 中 appSecret 的正确取值(v4.29 源码 ExternalApi.validateApplicationSecret 直接以该配置值比对请求串,查询日期 2026-10-23)。默认 changeme 必须替换为足够长的随机串:

play {
  # Secret key
  http.secret.key="facto-secret-2026-q1w2e3r4"
}

⚠️ 注意:更换该密钥后所有已登录会话立即失效(旧 Cookie 签名无法通过校验),外部 API 调用方也要同步更新 URL 中的 secret。生成随机串的简便方法:cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1(官方 README 同款)。

play.http.session.maxAge = 60d 控制登录态有效期,默认 60 天;家庭内网场景可维持默认,暴露公网时建议缩短(如 7d)。

5.2 界面与语言参数

play.i18n.langs(发行包写作 i18n.langs = ["en"],注释注明 Supported: "en" and "nl"):界面语言包选择。实测发行包 conf/ 只带 messages(英文)与 messages.nl(荷兰语)两份语言包,没有中文包;中文用户保持 ["en"] 即可。

5.3 数据库连接参数

db.default {
  driver = com.mysql.jdbc.Driver
  url = "jdbc:mysql://localhost/facto?user=facto&password=q1w2e3r4"
  slick.profile = "slick.jdbc.MySQLProfile$"
}

逐项说明:

  • driver:JDBC 驱动类名,官方默认 MySQL Connector/J 5.1.36 的类名(旧式 com.mysql.jdbc.Driver,实测 v4.29 直接可用);连接 MariaDB 10.x 实测正常;
  • url:完整 JDBC 连接串,库名、用户、密码都在这里。多参数用 & 连接(如 ?user=facto&password=q1w2e3r4&useSSL=false);
  • slick.profile:Slick ORM 方言,MySQL/MariaDB 用 slick.jdbc.MySQLProfile$。

💡 技术拓展:facto 支持的关系型数据库不止 MySQL/MariaDB。源码 build.sbt 捆绑了三套 JDBC 驱动,可选方案对比——

数据库driverslick.profile适用判断
MariaDB/MySQLcom.mysql.jdbc.Driverslick.jdbc.MySQLProfile$官方 README 推荐,生产首选
SQLiteorg.sqlite.JDBCslick.jdbc.SQLiteProfile$零部署、单文件库,适合低写入量家用
H2org.h2.Driverslick.jdbc.H2Profile$内存/嵌入式试验用,不建议存真实数据

本文采用官方推荐的 MariaDB:数据独立于应用目录,备份/迁移路径成熟。

5.4 应用路径与初始化参数

app {
  accounting.configYamlFilePath = "conf/accounting-config.yml"
  accounting.attachmentsFolder = "/opt/facto/attachments"
  setup.defaultPassword = "q1w2e3r4"
}
  • accounting.configYamlFilePath:记账建模 YAML 的路径,相对应用目录解析;想换文件名(如按年份拆分)时改这里;
  • accounting.attachmentsFolder:附件(票据照片)落盘目录,发行包默认值是占位符 /changeme/path/to/attachments/folder,不改会导致附件功能异常;建议指向独立数据盘目录并纳入备份;
  • setup.defaultPassword:仅在被 -DcreateAdminUser 调用时生效,作为 admin 账号密码写入数据库(实测输出 password: q1w2e3r4);运行期修改它不影响已有账号。

5.5 服务与 JVM 参数

HTTP 端口:Play 默认 9000,可用系统属性覆盖,实测有效:

export LANG=en_US.UTF-8
cd /opt/facto
bin/server -Dhttp.port=9001

实测输出:

[info] p.c.s.AkkaHttpServer - Listening for HTTP on /0:0:0:0:0:0:0:0:9001

健康检查同步验证通过:curl -s http://localhost:9001/externalapi/healthcheck/ -w " [%{http_code}]\n" 输出 OK [200]。配合反向代理(Nginx 等)做域名接入时可把端口挪到非特权位。

JVM 堆:facto 是单 JVM 进程,家庭规模(2-6 成员、日均几十笔流水)堆内存 256-512MB 足够。通过 JAVA_OPTS 环境变量透传,实测生效验证:

JAVA_OPTS="-Xms256m -Xmx256m" bin/server &
jps -v | grep -v Jps

实测输出:

5692 ProdServerStart -Xms256m -Xmx256m -Duser.dir=/opt/facto

长期运行把该变量写进服务定义(systemd 单元 Environment="JAVA_OPTS=-Xms256m -Xmx256m",注意含空格值必须加引号,否则 systemd 按空格拆分导致只有 -Xms256m 生效——实测踩坑)。

一次性初始化参数(详见 《Ubuntu 22.04 安装 Family Accounting Tool v4.29 指南》 4.7 节):

  • -DdropAndCreateNewDb:清空并重建全部表。实测日志 Dropping the database tables (if present) and creating new ones... Done. Exiting.——存在数据时执行等于清库;
  • -DcreateAdminUser:创建/重置 admin 账号后自动退出。

5.6 accounting-config.yml:categories(科目)

科目把支出/收入分类,是统计图表与汇总行的维度。字段(源码 Parsable.Category):

字段默认值说明
code无(必填)科目唯一编码,全大写惯用(如 LIFE);在模板/交易中引用
name无(必填)界面显示名(如 Groceries)
helpText""输入框旁的辅助提示语

演示配置示例(发行包自带 15 个科目,节选):

categories:
  - &catLife
      code: LIFE
      name: "Groceries"
      helpText: "Food, Toothpaste, .."
  - &catIn
      code: IN
      name: "Income"
      helpText: "wages, .."
  - &catAcc
      code: ACC
      name: "Accounting"
      helpText: "Non-real flows of money"
  - &catEndow
      code: ENDOW
      name: "Endowments"
      helpText: "Common account refill"

⚠️ 注意两个语义特殊科目(由 constants 节指定,见 5.11):Accounting 科目登记非真实收支(报销、内部转账腿),统计月度盈亏时自动排除;Endowments 科目登记向共同账户的注资。&catLife 这类是 YAML 锚点语法,供 accounts 节用 *catLife 引用,避免重复书写。

5.7 accounting-config.yml:accounts(账户)

账户分「成员账户」与「共同账户」。字段(源码 Parsable.Account):

字段默认值说明
code无(必填)账户唯一编码(如 Alice),交易 beneficiaryCode 引用它
longName无(必填)全名
shorterName无(必填)中短名(列表页用)
veryShortName无(必填)缩写(表格列头用,如 A.)
userLoginNamenull绑定登录用户名(须为数据库已存在用户;决定「该成员登录后看到什么」)
defaultCashReservoirCodenull该账户录入现金交易时的默认支付方式
defaultElectronicReservoirCode无(必填)默认电子支付方式
categories无(必填)该账户可选科目列表(锚点引用)
summaryTotalRows[<b>Total</b> 忽略无]汇总行定义:rowTitleHtml + categoriesToIgnore

共同账户与成员账户的差异主要在 userLoginName(共同账户不绑定登录用户)与科目集合(共同账户通常不含 Income/Taxes)。

5.8 accounting-config.yml:moneyReservoirs(支付方式)

支付方式是每一笔交易的资金载体(现金、银行卡、储蓄账户等),对账(Cash Flow)按它逐个核对。字段(源码 Parsable.MoneyReservoir):

字段默认值说明
code无(必填)唯一编码(如 CASH_ALICE)
name无(必填)显示名
shorterName回退为 name短名
owner无(必填)所属账户(锚点引用 *accountAlice)
hiddenfalse是否在界面隐藏(如不便公开的储蓄账户)
currencynull(本位币)外币支付方式在此填 ISO 代码(演示配置中 Card Common (£) 填 GBP)
assumeThisFollowsInflationUntilNextBalanceCheckfalse通胀校正相关:下次余额核对前是否假定该支付方式跟随通胀

演示配置示例(节选):

moneyReservoirs:
    - &reservoirCashCommon
        code: CASH_COMMON
        name: Cash Common
        owner: *accountCommon
    - &reservoirCardCommon
        code: CARD_COMMON
        name: Card Common (£)
        owner: *accountCommon
        currency: GBP
    - &reservoirSavingsAlice
        code: SAVINGS_ALICE
        name: Savings account Alice at Just-Another-Bank
        shorterName: Savings Alice
        owner: *accountAlice
        hidden: true

5.9 accounting-config.yml:templates(记账模板)

模板把重复性记账固化为一键操作。字段(源码 Parsable.Template):

字段默认值说明
code无(必填)模板编码(外部 API addfromtpl 按 code 调用)
name无(必填)显示名
placement无(必填)展示位置,取值 CASH_FLOW_VIEW / ENDOWMENTS_VIEW / TEMPLATE_LIST
onlyShowForUserLoginNamesnull(全员可见)限定可见用户(如工资模板只给本人看)
zeroSumfalse腿合计为零的平衡型模板(取现、注资)
icon"fa-plus-square"图标 CSS 类(FontAwesome/iconfont)
transactions无(必填)交易腿列表

交易腿字段(Parsable.Template.Transaction):beneficiaryCode(受益人,必填)、moneyReservoirCode(支付方式,可空串表示不适用)、categoryCode、description(默认 "")、flowAsFloat(默认 0;支出为负、收入为正)、detailDescription(默认 "")、tags(默认 null)。

双腿平衡示例(发行包自带的取现模板,实测语义:从电子卡转 50 到现金钱包):

  - code: new-withdrawal
    name: New Withdrawal
    placement: [CASH_FLOW_VIEW]
    zeroSum: true
    icon: fa fa-credit-card fa-fw
    transactions:
      - beneficiaryCode: ${account.code}
        moneyReservoirCode: ${account.defaultElectronicReservoir.code}
        categoryCode: ACC
        description: Withdrawal
        flowAsFloat: -50
      - beneficiaryCode: ${account.code}
        moneyReservoirCode: ${account.defaultCashReservoir.code}
        categoryCode: ACC
        description: Withdrawal
        flowAsFloat: 50

其中 ${account.code} 是运行时占位符:模板在界面上会对每个账户展开一份,调用时代入账户编码。⚠️ 这是 YAML 里合法的占位语法,不要与「配置未填」混淆。

5.10 accounting-config.yml:predefinedCharts(预定义图表)

字段:name(图表名)+ chartSpec(lines 必填;correctForInflation 默认 false;aggregationPeriod 默认 "Month",取值 Month/Year)。每条线:name + query(查询串,语法同交易搜索框:beneficiary:Alice、category:LIFE、minFlow:-100 等前缀过滤,可用引号包短语)。

predefinedCharts:
  - name: "Alice's transactions"
    chartSpec:
      correctForInflation: false
      aggregationPeriod: Month
      lines:
        - name: "Alice's transactions"
          query: "beneficiary:Alice"

5.11 accounting-config.yml:constants(全局常量)

常量默认值说明
commonAccount无(必填)指向共同账户锚点(*accountCommon),系统据此识别「注资/共同支出」
accountingCategory无(必填)指向 Accounting 科目锚点,统计盈亏时排除
endowmentCategory无(必填)指向 Endowments 科目锚点
liquidationDescription"Liquidation"清算交易的描述标记
zoneId"Europe/Brussels"时区(IANA 名)。实测填无效值启动即报 ZoneRulesException: Unknown time-zone ID,中国用户填 Asia/Shanghai
supportInflationCorrectionsfalse是否启用通胀校正开关(需配合特殊 <index> 币种的汇率数据)
firstMonthOfYear"January"财年起始月;填 April 即按「4 月至次年 3 月」切分年度

六、生产配置模板

适用场景:2 名成员 + 1 个共同账户的家庭,2 GB 内存 / 20 GB 磁盘的个人服务器,中文地区, MariaDB 本机部署。以下两份配置可直接作为起点(编码与名称按家庭情况替换)。

conf/application.conf 关键段:

play {
  http.secret.key="REPLACE-WITH-32-RANDOM-CHARS"   # cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1
  i18n.langs = ["en"]
  server.websocket.frame.maxLength = 100M
  http.session.maxAge = 60d
}

db.default {
  driver = com.mysql.jdbc.Driver
  url = "jdbc:mysql://localhost/facto?user=facto&password=q1w2e3r4"
  slick.profile = "slick.jdbc.MySQLProfile$"
}

app {
  accounting.configYamlFilePath = "conf/accounting-config.yml"
  accounting.attachmentsFolder = "/opt/facto/attachments"
  setup.defaultPassword = "q1w2e3r4"
}

conf/accounting-config.yml(两位成员 Wei 与 Lan,共同账户 Common):

!!app.models.accounting.config.Parsable$Config
categories:
  - &catLife
      code: LIFE
      name: "Groceries"
      helpText: "Food, daily goods"
  - &catFun
      code: FUN
      name: "Fun"
      helpText: "Eating out, movies"
  - &catRecur
      code: RECUR
      name: "Recurring"
      helpText: "Rent, utilities, subscriptions"
  - &catIn
      code: IN
      name: "Income"
      helpText: "Wages"
  - &catAcc
      code: ACC
      name: "Accounting"
      helpText: "Non-real flows"
  - &catEndow
      code: ENDOW
      name: "Endowments"
      helpText: "Common account refill"

accounts:
  - &accountCommon
      code: Common
      longName: Common
      shorterName: Common
      veryShortName: C.
      defaultElectronicReservoirCode: CARD_COMMON
      categories: [*catLife, *catFun, *catRecur, *catEndow, *catAcc]
  - &accountWei
      code: Wei
      longName: Wei
      shorterName: Wei
      veryShortName: W.
      userLoginName: wei
      defaultCashReservoirCode: CASH_WEI
      defaultElectronicReservoirCode: CARD_WEI
      categories: [*catLife, *catFun, *catRecur, *catIn, *catAcc, *catEndow]
  - &accountLan
      code: Lan
      longName: Lan
      shorterName: Lan
      veryShortName: L.
      userLoginName: lan
      defaultCashReservoirCode: CASH_LAN
      defaultElectronicReservoirCode: CARD_LAN
      categories: [*catLife, *catFun, *catRecur, *catIn, *catAcc, *catEndow]

moneyReservoirs:
    - &reservoirCardCommon
        code: CARD_COMMON
        name: Card Common
        owner: *accountCommon
    - &reservoirCashWei
        code: CASH_WEI
        name: Cash Wei
        owner: *accountWei
    - &reservoirCardWei
        code: CARD_WEI
        name: Card Wei
        owner: *accountWei
    - &reservoirCashLan
        code: CASH_LAN
        name: Cash Lan
        owner: *accountLan
    - &reservoirCardLan
        code: CARD_LAN
        name: Card Lan
        owner: *accountLan

templates:
  - code: new-endowment
    name: New Endowment
    placement: [ENDOWMENTS_VIEW]
    zeroSum: true
    icon: icon-crown
    transactions:
      - beneficiaryCode: Common
        moneyReservoirCode: ""
        categoryCode: ENDOW
        description: Endowment
      - beneficiaryCode: ${account.code}
        moneyReservoirCode: ""
        categoryCode: ENDOW
        description: Endowment

predefinedCharts:
  - name: "Family groceries"
    chartSpec:
      correctForInflation: false
      aggregationPeriod: Month
      lines:
        - name: "Groceries (all)"
          query: "category:LIFE"

constants:
  commonAccount: *accountCommon
  accountingCategory: *catAcc
  endowmentCategory: *catEndow
  liquidationDescription: Liquidation
  zoneId: "Asia/Shanghai"
  supportInflationCorrections: false
  firstMonthOfYear: January

配套运行参数:systemd 单元中 Environment="JAVA_OPTS=-Xms256m -Xmx512m"(2 GB 内存服务器预留系统与 MariaDB 后的上限值)。部署顺序:先在数据库创建 wei、lan 两个登录用户(admin 登录 /app/useradministration 添加),再让 YAML 中 userLoginName 与之一致,最后 systemctl restart facto。验证启动成功的实测标志:

[info] play.api.Play - Application started (Prod) (no global state)
[info] p.c.s.AkkaHttpServer - Listening for HTTP on /0:0:0:0:0:0:0:0:9000

七、常见问题(FAQ)

Q1:改完配置启动报 MalformedInputException: Input length = 1

应用按 JVM 默认字符集读 YAML;系统语言环境为 POSIX(locale 显示 LANG= 为空)时默认字符集是 ASCII,YAML 中的非 ASCII 字符(如 £)直接触发异常(实测错误行 [error] a.m.a.c.ConfigModule - Error when parsing accounting-config.yml: java.nio.charset.MalformedInputException)。解决:locale-gen 生成 en_US.UTF-8 并 export LANG=en_US.UTF-8 后重启(完整步骤见 《Ubuntu 22.04 安装 Family Accounting Tool v4.29 指南》 第八章 FAQ-1)。

Q2:YAML 里 code 重复或引用了不存在的编码会怎样

启动阶段即校验失败、应用拒绝启动。编码类错误与字符集错误都在 Error when parsing accounting-config.yml: 前缀之下,看到该前缀就检查 YAML:锚点拼写(*catLife 必须有对应 &catLife)、科目/账户/支付方式编码唯一性、userLoginName 是否为数据库已有用户。改对后前台 bin/server 确认 Application started (Prod) 再恢复服务托管。

Q3:杀进程后无法再次启动

报错实测原文:

This application is already running (or delete /opt/facto/RUNNING_PID file).

原因:进程被 kill -9 或异常退出后,PID 文件 /opt/facto/RUNNING_PID 残留,Play 启动时误判已有实例。解决:确认无 java 进程(ps -ef | grep [j]ava)后删除该文件再启动:rm -f /opt/facto/RUNNING_PID && bin/server。规范停止请用 service facto stop / systemctl stop facto(走 SIGTERM 并清理 PID 文件)。

Q4:时区填什么?想按财年统计怎么改

zoneId 填 IANA 时区名(中国 Asia/Shanghai),填错启动即报 Unknown time-zone ID(实测)。财年需求改 constants.firstMonthOfYear(默认 January),如填 April 后所有年度视图从 4 月起算。

Q5:改了 setup.defaultPassword 怎么 admin 密码没变

该参数只在执行 -DcreateAdminUser 的瞬间生效(写入新 admin 账号),不影响已存在的账号。重置密码的方法:服务停止后执行 bin/server -DcreateAdminUser(实测会重新打印 loginName: admin 与新密码),再启动服务。

八、参考链接

  • 配置文件原始样例(v4.29 发行包同款):https://github.com/nymanjens/facto/blob/v4.29/conf/application.conf
  • 记账建模 YAML 样例(字段最全的官方演示):https://github.com/nymanjens/facto/blob/v4.29/conf/demo-accounting-config.yml
  • 配置解析与默认值源码:https://github.com/nymanjens/facto/blob/v4.29/app/jvm/src/main/scala/app/models/accounting/config/Parsable.scala
  • 官方 README 配置节:https://github.com/nymanjens/facto
  • HOCON 格式说明(Play 配置格式):https://github.com/lightbend/config/blob/master/HOCON.md
  • Play Framework 2.8 配置文档:https://www.playframework.com/documentation/2.8.x/Configuration