Super Productivity SuperSync 数据库静止加密现状与安全边界全解析
【免费下载链接】super-productivitySuper Productivity is an advanced todo list app with integrated Timeboxing and time tracking capabilities. It also comes with integrations for Jira, GitLab, GitHub and Open Project.项目地址: https://gitcode.com/GitHub_Trending/su/super-productivity
本文基于 Super Productivity 仓库中
packages/super-sync-server/docs/encryption-at-rest.md(2026-07-29 验证)及其配套决策文档、架构文档与服务端源码整理而成。核心结论先行:当前 SuperSync 部署并不对 PostgreSQL 数据库文件与数据卷提供项目自管的静止加密(encryption at rest);历史上尝试过的 LUKS 与 PostgreSQL TDE 方案均因生产环境(OpenVZ)无法运行而被退役。本文将从"为什么没有加密"、"哪些数据被保护/不被保护"、"E2EE 与静止加密的区别"、"运维人员该怎么办"四个层面讲清这一安全边界,让部署者能准确判断自身部署的真实加密状态,并掌握备份加密、客户端 E2EE、恢复流程等配套手段的用法。
现状结论:SuperSync 不提供数据库静止加密
SuperSync 服务器是一个基于 PostgreSQL 的认证中继、排序服务与上传冲突门卫,承载着 Super Productivity 的多端同步协议。关于"数据库文件在磁盘上是否加密",packages/super-sync-server/docs/encryption-at-rest.md给出的状态非常明确:
Status:Not provided by the current SuperSync deployment
也就是说:
- PostgreSQL 数据文件(live database files)不由本项目加密;
- **数据卷(database volume)**同样不在项目加密范围之内;
- 项目当前不提供、也不支持一条可运行的 LUKS 或 PostgreSQL TDE(透明数据加密)部署路径。
仓库根目录的决策文档 docs/supersync-encryption-at-rest-decision.md(状态 Accepted,决策日期 2026-01)进一步给出了决策全貌:本仓库不提供、不支持 LUKS 或 PostgreSQL 透明数据加密的部署路径,此前实现的工具链已被整体退役。
为什么:OpenVZ 环境下的两次失败尝试
这并非疏漏,而是一次基于生产环境的实测决策。仓库文档明确记录了两次被退役的实现尝试:
| 尝试方案 | 依赖能力 | 失败原因 |
|---|---|---|
| LUKS 磁盘加密工具链 | 宿主内核的dm-crypt等能力 | 生产环境的 OpenVZ 虚拟化环境不提供这些内核能力,无法运行 |
| PostgreSQL TDE(透明数据加密)实验 | 数据库层的加密内核模块 | 同样在 OpenVZ 生产环境中不可行 |
关键设计原则:与其在活动部署路径中保留一个无法测试的安全机制,不如将其整体退役。因此这两个方案最终被移除,而不是以"看似存在但从未验证"的状态留在代码库中。
被移除的具体内容存放在归档目录 packages/super-sync-server/archive/encryption-attempts-openvz-incompatible/,其中 README.md 记录了历史提交指纹:
- LUKS 工具链起始于
cb2e2e65a2,其测试/迁移支持在c8bce3c8cf; - 安全跟进提交为
0573468797; - LUKS 方案的退役与归档提交为
e050eb99fa; - PostgreSQL TDE 实验在
1fdcc9a906落地、在3a58044826回退。
归档中只保留了说明性文档(README),可执行的 Compose override、脚本与 runbook 均已移除,避免被误认为受支持的生产路径;Git 历史仍保留全部实现,仅供取证与 forensic 参考。
哪些数据被加密、哪些没有:逐项核对
encryption-at-rest.md用一条清单明确了加密边界,仓库源码与配套文档可以逐项印证:
| 数据/能力 | 是否加密 | 依据 |
|---|---|---|
| 在线 PostgreSQL 数据文件 | 否 | 文档状态声明 + 决策文档 |
| 普通数据库 dump | 否(数据库层无自动 E2EE) | 文档明确说明 |
| 客户端启用 E2EE 后的操作 payload | 是(客户端加密,见下节) | 加密架构文档 |
| 同步路由与因果元数据 | 否(明文) | 服务端架构文档 |
| 加密的备份文件流 | 是(独立的运维控制,与在线库加密无关) | 备份与灾备指南 |
可以看到,"备份加密"与"在线数据库加密"是两个完全不同的控制面:前者只保护备份产物,并不加密在线数据库;后者才是通常意义的静态数据加密。运维者不要把两者混为一谈。
深入解读:客户端 E2EE 只加密 payload
SuperSync 的端到端加密是客户端特性,与数据库静止加密完全分离。从 docs/sync-and-op-log/supersync-encryption-architecture.md 可见其技术选型:
- AES-256-GCM认证加密(同时提供机密性与完整性);
- Argon2id密钥派生(CPU/内存困难型,抗暴力破解);
- 加解密全部发生在客户端(浏览器 WebCrypto),服务器不持有任何密钥。
服务端如何识别加密操作
服务端通过Operation接口上的isPayloadEncrypted布尔标志识别加密操作。在 sync.types.ts 中可以看到该字段的定义,其注释明确写着"True if payload is E2E encrypted"。该标志同时是数据库中的真实列(isPayloadEncrypted),并出现在 DUPLICATE_OP_SELECT 的去重比较字段集中——即使 payload 是密文,去重仍可基于元数据完成。
从源码结构看,服务端对加密 payload 的处理是"透传但校验结构":
- validatePayload 对字符串形态的 payload(即加密后的 base64 密文)直接放行,注释明确"Encrypted payloads are strings - allow them";加密的 DEL 操作 payload 也允许为字符串;
- 服务端校验的仍是操作标识符、操作类型、大小、时间戳、向量时钟、schema 版本、配额与冲突元数据等明文信封;
- validation.service.ts 中,只有
!op.isPayloadEncrypted的操作才会走明文 payload 的额外校验路径。
E2EE 边界:加密了什么,没加密什么
服务端架构文档 用一段话精确划定了 E2EE 边界:
启用 E2EE 时,只有
operation.payload在客户端加密。服务器无密钥,将其作为不透明值存储。路由与因果元数据——包括操作 ID 与客户端 ID、action/操作类型、实体 ID、向量时钟、时间戳、schema 版本、导入原因与加密标志——保持明文,用于校验、排序与冲突检测。
重要的安全推论:payload 的 AES-GCM 认证标签并不认证明文元数据。因此 E2EE 提供的是payload 机密性与完整性,而非元数据机密性,也不是对完整操作的端到端真实性。一个"任务内容完全加密"的账号,其"哪些实体在何时被谁修改过"这类元数据对服务器仍是可见的。
E2EE 对服务器侧能力也有实际约束,这在架构文档中多处体现:
- 快照缓存失效:加密的全量上传仍是 operation,但无法成为服务器可读的状态缓存(snapshot cache 是明文数据的可选优化);
- 服务器侧恢复不可用:当重放范围包含加密操作时,服务器无法生成 restore 状态(
generateSnapshotAtSeq会抛出EncryptedOpsNotSupportedError); - 清理策略不依赖明文:默认保留期为 45 天,基于因果全量边界的前缀清理对加密历史同样有效(边界来自操作流本身,无需快照游标)。
运维指南:在"无静止加密"前提下保护数据
既然项目不提供数据库静止加密,运维者必须把宿主、凭据、文件系统、快照与备份位置都当作敏感基础设施来保护。encryption-at-rest.md给出的运维指引可以归纳为三条:
- 保护宿主与凭据:PostgreSQL 凭据、文件系统、服务商快照、备份位置均属于敏感资产,按最小权限原则管理;
- 在受支持的基础设施层提供加密:如果业务确实需要静态加密,应在部署环境支持的基础设施层提供——例如具备合适虚拟化的 KVM 主机上的宿主级磁盘加密,或直接选用提供静态加密的托管数据库服务;
- 宣称"有加密"之前必须实测:在真实生产拓扑上演练迁移、启动/解锁、备份、恢复、密钥轮换、监控与回滚全流程。不能仅凭加密算法或归档实现就推断合规性。
运维者的三条保护路径对比
| 保护手段 | 保护对象 | 是否由本项目提供 | 说明 |
|---|---|---|---|
| 客户端 E2EE | 服务器上的操作 payload 内容 | 是(客户端特性) | 服务器不可读 payload,但元数据明文 |
| 加密备份流 / 安全备份 | 备份产物 | 备份流程受维护,加密是独立运维控制 | 见下节备份与恢复 |
| 基础设施层磁盘加密 | 在线数据文件 | 否(需部署环境支持) | 如 KVM 宿主加密、托管 PG 服务 |
备份与恢复:一个独立的控制面
加密的备份文件流与在线数据库加密无关,但它是当前受维护的恢复程序。详见 备份与灾备指南,这里提炼与安全边界直接相关的要点:
- 恢复模型的根基:Super Productivity 使用追加式操作日志同步,所有客户端(桌面、移动、Web)在本地 IndexedDB 保存完整数据副本,客户端才是数据真相来源,服务器只是中继。因此只要有一个客户端存活,全部数据都可恢复——这与传统服务器权威系统有本质区别。
- 备份内容矩阵:
| 数据 | 存放位置 | 备份原因 |
|---|---|---|
| 用户账户(邮箱、密码哈希) | 仅服务器 | 无此则无法认证 |
| Passkey(WebAuthn 凭据) | 仅服务器 | 无法重新生成 |
| 操作日志 | 服务器 + 所有客户端 | 客户端全灭时的最后手段 |
| 任务/项目/标签数据 | 由操作日志派生 | 客户端从 ops 重建 |
每日备份脚本
packages/super-sync-server/scripts/backup.sh生成两个 dump:- 全量 dump(
supersync_*.sql.gz,活动实例约 300MB+); - 仅账户 dump(
supersync_accounts_*.sql.gz,仅users与passkeys表,<1MB)。
脚本源码(backup.sh)印证了文档中的配置项:
BACKUP_DIR(默认../backups,且chmod 700)、RETENTION_DAYS(默认 14)、DB_CONTAINER(默认supersync-postgres)、POSTGRES_USER/POSTGRES_DB(默认supersync)、RCLONE_REMOTE(默认空,配合--upload做异地上传)。- 全量 dump(
推荐的恢复路径是"仅账户恢复":恢复 accounts dump 后,客户端重连时自动触发 gap detection 并重新上传各自完整状态,多客户端收敛到一致状态。该场景由 e2e 测试
e2e/tests/sync/supersync-server-backup-revert.spec.ts覆盖。全量恢复仅在所有客户端全部丢失时才作为兜底使用。加密账号的恢复特殊点:加密账号不能使用应用内 "Restore from History"(服务器无法解密 payload);若遭遇单账号被清空,优先使用客户端的本地恢复点(Settings → Sync & Backup → Import/Export → Browse backups)。服务器侧的
scripts/recover-user.ts可重放用户操作日志到指定serverSeq并解密生成可导入的AppDataCompleteJSON(只读数据库、通过RECOVER_ENCRYPT_KEY或--key-file提供密钥),但需注意其状态标注为"尚未针对真实加密数据端到端验证"。
何时会重新考虑:可回归条件与未来方向
决策文档 给出了明确的"重新考虑条件"——只有在运维方提出包含以下全部要素的提案时,才应重新评估该决策:
- 一个支持所选机制的部署环境(这是本次退役的直接教训);
- 在当前 Compose/数据库布局上实测过的迁移与回滚;
- 完整的启动、密钥轮换、备份与灾难恢复流程;
- 监控与一次实际执行的恢复测试;
- 一份更新后的威胁模型,清晰区分 payload E2EE、数据库文件加密与备份加密三个层面。
文档点名的两个可行未来方向是:迁移到支持基础设施托管磁盘加密的 KVM 宿主,或使用提供静态加密的托管 PostgreSQL 服务。归档在 Git 历史中的旧实现是"研究输入,而非通往批准的捷径"。
结语:准确理解安全边界是合规的第一步
Super Productivity 的 SuperSync 服务器在静止加密上的立场是清晰且经得起推敲的:项目自身不加密 PostgreSQL 数据文件,因为无法在 OpenVZ 生产环境中运行 LUKS/TDE;它把 payload 机密性交给客户端 E2EE,把文件级保护交给部署环境的基础设施层,把可恢复性交给客户端为真相源的备份体系。对部署者而言,最需要记住的三件事是:
- 不要因为仓库里存在"曾经实现过加密"的历史就宣称部署具备静态加密——归档实现是历史证据,不是生产能力;
- 需要服务器端盲内容机密性,就启用客户端 E2EE(AES-256-GCM + Argon2id),但要接受元数据仍为明文;
- 需要文件级静态加密,就在部署环境支持的层面提供(宿主加密或托管数据库),并在真实拓扑上完整演练迁移、恢复与密钥轮换之后再下结论。
深入阅读
- encryption-at-rest.md(关联文档原文)
- supersync-encryption-at-rest-decision.md(ADR 决策文档)
- archived LUKS/TDE 尝试归档说明
- SuperSync 服务端架构(含 E2EE 边界)
- SuperSync E2EE 加密架构
- 备份与灾难恢复指南
- 备份脚本实现
- 服务端 Operation 类型与 payload 校验
【免费下载链接】super-productivitySuper Productivity is an advanced todo list app with integrated Timeboxing and time tracking capabilities. It also comes with integrations for Jira, GitLab, GitHub and Open Project.项目地址: https://gitcode.com/GitHub_Trending/su/super-productivity
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考