共计 7142 个字符,预计需要花费 18 分钟才能阅读完成。
团队里用 [[Calendly]] 来管理面试和外部会议的预约,用起来确实很方便,候选人点开一个链接就能看到你的空闲时间,选一个时间段就能自动发 Google Meet 链接,省去了来回邮件确认时间的麻烦。但是 Calendly 的定价一直让我觉得不太舒服,个人免费版功能非常有限,只能创建一种事件类型,稍微想多用一点就得升级到 Standard 计划,每人每月 12 美元起步。如果是一个五六人的小团队,一年下来光日程预约工具就要花将近一千美元,这对于很多独立开发者或者小公司来说还是一笔不小的开支。后来我发现了 [[Cal.com]] 这个开源项目,不仅功能上完全不输 Calendly,而且可以自己部署,数据完全掌控在自己手里,用了一段时间之后觉得确实值得写一篇文章来分享。
Cal.com 是什么
Cal.com 的前身叫 Calendso,2021 年在旧金山成立,创始团队的初衷就是打造一个开源的日程预约基础设施。这个项目在 GitHub 上已经积累了超过 4 万颗 Star,代码仓库非常活跃,截至 2026 年 3 月最新版本是 v6.2.0。技术栈方面,Cal.com 使用 Next.js 构建前端和后端,Prisma 作为 ORM,PostgreSQL 作为数据库,整体架构是典型的现代全栈 JavaScript 应用。2024 年以来 Cal.com 还推出了 Cal.ai 功能,可以通过 AI 来处理日程安排的对话,虽然这个功能目前主要面向付费用户,但也能看出团队在产品方向上的投入。
从定位上来说,Cal.com 不只是一个简单的预约工具,它把自己定义为「scheduling infrastructure」,也就是日程预约的基础设施。这意味着你不仅可以像用 Calendly 一样创建预约页面让别人来约你的时间,还可以通过 API 把日程预约的能力嵌入到自己的应用里,甚至可以做白标(white-label)定制,把整个预约系统套上自己的品牌。对于做 SaaS 产品或者需要在自己平台内集成预约功能的开发者来说,这一点非常有吸引力。
Cal.com 和 Calendly 到底有什么不同
很多人第一次听说 Cal.com 的反应是「又一个 Calendly 的克隆」,但实际用下来会发现两者的设计哲学有很大的不同。Calendly 走的是纯 SaaS 路线,产品打磨得非常流畅,上手极其简单,几分钟就能创建好一个预约页面发出去。它的优势在于稳定、易用、集成生态丰富,基本上你能想到的日历服务和视频会议工具它都支持。但 Calendly 的问题也很明显,免费版限制太多,付费版按人头收费,而且所有数据都存在 Calendly 的服务器上,你没有任何导出或者迁移的自由度。
Cal.com 的核心差异在于开源和可自部署。代码在 GitHub 上完全公开(AGPL-3.0 协议),你可以 fork 下来自己改,也可以用 Docker 部署在自己的服务器上。自部署版本的所有功能都是免费的,没有按人头收费的限制。在功能层面,Cal.com 支持的东西其实已经相当全面了——多种事件类型、Round-Robin 轮询分配、团队日程、Google 和 Outlook 日历同步、支付集成(Stripe)、Webhook 自动化、工作流(Workflow)等等。Cal.com 还有一个 Calendly 没有的亮点,就是动态工作流功能,你可以设置条件逻辑,比如当预约时长超过两小时自动触发审批流程,这在 Calendly 里需要借助 Zapier 等第三方工具才能实现。
当然 Cal.com 也有它的短板。首先自部署的复杂度不低,尤其是涉及到 Google Calendar 的 OAuth 配置,需要在 Google Cloud Console 里创建项目、配置回调 URL,对于不太熟悉 OAuth 流程的人来说会比较头疼。其次 Cal.com 的 UI 虽然近几个版本改进了很多,但整体的流畅度和细节打磨跟 Calendly 比还是有差距。另外社区里有一些声音反馈自部署版本偶尔会遇到一些 bug,GitHub 上目前有超过 1300 个 open issue,其中不少跟自部署相关。所以如果你追求的是零折腾开箱即用的体验,Calendly 或者 Cal.com 的托管版可能更适合你;但如果你看重数据主权、想要深度定制、或者不想为每个用户付月费,自部署 Cal.com 是一个非常值得考虑的选择。
自部署前的准备
在开始部署之前,先确认一下服务器的配置。Cal.com 的资源需求并不算高,但因为它是一个完整的 Next.js 应用加上 PostgreSQL 数据库,所以也不算特别轻量。官方推荐的最低配置是 2GB 内存、1 核 CPU、20GB 硬盘空间,但根据我的实际体验,如果你只是个人使用或者小团队使用,2GB 内存是够用的,应用空闲时大约占用 300-400MB 内存,主要的内存消费来自 PostgreSQL。如果你的服务器上还跑了其他服务,建议至少给到 4GB 内存会比较宽裕。
除了服务器之外,你还需要准备一个域名。这不仅仅是为了好看,而是因为 Google Calendar 和 Outlook 的 OAuth 集成要求回调 URL 必须是 HTTPS 的域名地址,不能用 IP 地址。所以你需要提前把域名解析好,并配置好 SSL 证书。如果你用的是 [[Nginx]] 或者 [[Caddy]] 做反向代理,配置 Let’s Encrypt 的免费证书就行。
部署环境方面,推荐使用 Docker 和 Docker Compose,这是目前最省事的方式。Cal.com 官方在 Docker Hub 上提供了官方镜像 calcom/cal.com,目前已经有超过 100 万次拉取。虽然 Cal.com 官方的态度是「Docker 配置由社区驱动,官方不提供正式支持」,但从 v5.9 版本开始,Docker 文件已经由官方维护了,稳定性比以前好了不少。
使用 Docker Compose 部署
首先创建一个项目目录,然后在里面创建 docker-compose.yml 文件:
services:
calcom:
image: calcom/cal.com:latest
container_name: calcom
restart: unless-stopped
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://calcom:calcom_password@calcom-db:5432/calcom
- NEXTAUTH_SECRET=your-random-secret-key
- CALENDSO_ENCRYPTION_KEY=your-random-encryption-key
- NEXT_PUBLIC_WEBAPP_URL=https://cal.yourdomain.com
- NEXT_PUBLIC_API_V2_URL=https://cal.yourdomain.com/api/v2
- NEXT_PUBLIC_LICENSE_CONSENT=agree
depends_on:
calcom-db:
condition: service_healthy
networks:
- calcom-network
calcom-db:
image: postgres:15
container_name: calcom-db
restart: unless-stopped
environment:
- POSTGRES_USER=calcom
- POSTGRES_PASSWORD=calcom_password
- POSTGRES_DB=calcom
volumes:
- calcom-db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U calcom"]
interval: 10s
timeout: 5s
retries: 5
networks:
- calcom-network
volumes:
calcom-db-data:
networks:
calcom-network:
driver: bridge
这里有几个关键的环境变量需要注意。NEXTAUTH_SECRET 和 CALENDSO_ENCRYPTION_KEY 是两个加密密钥,用于 session 管理和数据加密,你需要用随机字符串来填充它们。可以用下面的命令生成:
openssl rand -base64 32
NEXT_PUBLIC_WEBAPP_URL 必须设置为你实际使用的域名地址(包含 https),这个值会被编译到前端代码中,所以如果后期要更换域名的话需要重新构建镜像。NEXT_PUBLIC_LICENSE_CONSENT=agree 是表示你同意 Cal.com 的开源许可协议。
配置好之后,启动服务:
docker compose up -d
第一次启动会自动运行数据库迁移,创建必要的表结构。等容器启动完成后,访问 https://cal.yourdomain.com 应该就能看到 Cal.com 的登录页面了。第一次访问时需要创建管理员账户,按照页面提示填写信息即可。
配置反向代理
如果你用 [[Nginx]] 做反向代理,配置大致如下:
server {
listen 443 ssl http2;
server_name cal.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/cal.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cal.yourdomain.com/privkey.pem;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
如果你用的是 [[Caddy]],配置就更简单了,Caddy 会自动处理 SSL 证书:
cal.yourdomain.com {
reverse_proxy localhost:3000
}
集成 Google Calendar
Cal.com 自部署版本集成 Google Calendar 是整个部署过程中最容易踩坑的一步,但也是最关键的一步,因为没有日历同步的话 Cal.com 基本上就失去了核心价值。你需要在 Google Cloud Console 中创建一个新项目,然后进行以下配置。
首先在「APIs & Services」中启用 Google Calendar API。然后进入「OAuth consent screen」配置 OAuth 同意屏幕,选择 External 类型,填写应用名称和你的邮箱。接下来在「Credentials」中创建一个 OAuth 2.0 Client ID,应用类型选择 Web application。在 Authorized redirect URIs 中添加回调地址,格式为 https://cal.yourdomain.com/api/integrations/googlecalendar/callback。创建完成后你会得到一个 Client ID 和 Client Secret。
拿到这两个值之后,在 docker-compose.yml 的 environment 中添加:
- GOOGLE_API_CREDENTIALS={"client_id":"your-client-id","client_secret":"your-client-secret","redirect_uris":["https://cal.yourdomain.com/api/integrations/googlecalendar/callback"]}
注意这个值是一个 JSON 字符串,格式要严格正确。添加完之后重启容器 docker compose restart calcom,然后在 Cal.com 的设置页面中就能看到 Google Calendar 的集成选项了,点击连接后会跳转到 Google 的授权页面,授权完成后你的 Google Calendar 就和 Cal.com 同步了。
如果你的 Google Cloud 项目还在测试模式(Test mode),那只有你手动添加的测试用户才能完成授权。如果你想让任何人都能通过你的预约页面来预约(预约时不需要他们授权 Google),测试模式其实就够用了,因为只有你自己需要授权 Google Calendar 来读取和写入日程。
集成 Outlook Calendar
如果你用的是 Outlook 或者 Microsoft 365 的日历,集成流程类似。你需要在 Azure Portal 的「App registrations」中注册一个新应用,然后在「Authentication」中添加重定向 URI https://cal.yourdomain.com/api/integrations/office365calendar/callback。在「Certificates & secrets」中创建一个 Client Secret。然后在环境变量中添加:
- MS_GRAPH_CLIENT_ID=your-azure-app-client-id
- MS_GRAPH_CLIENT_SECRET=your-azure-app-client-secret
配置好之后重启容器,就可以在 Cal.com 中连接 Outlook Calendar 了。
实际使用体验
部署完成之后,Cal.com 的核心使用体验和 Calendly 是非常接近的。你可以创建不同类型的事件,比如「30分钟快速沟通」、「1小时技术面试」等等,每种事件可以单独设置可用时间、缓冲时间、最大预约数等参数。预约页面的链接格式是 https://cal.yourdomain.com/your-username/event-type,可以直接发给对方。
团队功能方面,Cal.com 支持 Round-Robin(轮流分配)和 Collective(集体参与)两种模式。Round-Robin 会把预约请求轮流分配给团队成员,适合客服或者销售场景;Collective 则是所有人都要参加的会议类型,系统会自动找到所有人都有空的时间段。这两个功能在 Calendly 的免费版中是不提供的,需要升级到每人每月 16 美元的 Teams 计划。
Webhook 和工作流(Workflow)也是 Cal.com 很实用的功能。你可以设置在预约创建、取消、重新安排等事件发生时触发 Webhook,把数据推送到你的其他系统。工作流则可以在预约前后自动发送提醒邮件或者短信,这对于减少「no-show」(爽约)非常有效。
支付集成方面,Cal.com 支持通过 [[Stripe]] 收款,你可以给某些事件类型设置价格,预约者在预约时需要先付款才能确认。这对于做付费咨询或者付费课程的人来说很方便。
不过也有一些让人不太满意的地方。Cal.com 的邮件通知默认使用内置的邮件服务,如果你自部署的话建议配置自己的 SMTP 服务器,否则邮件可能会进垃圾箱甚至发不出去。另外 Cal.com 的文档虽然覆盖面很广,但有些地方写得不够清楚,特别是自部署相关的文档,很多细节需要到 GitHub 的 Discussion 里去找答案。还有一点要注意的是,Cal.com 使用的是 AGPL-3.0 协议,如果你基于它做修改并对外提供服务,理论上需要开源你的修改。如果不想受这个限制,Cal.com 也提供商业许可证。
数据备份
自部署最重要的一件事就是备份。Cal.com 的所有数据都存储在 PostgreSQL 中,所以你只需要定期备份数据库就行。可以用 cron 配合 pg_dump 来实现自动备份:
docker exec calcom-db pg_dump -U calcom calcom > /backup/calcom_$(date +%Y%m%d).sql
建议至少每天备份一次,并把备份文件同步到远程存储(比如 S3 或者 [[Cloudflare R2]]),避免服务器挂了之后数据也跟着丢失。
升级策略
Cal.com 的更新频率很高,基本上每隔一两周就会发一个新版本。升级的时候只需要拉取最新镜像然后重启容器:
docker compose pull calcom
docker compose up -d calcom
新版本启动时会自动检测并运行数据库迁移。不过在升级之前强烈建议先备份数据库,毕竟数据库迁移是不可逆的操作,万一新版本有问题你还能回滚。
最后
在自部署了 Cal.com 之后,我最大的感受是,这类基础工具的开源替代方案已经成熟到了一个值得认真考虑的程度。Calendly 的确是一个优秀的产品,但对于我个人来说,每月为一个日程工具付费 12 美元实在有些说不过去,尤其是当有一个功能几乎完全对等的开源替代品的时候。Cal.com 自部署版本虽然在初始配置上需要花一些时间,特别是 Google Calendar 的 OAuth 配置确实有点繁琐,但一旦部署好之后日常使用基本上是零维护的。
如果你是独立开发者、自由职业者、或者小团队负责人,经常需要让客户或者合作伙伴在线预约你的时间,Cal.com 的自部署方案绝对值得一试。你不需要为每个用户支付月费,数据完全存储在自己的服务器上,而且可以根据自己的品牌需求做定制。当然如果你完全不想折腾服务器,Cal.com 也提供托管版本,个人版免费就可以使用基础功能,也是一个不错的选择。
related
- [[Calendly]]
- [[TidyCal]]
- [[Spir]]

