Ubuntu 22.04 安装 Donetick 0.1.83 指南

在 Ubuntu 22.04 上从零安装 Donetick v0.1.83 的完整指南:官方二进制+systemd 与 Docker Compose 双方案实测,含配置、升级降级、卸载与常见故障排障。

Donetick任务管理自托管2026/10/23

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.gzLinux x86_64最常用的服务器架构,本文实测对象
donetick_Linux_arm64.tar.gzLinux ARM64树莓派 4/5(64 位系统)、ARM 云主机
donetick_Linux_armv6.tar.gzLinux ARMv6树莓派 1/Zero
donetick_Linux_armv7.tar.gzLinux ARMv732 位 ARM 板卡
donetick_Darwin_x86_64.tar.gzmacOS Intel桌面自用
donetick_Darwin_arm64.tar.gzmacOS 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 -fJSON 格式日志输出到 stdout,由 systemd 收集
二进制/opt/donetick/donetick单文件,内嵌前端资源

常用环境变量(均可写进 systemd 单元 Environment= 或 Compose environment:,实测有效):

变量作用默认行为
DT_ENV配置文件选择:selfhosted/local/prod/r2缺省按 local 找 config/local.yaml
DT_SQLITE_PATHSQLite 数据库文件路径未设置时落在工作目录下的 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

十一、参考链接

  1. 官方仓库:https://github.com/donetick/donetick
  2. Releases 页(版本与安装包):https://github.com/donetick/donetick/releases
  3. v0.1.83 发布页:https://github.com/donetick/donetick/releases/tag/v0.1.83
  4. Docker Hub:https://hub.docker.com/r/donetick/donetick
  5. 官方 README(环境变量与 Compose 示例):https://github.com/donetick/donetick#readme
  6. 本专栏认知篇:《Donetick 0.1.83 介绍与选型指南》
  7. 本专栏配置篇:《Donetick 0.1.83 配置参数详解》
  8. 本专栏接口篇:《Donetick 0.1.83 API 使用详解》