1. 部署背景
本人服务器为
2GB小内存配置,已部署Typecho博客,系统资源较为紧张。此前部署的Radicale日历服务仅支持单用户使用,无可视化后台,多用户配置繁琐,无法满足日常多设备使用需求。
因此选用轻量化的Baikal+InfCloud组合重新部署,核心需求明确:
- 适配苹果原生日历、提醒事项,实现iPhone设备双向同步
- 提供网页端管理能力,可在线新增、编辑日程与提醒事项
- 替代Radicale,支持多用户独立隔离使用,自带可视化管理后台
- 基于PHP+SQLite架构,内存占用极低,可复用现有PHP环境,不浪费服务器资源
组件说明:Baikal为CalDAV/CardDAV后端服务,负责数据存储与协议同步;InfCloud为纯前端网页客户端,提供可视化操作界面。
2. 前置说明
| 内容 | 说明 |
|---|---|
| 部署环境 | Centos7、Nginx已部署、HTTPS证书配置完成、域名已解析 |
| 技术栈 | Nginx、PHP-FPM(复用Typecho环境)、SQLite、Baikal、InfCloud |
| 部署域名 | plan.caihn.cc |
| 实现效果 | 网页端管理日程提醒、苹果原生设备同步、多用户独立使用 |
| 前置条件 | Nginx、PHP-FPM正常运行,拥有root权限,域名解析生效 |
全文操作基于root账户执行,PHP-FPM端口沿用已配置的19000
3. 详细部署流程
3.1 环境准备
本次部署直接复用
Typecho所用PHP环境,无需重复配置。全新服务器可执行以下命令安装依赖:# 安装依赖 yum install -y php php-fpm php-gd php-mbstring php-xml php-curl php-zip php-sqlite3 # 系统设置启用 systemctl enable --now php-fpm
3.2 部署Baikal服务端
Baikal作为核心后端,负责日历、待办数据存储与同步协议处理。
# 创建站点目录,后续通过nginx配置跳转 mkdir -p /var/www/baikal cd /var/www/baikal # 下载并解压Baikal wget https://github.com/sabre-io/Baikal/releases/download/0.9.4/baikal-0.9.4.zip unzip baikal-0.9.4.zip # 配置权限(关键,避免数据库写入失败) chown -R nginx:nginx /var/www/baikal chmod -R 770 /var/www/baikal/Specific
3.3 部署InfCloud网页前端
InfCloud提供网页可视化操作界面,无数据存储能力,仅对接Baikal后端。# 创建目录 mkdir -p /var/www/infcloud cd /var/www/infcloud # 下载解压前端文件 wget https://inf-it.com/open-source/download/InfCloud_0.13.1.zip unzip InfCloud_0.13.1.zip -d ../infcloud chown -R nginx:nginx /var/www/infcloud 修改前端配置,对接后端服务: vim /var/www/infcloudconfig.js 替换核心配置项: var globalNetworkCheckSettings 中的 href 设置为 https://plan.caihn.cc/dav.php/principals/; 设置中文 var globalInterfaceLanguage='zh_CN'; 打开刷新按钮 var globalEnableRefresh=true;
3.4 Nginx站点配置
这里baikal和inflcoud使用一个nginx配置,防止出现跨域问题参考如下:
server { listen 443 ssl; server_name plan.caihn.cc; ssl_certificate /etc/nginx/ssl/caihn.cc/caihn.cc.pem; ssl_certificate_key /etc/nginx/ssl/caihn.cc/caihn.cc.key; root /var/www/baikal/html; index index.php index.html; fastcgi_param HTTP_AUTHORIZATION $http_authorization; # ========== .well-known 重定向 ========== location /.well-known/caldav { return 301 https://$host/dav.php/; } location /.well-known/carddav { return 301 https://$host/dav.php/; } # ========== InfCloud 前端 ========== location /infcloud/ { alias /var/www/infcloud/; index index.html; } # ========== 合并所有 dav.php 请求(包括 OPTIONS) ========== location ~ ^/dav\.php(/.*)?$ { # ===== 先处理 OPTIONS 预检请求 ===== if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' 'https://plan.caihn.cc' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PROPFIND, PROPPATCH, REPORT, PUT, MOVE, DELETE, LOCK, UNLOCK' always; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Depth, User-Agent, X-File-Size, X-Requested-With, If-Modified-Since, X-File-Name, Cache-Control, Overwrite, X-Request-URL, Destination' always; add_header 'Access-Control-Max-Age' 86400; return 204; } # ===== 正常 PHP 处理 ===== # 关键修复:用 $fastcgi_script_name 代替手动拼接 fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_pass 127.0.0.1:19000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param HTTPS on; include fastcgi_params; # ===== 跨域头 ===== add_header 'Access-Control-Allow-Origin' 'https://plan.caihn.cc' always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PROPFIND, PROPPATCH, REPORT, PUT, MOVE, DELETE, LOCK, UNLOCK' always; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Depth, User-Agent, X-File-Size, X-Requested-With, If-Modified-Since, X-File-Name, Cache-Control, Overwrite, X-Request-URL, Destination' always; add_header 'Access-Control-Expose-Headers' 'DAV, Content-Length, Allow' always; } # ========== 路由规则(其他请求走这里) ========== location / { try_files $uri $uri/ /index.php?$query_string; } # ========== 其他 PHP 处理(admin 等) ========== location ~ ^(.+\.php)(.*)$ { fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_pass 127.0.0.1:19000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param HTTPS on; include fastcgi_params; } }校验配置并重启Nginx:
nginx -t nginx -s reload
3.5 后端初始化配置
- 浏览器访问初始化地址:https://plan.caihn.cc/
- 数据库选择SQLite,无需单独部署数据库,适配小内存服务器
- 设置管理员账号密码,完成安装向导
常用访问地址
- Baikal管理后台:https://plan.caihn.cc/
InfCloud网页前台:https://plan.caihn.cc/infcloud/
4. Web网页端完整使用流程
4.1 新建用户账号
所有登录账号均需在后台手动创建,前端不支持注册:
- 登录Baikal管理后台,进入用户管理页面

- 新建普通用户,设置用户名与密码


- 系统自动为用户生成日历、待办事项、通讯录目录
- 自己添加日历

4.2 网页端日常操作
- 访问 https://plan.caihn.cc/infcloud/,使用新建的普通用户账号登录

- 核心功能:在线新增编辑日程、添加待办提醒、管理联系人

- 所有操作数据实时同步至后端,手机端自动同步更新
5. 苹果手机同步配置教程
5.1 添加CalDAV账号
- 打开iPhone 设置 → 日历 → 日历账户
- 点击添加账户,选择底部其他
- 选择添加CalDAV账户
- 填写服务器信息:
- 服务器:plan.caihn.cc
- 用户名:Baikal后台创建的普通账号
- 密码:对应账号密码
5.2 开启同步服务
账号验证通过后,开启日历、提醒事项同步开关,保存配置即可。
5.3 同步效果
手机原生日历、提醒事项与网页端数据双向实时同步,全程使用苹果原生应用,无第三方广告,稳定流畅。
6. 常见问题与优化
- 日程保存失败:检查 /var/www/plan.caihn.cc/Specific 目录Nginx读写权限
- 设备同步失败:核对服务器地址、网络状态及SSL证书有效性
- 数据备份:所有数据存储在站点Specific目录,定期备份该目录即可
- 多用户隔离:不同账号的日历、提醒、联系人完全独立,互不干扰
7. 部署总结
本次部署以轻量化、资源复用为核心,用Baikal+InfCloud替代传统Radicale服务,完美适配2GB小内存服务器。整套服务复用现有Nginx、PHP运行环境,资源占用极低,同时解决了旧服务单用户、无网页管理的痛点。
部署完成后,可通过网页端随时随地管理日程与待办,苹果全设备原生同步,数据自主托管,无需依赖iCloud云端,兼顾实用性、隐私性与稳定性。