Donetick 0.1.83 配置参数详解
逐组解析 Donetick v0.1.83 全部配置参数:加载机制、DT_ 环境变量覆盖、JWT 强校验、SQLite/PostgreSQL 切换、实时推送与存储通知通道,关键行为均实测验证。
Donetick 0.1.83 配置参数详解
目标:逐组解析 Donetick v0.1.83 的全部配置参数——配置加载机制、
DT_环境变量覆盖规则、JWT 强校验、数据库切换、实时推送、对象存储与通知通道等,关键行为均附实测回显。基于 Ubuntu 22.04 实测环境(二进制 + systemd 与官方 Docker 镜像双通道验证)。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS x86_64(实测环境)
- Donetick 版本:v0.1.83(GitHub Releases 最新稳定版,查询日期 2026-10-23)
- 配置文件:
config/selfhosted.yaml(自托管形态,由DT_ENV=selfhosted决定加载) - 配置源码参照:
config/config.go(v0.1.83 源码,用于标注代码级默认值) - 运行形态:方案 A 二进制 + systemd(工作目录
/opt/donetick),方案 B 官方 Docker 镜像donetick/donetick:v0.1.83 - 服务端口:2021(默认)
- 安装过程见《Ubuntu 22.04 安装 Donetick 0.1.83 指南》
二、前置条件
- 已按安装指南完成 Donetick v0.1.83 部署并能访问
http://localhost:2021/api/v1/health(返回 200); - 二进制 + systemd 形态:对
/opt/donetick/config/selfhosted.yaml有写权限,能执行systemctl restart donetick; - Docker 形态:
docker与docker compose可用,配置目录挂载为容器的/config; - 理解 YAML 基本语法。参数修改后需要重启服务才生效(见 3.3 实测流程)。
三、参数查看与修改方式
3.1 配置文件加载机制
Donetick 用 Viper 加载 YAML 配置,加载哪份文件由环境变量 DT_ENV 决定:local → config/local.yaml、prod → config/prod.yaml、selfhosted → config/selfhosted.yaml、r2 → config/r2.yaml;DT_ENV 未设置时按 local 处理。搜索路径是工作目录下的 config/,所以 systemd 单元中 WorkingDirectory=/opt/donetick 必须正确。
启动时程序会打印实际加载的环境(实测启动日志首行):
--ConfigLoad config for environment: selfhosted
--ConfigLoad name : selfhosted
💡 说明:
config.Name同时参与安全校验的豁免逻辑——只有name: "local"(开发形态)会跳过 JWT 密钥强度校验;自托管配置name: "selfhosted"会执行校验。因此不要把自托管配置的name随手改成local来绕过校验(绕过会换来弱密钥风险)。
找不到配置文件时的行为分两种形态(实测):
- 官方发布包二进制:打印
Config file not found, using defaults and environment variables,继续以内置默认值 + 环境变量启动; - 官方 Docker 镜像:自动生成一份默认配置到
/config/selfhosted.yaml(实测日志:Config file not found, generating default config... Generated default config at config/selfhosted.yaml),生成时会自动写入随机 JWT 密钥。
3.2 环境变量覆盖规则
所有配置项都可以用环境变量覆盖而不动 YAML:前缀 DT_ + 配置键路径(点号换下划线)。实测有效的覆盖变量:
| 环境变量 | 覆盖目标 | 实测效果 |
|---|---|---|
DT_ENV | 配置文件选择 | selfhosted 加载 config/selfhosted.yaml |
DT_SERVER_PORT | server.port | 设为 2031 后监听 2031,健康检查返回 200 |
DT_SQLITE_PATH | SQLite 数据库文件路径 | 设为 /tmp/envtest/dt.db 后该位置生成库文件 |
DT_JWT_SECRET | jwt.secret | 32 字符测试值启动成功 |
另有少量专用环境变量(不遵循 DT_ 前缀规则):
| 环境变量 | 作用 |
|---|---|
DONETICK_TELEGRAM_TOKEN | 覆盖 telegram.token |
DONETICK_PUSHOVER_TOKEN | 覆盖 pushover.token |
DONETICK_DISABLE_SIGNUP | 设为 true 等价 is_user_creation_disabled: true |
DONETICK_LOG_LEVEL / DONETICK_LOG_ENCODING / DONETICK_LOG_DEVELOPMENT | 覆盖日志三项 |
BRIDGE_INSTANCE_TOKEN | Bridge 推送中继令牌(官方注释明确要求不写进配置文件) |
TZ | 时区;未设置时程序内部强制 UTC |
3.3 修改与生效流程(改 → 重启 → 验证实测)
参数修改后必须重启进程。以 server.serve_swagger(是否提供 Swagger API 文档页)为实测对象,完整闭环:
第一步,确认当前开启(/swagger/doc.json 返回 OpenAPI JSON):
curl -s -o /dev/null -w '%{content_type}\n' http://localhost:2021/swagger/doc.json
实测输出:
application/json; charset=utf-8
第二步,把 /opt/donetick/config/selfhosted.yaml 中的 serve_swagger: true 改为 false 并重启:
sudo sed -i 's/serve_swagger: true/serve_swagger: false/' /opt/donetick/config/selfhosted.yaml
sudo systemctl restart donetick
第三步,等服务起来后再验证(实测 Swagger 路由已注销,请求落入前端 SPA 兜底逻辑返回 HTML):
text/html; charset=utf-8
改回 true 重启后恢复 application/json; charset=utf-8。整个过程健康检查 api/v1/health 始终 200,证明只有目标行为受影响。
⚠️ 注意:
serve_swagger: false时直接访问/swagger/index.html仍会得到 200——那其实是前端单页应用的兜底页(serve_frontend: true时未匹配路由一律回退到index.html,见 5.4)。判断 Swagger 是否真开,用/swagger/doc.json的 Content-Type。
四、参数总览(配置组速查表)
v0.1.83 配置文件共 16 个顶层键/配置组。「代码默认」列指不写进 YAML 时程序内置的值(源自 config/config.go 结构体 default 标签);「示例值」列指官方 selfhosted.yaml.example 中的值:
| 配置组 | 作用 | 代码默认 | 示例值 |
|---|---|---|---|
name | 实例身份标识(local 跳过密钥校验) | 无 | "selfhosted" |
is_done_tick_dot_com | 官方云 SaaS 功能开关 | — | false(自托管必须) |
is_user_creation_disabled | 关闭注册入口 | — | false |
database | 数据库类型与连接 | type=sqlite, migration=true | sqlite |
jwt | 登录态密钥与有效期 | secret 随机生成,session 24h,refresh 1440h | 168h / 1440h |
server | 端口/超时/限流/CORS | port=2021, rate_limit=300 | 2021 |
scheduler_jobs | 三个后台调度周期 | 无默认(须显式配置) | 30m / 3h / 3h |
logging | 日志级别/编码 | level=info, encoding=console | info / json |
email | 邮件通知(SMTP/SMTP2Go) | provider=smtp | 空(log_raw_url: true) |
oauth2 | OIDC 单点登录 | 无 | 空 |
realtime | 实时推送(SSE/WebSocket) | enabled=true(详见 5.9) | enabled=true |
mfa | 两步验证 | enabled=true(详见 5.10) | 未含在示例中 |
storage | 附件对象存储 | 无 | 未含在示例中 |
telegram / pushover | 即时通知令牌 | 空 | "" |
webhook | Webhook 通知 | timeout=5s, queue_size=100 | 未含在示例中 |
feature_limits / stripe / revenuecat / iap / donetick_cloud / fcm / min_version | 官方云 SaaS 专用 | 见 5.13/5.15 | 自托管忽略 |
bridge | 推送中继(可选) | enabled=false | false |
选型解读:家庭自托管只需要动 jwt.secret(必改)与 database(默认 SQLite 免配置),其余按需开启。
五、核心配置组详解
5.1 name 与全局开关
name: "selfhosted"
is_done_tick_dot_com: false
is_user_creation_disabled: false
name:实例名。改为local会跳过 JWT 校验,自托管保持selfhosted;is_done_tick_dot_com:官方云专属功能总开关。自托管必须false——设true会启用 SaaS 商业化限制(Circle 成员数、子账号数等,见 5.13),实测源码中这些限制全部由if h.isDonetickDotCom守卫,false时完全放开;is_user_creation_disabled:true时关闭注册。实测注册接口返回 403:
{"error":"User creation is disabled"}
配套的顶层开关还有两个(示例文件注释中给出,默认关闭):
single_circle_instance: true:单圆圈模式,禁用加入/离开圆圈接口,新用户(含 OIDC 登录)一律加入共享家庭圆圈,适合「一家人一个实例」;disable_password_auth: true:SSO-only 模式,拒绝全部密码登录/注册/重置,登录页隐藏密码表单,配合oauth2使用。
5.2 database:SQLite(默认)与 PostgreSQL
database:
type: "sqlite"
migration: true
# these are only required for postgres
host: "secret"
port: 5432
user: "secret"
password: "secret"
name: "secret"
type:sqlite(默认)或postgres。SQLite 零依赖单文件,家庭规模首选;migration:true启动时自动执行数据库迁移(实测启动日志逐条打印Applying migration: ...,最后汇总Migrations: 10 successful, 0 failed, 0 skipped, 10 total in registry);- SQLite 数据文件路径不在本组配置,由环境变量
DT_SQLITE_PATH指定;未设置时落在工作目录下的donetick.db(源码实测逻辑)。
切换 PostgreSQL 实测(Docker 环境,用环境变量覆盖,不动 YAML):
docker run -d --name dt-pg --network donetick-0183-stack_default \
-e POSTGRES_USER=donetick -e POSTGRES_PASSWORD=q1w2e3r4 -e POSTGRES_DB=donetick postgres:16-alpine
docker run -d --name dt-pg-test --network donetick-0183-stack_default \
-e DT_ENV=selfhosted \
-e DT_JWT_SECRET=q1w2e3r4q1w2e3r4q1w2e3r4q1w2e3r4 \
-e DT_DATABASE_TYPE=postgres -e DT_DATABASE_HOST=dt-pg -e DT_DATABASE_PORT=5432 \
-e DT_DATABASE_USER=donetick -e DT_DATABASE_PASSWORD=q1w2e3r4 -e DT_DATABASE_NAME=donetick \
donetick/donetick:v0.1.83
对应 YAML 写法(二进制形态):
database:
type: "postgres"
host: "127.0.0.1"
port: 5432
user: "donetick"
password: "q1w2e3r4"
name: "donetick"
migration: true
实测结果:应用转 healthy,健康检查返回 HTTP/1.1 200 OK,PostgreSQL 库中自动建出 41 张表(information_schema.tables 计数),迁移日志报 10 successful。连接串格式(源码实测):host=%s port=%v user=%s password=%s dbname=%s sslmode=disable,数据库连不上时每 500ms 重试最多 31 次。
5.3 jwt:密钥强校验与登录态有效期
jwt:
secret: "q1w2e3r4q1w2e3r4q1w2e3r4q1w2e3r4"
session_time: 168h # 7 days
max_refresh: 1440h # 60 days
secret:登录令牌签名密钥。两条硬校验(name != "local"时执行,实测报错原文)——长度不足 32 字符:
🚨 SECURITY ERROR: JWT secret must be at least 32 characters long, got 0 characters
命中内置弱密钥黑名单(secret、password、changeme、donetick、官方示例占位值 change_this_to_a_secure_random_string_32_characters_long 等 13 个):
🚨 SECURITY ERROR: JWT secret is too weak: 'change_this_to_a_secure_random_string_32_characters_long' is not allowed
两种情况都直接 panic 拒绝启动。推荐用 openssl rand -base64 32 生成;Docker 镜像形态若让程序自动生成配置,密钥会随机写入生成文件(见 3.1)。
session_time:access_token 有效期。实测验证:登录响应access_token_expiry与refresh_token_expiry的间隔恰为配置值——
"access_token_expiry":"2026-10-30T02:28:24.008049364Z"
"refresh_token_expiry":"2026-12-22T02:28:24.008049802Z"
登录时刻为 2026-10-23,7 天与 60 天差值与 168h/1440h 完全吻合;
max_refresh:refresh_token 最长刷新窗口,超窗后必须重新登录。
5.4 server:端口、超时、限流与前端
server:
port: 2021
read_timeout: 10s
write_timeout: 10s
rate_period: 60s
rate_limit: 300
cors_allow_origins:
- "http://localhost:5173"
- "http://localhost:7926"
- "https://localhost"
- "http://localhost"
- "capacitor://localhost"
serve_frontend: true
serve_swagger: true
public_host: ""
port:监听端口,默认 2021(代码默认 2021,环境变量DT_SERVER_PORT可覆盖,实测见 3.2);read_timeout/write_timeout:HTTP 读写超时,代码默认 5s,官方示例调到 10s;rate_period+rate_limit:限流窗口与配额,默认 60 秒内 300 次(登录、注册等敏感接口另有独立限流中间件);cors_allow_origins:跨域白名单。示例中http://localhost:5173是前端开发服务器、capacitor://localhost是官方 Android 客户端的跨域来源;把 Web 界面反代到自有域名时,把域名加进来;serve_frontend:true时同端口托管内嵌前端。实现机制(源码实测):静态文件中间件 + NoRoute 兜底——任何未匹配路由一律重写为/返回 SPA 的index.html,所以关掉serve_swagger后/swagger/*也会落到这个兜底(见 3.3);serve_swagger:true时注册/swagger/*any路由,提供 API 文档页与/swagger/doc.json(实测开关效果见 3.3);public_host:对外公开访问地址(用于构造邮件里的链接、Swagger Host 等),代码默认http://localhost:2021;有公网域名时设为https://your.domain.com。
5.5 scheduler_jobs:三个后台调度周期
scheduler_jobs:
due_job: 30m
overdue_job: 3h
pre_due_job: 3h
due_job:到期任务扫描周期(默认示例 30 分钟),负责把到期任务推入通知计划;overdue_job:逾期任务处理周期(默认示例 3 小时);pre_due_job:到期前提醒周期(默认示例 3 小时)。
该组在源码结构体中没有内置默认值,务必显式配置(官方示例即为此目的)。周期取值用 Go duration 格式(30m/3h/24h)。通知何时发出还取决于任务自身的 notification 开关与通知元数据,本组只控制扫描节拍。
5.6 logging
logging:
level: "info"
encoding: "json"
development: false
level:debug/info/warn/error(源码大小写不敏感,warning亦可);encoding:json(示例值)或console(代码默认)。JSON 每行一条结构化日志,ts/caller/msg字段,适合journalctl/docker logs采集;实测日志行样例:
{"level":"info","ts":"2026-10-23T05:09:43.988+0800","caller":"realtime/service.go:83","msg":"Real-time service started","websocket_enabled":true,"max_connections":1000}
development:true时启用 zap 开发模式(更啰嗦的堆栈);- 环境变量
DONETICK_LOG_LEVEL/DONETICK_LOG_ENCODING/DONETICK_LOG_DEVELOPMENT可覆盖。
5.7 email:邮件通知
email:
host:
port:
key:
email:
user: # optional, will be filled with email.email if not set.
app_host:
log_raw_url: true
provider:代码默认smtp(空值等价 smtp),可设smtp2go走其 HTTP API;smtp 用host/port/user/key作为凭据,smtp2go 用key作 API Key;email:发件人地址;user未填时回退用email;app_host:构造邮件链接的站点地址(兼容旧键名appHost,源码有 legacy 回退);verify_template_id/reset_password_template_id:仅 smtp2go 形态使用的模板 ID;log_raw_url: true:把密码重置原始 URL 打印到日志(未配邮件时的自助改密通道,见安装指南 FAQ)。
5.8 oauth2:OIDC 单点登录
oauth2:
client_id:
client_secret:
auth_url:
token_url:
user_info_url:
redirect_url:
name:
# admin_groups:
# - "donetick-admins"
# manager_groups:
# - "donetick-managers"
标准 OIDC 五元组(auth_url/token_url/user_info_url/redirect_url + 客户端凭据)。可选组映射:admin_groups/manager_groups 里的 OIDC 组在每次登录时映射为对应角色。另支持 pkce: true(PKCE 流程)与 scopes。配合顶层 disable_password_auth: true 即为 SSO-only 部署;配合 single_circle_instance: true 时新 OIDC 用户直接进共享家庭圆圈。
5.9 realtime:实时推送
realtime:
enabled: true
sse_enabled: true
heartbeat_interval: 60s
connection_timeout: 120s
max_connections: 1000
max_connections_per_user: 5
event_queue_size: 2048
cleanup_interval: 2m
stale_threshold: 5m
enable_compression: true
enable_stats: true
allowed_origins:
- "*"
代码级默认值与示例值的差异一览(源码 config.go 对照官方示例):
| 键 | 代码默认 | 官方示例 |
|---|---|---|
enabled | true | true |
websocket_enabled | true | 未含(取代码默认 true) |
sse_enabled | true | true |
heartbeat_interval | 30s | 60s |
connection_timeout | 60s | 120s |
min_connection_interval | 5s | 未含(取默认 5s) |
max_connections | 1000 | 1000 |
max_connections_per_user | 5 | 5 |
event_queue_size | 2048 | 2048 |
cleanup_interval | 2m | 2m |
stale_threshold | 5m | 5m |
enable_compression | true | true |
enable_stats | true | true |
allowed_origins | ["*"] | ["*"] |
max_sse_tickets | 10000 | 未含(取默认 10000) |
实测启动日志确认运行态:
{"level":"info","ts":"2026-10-23T05:09:43.988+0800","caller":"realtime/service.go:83","msg":"Real-time service started","websocket_enabled":true,"max_connections":1000}
多设备登录频繁的家庭场景重点调 max_connections_per_user(默认 5,超出的新连接被拒);反向代理后端时记得放行 SSE 的长连接(关闭代理缓冲)。
5.10 mfa:两步验证
该组未包含在官方示例中,代码默认值即为运行值:
| 键 | 代码默认 | 说明 |
|---|---|---|
enabled | true | 允许用户在个人设置中开启 TOTP |
session_timeout_minutes | 15 | MFA 校验会话有效期(分钟) |
backup_code_count | 10 | 恢复码生成数量 |
max_verification_attempts | 5 | 验证码最大尝试次数 |
rate_limit_window | 5m | 尝试限流窗口 |
⚠️ 注意:开发示例
config/local.yaml里出现的是session_timeout/backup_code_count/rate_limit_attempts/rate_limit_window这组键——其中session_timeout、rate_limit_attempts与结构体键名(session_timeout_minutes、max_verification_attempts)不一致,绑定不生效;自托管配置请按上表键名书写。
5.11 storage:附件对象存储
该组同样未含在官方示例中(开发示例 local.yaml 有完整样例)。任务照片/附件支持本地与 S3 兼容对象存储:
storage:
storage_type: "local" # options: local, s3
max_user_storage: 10737418240
max_file_size: 102400
base_path: "./uploads"
storage_type:local(默认,存base_path指定目录)或s3;- S3 形态必填
bucket_name/region/access_key/secret_key/endpoint;base_path作对象前缀; path_style: true:MinIO 等自建 S3 兼容存储必须开启(源码注释明确:MinIO 不提供*.<endpoint-host>通配域名,需用路径式寻址);public_read: true:桶配置为匿名可读时返回不带签名的直链,绕开默认预签名 URL 的 7 天有效期上限;public_bucket_name/public_bucket_host可把公开资源(头像等)单独放一个桶/CDN 域名;max_user_storage(单用户配额,字节)与max_file_size(单文件上限,字节)按需调整;用量经/api/v1/users/storage接口查询。
5.12 telegram / pushover / webhook:通知通道
telegram:
token: ""
pushover:
token: ""
telegram.token:BotFather 签发的 Bot 令牌。实测未配置时启动日志出现无害提示:
Error creating bot: Post "https://api.telegram.org/bot/getMe": dial tcp 65.49.26.99:443: connect: connection refused
pushover.token:Pushover 应用令牌;webhook组(代码默认):timeout: 5s、queue_size: 100,控制 Webhook 通知的发送超时与待发队列长度;- 此外还有 Discord 通知(在用户/圆圈设置里配置,不经 YAML)。
5.13 feature_limits:配额组(仅官方云生效)
代码默认:max_circle_members: 2、plus_circle_max_members: 6、max_subaccounts: 1、plus_max_subaccounts: 5。
⚠️ 重要:实测源码,这套配额只在
is_done_tick_dot_com: true(官方云)时被强制——Circle 成员上限检查在if h.isDonetickDotCom守卫内,子账号上限同样。自托管实例(false)完全不受这组默认值限制,家庭十几口人也不需要动它。
5.14 bridge:推送中继(可选)
bridge:
enabled: false
base_url: "https://bridge.donetick.com"
instance_id: ""
instance_token: ""
timeout_seconds: 15
官方托管的推送通知中继:自托管实例没有常驻的 FCM 凭据时,可借官方 Bridge 服务给手机 App 推送。默认关闭,关闭时回落到实例自己的 fcm.* 直连配置。instance_token 官方明确要求不要写进配置文件,用环境变量 BRIDGE_INSTANCE_TOKEN 注入。
5.15 SaaS 专用配置组(自托管忽略)
stripe(订阅支付)、revenuecat(移动端订阅校验)、iap(Apple/Google 内购)、donetick_cloud(官方云的第三方登录 ClientID)、fcm(推送凭据路径/项目 ID)、min_version(最低客户端版本)均为官方云运行所需,自托管保持缺省即可,写了也不会有副作用。
5.16 顶层独立变量 DT_SQLITE_PATH
严格说这是环境变量而非 YAML 键(SQLite 文件路径没有对应的 YAML 字段,源码直接读环境变量),单独列出防遗漏:
# systemd 单元内
Environment=DT_SQLITE_PATH=/var/lib/donetick/donetick.db
实测设为 /tmp/envtest/dt.db 后启动即在该位置生成 520192 字节的库文件;未设置时落在程序工作目录下的 donetick.db。PostgreSQL 形态不需要它。
六、生产配置模板(家庭自托管)
适用场景:2–10 人家庭/小团队、SQLite 单机、内存 1 GB 以内的 NAS/小型 VPS。可直接落 /opt/donetick/config/selfhosted.yaml(secret 请替换为自己生成的随机值):
name: "selfhosted"
is_done_tick_dot_com: false
is_user_creation_disabled: false
database:
type: "sqlite"
migration: true
jwt:
secret: "q1w2e3r4q1w2e3r4q1w2e3r4q1w2e3r4" # 换成 openssl rand -base64 32 的结果
session_time: 168h # access_token 7 天,移动端免频繁重登
max_refresh: 1440h # 60 天内可静默刷新
server:
port: 2021
read_timeout: 10s
write_timeout: 10s
rate_period: 60s
rate_limit: 300
cors_allow_origins:
- "https://todo.example.com" # 有反代域名时加自有域名
- "capacitor://localhost" # 官方 Android 客户端需要
serve_frontend: true
serve_swagger: false # 家庭实例用不到 API 文档页就关掉
public_host: "https://todo.example.com"
logging:
level: "info"
encoding: "json"
development: false
scheduler_jobs:
due_job: 30m
overdue_job: 3h
pre_due_job: 3h
email:
log_raw_url: true # 未配邮件时重置链接走日志
realtime:
enabled: true
sse_enabled: true
heartbeat_interval: 60s
connection_timeout: 120s
max_connections: 1000
max_connections_per_user: 5
event_queue_size: 2048
cleanup_interval: 2m
stale_threshold: 5m
enable_compression: true
enable_stats: true
allowed_origins:
- "*"
bridge:
enabled: false
base_url: "https://bridge.donetick.com"
instance_id: ""
instance_token: ""
timeout_seconds: 15
模板解读:is_done_tick_dot_com: false 保住自托管无限成员数;serve_swagger: false 减少暴露面(需要调试 API 时临时打开);public_host 与反代域名一致保证邮件/重置链接可达;其余保持示例默认即可,与默认值不同的项都有注释说明理由。
七、常见问题(FAQ)
Q1:启动即 panic,报 SECURITY ERROR: JWT secret ...?
见 5.3:长度不足 32 字符或命中弱密钥黑名单(含官方示例自带的占位值)都会拒绝启动。用 openssl rand -base64 32 生成新值替换 jwt.secret,或用环境变量 DT_JWT_SECRET 注入后重启。
Q2:改了配置文件不生效?
三步排查:① 改的是不是程序实际加载的文件(DT_ENV 决定文件名,工作目录决定搜索路径,见 3.1);② 是否重启了服务(二进制形态 systemctl restart donetick;改过 systemd 单元要先 daemon-reload);③ 是否被同名环境变量覆盖(DT_ 前缀优先级高于 YAML,见 3.2)。验证手段推荐用 3.3 的开关回读法。
Q3:serve_swagger: false 后访问 /swagger/index.html 还是 200?
那是前端 SPA 的兜底页(serve_frontend: true 时未匹配路由一律回退 index.html)。用 /swagger/doc.json 判断:Swagger 真开时返回 application/json,关闭时返回 text/html(实测见 3.3)。
Q4:Docker 部署时重启后所有用户都要重新登录?
配置目录没挂载。镜像启动时若 /config 里没有 selfhosted.yaml 会自动生成一份(含随机 JWT 密钥,见 3.1),容器重建后密钥换新,旧登录态全部失效。把配置目录持久化挂载(如 -v ./config:/config),首次生成后固定下来。
Q5:切 PostgreSQL 时应用起不来、一直重连?
检查 database.type 是否真的被覆盖成 postgres(环境变量写法 DT_DATABASE_TYPE,注意不是 DT_DATABASE.TYPE),五项连接参数是否齐全;数据库未就绪时程序每 500ms 重试、最多 31 次(约 15 秒),等数据库先起来再启动应用最稳。实测成功后 PostgreSQL 中自动建表 41 张(见 5.2)。
Q6:想限制谁能注册?
is_user_creation_disabled: true 关闭注册口(实测返回 403 User creation is disabled),或用 DONETICK_DISABLE_SIGNUP=true 环境变量等价生效;家庭多人共用推荐 single_circle_instance: true 单圆圈模式,成员经邀请加入。