Gancio 介绍与选型指南
Gancio 1.28.2 认知篇:自托管社区活动发布平台的定位、Node.js 架构、功能特性与快速上手实测,并与 DAViCal/Baïkal/Radicale 等日历同步方案做量化选型对比。
Gancio 介绍与选型指南
目标:本文基于运行中的 Gancio 1.28.2 实例(Docker Compose 部署、Node.js v20.19.6、SQLite 后端)的逐条实测取证,并结合官网、Framagit 仓库、发行包内 CHANGELOG 与 Docker Hub 的联网溯源(查询日期 2026-11-01),梳理 Gancio 的产品定位、架构、功能特性与发布节奏,并与 DAViCal、Baïkal、Radicale 等日历类自托管方案做选型对比,帮助读者判断是否选用 Gancio。
一、环境信息
本文取证渠道与版本基线如下(查询日期均为 2026-11-01):
- 本地实测载体:运行中的 Gancio 实例,应用版本 v1.28.2,运行时 Node.js v20.19.6(
gancio --help回显),服务监听 13120 端口、本机映射 8149 端口;数据目录/opt/gancio/data(内含 SQLite 库gancio.sqlite与配置文件config.json)。 - 联网溯源渠道:
- 官网
https://gancio.org/(标题与 tagline,经代理访问实测) - 上游仓库 Framagit API
les/gancio(star/fork/活跃度/默认分支) - 部署实例程序目录
/home/node/CHANGELOG.md(1.28.x 发布日期与 1.x 停维声明)、/home/node/LICENSE(AGPL-3.0)、/home/node/locales/(语言清单实测计数)、/home/node/gancio_plugins/(内置插件清单) - Docker Hub API
cisti/gancio(pull 数、tag 列表与日期)
- 官网
- 版本基线:
| 组件 | 版本 | 来源 |
|---|---|---|
| Gancio | 1.28.2(2025-12-15,1.x 最后一版) | 发行包内 CHANGELOG.md |
| Node.js 运行时 | v20.19.6 | gancio --help 回显 |
| 官方发行 | cisti/gancio:1.28.2(解压约 898 MB) | 部署实例实测 |
| 2.0 开发线 | 2.0.0-beta.8(2026-10-23 发布) | Docker Hub tags API |
| DAViCal | 1.1.13 | 站内已收官文档 |
| Baïkal | 0.10.1 | 站内已收官文档 |
| Radicale | 3.9 | 站内已收官文档 |
⚠️ 网络说明:溯源当日宿主机直连
hub.docker.com与framagit.org超时不通,改用代理http://192.168.1.72:7897后经curl -x实测可用;gancio.org同样仅代理可达。
二、软件概述
2.1 Gancio 是什么
Gancio(意大利语「锚」)是一款面向本地社区的活动事件发布平台,官网 tagline 为 "A shared agenda for local communities"(来源:官网首页,查询日期 2026-11-01)。它不是给个人做多设备日历同步的服务器,而是给协会、社区中心、俱乐部这类组织做一个公开活动日历网站:成员或访客提交活动(标题、时间、地点、标签、图片),管理员/编辑审核后在首页日历上公开展示,同时通过 RSS、iCalendar(ICS)feed 对外输出订阅,并可接入 Fediverse(Mastodon 等)让活动被转发。
技术上 Gancio 是 Node.js 单体应用:Express 提供 REST API 与联邦端点,Nuxt(Vue SSR)渲染前端页面,Sequelize ORM 落 SQLite/PostgreSQL/MSSQL,ActivityPub 协议模块实现与 Fediverse 互操作。许可证为 AGPL-3.0(来源:部署实例程序目录 /home/node/LICENSE 实测首部),上游托管在 Framagit les/gancio(GitHub 上的 lesion/gancio 仅为同步副本、非主仓)。
💡 技术拓展:自托管「日历」类软件其实分两个物种,选型前务必分清——
物种 核心协议 数据流向 代表 日历同步服务器 CalDAV/CardDAV(读写) 个人日历在多客户端间双向同步 DAViCal、Baïkal、Radicale 活动发布平台 HTTP 网站 + RSS/ICS 只读订阅 + ActivityPub 组织者→公众的单向发布与聚合 Gancio、Luma 本文的 Gancio 属于后者:它没有 CalDAV 读写接口,只能被日历客户端只读订阅 ICS feed。
2.2 版本与社区活跃度(量化)
| 维度 | 数据 | 来源 |
|---|---|---|
| 上游仓库 | Framagit les/gancio,66 stars / 85 forks,2019-08-07 创建 | Framagit API,2026-11-01 |
| 最近活动 | 2026-11-01 仍有提交活动 | Framagit API last_activity_at |
| 发布节奏 | 1.x 约每月一版(1.9.0 2024-08 → 1.28.2 2025-12) | Docker Hub tags + CHANGELOG |
| 1.x 状态 | 1.28.0 起声明「1.x 最后一版」,功能开发转向 main 分支 2.0 | 发行包内 CHANGELOG.md |
| 2.0 进度 | 2.0.0-beta.8(2026-10-23),beta 线活跃 | Docker Hub tags API |
| 分发渠道 | Docker Hub cisti/gancio 累计 pull 48,380 | Docker Hub API |
| 多语言 | 44 个 locale 文件(含 zh.json 中文) | 发行包内 locales/ 实测计数 |
一句话解读:项目活跃但处于 1.x→2.0 换代期——1.28.2 是 1.x 末代稳定版(本文基线),2.0 尚在 beta,生产部署选 1.28.x,新功能观望 2.0。
三、核心架构
3.1 运行时形态
Gancio 是单进程 Node.js 应用(/usr/local/bin/gancio → server/cli.js,默认子命令 start),进程内同时承载四层:
- Nuxt SSR 前端:
pages/index.vue起的服务端渲染页面(日历首页、活动详情、管理后台); - Express API:
/api前缀的 REST 路由(事件/地点/标签/集合/用户/设置/导出等,路由总表实测约 70 条); - 联邦模块:
/federation(ActivityPub inbox/outbox)、/.well-known(webfinger、nodeinfo 2.0/2.1); - 任务管理器:进程内定时器,10 秒轮询一次,实测启动日志注册了 5 个周期任务——
ℹ [TASK] Add CREATE_RECURRENT_EVENT (30分钟)
ℹ [TASK] Add CLEAN_UNUSED_PLACES (1天)
ℹ [TASK] Add CLEAN_UNUSED_TAGS (1天和1分钟)
ℹ [TASK] Add CLEAN_FEDIVERSE_PAST_EVENT (6小时和5分钟)
ℹ [TASK] Add CLEAN_FEDIVERSE_AP_USERS (1天和10分钟)
ℹ START TASK MANAGER WITH LOOP INTERVAL OF 10 seconds
(来源:服务启动日志实测,docker compose logs 可见。)
3.2 配置三层结构(实测归纳)
Gancio 的「配置」分散在三层,这是排错时最容易踩坑的架构事实:
| 层 | 载体 | 管什么 | 生效方式 |
|---|---|---|---|
| 环境变量 | GANCIO_DATA/HOST/PORT、GANCIO_DB_*、GANCIO_PROXY_* | 数据目录、监听地址、数据库连接、出网代理 | 首次启动生成 config.json |
| 运行时配置文件 | data/config.json | 端口、日志级别/路径、DB 连接参数、上传目录 | 改后重启进程 |
| 站点设置 | 数据库 settings 表(实测 47 个键) | 标题/语言/时区/注册开关/匿名投稿/联邦开关/主题色/SMTP/插件 | 管理界面或 gancio settings set,改后需重启 |
⚠️ 实测陷阱:社区流传的 compose 示例里常见的
GANCIO_URL、GANCIO_NAME、GANCIO_LOCALE、GANCIO_TIMEZONE、GANCIO_EMAIL、GANCIO_ORIGIN在 1.28.2 全部源码中无任何引用(grep -rn "process.env.GANCIO" server/实测仅返回 DATA/HOST/PORT/DB_/PROXY_ 17 个变量),站点名称、语言、时区实际存在数据库 settings 表里,用这些环境变量设置不会生效。
3.3 数据与扩展
- 数据库:Sequelize 多方言。SQLite 为默认(
db.dialect=sqlite, storage=./gancio.sqlite,并针对SQLITE_BUSY配置了最多 15 次重试,实测 config.json 可见);生产推荐 PostgreSQL(CHANGELOG 中多处 postgres 修复);代码另有 MariaDB JSON 修正逻辑,官方文档支持 MSSQL。 - 插件体系:发行包内置 5 个插件(实测
gancio_plugins/:bluesky-bridge、discord-bridge、feed、telegram-bridge、webhook),默认全部enable=false,在管理界面或settings表plugin_<名>键开启;外部插件放data/plugins/。 - 认证:内置 OAuth2 授权服务器(oauth2orize + passport),前端与第三方都用
POST /oauth/login(password grant,公开 client_id=self)换 Bearer token,实测可用。 - 存储目录:
data/uploads(活动图片+缩略图)、data/logs(winston 按天滚动)、data/user_locale(用户自定义文案)。
四、功能特性
以下特性均在 1.28.2 实测或从 settings/路由表实证:
| 功能域 | 实测要点 |
|---|---|
| 活动发布 | 支持多日期活动(allow_multidate_event)、无结束时间活动、线上活动(allow_online_event)、重复活动(allow_recurrent_event,默认关);时间字段为 Unix 秒(实测传毫秒被拒:"are you sure?") |
| 地点与标签 | 地点自动按名称去重复用(实测同名地点返回同一 place.id);标签数组必填为 JSON 数组;可选 Nominatim/Photon 地理编码与 OSM 瓦片(allow_geolocation 默认关) |
| 集合(Collection) | 按标签/地点等过滤器组合出子日历页面,/api/collections、/feed/:format/collection/:name 实测存在 |
| 审核与角色 | admin/editor/user 三角色;未确认队列 /api/event/unconfirmed、举报/评论消息、禁用作者等路由实证 |
| 对外输出 | /feed/rss、/feed/ics 实测返回标准 RSS 2.0 与 ICS(X-PUBLISHED-TTL:PT1H);/api/export/json 实测返回全量事件 JSON;支持按 tag/place/collection 出 feed |
| ICS 导入 | POST /api/ics-import(文件)与 /api/ics-import/url 路由实证 |
| Fediverse 联邦 | enable_federation=true;nodeinfo 实测 protocols:["activitypub"]、outbound:["rss2.0"]、openRegistrations:true;应用 Actor 为 Application 型(实测 /federation/u/relay 返回 Mastodon 兼容 toot: 命名空间);可信实例/屏蔽/关注管理路由实证 |
| 匿名投稿 | allow_anon_event=true(默认开),匿名事件进入待确认队列 |
| 界面与主题 | 深/浅色主题色板、logo/头图/兜底图上传、custom_js/custom_css、页脚链接自定义(settings 实测键) |
| 多语言 | 44 个 locale(含中文 zh.json),instance_locale=zh 实测界面为中文 |
| 通知 | SMTP 设置与测试端点(/api/settings/smtp、test_smtp)实证;admin_email、to_notify 字段实证 |
五、快速开始(最小可用示例)
本节给出「一条 compose + 一次初始化」的最小路径,完整部署(发行版选型、持久化、Nginx 反代、升级)见 《Gancio 1.28.2 Docker Compose 部署指南》。
5.1 起一个最小实例
# docker-compose.yml(最小可用,SQLite)
services:
gancio:
image: cisti/gancio:1.28.2
restart: always
environment:
- GANCIO_DB_DIALECT=sqlite
- GANCIO_DB_STORAGE=./gancio.sqlite
volumes:
- ./data:/home/node/data
ports:
- "8149:13120"
docker compose up -d
5.2 初始化与验证(实测回显)
首次访问 http://127.0.0.1:8149/ 进入设置向导,确认后应用会**自动生成 admin 账号(用户名固定为 admin,随机密码,界面一次性展示)**并自动重启服务拉起。实测各端点:
curl -s http://127.0.0.1:8149/api/ping
OK
curl -s -X POST http://127.0.0.1:8149/oauth/login \
-d 'grant_type=password&client_id=self&username=admin&password=q1w2e3r4'
{"access_token":"qq5gf60z5hbbjyhly6nug0c0t6o1bdgi","refresh_token":"72y3gzrsdz5pjddzl6qdgkd6lyes0nyv","username":"admin","token_type":"Bearer"}
⚠️ 实测两个易错点:登录端点是
/oauth/login而不是/api/login;请求体必须是application/x-www-form-urlencoded且带client_id=self,发 JSON 或缺 client 一律Unauthorized。若向导随机密码未留存,用gancio users reset-password admin或重建账号(见运维篇)。
curl -s -X POST http://127.0.0.1:8149/api/event \
-H "Authorization: Bearer <access_token>" -H 'Content-Type: application/json' \
-d '{"title":"取证测试活动","start_datetime":1795370400,"place_name":"测试地点","place_address":"测试地址 1 号","tags":["测试"],"confirmed":true}'
{"id":2,"title":"取证测试活动","start_datetime":1795370400,"place":{"id":2,"name":"测试地点","address":"测试地址"},"tags":["测试"], ...}
curl -s http://127.0.0.1:8149/feed/ics | head -8
BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
PRODID:adamgibbons/ics
METHOD:PUBLISH
X-PUBLISHED-TTL:PT1H
BEGIN:VEVENT
UID:1@127.0.0.1
至此「发布→API→ICS 订阅」闭环全部打通;测试活动用 curl -X DELETE http://127.0.0.1:8149/api/event/2 -H "Authorization: Bearer <access_token>" 返回 OK 即可清理(实测)。
六、适用场景与限制
6.1 适用场景
- 社区/协会公开活动页:一个页面聚合展示活动日历,成员自助投稿、编辑审核,替代微信群接龙+网盘图片。
- Fediverse 活动推广:开启联邦后,活动以 AP 事件对象被 Mastodon 实例订阅/转发(实测 nodeinfo 声明 activitypub),适合去中心化社区。
- 市政/园区活动聚合:用「集合」把不同场馆/标签拆成子日历,各自出 RSS/ICS feed 供门户嵌入。
- 只读日历订阅源:把 Gancio 当 ICS 发布器,用户在自己的日历客户端订阅
https://<域名>/feed/ics(实测含X-PUBLISHED-TTL:PT1H自动刷新提示)。
6.2 限制(实测/实证)
- 不是 CalDAV 服务器:无读写日历同步能力,客户端只能订阅静态 ICS,不能把 Gancio 当个人日历后端(与 DAViCal 等的本质差异)。
- 1.x 停维、2.0 换代中:1.28.2 后 1.x 只修 bug;2.0 截至 2026-10 仍为 beta(
2.0.0-beta.8),跨大版本升级路径需观望。 - 单进程架构:任务管理器与 SSR 渲染同进程,无原生水平扩展/HA;官方定位即小规模社区场景。
- SQLite 并发上限:
SQLITE_BUSY重试 15 次是官方兜底,投稿量大应切 PostgreSQL。 - 无内置 TLS:Express 明文监听(实测
curl -I无 HSTS),需 Nginx/Caddy 反代终结 HTTPS;联邦场景要求baseurl为公网可达域名,IP 访问下 webfinger 实测报Bad request(要求acct:USER@DOMAIN)。 - 配置分散:环境变量陷阱(见 3.2)与「settings 改动需重启」是运维期主要困惑来源。
七、同类选型对比
7.1 定位矩阵:发布平台 vs 同步服务器
Gancio 与站内已收官的三款日历方案不是同类竞品,先分清再选:
| 维度 | Gancio 1.28.2 | DAViCal 1.1.13 | Baïkal 0.10.1 | Radicale 3.9 |
|---|---|---|---|---|
| 物种 | 活动发布平台 | CalDAV/CardDAV 同步服务器 | CalDAV/CardDAV 同步服务器 | CalDAV/CardDAV 同步服务器 |
| 技术栈 | Node.js 20 + Nuxt/Express | PHP 8 + Apache + PostgreSQL | PHP + SQLite/MySQL | Python 3 |
| 核心协议 | HTTP+RSS/ICS 只读+ActivityPub | CalDAV/CardDAV/iSchedule | CalDAV/CardDAV | CalDAV/CardDAV |
| 公开网页日历 | ✅(内置 SSR 前端) | ❌(需第三方前端) | 弱(极简) | ❌ |
| Fediverse 联邦 | ✅ 原生 | ❌ | ❌ | ❌ |
| 匿名投稿/审核流 | ✅ | ❌ | ❌ | ❌ |
| 许可证 | AGPL-3.0 | LGPL | GPL | GPL |
| 中文界面 | ✅(44 语言) | 部分 | 部分 | ✅ |
(DAViCal/Baïkal/Radicale 数据取自站内已收官文档,链接见 7.3。)
7.2 与真正的同类(活动发布平台)对比
同物种的自托管选择主要是 Gancio 与 Luma:
| 维度 | Gancio | Luma |
|---|---|---|
| 技术栈 | Node.js 单服务 | Django + PostgreSQL + Redis |
| 联邦 | ActivityPub 原生 | ActivityPub(部分) |
| 输出 | RSS/ICS/JSON | RSS/ICS |
| 部署复杂度 | 低(单服务) | 高(多服务) |
| 社区活跃度 | 月更、2.0 重写中 | 活跃 |
| 中文 | 内置 zh | 弱 |
Gancio 的差异化优势是单服务极简 + 联邦原生;Luma 更像「线上活动票务页」,无日历订阅生态。
7.3 选型建议(如果…则…)
- 要给社区做公开活动日历、希望成员自助投稿、并向 Mastodon/RSS/ICS 发布 → 选 Gancio,按 《Gancio 1.28.2 Docker Compose 部署指南》 部署。
- 要个人/团队多设备日历读写同步 → 不要选 Gancio;轻量单机选 《Radicale 介绍与选型指南》,PHP+MySQL 小团队选 《Baikal 0.10.1 介绍与选型指南》,重权限/群组调度选 《DAViCal 介绍与选型指南》。
- 两者可组合:Gancio 负责「发布」,DAViCal/Radicale 负责「同步」,用户日历客户端订阅 Gancio 的
/feed/ics即可兼得。 - 先要「凑大家的时间定档期」 → Gancio 不负责定时间,可先用排期投票工具收时间再回 Gancio 发布:参考 《Framadate 1.1.19 介绍与选型指南》、《Bitpoll 0.11.0 介绍与选型指南》。
- 生产环境:选 1.28.2(1.x 末代稳定版)并切 PostgreSQL;观望
2.0.0-beta,待 GA 再评估迁移。
八、参考链接
- 官网:https://gancio.org/(tagline 溯源,2026-11-01,代理可达)
- 上游仓库:https://framagit.org/les/gancio(活跃度/许可证溯源)
- 官方发行渠道:https://hub.docker.com/r/cisti/gancio(pull 数与 tag 时间线溯源)
- 站内相关阅读:《DAViCal 介绍与选型指南》、《Baikal 0.10.1 介绍与选型指南》、《Radicale 介绍与选型指南》