内容提要
作者因Twikoo功能冗余,自研并开源了极简评论系统Ecoku。该系统用Go编写、Docker部署、SQLite存储,支持多站点,仅保留纯文本评论,无Markdown、账号、点赞和审核,匿名发言只需昵称,不存IP和邮箱,内置人机验证与Telegram、邮件通知,并支持从Twikoo迁移数据。
延伸解读
极简设计的取舍与适用场景
Ecoku 明确舍弃了 Markdown、账号体系、点赞和审核队列,只保留纯文本评论。这种设计降低了 XSS 风险和维护成本,但也意味着不适合需要富文本、图片或复杂互动的社区。对于追求安静讨论的个人博客,这种极简反而能提升访客体验,因为匿名发言只需昵称,无需登录。
隐私保护的具体实现
Ecoku 不保存访客 IP、User-Agent 或地理位置,IP 仅在内存中用于限流,重启即清空。邮箱不公开,身份信息加密存储在 IndexedDB 中并按站点隔离。这些措施减少了数据泄露风险,但读者需注意,评论内容本身仍是公开的,且管理员可通过后台管理评论。
部署与迁移的注意事项
Ecoku 使用 Go 编写,通过 Docker 部署,数据存储在 SQLite 中,一个实例可服务多个站点。部署时需配置反向代理并正确设置 trusted_proxies,以确保限流准确。从 Twikoo 迁移只能在站点刚注册且无评论时进行,迁移后原数据不会自动同步,需提前备份。
人机验证与通知机制
Ecoku 内置 Cloudflare Turnstile 和 Cap 两种人机验证,作者更推荐自托管的 Cap。验证码只能阻挡部分机器评论,不能完全杜绝垃圾评论。通知支持 Telegram 和邮件,博主和留下邮箱的访客会收到回复提醒。这些功能需额外配置,且邮件通知依赖 SMTP 服务。
Q&A
Ecoku 评论系统是什么?它和 Twikoo 有什么关系?
Ecoku 是一个极简的自托管评论系统,由作者因 Twikoo 功能冗余而自研并开源。它用 Go 编写、Docker 部署、SQLite 存储,支持多站点,仅保留纯文本评论,无 Markdown、账号、点赞和审核,匿名发言只需昵称,不存 IP 和邮箱,内置人机验证与 Telegram、邮件通知,并支持从 Twikoo 迁移数据。
Ecoku 评论系统有哪些主要功能特点?
Ecoku 的主要特点包括:纯文本评论(不渲染 Markdown/HTML,只保留换行),可选表情包渲染;匿名评论只需昵称,邮箱和网址可选;不保存 IP、User-Agent 或地理位置;内置 Cloudflare Turnstile 或 Cap 人机验证;评论提交即公开,无前置审核;支持墓碑删除和彻底删除;支持博主身份口令;支持 Telegram 和邮件通知;嵌套评论深度达 16 层,视觉缩进到第 3 层;支持自定义 CSS 变量;用 Go 编写,Docker 部署,SQLite 存储,多站点隔离。
Ecoku 如何保护用户隐私?
Ecoku 不保存访客的 IP、User-Agent 或地理位置,日志中也没有这些记录。IP 只在内存中短暂用于限流,进程重启即清空。邮箱不出现在任何公开接口。评论区不请求第三方头像、统计或 IP 查询服务。
Ecoku 支持哪些人机验证方式?推荐哪种?
Ecoku 内置两种防垃圾评论的人机验证:Cloudflare Turnstile(需要 Cloudflare 账号)和 Cap(开源、可自托管的 PoW 验证服务,需要自己部署实例)。作者更推荐 Cap,难度保持默认即可。
如何从 Twikoo 迁移数据到 Ecoku?
Ecoku 支持从 Twikoo 导入数据,具体操作见导入 Twikoo 的 JSON 数据文档。迁移只能在站点刚注册、还没有评论时进行。
Ecoku 的评论通知功能如何设置?
Ecoku 支持 Telegram 和邮件通知。博主以及留下邮箱的访客都会收到评论和回复通知。Telegram 通知只需填一个 Bot Token,就能推送到个人、频道或群组;邮件通知走 SMTP 发信服务。
Ecoku 的部署流程是怎样的?
Ecoku 用 Go 编写,编译为单个二进制并打包成 Docker 镜像,数据存在 SQLite3 中(启用 WAL)。部署步骤:准备目录并设置权限,准备 compose.yml 和 config.yaml,启动 Docker 容器,配置反向代理(如 Nginx 或 Caddy),然后登录管理后台注册站点。首次启动会初始化数据库、生成管理员账号和临时密码,并保存密钥文件。
Ecoku 的评论嵌套和分页是如何设计的?
Ecoku 的嵌套深度支持到 16 层,但视觉缩进只到第 3 层,更深的回复与第 3 层左对齐。昵称旁的 @被回复者 可以点击回到原评论。有回复的评论都带 [-] 折叠按钮。分页以根评论为单位,一页固定条数,连同下面的整棵回复树一起返回,不会出现父评论在这页、回复在下一页的情况。