Cal.diy:把 Cal.com 开源社区版部署到自己的服务器
posts posts 2026-05-17T20:25:00+08:00Cal.diy 是 Cal.com 拆分出的开源社区版:100% MIT 许可,删掉了 Teams、Workflows、SAML SSO 等企业功能。本文按官方仓库核实它的部署流程、配置变量与功能边界,给出 Docker Compose 部署、日历与视频集成、备份升级和选型判断。技术笔记开源, 自托管, Docker, Cal.comCal.diy:把 Cal.com 开源社区版部署到自己的服务器
先给结论:Cal.diy 是 Cal.com 官方拆分出来的开源社区版(官网原话:“Cal.diy is the new open source community edition which was spun out of Cal.com”),整仓 MIT 许可,删掉了 Cal.com 的全部企业功能。它适合想把自己的预约数据留在自己服务器上的个人用户;官方 README 同时警告它"strictly recommended for personal, non-production use"(严格建议个人非生产用途),商业场景应该用 Cal.com 本身。
如果你正在找"Calendly 开源替代",这篇文章覆盖三件事:Cal.diy 和 Cal.com 的准确关系与功能边界;按官方仓库走一遍 Docker Compose 部署、日历/视频集成和日常运维;以及拿它和 Cal.com Cloud、Calendly 比较时怎么选。文中所有命令、环境变量和功能清单按 cal.diy v6.2.0(2026-03-01 发布)与主分支 2026-09-29 状态核实。
学习目标
读完本文,你可以:
- 说清 Cal.diy 与 Cal.com 的关系:哪个是 fork、各自什么许可、企业功能删了哪些
- 用 Docker Compose 把 Cal.diy 跑起来,并完成首次初始化
- 配置邮件发送、Google/Outlook/Apple 日历集成和 Zoom/Cal Video 视频会议
- 执行升级与备份,排查几个官方文档点名的常见报错
- 在 Cal.diy、Cal.com Cloud、Calendly 三者之间做出有依据的选型
Cal.diy 与 Cal.com:关系与功能边界
这段是全文最重要的判断,先讲清楚,后面部署时才不会对功能产生错误预期。
仓库已经改名
GitHub 上的开源主仓库经历过两代更名:2021 年 3 月创建时叫 Calendso,后来改名 calcom/cal.com,现在是 calcom/cal.diy(旧地址会自动重定向过去)。也就是说,你今天访问 github.com/calcom/cal.com,落到的是 cal.diy 仓库——截至 2026-09-29,它有 48,715 stars、15,239 forks,license 显示 MIT。
Cal.com 公司的产品没有消失,只是不再和这个开源仓库共用代码:SaaS 版本运行在 app.cal.com,按订阅收费。cal.diy README 写明"Cal.diy is a community fork. Contributions to this repo do not flow to Cal.com’s production platform"——给 cal.diy 提交的代码不会进入 Cal.com 的生产平台,两边各自演进。
删掉了什么
cal.diy 不是"Cal.com 换个部署方式",README 对自己的定义是"a fork of Cal.com with all enterprise/commercial code removed"。被移除的企业功能包括:
- 团队(Teams)与组织(Organizations)——多人协作、Round-Robin 轮换分配、集体会议都在这条线上
- SAML SSO 与 SCIM
- Workflows 工作流自动化
- Routing Forms 路由表单
- Insights 数据面板
- Admin Panel 管理后台
作为交换,cal.diy 没有 Open Core 的"开源版/企业版"切分。README License 节的原话是"Unlike Cal.com’s ‘Open Core’ model, Cal.diy has no commercial/enterprise code"——没有 license key,不需要 Cal.com 账号,整个代码库一个 MIT 许可证。
还剩什么
按 cal.diy 官网的功能对照表和仓库 app-store 目录,社区版保留了:
| 类别 | 包含的能力 |
|---|---|
| 排期与预订 | 事件类型、循环事件、带座位活动、付费活动(Stripe/PayPal)、私密链接、预订管理 |
| 可用性 | 工作时间表、日期覆盖、缓冲时间、最小通知期、旅行日程、外出(OOO) |
| 日历集成 | Google、Outlook、Apple、CalDAV、Zoho、Exchange、ICS 订阅 |
| 视频会议 | Cal Video(Daily.co)、Zoom、Google Meet、Microsoft Teams、Webex、Jitsi |
| 登录认证 | 邮箱密码、Google OAuth、Azure AD OAuth |
| 自动化 | Webhooks、Zapier、n8n/Make、CRM、消息应用、AI 代理 |
| 开发者能力 | Embed 嵌入、API v2、API Keys、Platform/OAuth Clients |
| 界面语言 | 37 种,含简体与繁体中文 |
两个名字相近、容易混淆的取舍:“团队预约"没了(属于被删的 Teams 功能),但"给一个预约页配 Zoom 会议链接"还在(视频应用是独立集成)。工作流(Workflows)没了,但"预约创建后收到 webhook 推送"还在——自动化要从"内置工作流"换成"webhook + 外部编排"的思路,后文细说。
用 Docker Compose 部署
这是官方 README 给出的主路径。官方没有提供"一行命令装完"的服务器安装脚本(仓库里的 deploy/install.sh 是 GitHub Codespaces 开发环境用的),但流程本身只有四步。
前置条件
- 一台装好 Docker 和 Docker Compose 的服务器(README 提醒现在主推不带连字符的
docker compose写法,即 Compose V2) - 开放 3000 端口(或你自定义的端口)
- 可选:一个解析到服务器的域名
硬件方面官方没有给最低配置表,安装文档的口径是:“Cal.diy runs with pretty minimal hardware requirements by itself. The most intensive part for the software is when you actually build the software, but once it’s running it’s relatively lightweight."——运行时占用不高,吃资源的是构建阶段(Docker 镜像的构建参数 MAX_OLD_SPACE_SIZE 默认给到 4096,可作内存规划的参考)。直接拉官方镜像可以跳过构建,资源压力更小。
第一步:拉代码
git clone --recursive https://github.com/calcom/cal.diy.git
cd cal.diy第二步:准备 .env
cp .env.example .env生成两组必填密钥,写进 .env:
# NEXTAUTH_SECRET:Cookie 加密密钥
openssl rand -base64 32
# CALENDSO_ENCRYPTION_KEY:凭证加密密钥(AES256 要求 32 字节)
openssl rand -base64 24NEXTAUTH_SECRET=<上一步生成的值>
CALENDSO_ENCRYPTION_KEY=<上一步生成的值>README 特别提醒不要把占位符 secret 带进生产环境。
还有一个官方文档没有明说、但照默认配置启动会踩到的坑:docker-compose.yml 里 calcom 服务的 DATABASE_URL 是用 ${POSTGRES_USER}:${POSTGRES_PASSWORD}@${DATABASE_HOST}/${POSTGRES_DB} 四个变量现场拼出来的,而 .env.example 并没有预置这四个变量。对照 compose 文件里 database 服务的默认值,在 .env 里补上四行:
POSTGRES_USER=unicorn_user
POSTGRES_PASSWORD=magical_password
DATABASE_HOST=database
POSTGRES_DB=calendso想让 cal.diy 连外部数据库,把这四行改成外部库的值、只启动 web 服务即可(见下一步)。
可选配置:如果你要用浏览器推送通知,遇到 Error: No key set vapidDetails.publicKey 报错,说明还缺 VAPID 密钥:
npx web-push generate-vapid-keysNEXT_PUBLIC_VAPID_PUBLIC_KEY=<公钥>
VAPID_PRIVATE_KEY=<私钥>第三步:启动
# 预拉镜像(可选)
docker compose pull
# 启动完整技术栈:Postgres 数据库 + web 应用 + Prisma Studio
docker compose up -dcompose 文件定义了五个服务,各司其职:
| 服务 | 作用 | 端口 |
|---|---|---|
database | Postgres 数据库,数据存 database-data 卷 | 无对外端口 |
redis | 缓存(compose 里把 REDIS_URL 注入给 calcom-api) | 6379 |
calcom | Cal.diy web 主应用 | 3000 |
calcom-api | API v2 服务 | 80(API_PORT 可改) |
studio | Prisma Studio 数据库管理界面 | 5555 |
studio 在 compose 注释里被明确标注为可选项,注释原话建议生产环境把这一段注释掉或删掉,避免数据库管理界面暴露在外。
如果用外部数据库,不需要本地 Postgres 和 Studio:
docker compose up -d calcom注意 ARM 机器(如 Oracle Cloud 的 A1 实例)要拉带 -arm 后缀的镜像标签,例如 calcom/cal.diy:v5.6.19-arm 的格式(版本号以最新 release 为准)。
第四步:初始化
浏览器打开 http://localhost:3000(或你设置的 NEXT_PUBLIC_WEBAPP_URL)。首次运行会出现初始化向导,创建第一个用户后即可使用。
向导中的"连接日历"一步看起来必选,实际可以跳过:README 给出的办法是直接访问 <NEXT_PUBLIC_WEBAPP_URL>/event-types 进入仪表盘,日历以后随时能在 Settings > Integrations 里补配。
源码方式运行
不改代码可以跳过本节。源码运行的要求是 Node.js 18+、PostgreSQL 13+ 和 Yarn(README 口径;官方 Docker 镜像基于 node:20 构建)。
开发环境最省事的入口是 yarn dx:它会用 Docker 起一个本地 Postgres 并写入几个测试账号(README 给出了默认凭据表,如 [email protected] / ADMINadmin2022!),登录地址 http://localhost:3000。
生产构建走标准流程:
yarn
yarn build
yarn start数据库迁移按环境二选一:开发用 yarn workspace @calcom/prisma db-migrate,生产用 yarn workspace @calcom/prisma db-deploy。安装文档特别警告:生产构建之前先把数据库升级到位(“Please make sure to upgrade your database before you build for production”)。
核心配置
运行时环境变量
README 定义的运行时必填/常用变量一共五个:
| 变量 | 说明 | 默认值 |
|---|---|---|
DATABASE_URL | 数据库连接串 | postgresql://unicorn_user:magical_password@database:5432/calendso |
NEXT_PUBLIC_WEBAPP_URL | 站点基础 URL | http://localhost:3000 |
NEXTAUTH_URL | 认证服务地址 | {NEXT_PUBLIC_WEBAPP_URL}/api/auth |
NEXTAUTH_SECRET | Cookie 加密密钥 | 必填 |
CALENDSO_ENCRYPTION_KEY | 凭证加密密钥(32 字节) | 必填 |
NEXT_PUBLIC_WEBAPP_URL 有个值得知道的细节:它会影响构建产物里的静态地址,运行时改值后容器启动时会做一次替换,所以"和构建时不一致"只带来短暂启动延迟,不算故障。
两个常用的行为开关:CALCOM_TELEMETRY_DISABLED=1 关闭匿名使用数据上报;CSP_POLICY="non-strict" 启用内容安全策略(登录页强制、其余 SSR 页面 report-only)。
公网部署时把 NEXT_PUBLIC_WEBAPP_URL 设为你的真实访问地址,这决定了预约页链接、OAuth 回调等所有对外 URL 的基准。
邮件发送
预订相关的邮件通知(确认、改期、取消)都依赖 SMTP。.env.example 里默认生效的只有发件人两项和本地调试地址:
EMAIL_FROM='[email protected]'
EMAIL_FROM_NAME='Cal.diy'
EMAIL_SERVER_HOST='localhost'
EMAIL_SERVER_PORT=1025真实发信要补 EMAIL_SERVER_USER 和 EMAIL_SERVER_PASSWORD 两个变量。.env.example 的注释里给了两份"verified to work"的官方示例:Office365 用 smtp.office365.com:587(开了两步验证就配 App Password),Gmail 用 smtp.gmail.com:465 加应用专用密码。国内场景的对应关系:QQ 邮箱、163 邮箱需要在邮箱设置里开启 SMTP 服务并使用"授权码"而不是登录密码;企业邮箱用服务商给的 SMTP 主机名和端口,字段还是同一组。
配置是否生效,最直接的验证是用一个新邮箱走一遍注册或预订流程,看确认邮件能不能到达。
日历集成
日历集成在 Settings > Integrations 里连接,OAuth 类应用要先把凭据配进环境变量。
Google Calendar:流程最长的一个。在 Google API Console 启用 Google Calendar API,配置 OAuth 同意屏幕,勾选 .../auth/calendar.events 和 .../auth/calendar.readonly 两个 scope,创建 OAuth 客户端时填两个回调地址:
<CALDIY_URL>/api/integrations/googlecalendar/callback
<CALDIY_URL>/api/auth/callback/google把下载的 JSON 整段贴进 .env 的 GOOGLE_API_CREDENTIALS,然后重新种子应用商店(README 命令:在 packages/prisma 目录执行 yarn seed-app-store),最后记得在 OAuth 同意屏幕点 “PUBLISH APP”。
Outlook / Microsoft:在 Azure 门户做应用注册,租户类型选多租户,Web 回调填 <CALDIY_URL>/api/integrations/office365calendar/callback,把应用(客户端)ID 和客户端密钥分别写进 MS_GRAPH_CLIENT_ID、MS_GRAPH_CLIENT_SECRET。
Apple Calendar:走 CalDAV,源码里的服务端点是 https://caldav.icloud.com,连接时用 Apple ID 和在苹果账户页生成的 App 专用密码。
自建 CalDAV(Nextcloud、Radicale 等):应用商店里的 CalDAV 应用给出了官方验证过的服务端列表——Baïkal、Kerio Connect、Nextcloud、Radicale,并提醒 CalDAV 服务端响应慢会直接拖慢预约页。
除此之外,app-store 目录里还有 Zoho、飞书(Feishu/Lark Calendar)、Exchange 2013/2016 等日历应用,按需启用。
视频会议
Cal Video(内置,Daily.co):默认视频方案,配一个 DAILY_API_KEY 即可用;开了 Daily Scale Plan 的把 DAILY_SCALE_PLAN 设为 true 可解锁录制。
Zoom:在 Zoom Marketplace 用 “Develop → Build App” 创建 General App(README 指定的类型;旧资料里让建 JWT 应用的步骤已过时),选 User-managed,回调地址填 <CALDIY_URL>/api/integrations/zoomvideo/callback,scope 勾 meeting:write:meeting 和 user:read:settings,把 Client ID/Secret 写进 ZOOM_CLIENT_ID、ZOOM_CLIENT_SECRET。
Google Meet:随 Google Calendar 集成自动可用,无需单独配置。
Microsoft Teams、Webex、Jitsi 等:各自是 app-store 里的独立应用,按应用内指引授权。
API 与 Webhooks
compose 里的 calcom-api 服务就是 API v2;API Keys、Platform/OAuth Clients 是官网特性表列明的内置能力。webhook 可以把预订事件推送到外部地址——这是 cal.diy 里替代"工作流"的正规做法:想实现"预约后写一条 CRM 记录"或"发一条 Slack 消息”,用 webhook 接到 n8n/Make 之类的编排工具里做。官方应用目录本身就带 Zapier、n8n、Make 集成。
API 有限流机制,用的是 Unkey,纯可选:不配置 UNKEY_ROOT_KEY 一切照常工作。
日常运维
升级
官方更新路径四步(README 原文顺序):
docker compose down
docker compose pull
# 有变量变更就更新 .env
docker compose up -d不需要手动跑迁移:镜像的启动脚本 start.sh 会依次执行 npx prisma migrate deploy、重新种子 app store,然后再启动应用,docker compose up -d 时迁移自动完成。
备份
数据在 database-data 卷里,备份用 pg_dump(凭据对应 compose 里 database 服务的默认值,改过就用你的值):
# 手动备份
docker compose exec -T database pg_dump -U unicorn_user calendso > cal_diy_$(date +%Y%m%d).sql
# 恢复
cat cal_diy_20260929.sql | docker compose exec -T database psql -U unicorn_user -d calendso恢复要导进空库:目标库里已有数据时先清掉,否则会撞主键。
定时备份加一条 crontab 即可,例如每天凌晨三点:
0 3 * * * mkdir -p /opt/backup && cd /path/to/cal.diy && docker compose exec -T database pg_dump -U unicorn_user calendso | gzip > /opt/backup/cal_diy_$(date +\%Y\%m\%d).sql常见问题排查
以下条目全部来自官方 README 的 Troubleshooting 一节:
CLIENT_FETCH_ERROR(getaddrinfo ENOTFOUND …):容器内解析不到你的访问域名所致。给 .env 加一行 NEXTAUTH_URL=http://localhost:3000/api/auth(换成你的地址),让认证回调走容器自己。
创建用户报 Invalid 'prisma.user.create()':把用户的 metadata 字段填成空对象 {} 再保存。
报 Error: No key set vapidDetails.publicKey:缺 Web Push 密钥,按前文生成 VAPID 密钥并写入 .env。
负载均衡器终结 SSL 后请求被拒:加环境变量 NODE_TLS_REJECT_UNAUTHORIZED=0。README 原话提醒只在清楚自己在做什么、并且信任前面的流量来源时才这么做。
ARM 机器拉不到镜像:标签加 -arm 后缀。
预约页打不开先查三件事:容器是否全部正常(docker compose ps)、NEXT_PUBLIC_WEBAPP_URL 是否与实际访问地址一致、日志有没有迁移报错(docker compose logs calcom)。
选型:Cal.diy、Cal.com Cloud 还是 Calendly
价格按 2026-09-29 各官网口径核实:Calendly 免费版只有 1 种事件类型和 1 个日历连接,Standard 每席位每月 10 美元(年付)、Teams 16 美元(年付)、Enterprise 起价每年 1.5 万美元;Cal.com Cloud 免费版不限事件类型和日历数,Teams 12 美元/人/月(年付)、Organizations 28 美元/人/月(年付,SAML SSO/SCIM 从这档开始)、Enterprise 另议。
| 维度 | Calendly | Cal.com Cloud | Cal.diy 自托管 |
|---|---|---|---|
| 软件/订阅费 | 免费版受限,付费 $10-16/席/月(年付) | 免费版够个人用,团队 $12 起/人/月(年付) | 免费,只承担服务器成本 |
| 许可 | 闭源 SaaS | 闭源 SaaS | MIT,代码完全开放 |
| 数据位置 | 厂商服务器 | 厂商服务器 | 你自己的服务器 |
| 团队/组织功能 | Teams 档起 | Teams/Organizations 档起 | 没有(已随企业功能移除) |
| SAML SSO/SCIM | Enterprise 档 | Organizations 档起 | 没有 |
| 内置工作流 | 付费档部分具备 | 有 | 没有;用 Webhooks + n8n/Make 替代 |
| 定制深度 | 有限 | 有限 | 可改前端、可加应用、可嵌入 |
| 维护责任 | 无 | 无 | 自己负责升级、备份、安全 |
选择判据其实官方已经写明:README 的 TIP 是"For any commercial and enterprise-ready scheduling infrastructure, use Cal.com, not Cal.diy”。翻译成决策语言——
- 个人预约页、数据要自主、愿意自己运维:Cal.diy 合适
- 要团队协作、轮换分配、组织级管控:直接上 Cal.com Cloud(Teams 档起),cal.diy 没有这些功能
- 预算敏感且只缺"无限事件类型 + 多日历 + 视频":Cal.com Cloud 免费版可能就够,不必自托管
- 深度嵌入自己产品(Embed、API、白标):cal.diy 的 MIT 许可是三者中最宽松的,可以先自托管验证再谈商业授权
cal.diy 官网没有托管版,“自托管"是它唯一的形态——不存在"先试试官方托管再决定"的路径,评估就得自己起一个实例。
练习与自测
问题 1:Cal.diy 和 Cal.com 是什么关系?
查看答案
Cal.diy 是 Cal.com 拆分出的开源社区版(fork),删掉了全部企业/商业代码;Cal.com 本身是闭源 SaaS 产品。两者代码各自演进,给 cal.diy 的贡献不会进入 Cal.com 生产平台。问题 2:哪些功能在 cal.diy 里用不了?
查看答案
团队(Teams)、组织(Organizations)、SAML SSO、SCIM、Workflows、Routing Forms、Insights、Admin Panel。需要这些就得上 Cal.com Cloud。问题 3:部署时哪两组密钥必填?怎么生成?
查看答案
`NEXTAUTH_SECRET`(`openssl rand -base64 32`)和 `CALENDSO_ENCRYPTION_KEY`(`openssl rand -base64 24`,AES256 要求 32 字节)。另外按默认 compose 启动还要在 `.env` 补 `POSTGRES_USER`、`POSTGRES_PASSWORD`、`DATABASE_HOST`、`POSTGRES_DB` 四个插值变量。问题 4:升级到新版本后需要手动执行数据库迁移吗?
查看答案
不需要。镜像启动脚本 `start.sh` 在应用启动前自动执行 `npx prisma migrate deploy` 并重新种子 app store,`docker compose up -d` 即完成迁移。问题 5:想要"预约创建后自动在 n8n 里触发一条流程”,在 cal.diy 里怎么实现?
查看答案
Workflows 已随企业功能移除,正规做法是配置 Webhook 把预订事件推给 n8n(或 Make/Zapier),由外部编排工具完成后续动作。cal.diy 保留 Webhooks 和 API v2,这条路是完整的。问题 6:一台 1 核 1G 的服务器能跑 cal.diy 吗?
查看答案
官方没有给最低配置表,安装文档只说运行本身硬件要求很低、构建阶段最吃资源(构建参数 MAX_OLD_SPACE_SIZE 默认 4096)。用官方预构建镜像可以绕开构建,1G 内存仍然偏紧,2G 以上更稳妥——这是基于官方口径的推断,不是官方承诺。进阶方向
- 自动化:Webhooks + n8n/Make/Zapier 组合替代被移除的 Workflows;需要更细的控制直接用 API v2 写脚本
- 嵌入:官方 Embed 库可以把预约页嵌进任何网站,参数在 app-store 的 embed 包里
- 参与贡献:cal.diy 是社区仓库,CONTRIBUTING.md 是入口;给它的代码不影响 Cal.com 产品,反过来也一样
- 迁回商业版:实例里长出了团队需求时,导出数据迁到 Cal.com Cloud 比在 cal.diy 上等团队功能更现实——官方没有计划把企业功能加回社区版
口径说明
- 功能边界、部署命令、环境变量、排错条目:对照 cal.diy 仓库 README、docker-compose.yml、.env.example、start.sh 与 cal.diy 官网,按 v6.2.0(2026-03-01 发布)及主分支 2026-09-29 状态核实
- stars/forks:GitHub API 2026-09-29 读数(48,715 / 15,239),会持续变化
- 定价:Calendly 与 cal.com/pricing 官网 2026-09-29 页面口径,年付/月付价格以官网实时为准
- Nginx 反代、certbot 等通用 Web 服务器做法未展开:与 cal.diy 无绑定关系,按你的接入层惯例配置即可
参与讨论
使用 GitHub 登录。欢迎补充事实、异议与实践。
讨论暂时无法加载。