多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

自托管 Todoist 替代 Conatus:能导入现有任务,docker-compose 就能跑

自托管 Todoist 替代 Conatus:能导入现有任务,docker-compose 就能跑 简介什么是 ConatusConatus是一个开源的自托管任务管理器适用于项目、循环任务、提醒和团队协作灵感源自Todoist。它可以帮助用户在一个安全可控的环境中以列表、看板或日历视图组织日常任务和个人项目数据完全掌握在自己手中。主要特点项目与组织支持通过项目、分区、标签和优先级来组织任务让工作结构清晰。循环任务与提醒可创建循环任务设置截止日期、到期时间和提醒支持直接在任务名称中输入日期、时间、时长和重复规则。协作与共享通过评论、文件附件和共享项目实现多人协作支持日历、列表或看板视图切换。Todoist 数据导入支持直接导入Todoist的任务数据降低迁移成本。API 与自动化提供版本化REST API/api/v1和Webhooks事件通知可通过API token集成第三方工具。MCP 支持提供独立的MCP服务器方便AI智能体直接管理任务。开源免费基于AGPL-3.0协议开源可免费使用和修改。应用场景个人任务管理个人用户可用它替代Todoist管理和跟踪日常待办、习惯与项目进度。家庭共享清单家庭成员可通过共享项目协作制定购物清单、家庭活动计划等。团队项目管理团队可通过评论、文件附件和看板视图管理迭代任务配合循环任务跟踪重复性工作。自动化与 AI 集成开发者可通过REST API、Webhooks和MCP协议接入CI流水线、通知机器人或AI助手。开发者测试开发人员可以快速搭建测试环境体验完整的任务管理API和前端功能。Conatus是一个功能全面、注重隐私的自托管Todoist替代品它把任务、循环工作和协作整合到一个你完全掌控的系统中。提供完整的Web端和REST API并支持通过MCP协议接入AI助手让自动化管理任务成为可能。安装在群晖上以 Docker 方式安装。本文写作时latest版本对应为1.0.0Conatus 采用多容器架构部署由dbPostgreSQL、minio对象存储、migrate、bootstrap初始化和引导、app主应用以及可选的backup、mcp等服务组成建议使用docker-compose进行部署可以自动处理服务间的依赖关系。docker-compose 安装1. 下载 Compose 文件和环境模板首先创建目录并下载官方提供的docker-compose.yml和.env.example# 新建文件夹 conatus 和 子目录mkdir-p/volume1/docker/conatus/{backups,data,mcp,minio}# 进入 conatus 目录cd/volume1/docker/conatus# 下载curl-Ohttps://raw.githubusercontent.com/nojusmorkunas/conatus/main/docker-compose.ymlcurl-oenv.txt https://raw.githubusercontent.com/nojusmorkunas/conatus/main/.env.example也可以不用下载直接复制老苏的env.txt和docker-compose.yml2. 编辑环境变量以下为完整的env.txt含中文注释# Compose 部署配置。 # CONATUS_VERSION 必须匹配一个已经发布的镜像版本标签 # 不要包含前面的 v。 # 例如GitHub Release v1.0.0 对应填写 1.0.0。 CONATUS_VERSIONlatest # Web 应用的宿主机端口。 # 容器内部监听端口为 3000。 CONATUS_PORT4399 # MCP 服务由 github.com/nojusmorkunas/conatus-mcp # 独立发布发布时间和主程序不同 # 因此 MCP 版本单独管理。 CONATUS_MCP_VERSIONlatest # 仅当从 fork 项目或其他镜像仓库部署时才需要修改这些值。 # CONATUS_IMAGEghcr.io/nojusmorkunas/conatus # CONATUS_MCP_IMAGEghcr.io/nojusmorkunas/conatus-mcp POSTGRES_USERapp POSTGRES_PASSWORDreplace-with-a-long-url-safe-password POSTGRES_DBapp # 当直接使用 npm 运行应用时使用。 # Docker Compose 会根据上面的 POSTGRES_* 配置 # 自动生成内部数据库连接地址。 DATABASE_URLpostgres://app:replace-with-a-long-url-safe-passwordlocalhost:5432/app # 当使用域名或反向代理时 # 两个值都应该设置为外部 HTTPS 地址。 # AUTH_URLhttps://tasks.example.com # PUBLIC_BASE_URLhttps://tasks.example.com # 身份认证密钥。使用 npx-auth-secret 命令生成。 # 老苏是用 penssl rand -hex 32 生成的 AUTH_SECRETgenerate-with-npx-auth-secret # 可选一次性管理员初始化。 # 在第一次执行 docker compose up 前设置这两个值。 # 当数据库为空时该任务会创建一个已验证的管理员账号。 # 第一次登录成功后删除这两个配置 # 并删除已经停止的 bootstrap 容器。 CONATUS_ADMIN_USERNAMEadmin CONATUS_ADMIN_PASSWORDreplace-with-a-long-random-password # 默认情况下注册模式为邀请制。 # 第一个注册账户会自动初始化服务器并成为管理员。 REGISTRATION_MODEinvite-only # 仅用于本地开发环境。 # 设置为 1 后 # - 禁用登录、注册、密码重置、邮件重新发送、错误报告等功能的频率限制 # - 开放所有人注册。 # # 注意 # 该配置不会根据 NODE_ENV 判断环境 # 因此不要在公网可访问的服务器上启用。 # CONATUS_DEV_MODE1 # S3 对象存储配置用于附件存储。 S3_ENDPOINTlocalhost S3_PORT9000 S3_ACCESS_KEYreplace-with-a-random-access-key S3_SECRET_KEYreplace-with-a-long-random-secret-key S3_BUCKETattachments # 邮件功能默认关闭。 # 只有以下三个配置全部填写后才会启用邮件功能。 # SMTP_HOSTmail.example.com # SMTP_PORT587 # SMTP_FROMConatus conatusexample.com # 可选接收 JSON 格式错误报告的远程接口地址。 # ERROR_WEBHOOK_URL # 可选远程 MCP sidecarMCP 辅助服务。 # 使用以下命令启动 # docker compose --profile mcp up --build # # 在 Settings设置中创建 TASKS_API_TOKEN。 # 对于支持通过 URL 连接的客户端推荐使用 OAuth。 # TASKS_API_TOKENtdm_replace_me # MCP_PUBLIC_URLhttps://mcp.example.com/mcp # MCP_OAUTH_PASSWORDgenerate-a-separate-long-random-password # MCP_ALLOWED_ORIGINShttps://your-ai-host.example # 静态备用配置 # 当客户端无法使用 OAuth 时 # 可以使用固定 Bearer Token 进行认证。 # MCP_BEARER_TOKENgenerate-a-long-random-token增加了中文注释记得要采用UTF-8格式保存只需要修改以下关键配置# 使用 latest 表示当前稳定版或指定版本号如 1.0.0 CONATUS_VERSION1.0.0 # Web 界面对外端口容器内部监听 3000 CONATUS_PORT4399 # 如果改了参数DATABASE_URL 也要相应的调整 POSTGRES_USERapp POSTGRES_PASSWORDconatus123 POSTGRES_DBapp # 认证密钥建议用较长随机字符串 AUTH_SECRETreplace-with-a-long-random-secret # 对象存储 S3 凭据MinIO S3_ACCESS_KEY7e609d7743b225544d4bc29877490b6b1c958709299d163ee9e9c6705682df26 S3_SECRET_KEYf7c61b439806e8b504abe8ef4b4be06b3710bafd98ab184a53846eb408a46b6e # 可选在空数据库上创建首个管理员 CONATUS_ADMIN_USERNAMEadmin CONATUS_ADMIN_PASSWORDlaosu123环境变量说明POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB用于配置 PostgreSQL 数据库的账号、密码和库名请使用强密码。S3_ACCESS_KEY/S3_SECRET_KEYMinIO 对象存储的凭据用于存放附件的持久化数据。CONATUS_ADMIN_USERNAME/CONATUS_ADMIN_PASSWORD首次在空数据库部署时用于初始化管理员账号登录后应将其移除。如果使用了域名或反向代理还需要设置AUTH_URL和PUBLIC_BASE_URL为外部HTTPS地址。3. 启动 Conatus以下为完整的docker-compose.yml核心配置示例含中文注释services:db:image:postgres:17-alpinecontainer_name:conatus-dbrestart:unless-stopped# ports:# - 127.0.0.1:${POSTGRES_PORT:-5432}:5432volumes:-./data:/var/lib/postgresql/data# 数据库数据持久化environment:POSTGRES_USER:${POSTGRES_USER:-app}POSTGRES_PASSWORD:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}POSTGRES_DB:${POSTGRES_DB:-app}healthcheck:test:[CMD-SHELL,pg_isready -U \$$POSTGRES_USER\ -d \$$POSTGRES_DB\]interval:5stimeout:5sretries:10start_period:10sminio:# MinIO stopped publishing to Docker Hub, so minio/minio no longer pulls.# Pinned because the console this file exposes on 9001 was dropped from# later releases.# image: quay.io/minio/minio:RELEASE.2025-04-22T22-12-26Zimage:chrislusf/seaweedfs:latestcontainer_name:conatus-miniorestart:unless-stopped# ports:# - 127.0.0.1:${MINIO_PORT:-9000}:9000# - 127.0.0.1:${MINIO_CONSOLE_PORT:-9001}:9001volumes:-./minio:/data# 对象存储数据持久化environment:MINIO_ROOT_USER:${S3_ACCESS_KEY:-minioadmin}MINIO_ROOT_PASSWORD:${S3_SECRET_KEY:-minioadmin}command:server /data--console-address :9001mailpit:profiles:[email-test]image:axllent/mailpitcontainer_name:conatus-mailpitrestart:unless-stoppedports:-1025:1025-8025:8025backup:image:postgres:17-alpinecontainer_name:conatus-backuprestart:unless-stoppedvolumes:-./backups:/backups# 备份数据持久化depends_on:db:condition:service_healthyenvironment:PGHOST:dbPGUSER:${POSTGRES_USER:-app}PGPASSWORD:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}PGDATABASE:${POSTGRES_DB:-app}BACKUP_INTERVAL:${BACKUP_INTERVAL:-86400}# 备份间隔默认每日一次BACKUP_KEEP:${BACKUP_KEEP:-7}# 保留备份份数默认 7entrypoint:[sh,-c]command:-|while true; do pg_dump -Fc -f /backups/app-$$(date -u %Y%m%dT%H%M%SZ).dump ls -1t /backups/app-*.dump | tail -n $$((BACKUP_KEEP 1)) | xargs -r rm -- sleep $$BACKUP_INTERVAL donemigrate:image:${CONATUS_IMAGE:-ghcr.io/nojusmorkunas/conatus}:${CONATUS_VERSION:-latest}-opscontainer_name:conatus-migratecommand:[npm,run,migrate]restart:nodepends_on:db:condition:service_healthyenvironment:DATABASE_URL:postgres://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}db:5432/${POSTGRES_DB:-app}bootstrap:image:${CONATUS_IMAGE:-ghcr.io/nojusmorkunas/conatus}:${CONATUS_VERSION:-latest}-opscontainer_name:conatus-bootstrapcommand:[npm,run,bootstrap]restart:nodepends_on:-migrateenvironment:DATABASE_URL:postgres://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}db:5432/${POSTGRES_DB:-app}CONATUS_ADMIN_USERNAME:${CONATUS_ADMIN_USERNAME:-}CONATUS_ADMIN_PASSWORD:${CONATUS_ADMIN_PASSWORD:-}app:image:${CONATUS_IMAGE:-ghcr.io/nojusmorkunas/conatus}:${CONATUS_VERSION:-latest}container_name:conatus-apprestart:unless-stoppeddepends_on:-db-migrate-bootstrapenvironment:DATABASE_URL:postgres://${POSTGRES_USER:-app}:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}db:5432/${POSTGRES_DB:-app}AUTH_SECRET:${AUTH_SECRET:?set AUTH_SECRET in .env}AUTH_URL:${AUTH_URL:-}PUBLIC_BASE_URL:${PUBLIC_BASE_URL:-}REGISTRATION_MODE:${REGISTRATION_MODE:-invite-only}# Local development only: disables rate limiting and opens registration.CONATUS_DEV_MODE:${CONATUS_DEV_MODE:-0}S3_ENDPOINT:minioS3_PORT:9000S3_ACCESS_KEY:${S3_ACCESS_KEY:?set S3_ACCESS_KEY in .env}S3_SECRET_KEY:${S3_SECRET_KEY:?set S3_SECRET_KEY in .env}S3_BUCKET:${S3_BUCKET:-attachments}SMTP_HOST:${SMTP_HOST:-}SMTP_PORT:${SMTP_PORT:-}SMTP_FROM:${SMTP_FROM:-}ERROR_WEBHOOK_URL:${ERROR_WEBHOOK_URL:-}ports:-${CONATUS_BIND_ADDRESS:-0.0.0.0}:${CONATUS_PORT:-4399}:3000# Optional per-user MCP proxy. Start with: docker compose --profile mcp up -d# Create a scoped tdm_ token in Settings before enabling this profile.mcp:profiles:[mcp]image:${CONATUS_MCP_IMAGE:-ghcr.io/nojusmorkunas/conatus-mcp}:${CONATUS_MCP_VERSION:-latest}container_name:conatus-mcprestart:unless-stoppeddepends_on:app:condition:service_healthyenvironment:TASKS_BASE_URL:http://app:3000TASKS_API_TOKEN:${TASKS_API_TOKEN:-tdm_configure_a_real_token_before_starting}MCP_HOST:0.0.0.0MCP_PORT:4398MCP_PUBLIC_URL:${MCP_PUBLIC_URL:-}MCP_OAUTH_PASSWORD:${MCP_OAUTH_PASSWORD:-}MCP_OAUTH_STORE_PATH:/data/oauth-store.jsonMCP_BEARER_TOKEN:${MCP_BEARER_TOKEN:-}MCP_ALLOWED_ORIGINS:${MCP_ALLOWED_ORIGINS:-http://localhost:4399}ports:-4398:3001volumes:-./mcp:/datahealthcheck:test:[CMD,wget,-qO-,http://127.0.0.1:4398/health]interval:30stimeout:5sretries:3start_period:10s可选MCP侧车服务用于接入AI助手在env.txt中设置token后运行docker compose --profile mcp up -d可启用。AI 助手 │ │ MCP ▼ ┌──────────────┐ │ MCP 侧车服务 │ └──────┬───────┘ │ ▼ ┌──────────────┐ │ 主应用 │ └──────────────┘执行下面的命令# 一键启动docker-compose--env-file env.txt up-d启动时需要拉取Conatus应用、操作工具、PostgreSQL和MinIO镜像完成后访问http://IP:4399即可。运行在浏览器中访问http://群晖IP:4399即可进入登录界面。使用env.txt中配置的CONATUS_ADMIN_USERNAME/CONATUS_ADMIN_PASSWORD登录管理员账号登录后从env.txt中移除CONATUS_ADMIN_USERNAME和CONATUS_ADMIN_PASSWORD这两项配置默认支持两种方式导入Todoist的数据使用Todoist的API Token或者备份的数据但老苏没用过Todoist只能自己新建先建Project再建Task可以根据需要添加需要的描述、优先级、重复、提醒、附件等API 调用从Preferences--API tokens创建API Token调用REST接口获取尚未完成的任务列表curl-HAuthorization: Bearer tdm_P9i382EHuTTWpAbUEc8wGJDxaNcQC0Zuhttp://192.168.0.197:4399/api/v1/tasks?completedfalseMCP默认情况下MCP服务并没有启动如果需要使用需要先启用env.txt中的相关参数然后再执行# 启动 mcp 服务docker-compose--env-file env.txt--profilemcp up-d如果一切正常应该能看到conatus-mcp服务但是老苏没搞定从日志看需要Issuer URL must be HTTPS但老苏手上的freenom域名都过期了注意事项数据库备份升级前务必先备份数据库某些数据库迁移需要恢复才能安全回滚。可使用内置backup服务自动备份默认每日执行并保留最新7份。初始管理员只有在数据库为空时Bootstrap进程才会创建管理员首次登录后请及时移除env.txt中的相应配置。端口冲突默认宿主端口为4399可通过修改CONATUS_PORT来更换数据库、MinIO没有对外暴露端口。反向代理与 HTTPS若使用域名或反向代理必须设置AUTH_URL和PUBLIC_BASE_URL为外部HTTPS地址。安全建议默认注册模式为邀请制invite-only请使用强密码并妥善保管API Token仅在创建时显示一次。切勿在生产环境中启用CONATUS_DEV_MODE1它会关闭限流并开放注册。参考文档nojusmorkunas/conatus: A self-hosted task manager for projects, recurring work, reminders, collaboration and automation. Inspired by Todoist.地址https://github.com/nojusmorkunas/conatusConatus 官方主页地址https://useconatus.comnojusmorkunas/conatus-mcp: Conatus 的 MCP 服务器提供 stdio 与远程 Streamable HTTP 传输供 MCP 兼容的 AI 智能体管理任务地址https://github.com/nojusmorkunas/conatus-mcp
返回列表