Ubuntu 22.04 安装 Donetick 0.1.83 指南
在 Ubuntu 22.04 上从零安装 Donetick v0.1.83 的完整指南:官方二进制+systemd 与 Docker Compose 双方案实测,含配置、升级降级、卸载与常见故障排障。
Ubuntu 22.04 安装 Donetick 0.1.83 指南
目标:在 Ubuntu 22.04 服务器上从零安装 Donetick v0.1.83 任务与家务分工管理系统,覆盖官方二进制 + systemd 托管与 Docker Compose 两种安装方案、配置、升级、卸载与常见故障排障。全部命令与回显已在 Ubuntu 22.04.5 LTS x86_64 + Donetick v0.1.83 实测通过。
一、环境信息
本文所有命令与输出均在以下环境实测采集:
- 操作系统:Ubuntu 22.04.5 LTS x86_64(
cat /etc/os-release实测,内核自带 systemd 249) - Donetick 版本:v0.1.83(GitHub Releases 最新稳定版,查询日期 2026-10-23)
- 安装形态:方案 A 为官方发布包二进制 + systemd 托管(推荐),方案 B 为 Docker Compose
- 服务端口:2021(HTTP,同时服务 Web 界面与 API,接口全景见《Donetick 0.1.83 API 使用详解》)
- 关键路径(方案 A):程序目录
/opt/donetick/、配置文件/opt/donetick/config/selfhosted.yaml、数据库/var/lib/donetick/donetick.db、服务单元/etc/systemd/system/donetick.service - 运行账户:专用系统用户
donetick(uid=999,实测) - 二进制体积:122301268 字节(约 117 MB,内嵌前端静态资源);空载常驻内存约 26.7 MB
二、前置条件
安装前需确认服务器满足以下条件,逐项给出核对命令与实测回显。
1. 操作系统与架构。Donetick 官方发布包覆盖 Linux x86_64/arm64/armv6/armv7 与 macOS,本文以 Ubuntu 22.04 x86_64 为准:
cat /etc/os-release | head -2 && uname -m
实测输出:
PRETTY_NAME="Ubuntu 22.04.5 LTS"
NAME="Ubuntu"
x86_64
2. systemd 可用。方案 A 依赖 systemd 托管服务(Ubuntu 22.04 服务器默认具备):
systemd --version | head -1
实测输出:
systemd 249 (249.11-0ubuntu3.23)
3. 基础工具。wget、curl、sha256sum 用于下载与校验,Ubuntu 22.04 默认自带;缺失时先补齐:
sudo apt update && sudo apt install -y wget curl ca-certificates
4. 端口 2021 未被占用。默认配置监听 2021 端口,确认无冲突(被占用时的改法见「九、常见问题」):
ss -ltn | grep 2021 || echo "2021 端口空闲"
实测输出:
2021 端口空闲
5. 磁盘空间。二进制约 117 MB,加上 SQLite 数据库与日志,预留 1 GB 以上即可。
⚠️ 注意:方案 A 需要 systemd 的 Linux 真机或虚拟机;容器内默认无 systemd,不适合该方案的验证环境。
三、版本选型说明
Donetick 遵循「单主干 + 持续发布」模式,安装时应选择 GitHub Releases 的最新稳定版。官方发布资产共 6 个安装包 + 1 个校验文件(v0.1.83 实查,查询日期 2026-10-23):
| 发布资产 | 平台/架构 | 说明 |
|---|---|---|
| donetick_Linux_x86_64.tar.gz | Linux x86_64 | 最常用的服务器架构,本文实测对象 |
| donetick_Linux_arm64.tar.gz | Linux ARM64 | 树莓派 4/5(64 位系统)、ARM 云主机 |
| donetick_Linux_armv6.tar.gz | Linux ARMv6 | 树莓派 1/Zero |
| donetick_Linux_armv7.tar.gz | Linux ARMv7 | 32 位 ARM 板卡 |
| donetick_Darwin_x86_64.tar.gz | macOS Intel | 桌面自用 |
| donetick_Darwin_arm64.tar.gz | macOS Apple Silicon | 桌面自用 |
| donetick_0.1.83_checksums.txt | 校验文件 | 全部安装包的 SHA256 |
选型解读:服务器/NAS 部署按 CPU 架构选对应 Linux 包;每包内含 donetick 二进制与示例配置,无需额外运行时依赖(Go 静态编译,单文件运行)。v0.1.83 版本号仍处 0.x,升级可能带行为变化,升级前务必备份数据库(见「八、升级、降级与多版本管理」)。
四、方案 A:官方二进制 + systemd 托管安装(推荐)
4.1 方案说明
这是 Donetick 官方最直接的安装路线:下载 GitHub Releases 发布包,解压到 /opt/donetick,用专用系统用户运行,并以 systemd 单元托管开机自启。全程约 5 分钟,不依赖 Docker。
4.2 下载与校验
先下载 v0.1.83 发布包与官方校验文件:
cd /tmp
wget https://github.com/donetick/donetick/releases/download/v0.1.83/donetick_Linux_x86_64.tar.gz
wget https://github.com/donetick/donetick/releases/download/v0.1.83/donetick_0.1.83_checksums.txt
计算安装包 SHA256 并与官方校验文件比对:
sha256sum donetick_Linux_x86_64.tar.gz
grep Linux_x86_64 donetick_0.1.83_checksums.txt
实测输出(两行哈希一致即校验通过):
b6e5deae6af9ec43f0437a472117c17c85bd1bfaa1d7e53bbba5dbbbd0580299 donetick_Linux_x86_64.tar.gz
b6e5deae6af9ec43f0437a472117c17c85bd1bfaa1d7e53bbba5dbbbd0580299 donetick_Linux_x86_64.tar.gz
确认包内容结构(一个二进制 + 两份配置):
tar -tzf donetick_Linux_x86_64.tar.gz
实测输出:
config/local.yaml
config/selfhosted.yaml.example
donetick
4.3 安装步骤
创建专用系统用户(不可登录,仅用于运行服务),并建立程序与数据目录:
sudo useradd --system --home /opt/donetick --shell /usr/sbin/nologin donetick
sudo mkdir -p /opt/donetick /var/lib/donetick
解压发布包到程序目录,并从官方示例复制出运行配置:
sudo tar -xzf donetick_Linux_x86_64.tar.gz -C /opt/donetick
sudo cp /opt/donetick/config/selfhosted.yaml.example /opt/donetick/config/selfhosted.yaml
目录所有权整体交给 donetick 用户:
sudo chown -R donetick:donetick /opt/donetick /var/lib/donetick
核对安装结果:
id donetick
ls -la /opt/donetick/
实测输出:
uid=999(donetick) gid=999(donetick) groups=999(donetick)
total 119464
drwxr-x--- 4 donetick donetick 4096 Oct 22 18:33 .
drwxr-xr-x 1 root root 4096 Oct 22 18:32 ..
drwxr-xr-x 2 donetick donetick 4096 Oct 22 18:33 config
-rwxr-xr-x 1 donetick donetick 122301268 Oct 18 13:47 donetick
4.4 配置文件
编辑 /opt/donetick/config/selfhosted.yaml,首次安装至少要改 jwt.secret。全部参数的逐项说明见《Donetick 0.1.83 配置参数详解》。先生成一个随机密钥:
openssl rand -base64 32
实测输出(每次生成结果不同,取你自己的一次性结果):
Lp/XTkpWMCLm5nmelRZDXe5Q+NSXvSP89D4hAbD0h8g=
将配置文件中 jwt.secret 的占位值替换为生成的随机串(演示环境统一用测试值 q1w2e3r4q1w2e3r4q1w2e3r4q1w2e3r4,生产必须随机生成):
jwt:
secret: "q1w2e3r4q1w2e3r4q1w2e3r4q1w2e3r4"
session_time: 168h # 7 days
max_refresh: 1440h # 60 days
关键项说明:
jwt.secret:登录态签名密钥,必须 ≥32 字符,且不能命中程序内置的弱密钥黑名单(如示例文件自带的change_this_to_a_...占位值,不改直接启动会panic拒绝运行,实测报错见「九、常见问题」);jwt.session_time:access_token 有效期,默认示例为 168h(7 天);jwt.max_refresh:refresh_token 最长可刷新窗口,1440h(60 天);database.type:默认sqlite,单文件零依赖;家庭规模直接用 SQLite,更大并发再切 PostgreSQL;server.port:默认 2021;- 其余参数(通知、OAuth2、实时推送等)在示例文件中均有注释说明。
数据库文件路径不在该 YAML 中,由 systemd 单元的环境变量 DT_SQLITE_PATH 指定(见 4.5),默认落到 /var/lib/donetick/donetick.db。
4.5 systemd 托管
创建服务单元 /etc/systemd/system/donetick.service(内容实测):
sudo tee /etc/systemd/system/donetick.service > /dev/null <<'EOF'
[Unit]
Description=Donetick Task & Chore Management Server
Documentation=https://github.com/donetick/donetick
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=donetick
Group=donetick
WorkingDirectory=/opt/donetick
Environment=DT_ENV=selfhosted
Environment=DT_SQLITE_PATH=/var/lib/donetick/donetick.db
Environment=TZ=Asia/Shanghai
ExecStart=/opt/donetick/donetick
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
单元关键项说明:
User/Group=donetick:以专用低权限用户运行,不使用 root;WorkingDirectory=/opt/donetick:必须正确,程序按「工作目录下的config/」查找配置文件,DT_ENV=selfhosted时加载config/selfhosted.yaml;Environment=DT_ENV=selfhosted:决定加载哪份配置(local/prod/selfhosted/r2四选一,自托管固定selfhosted);Environment=DT_SQLITE_PATH=...:SQLite 数据库文件绝对路径;Restart=on-failure+RestartSec=5:异常退出 5 秒后自动拉起。
⚠️ 注意:每行
Environment=只设置一个变量;如需覆盖端口,追加一行Environment=DT_SERVER_PORT=2031(实测有效,见「九、常见问题」)。
加载单元并设置开机自启、立即启动:
sudo systemctl daemon-reload
sudo systemctl enable donetick
sudo systemctl start donetick
4.6 验证
逐项确认服务状态、监听端口与 HTTP 健康:
systemctl is-enabled donetick
systemctl is-active donetick
systemctl status donetick --no-pager -l | head -12
实测输出:
enabled
active
● donetick.service - Donetick Task & Chore Management Server
Loaded: loaded (/etc/systemd/system/donetick.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2026-10-22 21:15:02 UTC; 5h 9min ago
Docs: https://github.com/donetick/donetick
Main PID: 3565 (donetick)
Tasks: 13 (limit: 629145)
Memory: 41.8M
CPU: 717ms
CGroup: /system.slice/donetick.service
└─3565 /opt/donetick/donetick
健康检查接口实测:
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:2021/api/v1/health
实测输出:
200
数据库文件已按 DT_SQLITE_PATH 落盘:
ls -la /var/lib/donetick/
实测输出:
total 524
drwxr-xr-x 2 donetick donetick 4096 Oct 23 00:34 .
drwxr-xr-x 1 root root 4096 Oct 22 18:35 ..
-rw-r--r-- 1 donetick donetick 520192 Oct 23 00:34 donetick.db
注册首个账号。浏览器访问 http://<服务器IP>:2021 进入注册页;也可以直接用注册接口验证(首个注册用户自动创建自己的 Circle 圆圈并成为管理员)。用 curl 实测:
curl -s -w '\n[%{http_code}]\n' -X POST http://localhost:2021/api/v1/auth/ \
-H 'Content-Type: application/json' \
-d '{"username":"wangli","password":"q1w2e3r4","email":"wangli@example.com","displayName":"王丽"}'
实测输出:
{}
[201]
字段要求(实测约束):username 4–20 字符、password 至少 8 字符、email 必填且需合法格式。注册成功后用同账号登录验证:
curl -s -X POST http://localhost:2021/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"username":"wangli","password":"q1w2e3r4"}'
实测输出(JWT 串过长,节选首尾):
{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3OTMzMjczMDQsImlkIjoid2FuZ2xpIiwib3JnX2lhdCI6MTc5MjcyMjUwNH0.SwHdmVKxH41p_JwrUPdlRRlQ4sNHKgtX5fOxZVOMMMY","refresh_token":"d0a55a2a9cc0646d0776daa2f22b261e19ea912b0b1b2cffa1a0647594b48e51","access_token_expiry":"2026-10-30T02:28:24.008049364Z","refresh_token_expiry":"2026-12-22T02:28:24.008049802Z","token_type":"Bearer","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...","expire":"2026-10-30T10:28:24.002063157+08:00"}
拿到 access_token 即安装完成。日常查日志用 journalctl -u donetick -f。
五、方案 B:Docker Compose 安装
5.1 方案说明
官方维护 donetick/donetick 镜像(Docker Hub 拉取量 2M+),适合已用 Docker 管理服务的机器。数据与配置通过 bind mount 落到宿主机目录,升级只需换镜像 tag 重建。
5.2 部署步骤
建立部署目录:
sudo mkdir -p /opt/donetick-compose/{data,config}
创建 docker-compose.yml:
sudo tee /opt/donetick-compose/docker-compose.yml > /dev/null <<'EOF'
name: donetick-0183-stack
services:
donetick:
image: donetick/donetick:v0.1.83
restart: unless-stopped
ports:
- 2021:2021
volumes:
- ./data:/donetick-data
- ./config:/config
environment:
- DT_ENV=selfhosted
- DT_SQLITE_PATH=/donetick-data/donetick.db
- TZ=Asia/Shanghai
healthcheck:
test: wget --no-verbose --tries=1 --spider http://localhost:2021/api/v1/health || exit 1
start_period: 1m
timeout: 5s
interval: 1m
retries: 3
EOF
⚠️ 注意:Compose 项目名不允许点号,
name写donetick-0183-stack这类无点号形式(实测donetick-0.1.83-stack会被自动降级为donetick-0183-stack,容器名随之变化,脚本引用容器名时容易踩坑)。
把配置文件放进 config/(同样以官方示例为底、替换 jwt.secret,密钥生成方法见 4.4):
cd /opt/donetick-compose
wget -O config/selfhosted.yaml https://raw.githubusercontent.com/donetick/donetick/v0.1.83/config/selfhosted.yaml.example
sed -i 's/change_this_to_a_secure_random_string_32_characters_long/q1w2e3r4q1w2e3r4q1w2e3r4q1w2e3r4/' config/selfhosted.yaml
启动并确认健康状态:
docker compose up -d
docker compose ps
实测输出(首次拉镜像约 30 秒,等待健康检查转 healthy):
Network donetick-0183-stack_default Created
Container donetick-0183-stack-donetick-1 Created
Container donetick-0183-stack-donetick-1 Started
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
donetick-0183-stack-donetick-1 donetick/donetick:v0.1.83 "/donetick" donetick 3 minutes ago Up 3 minutes (healthy) 0.0.0.0:2021->2021/tcp, [::]:2021->2021/tcp
5.3 验证与数据持久化
健康检查与注册登录验证方法与方案 A 相同(http://<服务器IP>:2021,接口路径一致)。
数据持久化实测:建一条任务 → 重启整个栈 → 任务仍在,即证明 SQLite 数据经 bind mount 落盘。创建任务:
TOKEN=$(curl -s -X POST http://localhost:2021/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"username":"wangli","password":"q1w2e3r4"}' | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p')
curl -s -X POST http://localhost:2021/api/v1/chores/ \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"快递代取","frequencyType":"weekly","frequency":1,"isActive":true,"assignStrategy":"no_assignee"}'
实测输出(任务 id=2 创建成功):
{"res":2,"warnings":["priority not provided, defaulting to 0","isPrivate not provided, defaulting to false"]}
重启并复查:
docker compose restart
sleep 30
docker compose ps
实测输出:
Container donetick-0183-stack-donetick-1 Restarting
Container donetick-0183-stack-donetick-1 Started
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
donetick-0183-stack-donetick-1 donetick/donetick:v0.1.83 "/donetick" donetick 5 hours ago Up 6 seconds (health: starting) 0.0.0.0:2021->2021/tcp, [::]:2021->2021/tcp
重启后查询 id=2 的任务,实测数据完整返回:
{"res":{"completionActions":null,"id":2,"name":"快递代取","frequencyType":"weekly","frequency":1,"frequencyMetadata":null,"nextDueDate":null,"isRolling":false,"assignedTo":null,"assignees":[],"assignStrategy":"no_assignee","isActive":true,...}}
宿主机数据目录实测:
/stack/data/
└── donetick.db (520192 字节)
六、方案对比与选择建议
两方案实测对照:
| 维度 | 方案 A:二进制 + systemd | 方案 B:Docker Compose |
|---|---|---|
| 安装来源 | GitHub Releases 发布包 | Docker Hub 镜像 |
| 是否需联网 | 需要(下载发布包) | 需要(拉取镜像) |
| 进程托管 | systemd(开机自启/崩溃拉起) | Compose restart: unless-stopped |
| 健康检查 | 自行用 curl 验证 | 内置 healthcheck(docker compose ps 可见 healthy) |
| 升级方式 | 下载新包替换二进制 | 改镜像 tag 后 up -d |
| 数据位置 | /var/lib/donetick/donetick.db | 部署目录 data/donetick.db |
| 额外依赖 | 无(单二进制) | Docker Engine + Compose 插件 |
选择建议:装在干净的服务器/虚拟机上追求最简依赖选方案 A;机器上已有 Docker 生态、习惯用 Compose 统一编排的选方案 B。两方案数据结构完全一致(同一个 SQLite 库文件),迁移时直接拷贝 donetick.db 即可互换。
七、配置说明
安装后的日常配置入口与关键路径(方案 A 为准,方案 B 对应挂载目录内同名文件):
| 对象 | 路径/命令 | 说明 |
|---|---|---|
| 主配置文件 | /opt/donetick/config/selfhosted.yaml | 由 DT_ENV 决定加载哪份(selfhosted/local/prod/r2) |
| 服务单元 | /etc/systemd/system/donetick.service | 改环境变量后需 daemon-reload |
| SQLite 数据库 | /var/lib/donetick/donetick.db | 由 DT_SQLITE_PATH 指定 |
| 日志 | journalctl -u donetick -f | JSON 格式日志输出到 stdout,由 systemd 收集 |
| 二进制 | /opt/donetick/donetick | 单文件,内嵌前端资源 |
常用环境变量(均可写进 systemd 单元 Environment= 或 Compose environment:,实测有效):
| 变量 | 作用 | 默认行为 |
|---|---|---|
DT_ENV | 配置文件选择:selfhosted/local/prod/r2 | 缺省按 local 找 config/local.yaml |
DT_SQLITE_PATH | SQLite 数据库文件路径 | 未设置时落在工作目录下的 donetick.db |
DT_SERVER_PORT | 覆盖监听端口 | 未设置时用配置文件的 server.port(2021) |
DT_JWT_SECRET | 覆盖 JWT 密钥 | 未设置时读配置文件 jwt.secret |
TZ | 时区 | 未设置时程序内部强制 UTC |
配置文件中每个参数在官方示例内均有行内注释,修改前先读对应注释段。
八、升级、降级与多版本管理
升级。Donetick 无内置升级命令,标准做法是「备份数据库 → 下载新版发布包 → 替换二进制 → 重启」:
sudo systemctl stop donetick
cp /var/lib/donetick/donetick.db /var/lib/donetick/donetick.db.bak-$(date +%F)
cd /tmp && wget https://github.com/donetick/donetick/releases/download/v<新版本号>/donetick_Linux_x86_64.tar.gz
sudo tar -xzf donetick_Linux_x86_64.tar.gz -C /opt/donetick
sudo chown donetick:donetick /opt/donetick/donetick
sudo systemctl start donetick
新版首次启动会自动执行数据库迁移(实测启动日志可见 Applying migration: ... 序列,例如 20260511_backfill_sync_versions_for_existing_data 等),无需手动干预。升级后用 4.6 的方法验证健康状态。
降级。保留旧版发布包,出现问题时反向替换:
sudo systemctl stop donetick
sudo tar -xzf donetick_Linux_x86_64-v旧版.tar.gz -C /opt/donetick
sudo systemctl start donetick
⚠️ 注意:若新版已执行过数据库迁移,直接降级二进制可能遇到新表/新列不被旧版识别的问题,此时用升级前备份
donetick.db.bak-*恢复数据库再启动旧版。
多版本管理。将各版本发布包存放在 /opt/donetick/releases/ 下(如 v0.1.83/、v0.1.82/),用符号链接切换当前版本,ExecStart 指向固定链接路径,回滚只需改链接指向并重启。
九、常见问题(FAQ)
Q1:启动即失败,日志报 SECURITY ERROR: JWT secret is too weak?
这是 v0.1.83 的强校验机制:jwt.secret 少于 32 字符、或命中内置弱密钥黑名单(包括官方示例文件自带的 change_this_to_a_secure_random_string_32_characters_long 占位值)都会拒绝启动。实测直接用示例文件启动的报错:
🚨 SECURITY ERROR: JWT secret is too weak: 'change_this_to_a_secure_random_string_32_characters_long' is not allowed
不设任何配置时的另一形态:
🚨 SECURITY ERROR: JWT secret must be at least 32 characters long, got 0 characters
解决方案:openssl rand -base64 32 生成随机串替换 jwt.secret(见 4.4),或用环境变量 DT_JWT_SECRET 注入。
Q2:2021 端口被占用,如何换端口?
在 systemd 单元追加一行 Environment=DT_SERVER_PORT=2031,daemon-reload 后重启服务。实测:2031 端口健康检查返回 200,且不影响同机其他实例(另一实例监听 2021 同时返回 200):
probe2031=200
probe2021=200
DT_SQLITE_PATH 指向不同文件即可双实例并存。
Q3:日志里出现 Error creating bot: Post "https://api.telegram.org/bot/getMe": ... connection refused?
无害。这是未配置 Telegram 通知令牌时程序仍尝试初始化 Bot 的提示,不影响任何功能;配置 telegram.token 后消失,或忽略即可。
Q4:注册接口返回 403 {"error":"User creation is disabled"}?
配置文件 is_user_creation_disabled: true 或环境变量 DONETICK_DISABLE_SIGNUP=true 会关闭注册入口(SSO-only 场景配合 disable_password_auth: true 使用)。家庭实例放开注册即可;若要控制人数,改用邀请成员的方式在 Circle 内添加。
Q5:忘记密码怎么办?
配置 email.* 邮件参数并将 email.log_raw_url: true(示例默认已开)后,通过登录页「忘记密码」触发 POST /api/v1/auth/reset,重置链接会同时打印到服务日志;未配邮件时可直接在日志里找到重置 URL 完成改密。
Q6:donetick --version 没有版本输出?
实测该二进制不支持 --version 参数,任何参数都会直接进入配置加载流程。版本以下载的发布包版本为准(文件名含 v0.1.83),线上版本可通过对比二进制 SHA256 与 Release 页校验文件确认。
十、卸载与清理
方案 A 完整卸载(数据备份后执行):
sudo systemctl stop donetick
sudo systemctl disable donetick
sudo rm /etc/systemd/system/donetick.service
sudo systemctl daemon-reload
sudo rm -rf /opt/donetick /var/lib/donetick
sudo userdel donetick
方案 B 卸载:
cd /opt/donetick-compose
docker compose down
cd / && sudo rm -rf /opt/donetick-compose
十一、参考链接
- 官方仓库:https://github.com/donetick/donetick
- Releases 页(版本与安装包):https://github.com/donetick/donetick/releases
- v0.1.83 发布页:https://github.com/donetick/donetick/releases/tag/v0.1.83
- Docker Hub:https://hub.docker.com/r/donetick/donetick
- 官方 README(环境变量与 Compose 示例):https://github.com/donetick/donetick#readme
- 本专栏认知篇:《Donetick 0.1.83 介绍与选型指南》
- 本专栏配置篇:《Donetick 0.1.83 配置参数详解》
- 本专栏接口篇:《Donetick 0.1.83 API 使用详解》