Firefly III 常用命令与运维实战
Firefly III v6.7.9 运维命令全家桶实测:artisan 完整性/修复/升级/定时任务、REST API 账户交易预算规则真实回显、Data Importer CSV 自动导入三次失败排障、pg_dump 备份盘点与 APP_KEY 变更破坏性演练实录。
Firefly III 常用命令与运维实战
目标:给出 Firefly III v6.7.9 日常运维的完整命令面——artisan 命令行(版本/完整性/修复/升级/定时任务全家桶)、REST API 实测(账户/交易/预算/规则的真实 curl 与回显)、Data Importer CSV 自动导入实测(含三次失败的真实排障)、数据库备份卷盘点,以及 APP_KEY 变更的破坏性演练全记录。全部命令与回显均在 6.7.9 实测环境逐条执行;部署栈见《Firefly III Docker Compose 部署实战》,参数体系见《Firefly III 配置参数详解》。
一、环境信息
| 项目 | 值 |
|---|---|
| Firefly III 版本 | 6.7.9(fireflyiii/core:latest,PHP 8.5.12) |
| Data Importer | v2.3.5(fireflyiii/data-importer:latest) |
| 数据库 | PostgreSQL 16(DB_CONNECTION=pgsql,库名/用户 firefly) |
| 服务监听 | 主程序 8130、Data Importer 8133(192.168.146.128) |
| API 认证 | 静态令牌(Personal Access Token),Authorization: Bearer <token> |
| 实测账号 | admin@firefly.local / q1w2e3r4q1w2e3r4(密码策略至少 16 字符) |
| 演示数据 | 首启向导创建的 3 个资产账户(Demo Bank 等)+ 本文实测创建的交易 |
⚠️ 本文出现的令牌(
TOKEN变量)、口令均为实测演示值;生产环境请使用自己的密钥。
二、前置条件
- 已按《Firefly III Docker Compose 部署实战》完成部署,四个服务全部 Up;
- 已在主程序 Web 界面(Profile 页)创建静态令牌,导出为 shell 变量:
TOKEN="<你的静态令牌>" - artisan 命令统一经编排内执行入口调用:
docker compose exec app php artisan <命令>。
三、版本与系统命令
3.1 版本与运行概览
$ docker compose exec app php artisan firefly-iii:output-version
6.7.9
$ curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" http://192.168.146.128:8130/api/v1/about
{"data":{"version":"6.7.9","api_version":"6.7.9","php_version":"8.5.12","os":"Linux","driver":"pgsql"}}
3.2 数据库连接与迁移状态
$ docker compose exec app php artisan firefly-iii:verify-database-connection
[✓] Connected to the database.
$ docker compose exec app php artisan migrate:status | tail -3
2026_04_13_185808_migrations_04_2026 ............................... [1] Ran
2026_10_09_062600_migrations_10_2026 ............................... [1] Ran
💡 说明:
firefly-iii:output-version输出后没有换行(与下一命令输出粘连是正常现象);artisan 命令体系共 213 条命令,其中firefly-iii:*系列 20 条(php artisan list实测盘点)。
四、artisan 日常命令
4.1 数据库完整性体检与修复
完整性报告(只读检查,不改数据):
$ docker compose exec app php artisan firefly-iii:report-integrity
(输出节选)
[11:35:06] Now executing command integrity:total-sums
[✓] Amount integrity OK for user #1
[11:35:06] Command integrity:total-sums took 0.0088 seconds.
[11:35:06] Now executing command integrity:file-permissions
[i] All necessary file paths seem to exist, and are writeable.
[11:35:06] Command integrity:file-permissions took 0.0041 seconds.
自动修复(校验并修正可修复项,幂等可重复执行):
$ docker compose exec app php artisan firefly-iii:correct-database
(输出节选,末行)
[11:34:26] Command firefly-iii:report-integrity took 0.0100 seconds.
升级数据库(版本升级后执行,内部串联完整性检查与修复):
$ docker compose exec app php artisan firefly-iii:upgrade-database
(输出节选,末行)
[11:35:14] Command firefly-iii:correct-database took 0.1400 seconds.
⚠️ 排障实录:本实测环境首跑
report-integrity时报出真实问题——[x] Directory "/var/www/html/storage/upload" is not writeable. Uploading attachments may fail silently.,日志同步记production.ERROR。根因:上传目录绑定到宿主侧时属主为 root(uid 0),而主程序以 www-data(uid 33)运行,目录不可写且附件上传会静默失败。修复:宿主侧chown -R 33:33 <部署目录>/data/upload后复跑,回显转为[i] All necessary file paths seem to exist, and are writeable.。该检查脚本化后可作每日体检项。
4.2 定时任务与测试邮件
$ docker compose exec app php artisan firefly-iii:cron
[✓] "Create recurring transactions" cron ran with success: Recurring transactions cron job fired successfully.
[i] "Create auto budgets" cron fired: Auto-budget cron job fired successfully.
[✓] "Create auto budgets" cron ran with success: Auto-budget cron job fired successfully.
[i] "Send subscription warnings" cron fired: Bill notification cron job fired successfully.
[✓] "Send subscription warnings" cron ran with success: Bill notification cron job fired successfully.
[i] "Webhook" cron fired: Send webhook messages cron job fired successfully.
[✓] "Webhook" cron ran with success: Send webhook messages cron job fired successfully.
[i] More feedback on the cron jobs can be found in the log files.
$ docker compose exec app php artisan firefly-iii:send-test-email
$ echo $?
0
💡 说明:
send-test-email退出码 0 但控制台无输出;在MAIL_MAILER=log+APP_LOG_LEVEL=notice的默认组合下,邮件正文也不会落日志文件(实测日志仅出现No Pushover token, channel is disabled.的通知渠道警告)。要真实验证邮件链路,请改 SMTP 驱动后重跑。
4.3 其他实用命令速查(同系列 20 条中的常用项)
| 命令 | 用途 |
|---|---|
firefly-iii:create-database | 尝试创建不存在的数据库(PostgreSQL 下自动跳过) |
firefly-iii:force-migrations | 强制重跑全部迁移(排障用,谨慎) |
firefly-iii:refresh-running-balance | 重算所有账户的滚动余额(大量数据时耗时) |
firefly-iii:scan-attachments | 重扫附件并修正 MD5/MIME |
firefly-iii:check-for-updates | 检查新版本 |
firefly-iii:export-data | 导出用户数据(JSON/CSV 形态) |
firefly-iii:laravel-passport-keys | 重新生成 OAuth 签名密钥对(不报错退出) |
firefly-iii:verify-security-alerts | 检查当前版本安全通告 |
五、REST API 实测
Firefly III 的 JSON REST API(/api/v1/*,本版本 api_version 2.1.0)是脚本化运维的主通道。以下全部为真实 curl 与真实回显。
5.1 创建费用账户
$ curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"name":"Shell Gas Station","type":"expense","currency_code":"USD","notes":"D1 实测创建"}' \
"http://192.168.146.128:8130/api/v1/accounts" | python3 -c "import json,sys; a=json.load(sys.stdin)['data']; print(a['id'], a['attributes']['name'], a['attributes']['type'], a['attributes']['active'])"
8 Shell Gas Station expense True
5.2 记一笔提现交易(资产账户 → 费用账户)
$ curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"transactions":[{"type":"withdrawal","date":"2026-10-28","amount":"32.50","description":"加油(D1 实测)","currency_code":"USD","source_id":"1","destination_id":"8","category_name":"交通","tags":["d1-test","fuel"]}]}' \
"http://192.168.146.128:8130/api/v1/transactions" | python3 -c "import json,sys; d=json.load(sys.stdin); t=d['data']; x=t['attributes']['transactions'][0]; print('tx id:',t['id'],'|',x['type'],'|',x['amount'],'|',x['source_name'],'->',x['destination_name'],'| tags:',x['tags'])"
tx id: 5 | withdrawal | 32.500000000000 | Demo Bank -> Shell Gas Station | tags: ['d1-test', 'fuel']
查询与汇总(⚠️ 两个真实 API 行为差异见注记):
$ curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" http://192.168.146.128:8130/api/v1/transactions/5 | python3 -c "import json,sys; x=json.load(sys.stdin)['data']['attributes']['transactions'][0]; print('amount:',x['amount'],'| date:',x['date'],'| category:',x['category_name'])"
amount: 32.500000000000 | date: 2026-10-28T00:00:00+08:00 | category: 交通
$ curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" "http://192.168.146.128:8130/api/v1/summary/basic?start=2026-10-01&end=2026-10-31" | python3 -c "
import json,sys
d=json.load(sys.stdin)
for k,v in d.items():
if any(w in k for w in ('balance','net-worth','spent','earned')): print(k,'=>',v.get('value_parsed'))"
balance-in-USD => -$32.50
spent-in-USD => -$32.50
earned-in-USD => $0.00
net-worth-in-USD => $5,967.50
⚠️ 注记(实测行为差异):
- 交易更新用 PUT 而非 PATCH:对
/api/v1/transactions/{id}发 PATCH 会收到"The PATCH method is not supported for route api/v1/transactions/5. Supported methods: GET, HEAD, PUT, DELETE.";改用 PUT 且提交完整交易字段。- summary/basic 必须带
start与end参数:缺省请求直接 422,回显{"message":"The start field is required. (and 1 more error)","errors":{"start":["The start field is required."],"end":["The end field is required."]}}。- 净资产 5967.50 = 期初 1000 + 5000 − 32.50,与预期吻合(复式记账的资金守恒自洽)。
5.3 预算实测(创建 → 设限额 → 交易入预算)
$ curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"name":"交通(D1 实测)","active":true}' http://192.168.146.128:8130/api/v1/budgets | python3 -c "import json,sys; b=json.load(sys.stdin)['data']; print('budget id:',b['id'],b['attributes']['name'],b['attributes']['active'])"
budget id: 1 交通(D1 实测) True
$ curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"start":"2026-10-01","end":"2026-10-31","amount":"200","currency_code":"USD"}' \
http://192.168.146.128:8130/api/v1/budgets/1/limits | python3 -c "import json,sys; l=json.load(sys.stdin)['data']; print('limit id:',l['id'],'| amount:',l['attributes']['amount'],'| period:',l['attributes']['start'],'~',l['attributes']['end'])"
limit id: 1 | amount: 200 | period: 2026-10-01T00:00:00+08:00 ~ 2026-10-31T23:59:59+08:00
$ curl -s -X PUT -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"transactions":[{"type":"withdrawal","date":"2026-10-28","amount":"32.50","description":"加油(D1 实测)","currency_code":"USD","source_id":"1","destination_id":"8","category_name":"交通","budget_name":"交通(D1 实测)","tags":["d1-test","fuel"]}]}' \
http://192.168.146.128:8130/api/v1/transactions/5 | python3 -c "import json,sys; x=json.load(sys.stdin)['data']['attributes']['transactions'][0]; print('tx5 budget:',x['budget_name'],'| amount:',x['amount'])"
tx5 budget: 交通(D1 实测) | amount: 32.500000000000
5.4 规则实测(创建 → 手工触发 → 验证效果)
先建规则组(⚠️ 实测全新部署 GET /api/v1/rule-groups 返回空列表 {"data":[],"meta":{"pagination":{"total":0,...}}},创建规则时服务端要求组必须存在):
$ curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"title":"D1 实测规则组"}' http://192.168.146.128:8130/api/v1/rule-groups | python3 -c "import json,sys; g=json.load(sys.stdin)['data']; print('group id:',g['id'],'|',g['attributes']['title'],'| active:',g['attributes']['active'])"
group id: 1 | D1 实测规则组 | active: True
$ curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"title":"加油交易自动打标","description":"D1 实测规则","rule_group_title":"D1 实测规则组","trigger":"store-journal","active":true,"strict":false,"triggers":[{"type":"description_is","value":"加油(D1 实测)","active":true,"order":0}],"actions":[{"type":"add_tag","value":"rule-applied","active":true,"order":0}]}' \
http://192.168.146.128:8130/api/v1/rules | python3 -c "import json,sys; r=json.load(sys.stdin)['data']; print('rule id:',r['id'],'|',r['attributes']['title'],'| trigger:',r['attributes']['trigger'],'| strict:',r['attributes']['strict'])"
rule id: 1 | 加油交易自动打标 | trigger: store-journal | strict: False
$ curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"start":"2026-10-01","end":"2026-10-31"}' http://192.168.146.128:8130/api/v1/rules/1/trigger
(无响应体,成功即触发)
$ curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" http://192.168.146.128:8130/api/v1/transactions/5 | python3 -c "import json,sys; x=json.load(sys.stdin)['data']['attributes']['transactions'][0]; print('tx5 tags:',x['tags'],'| budget:',x['budget_name'])"
tx5 tags: ['d1-test', 'fuel', 'rule-applied'] | budget: 交通(D1 实测)
⚠️ 版本差异实测:尝试创建
prepend_description(描述加前缀)动作时被 422 拒绝——The selected actions.0.type is invalid.。核对源码配置(config/firefly.php 第 442 行)发现该动作类在 6.7.9 已被注释禁用,旧版规则引擎的描述/备注增删类动作(prepend/append description、notes 等)不再可用,当前启用动作共 22 类(set_description/set_category/set_budget/add_tag/convert_withdrawal/delete_transaction 等,docker compose exec app grep -E "=> [A-Za-z]+::class"可自查)。写作时曾按旧版文档预期配置,实查修正。
六、Data Importer CSV 导入实测
Data Importer v2.3.5 除网页交互导入外,提供自动导入接口 POST /autoimport——指定一个目录,导入器成对读取其中的 文件.csv + 文件.json(同名配置),自动完成转换与提交。这比网页流程更适合脚本化运维,本节完整实测(含三次失败的真实排障)。
6.1 启用自动导入
导入器编排增加四个环境变量并挂载导入目录(完整编排见部署篇):
environment:
FIREFLY_III_URL: http://app:8080
FIREFLY_III_ACCESS_TOKEN: <主程序静态令牌>
CAN_POST_AUTOIMPORT: "true"
AUTO_IMPORT_SECRET: <至少16位的调用口令>
IMPORT_DIR_ALLOWLIST: /import
TZ: Asia/Shanghai
volumes:
- ./import:/import
逐项说明:FIREFLY_III_ACCESS_TOKEN 让导入器免 OAuth 网页授权直连主程序 API;CAN_POST_AUTOIMPORT 打开 /autoimport 接口;AUTO_IMPORT_SECRET 为接口调用口令(≥16 位);IMPORT_DIR_ALLOWLIST 是目录白名单(逗号分隔,不在表内的目录一律拒绝,源码 isAllowedPath 实查)。改后 docker compose up -d 重建导入器生效。
6.2 准备导入文件
import/demo.csv(两笔银行支出流水,负数金额表示支出):
date,description,amount,expense_account
2026-10-27,Whole Foods Market (D1 import test),-15.75,Whole Foods Market
2026-10-26,Metro Card (D1 import test),-8.00,Metro Card
import/demo.json(导入配置,必须用内部键名格式,见 6.3 排障):
{
"flow": "file",
"content_type": "csv",
"headers": true,
"date": "Y-m-d",
"delimiter": ",",
"default_account": 1,
"rules": true,
"webhooks": false,
"add_import_tag": true,
"skip_form": true,
"roles": ["date_transaction", "description", "amount", "opposing-name"],
"do_mapping": [],
"mapping": []
}
⚠️ 注意角色名是混合命名:
date_transaction(下划线)但opposing-name(连字符)——必须与导入器源码config/csv.php的role_to_transaction映射逐字一致,写错即 500(见 6.3 第三次失败)。default_account: 1为资产账户 Demo Bank 的 ID(/api/v1/accounts?type=asset查询),提现的资金流出账户。
6.3 执行导入与排障实录
第 1、2 次失败(配置格式不兼容):先按官方网页向导下载的经典配置格式("version":1 或 "version":3 + import-account/column-roles 键)编写 JSON,接口返回 {"message":"Seems to have worked!"} 但实际导入失败,导入器日志给出真实错误:
$ docker logs firefly-iii-6.7.9-importer 2>&1 | grep ERROR | tail -2
[2026-10-28 11:48:11] production.ERROR: [2.3.5]: Error accessing "http://app:8080/api/v1/accounts/0?". Status code is 404. Body is: {"message":"Resource not found","exception":"NotFoundHttpException"}
[2026-10-28 11:48:11] production.ERROR: Could not complete import from file "/import/demo.csv".
[2026-10-28 11:48:11] production.ERROR: [2.3.5]: The default account in your configuration file (0) does not exist.
根因(源码实查):自动导入路径解析配置用的是 Configuration::fromArray(内部键名 default_account/roles),不是网页流程的 fromFile(经典键名 import-account/column-roles)——两种格式不兼容,import-account: 1 被静默忽略导致 default account 解析为 0。这是官方文档未明确覆盖的真实差异。
第 3 次失败(角色名拼写):改用内部键名后仍 500:No place for role "date-transaction"——内部角色表中日期角色是下划线 date_transaction(而 opposing-name 是连字符)。修正后导入成功。
最终成功:
$ curl -s -X POST -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"secret":"<AUTO_IMPORT_SECRET>","directory":"/import"}' \
http://192.168.146.128:8133/autoimport
{"message":"Seems to have worked!"}
导入结果核验(交易总数 1 → 3,两笔新交易自动附加导入标签):
$ curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" "http://192.168.146.128:8130/api/v1/transactions?page=1" | python3 -c "
import json,sys
d=json.load(sys.stdin)
m=d['meta']; print('total:',m['pagination']['total'])
for t in d['data']:
a=t['attributes']; x=a['transactions'][0]
print('#%s'%t['id'], x['type'],'|',x['date'][:10],'|',x['amount'],'|',x['description'],'|',x['source_name'],'->',x['destination_name'],'| tags:',x['tags'])"
total: 3
#5 withdrawal | 2026-10-28 | 32.500000000000 | 加油(D1 实测) | Demo Bank -> Shell Gas Station | tags: ['d1-test', 'fuel', 'rule-applied']
#9 withdrawal | 2026-10-27 | 15.750000000000 | Whole Foods Market (D1 import test) | Demo Bank -> Whole Foods Market | tags: ['Data Import on 2026-10-28 @ 11:50']
#10 withdrawal | 2026-10-26 | 8.000000000000 | Metro Card (D1 import test) | Demo Bank -> Metro Card | tags: ['Data Import on 2026-10-28 @ 11:50']
CSV 中负数金额被正确识别为 withdrawal,expense_account 列自动落为目标费用账户,add_import_tag: true 自动打上 Data Import on <日期> @ <时间> 标签便于回溯。导入器日志同时可见其内部调用了主程序的批量 API(POST /api/v1/transactions、POST /api/v1/batch/finish?apply_rules=true)。
七、备份与恢复
7.1 数据存放盘点
| 数据 | 位置 | 持久化方式 |
|---|---|---|
| 全部业务数据(账户/交易/规则/预算/用户/令牌) | PostgreSQL 数据目录 | 命名卷 firefly-iii-679-stack_firefly_iii_db |
| 上传附件/导入导出文件 | /var/www/html/storage/upload | 绑定目录 <部署目录>/data/upload |
| 会话/缓存 | file 驱动 | 未持久化(重启需重新登录,属预期) |
卷盘点实测:
$ docker volume ls --format '{{.Name}}' | grep firefly
firefly-iii-679-stack_firefly_iii_db
$ docker volume inspect firefly-iii-679-stack_firefly_iii_db --format 'mountpoint: {{.Mountpoint}} | driver: {{.Driver}}'
mountpoint: /var/lib/docker/volumes/firefly-iii-679-stack_firefly_iii_db/_data | driver: local
7.2 组合备份实测
$ mkdir -p backup
$ docker exec firefly-iii-6.7.9-db pg_dump -U firefly firefly > backup/firefly-2026-10-28.sql
$ ls -ln backup/
total 212
-rw-r--r-- 1 0 0 212623 Oct 28 11:42 firefly-2026-10-28.sql
-rw-r--r-- 1 0 0 116 Oct 28 11:43 upload-2026-10-28.tar.gz
$ grep -c "CREATE TABLE" backup/firefly-2026-10-28.sql
81
$ grep -m1 "COPY public.transactions" backup/firefly-2026-10-28.sql
COPY public.transactions (id, created_at, updated_at, deleted_at, account_id, transaction_journal_id, description, amount, identifier, transaction_currency_id, foreign_amount, foreign_currency_id, reconciled, balance_before, balance_after, balance_dirty, native_amount, native_foreign_amount) FROM stdin;
- 数据库备份:
pg_dump纯 SQL 导出,实测 208KB、81 张表(upload-2026-10-28.tar.gz为上传目录归档)。生产建议加| gzip压缩并按日轮转保留; - 恢复:空库上
psql -U firefly firefly < 备份文件.sql全量重建;或新部署一次(见部署篇 4.4 编排)后停写入再导入; - 定时备份脚本示例(服务器 crontab 每日 02:30):
30 2 * * * docker exec firefly-iii-6.7.9-db pg_dump -U firefly firefly | gzip > /opt/firefly-iii/backup/firefly-$(date +\%F).sql && find /opt/firefly-iii/backup -name 'firefly-*.sql.gz' -mtime +30 -delete
八、APP_KEY 变更演练实录(破坏性)
⚠️ 演示目的:验证
APP_KEY变更的真实破坏面。演练全程在实测环境完成,密钥已恢复。
演练步骤与真实回显:
$ curl -s -o /dev/null -w '%{http_code}' -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" http://192.168.146.128:8130/api/v1/about
200 # 基线:令牌有效
$ sed -i 's/^APP_KEY=.*/APP_KEY=whgpaoN84y57RTcmZkuLxxZGxDcuG01Z/' .env && docker compose up -d
$ curl -s -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" http://192.168.146.128:8130/api/v1/about
{"message":"Unauthenticated.","exception":"AuthenticationException"} # HTTP 401,静态令牌立即失效
$ docker logs firefly-iii-6.7.9-app 2>&1 | grep -iE 'decrypt|payload|MAC' | tail -2
[2026-10-28 11:39:22] production.ERROR: Could not decrypt pub/private keypair.
[2026-10-28 11:39:22] production.ERROR: The MAC is invalid.
演练结论(真实观察):
- 静态 API 令牌立即失效(HTTP 401):令牌在数据库中经
APP_KEY加密存储,换钥即解密失败; - Passport 密钥对解密失败(日志
Could not decrypt pub/private keypair./The MAC is invalid.):OAuth 签发链路异常; - 密码登录与业务数据不受影响:实测
admin@firefly.local仍可正常登录(口令哈希用 bcrypt,不依赖APP_KEY),仪表盘/账户/交易全部完好(74211 字节的 Dashboard 页含全部账户数据); - 恢复原钥后旧令牌不会复活:把
APP_KEY改回原值并重建后,原令牌仍 401——故障窗口内 Passport 密钥对已被重新生成入库(配合firefly-iii:laravel-passport-keys机制),需到 Profile 页重新签发令牌;实测新签令牌立即恢复 200; - 一个容易被忽略的恢复坑:把
.env里的APP_KEY改回原值后直接docker compose up -d,编排检测到配置与运行中服务一致不会重建,主程序仍带着错钥运行——必须docker compose up -d --force-recreate app强制重建。实测在恢复阶段即踩到该坑(401 持续),强制重建并重签令牌后才恢复。
运维结论:APP_KEY 一经启用永远固定;它保护的是"加密态数据"(静态令牌、OAuth 密钥、会话 Cookie),不是业务数据本身——但令牌失效会让所有 API 自动化当天瘫痪。务必在首次部署时就把 APP_KEY 写入部署目录并纳入备份(本文密钥备份随 .env 存档)。
九、常见问题(FAQ)
Q1:php artisan route:list 报错?
实测 6.7.9 在该镜像内执行 route:list 触发异常(Target class [hash] does not exist 类错误,官方 v6.7.9 发布说明亦提及自托管用户可能遇到此错误并已修复)。巡检路由请改看源码 routes/web.php / routes/api.php,或升级到包含修复的版本。
Q2:附件上传后看不到文件?
先跑 firefly-iii:report-integrity——若报 Directory "/var/www/html/storage/upload" is not writeable,按 4.1 的排障实录修复目录属主(chown -R 33:33)。该问题不报页面错误,只有完整性检查能发现。
Q3:脚本批量导入报"configuration file (0) does not exist"?
自动导入的 JSON 配置必须用内部键名格式(default_account/roles),不能用网页向导下载的经典格式(import-account/column-roles)。完整正确示例与两种格式的差异见第六章。
Q4:API 返回 "The PATCH method is not supported"?
交易更新用 PUT(全字段提交),见 5.2 注记;summary/basic 记得带 start/end。
Q5:docker compose up -d 改了 .env 却没生效?
编排只重建配置发生变化的服务;把变量改回原值时不会触发重建,需 docker compose up -d --force-recreate <服务名>。见第八章第 5 条实录。
十、参考链接
- 部署与编排基线:《Firefly III Docker Compose 部署实战》
- 配置参数体系:《Firefly III 配置参数详解》
- 产品与选型背景:《Firefly III 介绍与选型指南》
- 官方 REST API 文档(v2.1.0 端点清单):https://api-docs.firefly-iii.org/
- 官方 Data Importer 自动导入文档:https://docs.firefly-iii.org/how-to/data-importer/usage/auto-import/
- 官方 cron 配置文档:https://docs.firefly-iii.org/how-to/firefly-iii/advanced/cron/
- v6.7.9 发布说明(含 hash 类错误修复记录):https://github.com/firefly-iii/firefly-iii/releases/latest