为什么还需要另一个待办 App
市面上待办工具多到数不清——Todoist、微软 To-Do、Notion、TickTick……选一个看起来不难。但这些工具有一个共同问题:你的任务数据存在别人服务器上。数据迁移、隐私、付费墙,每个都是潜在隐患。
自部署待办系统的需求一直在。很多人试过 Memos,但它只是一个轻量备忘录,没有「进行中」「已完成」这类状态字段。Nextcloud Tasks 能做,但需要部署一整套 Nextcloud 生态,太重了。OpenProject 更偏项目管理,对个人待办来说大炮打蚊子。
Vikunja 卡在了一个刚好的位置:该有的都有,不该有的不乱加。
Vikunja 是什么
Vikunja 是一个开源的(AGPLv3)待办管理平台,Go + Vue 构建,单二进制部署。原生支持四种视图——列表、甘特图、看板、表格,子任务、标签、优先级、提醒、重复任务全部内置。
我个人最看重的两个特性是 CalDAV 手机同步 和 完整的 REST API,前者解决移动端的问题,后者解决自动化的问题。
对比下同类自部署方案:
| 方案 | 状态跟踪 | 手机同步 | 部署复杂度 | 项目规模 |
|---|---|---|---|---|
| Vikunja | ✅ 原生 | ✅ CalDAV | 低(单容器) | 个人到小团队 |
| Nextcloud Tasks | ✅ | ✅ | 高 | 需要完整 Nextcloud |
| Taskwarrior | ✅ | ❌ | 中等(CLI) | 纯 CLI 用户 |
| OpenProject | ✅ | ⚠️ 有限 | 高 | 团队项目管理 |
Docker Compose 部署
最新版 Vikunja 已经把 API 和前端合并为一个镜像,不再需要 nginx sidecar 架构。一个 docker-compose.yml 文件就够了:
services:
vikunja:
image: vikunja/vikunja
environment:
VIKUNJA_SERVICE_PUBLICURL: https://todo.yourdomain.com
VIKUNJA_DATABASE_HOST: db
VIKUNJA_DATABASE_PASSWORD: changeme
VIKUNJA_DATABASE_TYPE: postgres
VIKUNJA_DATABASE_USER: vikunja
VIKUNJA_DATABASE_DATABASE: vikunja
VIKUNJA_SERVICE_SECRET: generate-a-random-secret-here
VIKUNJA_SERVICE_ENABLEREGISTRATION: false
ports:
- 3456:3456
volumes:
- ./files:/app/vikunja/files
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: changeme
POSTGRES_USER: vikunja
volumes:
- ./db:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -h localhost -U vikunja"]
interval: 5s
start_period: 30s

注意几个配置细节:
VIKUNJA_SERVICE_PUBLICURL必须填公网 URL,不能写内网 IP。这个值影响 CalDAV 同步和链接分享,填错了后面修起来很麻烦。VIKUNJA_SERVICE_SECRET是 JWT 签名密钥,用openssl rand -base64 32生成一个随机字符串。VIKUNJA_SERVICE_ENABLEREGISTRATION: false关闭开放注册,所有人必须通过管理员创建帐号。做自部署的应该都有这个安全意识。- 数据库用 PostgreSQL 16,也可以选 MySQL 或 SQLite,但 PostgreSQL 最稳定。
如果想用 docker run 而不是 Compose,把上面的环境变量和端口映射搬到 -e 和 -p 参数里就行。Compose 的好处是升级时只需换 tag 再 docker compose up -d。
用户管理
Vikunja 默认没有管理员账号,需要在容器内创建。这种设计比默认 admin/admin 然后让用户改密码更安全,但也意味着部署后多一步操作:
docker exec vikunja-vikunja-1 /app/vikunja/vikunja user create \
-e admin@example.com \
-p <your-strong-password> \
-u adminusername
如果想给自动化脚本用一个独立账号,同样的命令跑一次就行。API Token 在 Web UI 里生成,也可以通过 CLI 获取。
公网访问
自部署的痛点之一是公网访问。Vikunja 本身只是一个监听 3456 端口的服务,怎么让它在外网可用,取决于你的网络环境。
几种主流方案:
Cloudflare Tunnel(推荐)
不暴露任何端口,安全性最高。在另一台机器上跑 cloudflared 容器,ingress 规则指向 localhost:3456。Cloudflare 的 CDN 还能起到加速作用。缺点是依赖 Cloudflare 的服务。
反向代理 + DDNS
如果你有公网 IP,用 Nginx/Caddy/Traefik 反向代理到本机 3456,配合 DDNS 绑定域名。控制力更强,不受限于 Cloudflare,但需要操心防火墙、HTTPS 证书续期、端口暴露的安全风险。
Tailscale / WireGuard
纯内网访问,最安全但只适合自用。如果只是自己用不分享给别人,这是最简单的方案——连域名都不需要。
我踩过的一个坑:首次部署 PUBLICURL 只填了内网 IP,结果 CalDAV 同步一直连不上,Web UI 里的共享链接也打不开。修改为域名后一切正常。
CalDAV 手机同步
这是 Vikunja 区别于大多数自部署待办系统的核心卖点——通过标准 CalDAV 协议直接同步到手机原生待办 App。
Android 上推荐 Tasks.org,一款开源待办 App,原生支持 CalDAV:
- 安装 Tasks.org(Google Play / F-Droid)
- 设置 → 同步 → 添加账户 → CalDAV
- URL 填你的 Vikunja 地址(
https://todo.yourdomain.com),用户名和密码用 Vikunja 的登录凭据 - App 自动通过
/.well-known/caldav发现目录
同步完成后,手机上创建的任务会在 Vikunja Web UI 出现,反之亦然。

有一个已知的坑:CalDAV 协议不会保留子任务的层级关系。如果重度依赖子任务,建议主任务在 Web UI 管理,手机端只处理顶层任务。Tasks.org 社区有人提过这个 issue,但短期内不会有解决方案。
REST API 和自动化
Vikunja 内置了完整的 REST API,Swagger 文档挂在 https://todo.yourdomain.com/api/v1/docs,部署完成就能打开。
几个常用的操作:
# 列出项目
curl -H "Authorization: Bearer <token>" \
https://todo.yourdomain.com/api/v1/projects
# 创建任务
curl -X PUT -H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"title": "调研下周部署方案"}' \
https://todo.yourdomain.com/api/v1/projects/1/tasks
这个 API 可以接很多自动化场景:RSS 订阅自动创建任务、n8n 工作流推送、Home Assistant 联动、甚至定时脚本检查新任务并自动处理。

我个人用它做 AI Agent 的任务队列——Agent 扫描 Vikunja 的新任务,自动执行并更新状态。这个组合让「自部署」从一个运维动作变成了工作流基础设施。
踩坑总结
| 问题 | 原因 | 解决 |
|---|---|---|
| CalDAV 连不上 | PUBLICURL 用了内网 IP | 改为 https://todo.domain.com |
| 浏览器一直加载旧页面 | Service Worker 缓存了前端 | 清除 Service Worker 或反向代理加版本号 |
| Docker Hub 拉取镜像很慢 | Docker Hub 匿名限流 | 用 hub.rat.dev 镜像或登录后拉取 |
| CalDAV 子任务层级丢失 | CalDAV 协议限制 | 主任务和子任务分开管理 |
| CORS 报错 | 反向代理未配置跨域头 | 在代理层加上 CORS 响应头 |
这些坑大部分是在部署后三天内遇到的。最有价值的教训是第一条——PUBLICURL 这个配置看起来不紧急,但漏掉之后 CalDAV、链接分享、Webhook 全部受影响,排查一圈才发现是它。
什么时候值得上自部署待办
如果你只是记几件杂事,A4 纸比任何一个待办 App 都快。如果你用 Todoist 已经满足需求且不在乎数据存在哪,没必要折腾。
自部署 Vikunja 最合适的场景是:你已经有服务器在跑了,需要一个管线式的任务系统跟你的自动化脚本、Agent 或者团队成员协同。Vikunja 提供的 REST API + CalDAV 双通道,让任务系统和外部世界的连接非常自然。
它不是 Todoist 的平替——它解决的是不同的需求。