Baikal 0.10.1 管理与运维实战
Baikal 0.10.1 运维手册:用户/日历/地址簿管理、巡检自检、SQLite 备份恢复与演练、协议级 ICS/VCF 导出、升级回滚与跨用户权限语义等实测排障沉淀。
Baikal 0.10.1 管理与运维实战
目标:面向已部署 Baikal 0.10.1 的管理员,覆盖用户/日历/通讯录的日常管理、巡检自检、备份恢复(含恢复演练)、数据库切换与版本升级回滚,并把实测踩到的权限语义、切库异常等问题沉淀成排障手册。全部命令与回显在本地 0.10.1 实例实测;部署见《Baikal 0.10.1 Docker Compose 部署指南》,参数口径见《Baikal 0.10.1 配置参数详解》。
一、环境信息
- 软件版本:Baikal 0.10.1(sabre/dav ~4.7.0,PHP 8.2 运行环境)
- 部署形态:见部署指南;数据目录
config/+Specific/,数据库为 SQLite(Specific/db/db.sqlite) - 管理账号:Web 后台
admin/q1w2e3r4;DAV 示例用户root、linday、eve(密码均q1w2e3r4) - 实测结束时实例统计:用户 3、日历 6、事件 3、地址簿 5、联系人 3
- 命令约定:
https://dav.example.com为站点示意地址;sqlite3 为系统自带命令行工具(官方运行环境含 SQLite3)
二、日常巡检
2.1 Web 后台巡检
登录 /admin/,Dashboard 的 Statistics 区块给出核心水位(实测回显):
Statistics | Users | Registered users 3
CalDAV | Number of calendars 6 | Number of events 3
CardDAV | Number of address books 5 | Number of contacts 3
配合 About this system 区块的版本信息(This systems runs Baïkal 0.10.1)与 Services 区块的三个 On 状态(Web admin / CalDAV / CardDAV),一分钟内可确认服务全貌。版本异常变化优先怀疑有人动过配置文件(configured_version 键)。
2.2 HTTP 与协议自检
curl -s -o /dev/null -w 'home: %{http_code}\n' https://dav.example.com/
curl -s -o /dev/null -w 'dav: %{http_code}\n' -X PROPFIND -H 'Depth: 0' https://dav.example.com/dav.php/
curl -s -o /dev/null -w 'caldav: %{http_code}\n' -u root:q1w2e3r4 \
-X PROPFIND -H 'Depth: 0' https://dav.example.com/dav.php/calendars/root/
实测回显:
home: 200
dav: 401
caldav: 207
判读:首页 200、DAV 无凭据 401(认证层活着)、带凭据 207(协议层活着)即为健康;401 变 200 或 207 变 403 都说明配置被动过。
2.3 数据库巡检(SQLite 后端)
sqlite3 /var/www/baikal/Specific/db/db.sqlite "PRAGMA integrity_check; \
SELECT (SELECT COUNT(*) FROM users) users, (SELECT COUNT(*) FROM calendars) cals, \
(SELECT COUNT(*) FROM calendarobjects) events, (SELECT COUNT(*) FROM cards) cards;"
实测回显:
ok
3 6 3 3
integrity_check 返回 ok 为健康;数字应与后台 Dashboard 统计一致,不一致说明统计水位在涨(正常)或库被并发写坏(异常,进排障手册)。
2.4 日志巡检
认证失败会按 failed_access_message 配置写入错误日志(实测触发一次错误密码登录后,错误日志通道出现该文案)。出现频率高时结合防火墙封禁来源 IP;日志通道位置:以独立服务方式部署时进 stderr(由 systemd 等服务管理器收取),裸机部署进 PHP-FPM/nginx 错误日志。
三、用户、日历与通讯录管理
Baikal 0.10.1 无 CLI、无管理 API,管理动作全部在 Web 后台完成(表单提交),或直接操作数据库(不推荐,密码哈希等逻辑在应用侧)。
3.1 用户管理
Users 页(/admin/?/users/)列表展示每个用户的 DAV 主页地址(实测显示形如 http://…/dav.php 的 URI)、用户名、显示名与密码状态,行内提供 Calendars / Address Books / Edit / Delete 四个入口。实测创建用户:Users → + Add user,填 Username(登录名,可非邮箱)、Display name(客户端展示名)、Email、Password ×2,保存后回显:
User root has been created.
新用户自动获得 default 日历与 default 地址簿(实测 PROPFIND calendars/root/ 出现 default/、inbox/、outbox/)。实测删除入口在用户行 Delete,删除用户会级联清理其日历与通讯录——生产删除前先做 3.2 节的备份。
3.2 按用户管理日历与地址簿
进入用户行的 Calendars 入口可为其新建/改名/删除日历(实测页面提供 Creating new Calendar 表单);Address Books 入口同理。协议侧等效操作(排查后台问题时可交叉验证):
curl -s -o /dev/null -w '%{http_code}\n' -u root:q1w2e3r4 -X MKCALENDAR \
https://dav.example.com/dav.php/calendars/root/teamcal/
实测回显:
201
重复创建同名日历返回 405 Method Not Allowed;新建地址簿用 MKCOL + card:addressbook 资源类型,实测同样返回 201。
3.3 密码重置与权限语义
- 用户密码:Users → Edit 直接改密码保存,立即生效(哈希按
md5(用户名:auth_realm:密码)重写,参数口径见配置详解 5.2 节)。 - 跨用户权限:实测确认「读隔离、写禁绝」语义——用户 A 对用户 B 的日历/地址簿发起 PROPFIND,HTTP 外层返回 207,但响应内该资源的
d:status为HTTP/1.1 403 Forbidden(拿不到内容);写操作(PUT/PROPPATCH)直接 403;匿名访问一律 401。排查「客户端报 207 但看不到数据」时先核对这个语义。
四、备份与恢复
4.1 备份对象与节奏
Baikal 的全部状态 = config/(baikal.yaml)+ Specific/(SQLite 库、INSTALL_DISABLED 标记、用户数据)两个目录。MySQL/PostgreSQL 后端时改备数据库(mysqldump / pg_dump)。建议每日一次全量,升级前必须备份。
4.2 文件级备份(实测)
tar czf /var/backups/baikal-backup.tgz -C /var/www/baikal config Specific
实测回显(备份完成):
-rw-r--r-- 1 root root 4.4K Oct 30 11:32 /tmp/baikal-backup.tgz
⚠️ 注意:SQLite 在写入时直接拷库文件可能得到不一致快照,生产建议先做 4.3 的一致性导出,或把 tar 安排在业务低谷并用 2.3 节 integrity_check 验证。
4.3 SQLite 一致性导出与恢复演练(实测)
在线备份(SQLite 原生 .backup,得到一致性副本):
sqlite3 /var/www/baikal/Specific/db/db.sqlite ".backup /var/backups/bk-bak.sqlite"
实测产出 108K 副本。SQL 文本导出(可跨版本、可读性强):
sqlite3 /var/www/baikal/Specific/db/db.sqlite .dump > /var/backups/bk-dump.sql
实测 8.1K,文件头:
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE addressbooks (
id integer primary key asc NOT NULL,
principaluri text NOT NULL,
displayname text,
恢复演练(导入到新库文件并验证,实测通过):
sqlite3 /var/backups/restored.sqlite ".read /var/backups/bk-dump.sql"
sqlite3 /var/backups/restored.sqlite "PRAGMA integrity_check; SELECT COUNT(*) FROM users;"
实测回显:
ok
3
正式恢复 = 停服务 → 用备份替换 Specific/db/db.sqlite(保持属主)→ 起服务 → 重跑 2.2/2.3 节自检。
4.4 协议级导出(ICS/VCF,跨实例迁移通用)
内置导出插件实测可用,导出的是标准 iCalendar/vCard,与数据库后端无关,是「换后端、换实例」时的首选数据通道:
curl -s -o root-teamcal.ics -u root:q1w2e3r4 -w '%{http_code} %{content_type}\n' \
'https://dav.example.com/dav.php/calendars/root/teamcal/?export'
curl -s -o root-clients.vcf -u root:q1w2e3r4 -w '%{http_code} %{content_type}\n' \
'https://dav.example.com/dav.php/addressbooks/root/clients/?export'
实测回显:
200 text/calendar;charset=UTF-8
200 text/directory;charset=UTF-8
恢复到新实例 = MKCALENDAR/MKCOL 建同名集合后逐文件 PUT 回去(或用客户端的本地导入功能)。
五、数据库切换与迁移
SQLite 与 MySQL/PostgreSQL 的切换流程、官方 db.sql 导入、配置文件修改与验证,已实测沉淀在《Baikal 0.10.1 配置参数详解》5.4 节,此处只列迁移决策要点:
- 切库不做数据迁移:先导出(4.4 节)再切,切完在新后端重建用户;
- Web 后台 Database settings 页在 0.10.1 存在切库异常(配置详解常见问题 7.1),一律走配置文件途径;
- 切回 SQLite 实测原数据无损,可以作为切换失败时的回退路径;
- MySQL 后端的日常备份改走 mysqldump,
Specific/只剩配置与标记。
六、升级与回滚
6.1 版本策略与当前水位
版本节奏实测(GitHub Releases Atom,查询日期 2026-10-30):0.10.1(2024-11-10)→ 0.11.0/0.11.1(2025-11-29/30)→ 0.12.0/0.12.1(2026-08-03/05)→ 0.13.0(2026-10-19)。0.10.1 属稳定但偏旧的版本线,升级前先在测试实例完整演练本文流程。
6.2 升级原则与流程(tar 包部署)
Baikal 程序与数据严格分离(config/、Specific/ 属数据),升级 = 换程序、保数据:
- 备份(4.2 节 tar 命令,实测);
- 从官方 Releases 下载新版本包并解压到新目录(不要原地覆盖);
- 把旧实例的
config/与Specific/移入新目录(保留属主与INSTALL_DISABLED); - 核对新版本的升级说明与配置键变化(0.10 起配置体系为 baikal.yaml,老版本 PHP 配置文件不再适用,对照键名见配置详解参数总览);
- 切换 Web 服务器根目录指向新包的
html/,重载 Web 服务器(实测nginx -t && nginx -s reload语法检查通过后平滑重载); - 验证:后台 About this system 的版本号、2.2 节协议自检、抽样登录一个客户端账号。
配置文件中的 configured_version 是版本对账锚点:升级后它由程序/向导更新,若与 Dashboard 显示不一致,说明新包没有正确接管数据目录。
6.3 交付形态差异说明
以官方包(tar)交付时按 6.2 节流程升级;若采用《Baikal 0.10.1 Docker Compose 部署指南》第十章的交付方式,升级动作是「更新交付版本 → 重建服务」,config/ 与 Specific/ 数据目录跨版本保留,回滚同样只需换回旧交付版本。无论哪种形态,6.2 第 1 步的备份与 6.4 节的回滚清单都是强制前置。
6.4 回滚清单
回滚动作按序:停服务 → 恢复程序目录或旧交付版本 → 恢复 config/+Specific/ 备份 → 起服务 → 2.2 节自检 → 抽查客户端同步。全程不需要动 Web 服务器配置(除非升级时改过反代规则)。
七、故障排查手册
7.1 客户端报 207 但看不到任何数据
现象:PROPFIND 返回 207,客户端却空空如也。定位:逐资源看 d:status——实测跨用户访问时外层 207、资源级 403 Forbidden(3.3 节)。解决:改用资源所有者账号连接;这是 Baikal 的权限语义而非故障。
7.2 全部 DAV 用户 401
定位顺序:backend/sqlite_file 指向 → 库文件存在性 → users 表记录数(配置详解常见问题 7.4)。实测空 users 表(刚切库未迁数据)时全部凭据 401。解决:切回原后端或重建用户。
7.3 后台切库保存报 PHP 异常
实测异常全文与根因见配置详解常见问题 7.1(Element prop='sqlite_file' not found)。解决:弃用该页面,直改 baikal.yaml(配置详解 5.4 节流程实测可用,切回亦无损)。
7.4 配置改错导致全站异常页
实测坏 yaml(未闭合数组)后首页/DAV 全部返回 ParseException: Malformed inline YAML string at line 3(配置详解常见问题 7.2 实测全文)。解决:恢复 baikal.yaml.bak,立即生效。
7.5 安装向导重新暴露或永久禁用
Specific/INSTALL_DISABLED 是唯一开关:实测存在时访问安装器显示「Installation was already completed.」;恢复备份时该文件丢失会让向导重新可进(管理员可被重设)。解决:缺文件时手工补 touch;误禁用时删除文件并重启服务重走向导(数据保留,向导第二步会沿用现有库)。
7.6 事件/联系人计数与 Dashboard 不符
Dashboard 统计实时读库,实测与 sqlite3 计数一致(2.3 节)。不一致时优先核对 backend 是否被改动(读了另一个库),其次跑 integrity_check。
八、常见问题
Q1:能批量建用户吗?
0.10.1 无 CLI 与管理 API,批量建用户只能脚本模拟后台表单提交(注意 CSRF_TOKEN),或直接按 digesta1 = md5(user:realm:pass) 向 users/principals 表写入(官方 schema 见配置详解参考链接)。前者稳妥后者要严格对齐表结构。
Q2:删除用户前只备 ICS/VCF 够吗? 够同步场景使用(4.4 节实测导出格式标准);但共享关系、订阅等集合属性不随 ICS/VCF 走,长期迁移建议叠加 4.2/4.3 的文件级备份。
Q3:日志里出现 user %u authentication failure for Baikal 是被爆破吗?
是认证失败记录(failed_access_message 的默认文案)。偶发多为客户端改密后旧凭据重试;高频同源出现再结合防火墙处置,并核对 %u 是否被替换为 (name stripped-out)(源码行为,防用户名泄露)。
Q4:升级到 0.13.0 有什么前置动作? 先按 6.2 备份并演练回滚;0.10→0.13 跨三个次版本线,逐版阅读官方 Releases 说明核对配置键与数据库结构变化;交付形态差异与对应升级动作见 6.3 节。升级验证清单:版本号、协议自检、抽样账号、共享关系抽查。
九、参考链接
- Baikal 官方文档:https://sabre.io/baikal/
- GitHub Releases(版本时间线):https://github.com/sabre-io/Baikal/releases
- 官方数据库表结构:https://github.com/sabre-io/Baikal/tree/master/Core/Resources/Db
- sabre/dav WebDAV Sync(sync-token 机制):https://sabre.io/dav/sync/
- SQLite 命令行文档(.backup/.dump):https://sqlite.org/cli.html
- 社区维护部署仓库(升级路径参照):https://github.com/ckulka/baikal-docker
站内相关阅读:
- 《Baikal 0.10.1 介绍与选型指南》:定位、架构与选型
- 《Baikal 0.10.1 Docker Compose 部署指南》:部署、初始化与反代
- 《Baikal 0.10.1 配置参数详解》:参数与切库实操
- 《Radicale 3.9 常用 CLI 命令与运维详解》:同领域带 CLI 方案的运维对照