mirror of
https://github.com/nyakang/nyaterm.git
synced 2026-11-14 08:07:59 +00:00
- Added new modules for cloud synchronization, including `sync_schema`, `encryption`, and `ai`. - Implemented encryption for credential values to enhance security. - Introduced AI configuration policies and structures for managing AI-related data. - Enhanced `CloudSyncRemote` trait with methods for writing and listing sync files. - Updated `Cargo.toml` and `Cargo.lock` to include new dependencies and workspace members. - Added tests for new functionalities to ensure reliability and correctness.
327 lines
17 KiB
Markdown
327 lines
17 KiB
Markdown
# 云同步
|
||
|
||
## Cloud Sync V3 预览
|
||
|
||
设置中的 **Cloud Sync V3** 提供独立的 V4 同步空间,首批支持 WebDAV、S3 和本地目录后端。选择 V3 后先保存设置,再生成同步预览。确认时会重新检查本地数据和已可见的远端发布;预览过期时须重新生成。
|
||
|
||
连接、分组、代理、隧道、快捷命令、笔记、自定义图标和主题按稳定 ID 合并。不同字段可自动合并,同字段冲突保留候选和本机当前值;可以在预览中选择候选,也可以先同步无冲突部分。删除和并发编辑会保留存在性冲突。外观偏好可单独开启,仅同步主题、终端字体、光标和对比度白名单。快捷键是独立的可选范围,按操作合并;关闭后保留已有配置。
|
||
|
||
首次确认会在配置目录创建并回读验证加密的 `cloud-sync-v3-safety-<id>.nya` 备份。旧云端数据保留,检测到旧客户端后续写入时暂停自动同步;可手动生成导入预览,确认后保留双方资源和冲突候选。V4 的合并结果先原子应用到本机,再发布;上传失败显示“等待发布”,重试会复用已保留的精确密文。已完成回读验证的状态会单独显示。
|
||
|
||
AI 非敏感配置是独立的可选范围,包含供应商配置、手动添加的模型、自定义操作及默认模式。API 密钥和请求头由独立的敏感数据范围控制;代理、执行权限、外部工具路径和自动发现的模型保留在本机。未开启敏感数据同步时,涉及本机密钥的地址变更和删除会暂缓,需先在本机编辑确认。无效引用、循环和不完整配置也会暂缓相关原子组;预览列出暂缓字段,其他有效修改继续应用,完整候选保留在副本中。
|
||
|
||
密码、私钥、凭据、OTP、连接/代理密码及 AI 密钥可在独立的敏感数据范围中开启,默认关闭。因果副本只保存版本引用,值使用独立加密对象;接收后用本机密钥重新加密。SSH/VNC 信任范围也默认关闭,每项收到的身份新增、变更和删除都须在本机预览中单独确认;自动同步不会授予信任。关闭范围保留已有数据,重新开启会重新合并。其他 Provider 的 V4 写入尚未开放。引用缺失凭据的认证组会暂缓,待接收设备补齐本机凭据后重新应用。原有 Provider 的旧协议入口保留;选择 V3 后不会因失败而自动写回旧协议。自动双向同步要求首次迁移已确认、自动推送和拉取均开启,并且没有活动会话或未保存设置。
|
||
|
||
完成 V3 迁移后,在安全设置修改主密码会先发布并回读验证新的 `rotation-<id>` 子空间,再原子切换密码、远程命名空间和本地副本。失败或上传期间有新的本地编辑时,原密码和原空间继续有效;重试复用已保存的密文。旧空间保留,其他设备须使用新的命名空间和密码接入。云账户/范围变更须与改密分开保存。已有 V4 副本时不能直接关闭主密码。
|
||
|
||
下面介绍的是保留用于兼容的旧快照协议与 Provider 设置。`.nya` 始终是独立备份,不携带 V4 Writer 身份、发布历史或同步副本。
|
||
|
||
NyaTerm 的 **云同步** 能力,解决的不是“远程文件传输”,而是把应用里的可移植配置数据同步到一份加密的远端核心快照。
|
||
|
||
远端使用不可变快照和每台设备独立的提交记录:
|
||
|
||
- `sync/snapshots/<revision>.redb.enc` 保存加密快照,是当前协议的正常数据路径
|
||
- `sync/heads/` 保存每台设备的提交记录及上传中的临时标记,用于识别并保留并发修改
|
||
- `sync/latest.redb` 保存供兼容读取使用的最新 revision、设备、时间和 hash 元数据
|
||
- `sync/current.redb.enc` 是尽力更新的兼容/恢复副本,不是唯一权威数据源
|
||
|
||
两台设备同时推送时,各自的提交都会保留;下一次检查发现并发分支后,会要求明确选择本地或云端。远端存储若存在可见性延迟,冲突可能在后续检查才出现。判断先后关系使用因果记录,不依赖设备时钟。
|
||
|
||
`.nya` 本地导出 / 导入仍然是配置备份和迁移入口。云端旧快照会按保留策略清理;设备正在引用、尚未解决的并发分支及上传中的快照受到保护。云同步不会自动删除用户云端已有的旧 `backups/` 数据,保留的快照也不替代独立备份。
|
||
|
||
当前支持这些远程存储提供方:
|
||
|
||
- **WebDAV**
|
||
- **S3 兼容**存储
|
||
- **Gitee 代码片段(Gitee Snippet)**
|
||
- **GitHub Gist**
|
||
- **Google Drive**
|
||
- **OneDrive**
|
||
- **AliyunDrive**
|
||
|
||
## 先决条件:先设置主密码
|
||
|
||
在使用 **设置 → 云同步** 前,你必须先到 **设置 → 安全** 设置 **主密码**。
|
||
|
||
这是硬性前置条件。没有主密码时:
|
||
|
||
- 不能启用云同步
|
||
- 不能执行测试连接、推送、拉取等手动操作
|
||
|
||
上传到云端的是**加密后的可移植快照**。新快照使用随机盐的 Argon2id 派生密钥,再通过 AES-256-GCM 加密和认证;版本头、参数、盐和 nonce 也参与认证。
|
||
|
||
旧 NyaTerm 和 Dragonfly 快照仍可读取。下次实际上传或显式覆盖会写成新格式;仅检查到内容相同不会重写旧密文。新格式需要所有参与同步的设备升级到支持它的版本,旧客户端无法解密新快照,也不具备新的并发保护。升级前建议保留本地 `.nya` 备份。
|
||
|
||
升级后第一次检查,如果旧同步基线无法证明完整数据未变,可能需要手动确认冲突;这是为了保护此前未计入变更 hash 的 VNC 信任记录和扩展数据。
|
||
|
||
## 从哪里进入
|
||
|
||
这项功能主要有两个入口:
|
||
|
||
### 1. 设置 → 云同步
|
||
|
||
这里是主要配置页,负责:
|
||
|
||
- 选择 provider
|
||
- 配置远程命名空间与 provider 根路径
|
||
- 设置自动同步策略
|
||
- 运行测试连接、立即推送、立即拉取
|
||
- 在冲突发生时执行处理
|
||
|
||
### 2. 工作区中的 Cloud Sync / 云同步面板
|
||
|
||
主工作区侧栏里的 **云同步** 面板用于查看:
|
||
|
||
- 当前状态
|
||
- 最近的同步活动
|
||
- 最近一次检查、同步时间
|
||
- 冲突状态与快速处理入口
|
||
|
||
改配置去设置页,看运行状态看工作区面板。
|
||
|
||
## Provider 配置
|
||
|
||
### 通用项
|
||
|
||
无论使用哪种 provider,都需要先确认这几项:
|
||
|
||
- **启用云同步**
|
||
- **存储提供方配置**
|
||
- **设备名称**
|
||
- **远程命名空间**
|
||
|
||
其中:
|
||
|
||
- **设备名称** 会写入快照元数据,方便你识别是哪台设备上传的内容
|
||
- **远程命名空间** 是 NyaTerm 在远端保存云同步快照时使用的顶层路径前缀
|
||
|
||
### WebDAV
|
||
|
||
如果 provider 选的是 **WebDAV**,通常需要填写:
|
||
|
||
- **WebDAV Endpoint**
|
||
- **Provider Root**(可选)
|
||
- **用户名**
|
||
- **密码**
|
||
|
||
WebDAV 认证同时支持 **Basic** 和 **Digest** 两种方式。当服务端要求 Digest 时,NyaTerm 会自动改用 Digest,以提升对 NAS / 网关的兼容性。
|
||
|
||
### S3 兼容存储
|
||
|
||
如果 provider 选的是 **S3 兼容**,通常需要填写:
|
||
|
||
- **S3 Endpoint**
|
||
- **Bucket**
|
||
- **Region**
|
||
- **Provider Root**(可选)
|
||
- **Access Key ID**
|
||
- **Secret Access Key**
|
||
- **Session Token**(可选)
|
||
- **Virtual Host Style**(按 provider 要求决定是否开启)
|
||
|
||
### Gitee 代码片段(Snippet)
|
||
|
||
如果 provider 选的是 **Gitee 代码片段**,NyaTerm 会把加密后的云同步对象保存到一个 Gitee 代码片段中。
|
||
|
||
Gitee 的文件数量限制也适用于快照、设备提交及临时标记。设备较多或保留了多个冲突分支时,可能需要使用新的代码片段或更换存储提供方;不会为了腾出位置删除未解决的分支。
|
||
|
||
通常需要填写:
|
||
|
||
- **Gitee 个人访问令牌(Personal Access Token)**
|
||
- **代码片段 ID**
|
||
|
||
### GitHub Gist
|
||
|
||
如果 provider 选的是 **GitHub Gist**,NyaTerm 会通过 GitHub device flow 授权,并把加密后的云同步对象保存到一个私有 Gist 中。
|
||
|
||
通常需要:
|
||
|
||
- 点击 **连接 GitHub**
|
||
- 在浏览器打开的 GitHub 授权页面输入设备码
|
||
- 授权 `gist` scope
|
||
|
||
在 GitHub device-flow 授权流程中,如果没有填写 Gist ID,NyaTerm 会在授权成功后自动创建并回填一个私有 Gist;已有 Gist ID 时,会先验证并复用该 Gist。
|
||
|
||
### Google Drive / OneDrive / AliyunDrive
|
||
|
||
如果 provider 选的是 **Google Drive**、**OneDrive** 或 **AliyunDrive**,NyaTerm 会通过桌面端原生 HTTP adapter 访问对应网盘服务。
|
||
|
||
当前需要手动填写 OAuth 信息:
|
||
|
||
- **Refresh Token**
|
||
- **Client ID**
|
||
- **Client Secret**
|
||
- **Access Token**(可选,长期同步建议依赖 Refresh Token)
|
||
- **Provider Root**(可选)
|
||
|
||
AliyunDrive 还需要填写 **Drive Type**,通常为 `resource`。
|
||
|
||
### 配置校验
|
||
|
||
当前实现会先做最基本的 provider 校验:
|
||
|
||
- WebDAV 至少需要填写 endpoint
|
||
- S3 至少需要填写 endpoint 与 bucket
|
||
- `Access Key ID` 和 `Secret Access Key` 需要成对出现
|
||
- GitHub Gist 需要完成 GitHub 授权;Gist ID 可以在授权流程中自动创建并回填,也可以使用已有 ID
|
||
- Google Drive / OneDrive / AliyunDrive 需要填写 Refresh Token、Client ID、Client Secret
|
||
|
||
建议在真正启用自动策略前,先执行一次 **测试连接**。
|
||
|
||
## 自动同步策略
|
||
|
||
### 启动时检查
|
||
|
||
开启后,NyaTerm 会在启动时检查远端是否已经有新的同步快照。
|
||
|
||
常见结果包括:
|
||
|
||
- 本地与云端一致
|
||
- 远端有更新,可以拉取
|
||
- 本地有尚未同步的变化
|
||
- 本地和云端都变了,进入冲突状态
|
||
|
||
所有 Provider(包括 GitHub Gist)还会每 15 分钟检查一次;窗口重新聚焦时也会检查,聚焦检查至少间隔 120 秒。关闭“启动时检查”只跳过启动检查。失败时会退避重试,限流时遵守服务端有效的 `Retry-After`;认证失效会暂停,修改设置后恢复。
|
||
|
||
### 自动拉取远端变更
|
||
|
||
开启 **自动拉取远端变更** 后,如果启动检查或同步检查发现“只有远端发生变化”,NyaTerm 会自动拉取并应用当前云端快照。
|
||
|
||
它只处理本地没有未同步变更的情况;存在活动会话或未保存设置草稿时,会等到安全后再拉取。本地和云端都变了时仍然进入冲突状态,不会自动选一边覆盖另一边。
|
||
|
||
### 本地变更后的自动推送
|
||
|
||
开启后,当受支持的本地配置数据发生变化并保存完成时,NyaTerm 会在一个防抖窗口后自动推送快照。
|
||
|
||
你可以设置:
|
||
|
||
- **同步防抖秒数**
|
||
|
||
它是「保存后延迟推送」,不是实时双向同步。
|
||
|
||
## 手动操作
|
||
|
||
### 测试连接
|
||
|
||
先验证 provider 配置与远端布局是否可用。
|
||
|
||
### 立即推送
|
||
|
||
把当前设备的可移植配置快照上传到云端。用于刚完成一组设置调整后,或需要明确控制何时写入云端时。
|
||
|
||
### 立即拉取
|
||
|
||
把云端当前最新同步快照拉回本地并应用。用于另一台设备已经推送过更新,需要让当前设备显式对齐时。
|
||
|
||
## 冲突是怎么出现的?
|
||
|
||
如果**本地状态**和**云端状态**自上次同步后都发生了变化,就会进入冲突状态。
|
||
|
||
典型场景:
|
||
|
||
- A 设备改了设置但还没拉取 B 的更新
|
||
- B 设备已经把新的同步快照推到了云端
|
||
- A 再尝试推送或启动检查时发现双方都变了
|
||
|
||
这时你会看到冲突预览,例如:
|
||
|
||
- 本地快照哈希
|
||
- 远程 revision
|
||
- 远程设备信息
|
||
- 当前云端快照时间与 hash
|
||
- 冲突提示信息
|
||
|
||
## 冲突怎么处理?
|
||
|
||
当前实现提供两种处理方式:
|
||
|
||
### 下载远程版本
|
||
|
||
分支列表显示每个并发 revision、设备名称(旧快照显示缩短的 UUID)、时间、可读状态及差异数量。仅有一个可读分支时自动选中;有多个可读分支时必须先选择。差异摘要仅展示已知集合新增、删除、修改数量、设置分类以及未知实体是否变化,不显示凭据、OTP、笔记或命令正文。
|
||
|
||
把选定的远端快照拉回当前设备并应用。**当前设备上未同步的本地变更会丢失**,选它之前先确认云端版本是要保留的那份。
|
||
|
||
### 上传本地版本
|
||
|
||
用当前设备的本地快照解决当前预览中已观察到的分支。确认时会重新校验本地内容、所选快照和分支集合;发生变化会刷新预览,要求再次确认。**远端那份变更会被覆盖**,其他设备后续会以这份状态为准。
|
||
|
||
这里要特别注意:
|
||
|
||
- 当前不是字段级 merge
|
||
- 也不是多人协作式冲突解决
|
||
- 本质上是“本地快照”和“远程快照”二选一
|
||
|
||
NyaTerm 保留独立的设备提交和因果记录。明确选择本地或云端会生成覆盖已观察到分支的新提交;选择云端时会固定使用预览中明确选定的 revision。若其他设备随后提交新的并发修改,仍会再次提示冲突。`sync/snapshots/` 是现行协议的数据路径,不要手动清空。
|
||
|
||
## 会同步哪些内容?
|
||
|
||
当前实现基于 **portable snapshot**,覆盖的是 NyaTerm 的可移植配置数据,例如:
|
||
|
||
- 已保存连接 / 分组
|
||
- 密钥、密码、OTP 配置
|
||
- 代理与隧道
|
||
- 快捷命令
|
||
- 大部分应用设置
|
||
- known_hosts 与主密钥 token
|
||
|
||
命令历史不会进入云同步核心快照;如需离线留档或迁移,使用本地 `.nya` 导出 / 导入。
|
||
|
||
当前实现会保留一部分设备本地 UI 状态,例如:
|
||
|
||
- 当前打开的标签页
|
||
- 面板开合与尺寸等运行态布局
|
||
|
||
所以它同步的是可移植配置,让多台设备共享当前核心配置状态,不是完整的桌面会话镜像。
|
||
|
||
## 建议的首次配置顺序
|
||
|
||
首次启用按这个顺序:
|
||
|
||
1. 在 **设置 → 安全** 中设置主密码
|
||
2. 打开 **设置 → 云同步**
|
||
3. 先选 provider,再填写 endpoint / bucket / root / 凭据
|
||
4. 设置设备名称与远程命名空间
|
||
5. 先执行 **测试连接**
|
||
6. 再决定是否启用:
|
||
- 启动时检查
|
||
- 自动拉取远端变更
|
||
- 自动推送
|
||
7. 最后手动执行一次 **立即推送**,确认整条链路可用
|
||
|
||
## 凭据、设备名称与活动历史
|
||
|
||
三个网盘刷新令牌后,会先加密保存新的 Access Token 和服务端返回的 Refresh Token,再继续认证请求;未返回 Refresh Token 时保留原值。保存失败会停止操作,后续同步失败或取消不会撤销已完成的令牌保存。未编辑的设置令牌字段会跟随轮换更新,显式编辑的凭据仍需通过保存冲突检查。
|
||
|
||
设备名称保存在加密快照中;UUID 仍是设备身份。名称修改在下一次实际发布时生效,不会仅为改名重新上传。
|
||
|
||
自动上传、下载、冲突、失败和恢复成功会由进程统一写入活动历史,多窗口共享一条记录。无变化、忙碌、防抖或禁用检查不会刷屏;相同错误分类、触发原因和 revision 在 15 分钟内去重。错误只包含受控分类、Provider、操作和 HTTP 状态,不包含请求 URL、签名地址或响应正文;历史写入故障不会改变已经成功的同步结果。
|
||
|
||
## 后台检查与流量
|
||
|
||
自动检查先检查指针和全部设备提交,已验证且未变化的快照最多每 24 小时完整下载校验一次。轻量检查不会延长这个期限。S3 支持 ETag 条件请求时,未变化的指针返回 304,设备提交可以复用本次列表确认的缓存;服务不支持时退回普通 GET。
|
||
|
||
其他 Provider 仍需传输各自的指针和目录 API 响应;Gist/Snippet 的容器响应还可能包含文件内容。因此每日校验限制针对显式快照读取和验证,不能保证每个 Provider 的网络正文都只包含元数据。
|
||
|
||
缓存由同一进程的窗口共享,关闭应用后丢弃。首次启动、切换远端配置或账号、轮换凭据、修改主密码、缓存淘汰及分支变化都可能增加完整读取。实际推送、拉取、恢复和冲突确认仍验证快照;每日历史清理、上传回读及兼容副本也会产生流量。
|
||
|
||
本地变更通知没有改变实际同步内容时,可以跳过联网。持续编辑不会推迟定时远端检查,但上传仍等待防抖结束。最近成功的手动或自动检查会推迟下一次定时检查,并在 120 秒内抑制聚焦重复检查;测试连接不算完整检查。关闭“启动时检查”不会关闭 15 分钟定时检查。
|
||
|
||
日志提供受控的操作汇总:请求数、上传和下载正文的字节、304、缓存命中及完整校验次数。所有 Provider 均在 HTTP 边界统计,包含认证重试和已读取的错误正文;上传字节为每次尝试提交的正文大小,下载字节为应用实际读取量,不包含 HTTP 头和 TLS 开销,不能直接视为云厂商账单。日志不包含地址、对象路径、ETag、凭据或同步正文。实际流量取决于在线时长、设备数、快照大小、变更、重试和存储服务能力。
|
||
|
||
## 排障建议
|
||
|
||
按钮不可用或操作被拦住时,依次检查:
|
||
|
||
- 是否已经设置主密码
|
||
- 当前设置是否已经保存(未应用的草稿会阻止某些手动操作)
|
||
- provider 必填项是否已经补齐
|
||
- 远端命名空间、provider root、endpoint 是否填写正确
|
||
|
||
查看最近发生了什么看工作区的 **云同步** 面板,改配置回设置页。
|
||
|
||
:::tip 使用建议
|
||
- 首次接入新 provider 时,先“测试连接”,再启用自动策略。
|
||
- 做较大范围的连接、OTP、快捷命令调整前,如果需要可回退点,请先使用本地 `.nya` 导出。
|
||
- 在多台设备之间切换时,统一远程命名空间规则,并给每台设备设置可区分的设备名称。
|
||
:::
|