Hatsu 0.3.5 配置参数详解
Hatsu 0.3.5 配置体系实测:进程环境变量与 .env(dotenvy)双层加载顺序、HATSU_ENV_FILE 兜底路径的文档与源码不一致、10 个 HATSU_* 参数逐项默认值与实测效果,含缺省 sqlite::memory: 连接池陷阱、主账号 Feed 校验、ACCESS_TOKEN 开关与 NodeInfo 元数据注入的逐行回显,查询与实测日期 2026-11-02。
Hatsu 0.3.5 配置参数详解
目标:把 Hatsu 0.3.5 的全部配置面——10 个
HATSU_*环境变量、dotenv 双层加载顺序、数据库 URL 格式——逐项给出默认值、实测效果与配错的真实后果。全部回显为 2026-11-02 在三套实测实例(SQLite 栈、PostgreSQL 栈、故障复现栈)上的记录,源码口径以官方仓库v0.3.5标签的src/commands/run.rs为准。部署过程见 《Hatsu 0.3.5 Docker Compose 部署指南》,命令工具面见 《Hatsu 0.3.5 常用 CLI 命令与工具详解》。
一、环境信息
- 组件与版本:Hatsu 0.3.5(启动日志自报
Hatsu v0.3.5 "Strobe Nights")。 - 配置体系:官方文档 Environments 一节明确「Hatsu supports dotenv」——配置只有环境变量与
.env文件两层,没有独立的 TOML/YAML 配置文件;.env由 Rust 的 dotenvy 库在进程内加载。 - 实测口径:三套实例分别演示不同配置层——SQLite 栈全部走编排注入的环境变量;PostgreSQL 栈演示
postgres://URL;故障复现栈演示缺省值陷阱与.env文件层。 - 必填口径(官方文档规则原文):变量名无
(optional)后缀即必填,除非源码内置缺省值或.env.example给出示例值。
二、配置加载顺序与优先级
2.1 源码加载序列
src/commands/run.rs(v0.3.5)的启动序列决定了各配置层的生效性:
pub async fn run() -> Result<(), AppError> {
hatsu_tracing::init()?;
tracing::info!("{}", AppEnv::info());
tracing::info!("loading environment variables");
if dotenvy::dotenv().is_err() {
let env_file =
env::var("HATSU_ENV_FILE").unwrap_or_else(|_| String::from("/etc/hatsu/.dev"));
if dotenvy::from_path(Path::new(&env_file)).is_err() {
tracing::debug!("no .env file found");
}
}
let env = AppEnv::init()?;
对应的实测日志序列(故障复现栈,时间戳为 2026-11-02):
2026-11-02T06:18:44.398962Z INFO hatsu::commands::run: Hatsu v0.3.5 "Strobe Nights"
2026-11-02T06:18:44.398982Z INFO hatsu::commands::run: loading environment variables
2026-11-02T06:18:44.399001Z INFO hatsu::commands::run: connecting database: sqlite::memory:
2026-11-02T06:18:44.399366Z INFO hatsu::commands::run: running database migration
2.2 优先级结论
由上述序列可确定生效顺序(高→低):
- 进程环境变量(编排
environment:、systemdEnvironment=等注入)——dotenvy 的dotenv()语义是只补齐缺失项、不覆盖已存在变量,因此同名变量进程环境赢; - 当前工作目录向上查找到的
.env文件(官方制品工作目录为/app,即/app/.env); HATSU_ENV_FILE指定路径的文件(仅当第 2 步找不到.env时才尝试);- 源码内置缺省值(见第六章总表)。
⚠️ 两个源码级细节:
HATSU_ENV_FILE的兜底路径:官方文档写缺省为/etc/hatsu/.env,但 v0.3.5 源码run.rs的unwrap_or_else分支实际写的是/etc/hatsu/.dev——文档与源码不一致,以源码为准(实测口径:给制品挂/etc/hatsu/.env并不会被兜底读到,除非显式设置HATSU_ENV_FILE)。hatsu_tracing::init()发生在dotenvy::dotenv()之前,日志级别只读进程环境变量——写在.env文件里的HATSU_LOG不生效,必须走环境注入。
2.3 双层配置的实测证据
SQLite 栈只用了编排环境注入(9 个变量,无 .env 文件):
HATSU_ACCESS_TOKEN=123e4567-e89b-12d3-a456-426614174000
HATSU_DATABASE_URL=sqlite://hatsu.sqlite3
HATSU_DOMAIN=hatsu.local
HATSU_LISTEN_HOST=0.0.0.0
HATSU_LISTEN_PORT=3939
HATSU_LOG=info
HATSU_NODE_DESCRIPTION=S8 test instance
HATSU_NODE_NAME=My Hatsu
HATSU_PRIMARY_ACCOUNT=github.blog
故障复现栈则演示 .env 层:编排环境里只有 5 个变量、不含 HATSU_NODE_NAME/HATSU_NODE_DESCRIPTION:
HATSU_DOMAIN=hatsu.local
HATSU_LISTEN_HOST=0.0.0.0
HATSU_LISTEN_PORT=3939
HATSU_LOG=info
HATSU_PRIMARY_ACCOUNT=github.blog
而挂载进 /app/.env 的文件内容为:
HATSU_NODE_NAME=Hatsu Dotenv 实例
HATSU_NODE_DESCRIPTION=由 .env 文件注入的 NodeInfo 元数据
其 NodeInfo 实测回显(8146 端口)——两个仅存在于 .env 文件的值被进程读到:
{"version":"2.1","software":{"name":"hatsu","version":"0.3.5","repository":"https://github.com/importantimport/hatsu","homepage":"https://hatsu.cli.rs"},"protocols":["activitypub"],"services":{"inbound":[],"outbound":[]},"openRegistrations":false,"usage":{"users":{"total":1},"localPosts":0},"metadata":{"nodeName":"Hatsu Dotenv 实例","nodeDescription":"由 .env 文件注入的 NodeInfo 元数据"}}
三、核心参数逐项实测
3.1 HATSU_DOMAIN(必填,缺省 None)
实例对外域名(不带 https://),是所有联邦对象 URL 的骨架。实测 hatsu.local 的效果链:
- actor 地址:
https://hatsu.local/users/github.blog; - WebFinger subject:
acct:github.blog@hatsu.local; - host-meta 的 lrdd 模板:
https://hatsu.local/.well-known/webfinger?resource={uri}。
同时它决定主账号校验时生成的用户 URL(generate_user_url(domain, primary_account))。生产必须与反代对外域名一致,否则对端实例解析到的对象地址与可达地址不符。
3.2 HATSU_PRIMARY_ACCOUNT(必填,缺省 None)
实例的签名主体账号(signed_fetch_actor),取值为带有效 Feed 的站点域名。源码语义(run.rs):启动时按 HATSU_DOMAIN + HATSU_PRIMARY_ACCOUNT 组出的用户 ID 查库,查不到则现场创建——创建过程要真实拉取该域名 Feed 发现 Feed URL。
实测三种行为:
github.blog(有 RSS):启动日志checking primary account: github.blog通过,账号自动入库(psql 回显The GitHub Blog | github.blog | t);example.com(无 Feed):启动即致命错误、重启循环:
Error: AppError { error: "Unable to find Feed Url named example.com", error_id: 01a19a40-6c59-7a72-8824-fa925477e5a1, status: 404, context: SpanTrace [] }
- 主账号不可删除:Admin API 对
github.blog返回 405(Remove account API not yet implemented,且不止主账号——0.3.5 所有删号都是 405,见命令篇)。
3.3 HATSU_LISTEN_HOST / HATSU_LISTEN_PORT(缺省 127.0.0.1 / 3939)
监听地址与端口。官方制品的环境基线里已注入 HATSU_LISTEN_PORT=3939(制品配置的 Env 项实测可见),编排部署必须显式 HATSU_LISTEN_HOST: 0.0.0.0 才能被宿主端口映射打通(127.0.0.1 缺省只监听回环)。实测三套栈分别映射宿主 8144/8145/8146 → 服务内 3939。
另见部署篇第十章 10.1 节:官方制品的探针把该变量写进了不展开的 exec 形式里,是制品缺陷而非本参数问题。
3.4 HATSU_DATABASE_URL(缺省 sqlite::memory:——生产必须显式设置)
只接受 sqlite: 或 postgres: URL(SeaORM/sqlx 口径)。官方文档自述缺省值动机:「sqlite::memory: is used by default to ensure that hatsu does not report errors as a result」——仅为让 Hatsu 不因缺配置而直接报错。
实测两种取值:
SQLite 文件路线(官方推荐 sqlite://hatsu.sqlite3,相对制品工作目录 /app,需与挂载目标对齐):
2026-11-02T03:14:12.201110Z INFO hatsu::commands::run: connecting database: sqlite://hatsu.sqlite3
PostgreSQL 路线(口令走编排内部网络,数据库不映射宿主端口;示例口令 q1w2e3r4):
HATSU_DATABASE_URL: postgres://hatsu:q1w2e3r4@db:5432/hatsu
缺省值的真实后果(故障复现栈全程实录):不设该变量 → connecting database: sqlite::memory: → 启动时迁移与主账号写入发生在连接池的第一个连接上,而 :memory: 是每连接独立的私有库——后续请求被派到其他连接时表根本不存在:
{"error":"Query Error: error returned from database: (code: 1) no such table: user","error_id":"01a19ae5-2ca0-7252-8de1-f20a0d270f74"} [HTTP 500]
表现为间歇性 500(刚启动时部分请求 200,之后越来越 500),日志里迁移明明全部 has been applied。结论:sqlite::memory: 与连接池模型不兼容,不具备生产可用性,任何部署都必须显式设置本参数。
3.5 HATSU_LOG(缺省 info)
格式同 RUST_LOG(tracing EnvFilter 语法)。官方示例:
info,tokio::net=debug,sqlx::query=warn
实测 HATSU_LOG=info 时,sqlx 的逐条 SQL 会以 INFO 级别刷屏(部署篇第五、八章日志里大量 summary: "SELECT \"user\"... 行即此),生产建议按示例把 sqlx::query 压到 warn。注意 2.2 节结论:本参数写进 .env 文件不生效(tracing 初始化早于 dotenv 加载),必须走进程环境注入。
四、可选参数
4.1 HATSU_ACCESS_TOKEN(可选——Admin API 总开关)
官方文档:「If this value is not set, the Hatsu Admin API will not be available.」建议 uuid v4,示例生成命令:
echo "\nHATSU_ACCESS_TOKEN = \"$(cat /proc/sys/kernel/random/uuid)\"" >> .env
实测三态(token 值 123e4567-e89b-12d3-a456-426614174000):
- 未设置该变量(故障复现栈):任何 Admin API 调用直接 401 空响应:
HTTP 401
- 设置了但 token 传错(SQLite 栈):同样 401 空响应:
HTTP 401
- 正确 token:建号 201、封禁 200 等(见部署篇第七章)。
即本参数是 Admin API 的存在性开关,无 token 实例等于关闭全部管理能力。
4.2 HATSU_NODE_NAME / HATSU_NODE_DESCRIPTION(可选)
只影响 NodeInfo 的 metadata.nodeName / nodeDescription 两字段(源码 NodeInfoMetadata::new 直接克隆 data.env 对应字段,skip_serializing_if = Option::is_none)。实测对照:
- SQLite 栈(环境注入):
"metadata":{"nodeName":"My Hatsu","nodeDescription":"S8 test instance"}; - 故障复现栈(
.env注入):"metadata":{"nodeName":"Hatsu Dotenv 实例","nodeDescription":"由 .env 文件注入的 NodeInfo 元数据"}; - PostgreSQL 栈(两者都没设):
"metadata":{}——字段整体消失,合法降级。
除展示外无功能影响,FEP-f1d5 口径的实例元数据。
4.3 HATSU_ENV_FILE(可选)
.env 兜底路径开关,仅在「工作目录链上找不到 .env」时生效(见 2.1 序列)。文档缺省写 /etc/hatsu/.env、源码实际兜底 /etc/hatsu/.dev(2.2 节不一致点);要固定路径建议显式设置本变量,别赌兜底。
五、数据库 URL 格式与迁移机制
两种 URL 实测均可用(3.4 节),建库建表由启动时 SeaORM Migrator 自动完成,无独立迁移命令(CLI 里没有 migrate 子命令,实测 error: unrecognized subcommand 'migrate',见命令篇)。
迁移版本表实测(PostgreSQL 栈 psql,SQLite 栈同构):
version
--------------------------------------------
m20240131_000001_user
m20240131_000002_user_feed_item
m20240131_000003_post
m20240131_000004_activity
m20240131_000005_received_follow
m20240501_000001_received_like
m20240501_000002_received_announce
m20240515_000001_user_feed_hatsu_extension
m20240515_000002_user_feed
m20240926_000001_blocked_url
m20241028_000001_user_language
(11 rows)
对应 9 张业务表(user/post/activity/user_feed_item/received_follow/received_like/received_announce/blocked_url/seaql_migrations)。升级版本时重启即自动补迁移,回滚需谨慎(无 down 流程暴露给运维)。
六、参数总表
| 参数 | 必填 | 缺省 | 实测要点 |
|---|---|---|---|
HATSU_LOG | 否 | info | RUST_LOG 语法;.env 里设置不生效(时序) |
HATSU_ENV_FILE | 否 | 文档 /etc/hatsu/.env,源码 /etc/hatsu/.dev | 仅 .env 缺失时兜底;文档/源码不一致 |
HATSU_DATABASE_URL | 否(但必须设) | sqlite::memory: | 缺省值与连接池冲突→间歇 500;用 sqlite://hatsu.sqlite3 或 postgres:// |
HATSU_DOMAIN | 是 | None | 对象 URL/WebFinger 骨架;须与反代域名一致 |
HATSU_LISTEN_HOST | 否 | 127.0.0.1 | 编排/反代部署必改 0.0.0.0 |
HATSU_LISTEN_PORT | 否 | 3939 | 制品基线已注入 3939;探针缺陷波及本变量 |
HATSU_PRIMARY_ACCOUNT | 是 | None | 必须有有效 Feed,否则启动崩溃循环;不可删除 |
HATSU_ACCESS_TOKEN | 可选 | None | 未设则 Admin API 整体 401 |
HATSU_NODE_NAME | 可选 | None | NodeInfo metadata.nodeName;环境/.env 两层均可注入 |
HATSU_NODE_DESCRIPTION | 可选 | None | NodeInfo metadata.nodeDescription;同上 |
七、常见错配速查
- 忘设
HATSU_DATABASE_URL:服务能起、日志显示迁移成功,但接口间歇 500no such table: user——不是数据库坏了,是缺省内存库(3.4 节)。 HATSU_PRIMARY_ACCOUNT填了无 Feed 的域名:启动即崩、重启循环,日志尾行Unable to find Feed Url named <域名>(3.2 节)。- 没设
HATSU_ACCESS_TOKEN:Admin API 全部 401,无法建号/封禁(4.1 节)。 HATSU_LISTEN_HOST留缺省:宿主端口映射不通(3.3 节)。HATSU_LOG写进.env:静默无效,日志级别不会变(2.2 节时序)。- SQLite 相对路径与挂载目标不对齐:
sqlite://hatsu.sqlite3相对/app,挂载必须落在/app/hatsu.sqlite3(部署篇第四章要点 4)。
完整故障定位过程(含探针缺陷案例)见 《Hatsu 0.3.5 Docker Compose 部署指南》 第十章;配置改完后的重启与验证命令见 《Hatsu 0.3.5 常用 CLI 命令与工具详解》。