gog backup push 完全指南:用 age 加密分片将 Google Workspace 数据安全推入 Git 仓库
【免费下载链接】gogcliGoogle Workspace in your terminal.项目地址: https://gitcode.com/GitHub_Trending/gogcl/gogcli
gog backup push是 gogcli 备份体系的写入命令,它把 Gmail、日历、联系人、云端硬盘等服务数据导出为确定性 JSONL 行,经 gzip 压缩后用 age(X25519)加密成多个*.jsonl.gz.age分片,只将密文提交并推送到你指定的 Git 远程仓库。读完本文,你将掌握gog backup push的全部参数语义、加密与分片原理、检查点续传机制,以及如何用--dry-run、--query/--max等参数安全地做小规模试运行,从而把 Google 账户数据完整、私密、可验证地备份到私有仓库。
命令概览与适用场景
gog backup push属于 gog backup 命令族,其职责(help 原文)是 “Export services into encrypted backup shards”,即把服务导出为加密备份分片。它默认只备份gmail一个服务,可通过--services all扩展到全部受支持的服务;每次 push 只会更新被选中服务的分片,未选中服务的既有分片会被原样保留(前提是 age 接收者集合未变)。对应的单服务变体是gog backup gmail push(见 internal/cmd/backup.go),它聚焦 Gmail 备份并暴露精简后的--checkpoint-rows/--checkpoint-interval参数。
推荐工作流是先gog backup init完成一次性初始化,再用gog backup push定期执行:
# 初始化:创建 age 身份、写入本地配置、播种备份仓库、打印公钥接收者 gog backup init \ --repo ~/Projects/backup-gog \ --remote https://github.com/steipete/backup-gog.git # 备份全部受支持服务 gog backup push --services all --account steipete@gmail.com # 仅备份 Gmail gog backup push --services gmail --account steipete@gmail.com # 有界冒烟测试:只取最近 7 天、最多 25 封邮件 gog backup push --services gmail --account steipete@gmail.com --query 'newer_than:7d' --max 25初始化生成的本地配置默认位于~/.gog/backup.json,age 私钥默认位于~/.gog/age.key;默认远程仓库为https://github.com/steipete/backup-gog.git(见 internal/backup/config.go)。需要说明的是:备份仓库应为私有仓库,因为 Git 历史中会长期保存密文分片;服务载荷在 Git 见到之前就已加密。
完整参数表(Flags)
gog backup push的完整参数如下,这些参数均已在 internal/cmd/backup.go 中定义并由 kong 解析:
| Flag | 类型 | 默认值 | 说明 |
|---|---|---|---|
--access-token | string | 直接使用提供的 access token(绕过存储的 refresh token;token 约 1 小时过期) | |
-a--account--acct | string | 认证的 Google API 命令所用账户邮箱、别名或auto | |
--best-effort | bool | true | 将可选服务的错误记录为备份行后继续 |
--client | string | OAuth 客户端名称(选择存储的凭据与 token 桶) | |
--color | string | auto | 颜色输出:auto|always|never |
--config | string | 备份配置路径 | |
--disable-commands | string | 逗号分隔的禁用命令列表;支持点路径 | |
--drive-binary-contents | bool | 在加密分片中包含非 Google 的 Drive 二进制文件字节 | |
--drive-collaboration | bool | true | 备份 Drive 权限、评论与修订元数据 |
--drive-content-max-bytes | int64 | 0 | 跳过大于该字节数的单个 Drive 内容导出;0 表示不限制 |
--drive-content-timeout | time.Duration | 2m | 每个 Drive 文件的导出/下载超时 |
--drive-contents | bool | true | 将 Drive 文件内容下载/导出进加密分片 |
-n--dry-run--dryrun--noop--preview | bool | 不实际修改;打印预期动作并成功退出 | |
--enable-commands | string | 逗号分隔的启用命令前缀列表;支持点路径(限制 CLI) | |
--enable-commands-exact | string | 逗号分隔的精确启用命令列表;父命令不自动启用子命令 | |
-y--force--assume-yes--yes | bool | 对破坏性命令跳过确认 | |
--gmail-cache | bool | true | 在本地缓存已抓取的 Gmail 原始邮件,使中断的全量备份可续跑 |
--gmail-checkpoint-interval | time.Duration | 30m | 抓取期间两次 Gmail 检查点推送之间的最大间隔;0 禁用时间触发检查点 |
--gmail-checkpoint-rows | int | 10000 | 每个加密检查点块的 Gmail 邮件数;0 禁用行数触发检查点 |
--gmail-checkpoints | bool | true | 在长时间缓存抓取期间提交并推送不完整的加密 Gmail 检查点 |
--gmail-no-send | bool | false | 阻止 Gmail 发送操作(Agent 安全) |
--gmail-refresh-cache | bool | 即使本地备份缓存已有条目也重新抓取 Gmail 邮件 | |
-h--help | kong.helpFlag | 显示上下文相关帮助 | |
--home | string | 覆盖 gogcli 的 config/data/state/cache 根目录(等价于GOG_HOME) | |
--identity | string | 本地 age 身份路径 | |
--include-spam-trash | bool | true | 包含 Gmail 垃圾邮件与回收站 |
-j--json--machine | bool | false | 向 stdout 输出 JSON(最适合脚本) |
--max--limit | int64 | 0 | 最多导出的 Gmail 邮件数;0 表示全部 |
--no-input--non-interactive--noninteractive | bool | 从不提示;失败即退出(适合 CI) | |
--no-push | bool | 仅在本地提交,不推送到远程 | |
-p--plain--tsv | bool | false | 向 stdout 输出稳定、可解析的纯文本(TSV;无颜色) |
--query | string | 用于有界/测试备份的 Gmail 查询 | |
--quota-project | string | 承担 API 用量费用的 Google Cloud 项目(作为 X-Goog-User-Project 发送;部分 API 在使用--access-token或 ADC 时需要) | |
--readonly | bool | false | 在运行时阻止变更型 API 请求;auth add也会请求只读 OAuth 作用域 |
--recipient | []string | 公共 age 接收者(可重复) | |
--remote | string | 备份 Git 远程 URL | |
--repo | string | 本地备份仓库路径 | |
--results-only | bool | JSON 模式下只输出主结果(丢弃 nextPageToken 等信封字段) | |
--select--pick--project | string | JSON 模式下选择逗号分隔的字段(尽力而为;支持点路径) | |
--services | string | gmail | 逗号分隔的待备份服务列表 |
--shard-max-rows | int | 1000 | 每个加密分片的最大行数 |
-v--verbose | bool | 开启详细日志 | |
--version | kong.VersionFlag | 打印版本并退出 | |
--workspace-max-files | int | 0 | 每类 Docs/Sheets/Slides 的原生 Workspace 元数据最大文件数;0 表示全部 |
--workspace-native | bool | 在 Drive 导出之外,额外抓取完整的原生 Docs/Sheets/Slides API JSON | |
--wrap-untrusted | bool | false | JSON/raw 输出中,将抓取的文本字段包裹在外部不可信内容标记内 |
从 internal/cmd/backup.go 可见 push 命令会校验参数合法性:--max、--drive-content-max-bytes、--workspace-max-files、--gmail-checkpoint-rows、--gmail-checkpoint-interval必须非负,--shard-max-rows必须大于 0,--drive-content-timeout必须大于 0,否则直接以 usage 错误退出——这保证了在发起昂贵抓取之前参数即已有效。
默认启用的行为开关
gog backup push默认开启以下四项关键能力(docs/backup.md):
--drive-contents:下载/导出 Drive 文件内容进加密分片;用--no-drive-contents做仅元数据 Drive 备份;--drive-collaboration:备份每文件的权限、评论、修订元数据;用--no-drive-collaboration跳过;--gmail-cache:在本地缓存抓取的原始 Gmail 邮件;用--no-gmail-cache关闭;--best-effort:可选服务出错时把错误记录为加密errors分片并继续,而不是中断整个备份;用--no-best-effort让错误直接上抛。
--drive-content-timeout(默认 2m)约束单个 Drive 文件的导出/下载耗时,超时的文件被表示为加密错误行,这样一次卡住的 Google 导出不会拖垮整个运行。--drive-content-max-bytes则允许你跳过体积过大的单文件下载。建议仅在明确需要把非 Google 二进制文件字节放进 Git 分片时才开启--drive-binary-contents(个人 Drive 很容易包含数十 GB 二进制内容);同理,仅当需要比可读 Drive 导出更重的原生 API JSON 时才开启--workspace-native,并用--workspace-max-files限制原生抓取规模用于冒烟测试。
支持的服务清单
--services接受逗号分隔的服务名,all展开为全部服务(常量定义见 internal/cmd/backup.go):
gmail:标签与原始 MIME 邮件;gmail-settings:过滤器、转发地址、自动转发、send-as 别名、假期回复、委托可见性、POP、IMAP 与语言设置;calendar:日历列表条目、ACL、设置/颜色以及全部事件(含已删除事件);contacts:People API 联系人、其他联系人与联系人分组;tasks:任务列表与任务(含已完成、已删除、隐藏与指派任务);drive:共享云端硬盘、文件元数据、权限、评论、修订元数据以及下载/导出的文件内容;workspace:Docs/Sheets/Slides 清单,加上通过 Drive 发现的 Forms 与表单响应;appscript:通过 Drive 发现的 Apps Script 项目与源码内容;chat:聊天空间与消息(账户/API 允许时);classroom:课程、主题、公告、作业、材料与提交内容;groups:账户所属 Cloud Identity 群组及成员列表(仅 Workspace,需显式 Workspace 账户 + service-account 委派或等效的cloud-identity.groups.readonly直连 token/ADC 访问);admin:Workspace Admin Directory 用户、群组与群组成员(需既有 Admin SDK/全网域委派配置);keep:Google Keep 笔记(仅 Workspace,需既有 Keep service-account 配置)。
Drive 内容导出的默认格式为:Google Docs 导出.docx与 Markdown,Sheets 导出.xlsx,Slides 导出.pptx与 PDF,Drawings 导出 PNG 与 PDF,二进制文件仅保留元数据(除非设置--drive-binary-contents)。groups、admin、keep为 Workspace-only 服务,普通消费者账户访问会得到加密错误行(--best-effort下)。
加密管线与仓库布局
每次 push 的分片写入由 internal/backup/backup.go 的PushSnapshot驱动,加密细节在 internal/backup/crypto.go。对每个分片,管线为:
- 导出确定性 JSONL 行(
encodeJSONL逐行 JSON 编码,见 backup.go); - 用固定 gzip 时间戳(Unix 0)压缩 JSONL——固定时间戳让相同内容的 gzip 输出确定,便于增量检测;
- 用
filippo.io/age的 X25519 对每个配置的接收者加密压缩字节; - 只向 Git 写入加密的
*.jsonl.gz.age文件(临时文件先写.shard-*.age,随后原子 rename 并chmod 0600,见 crypto.go); - 写入明文
manifest.json,内含供 status/verify 使用的元数据。
备份仓库布局(密文分片按账户哈希分目录、Gmail 邮件按月分桶):
README.md manifest.json data/gmail/<account-hash>/labels.jsonl.gz.age data/gmail/<account-hash>/messages/YYYY/MM/part-0001.jsonl.gz.age data/calendar/<account-hash>/... data/contacts/<account-hash>/... data/drive/<account-hash>/... data/tasks/<account-hash>/... data/groups/<account-hash>/... data/admin/<account-hash>/... data/keep/<account-hash>/...账户哈希是sha256(小写账户字符串)的前 12 字节 hex(见 internal/cmd/backup.go),用来避免在路径中直接出现邮箱明文。Gmail 邮件分片先按邮件InternalDate归入YYYY/MM月桶,桶内按内部日期与消息 ID 排序,再按行数与保守的明文字节上限切分(分片默认最多 1000 行、32 MiB 明文上限,见 internal/backup/gmail/planner.go 与 backup.go),超大邮件也不会产生被 GitHub 拒绝的巨型 blob。
manifest.json:刻意保持明文的元数据
manifest.json是有意不加密的(结构定义见 internal/backup/backup.go),它包含格式版本、导出时间、公共 age 接收者、服务名、账户哈希、分片路径、行数、加密字节大小以及用于校验的明文 SHA-256 哈希。它不包含邮件主题、发件人、收件人、正文、原始消息 ID 或标签。因此它必然向仓库读者泄露以下运维元数据:导出时间、公共接收者、服务名、账户哈希、分片路径与月桶、行数、加密字节大小、明文分片哈希、备份节奏与 Git 历史中哪些分片发生了变化。
账户哈希不是匿名手段——它只是避免把邮箱字面量写进路径;能猜到地址的人可以算出并比对同样的哈希。备份启动时还会调用rejectSymlinkPath(backup.go)拒绝仓库内任何符号链接,防止路径逃逸;读取时resolveShardPath会把分片路径严格限制在data/与checkpoints/目录下的.age文件内(backup.go)。
断点续传:Gmail 缓存与检查点
大邮箱全量备份可能耗时数小时,为此--gmail-cache(默认开启)会在本地 OS 用户缓存目录gogcli/backup/gmail/<account-hash>/下缓存抓取结果:消息列表分页检查点位于list-v1/,已抓取的原始消息位于raw-v1/,缓存文件以 Gmail 消息 ID 的 SHA-256 为键,存储的正是将要加密进分片的同一行。中断后重跑可以复用已抓取的消息,且加密分片是从缓存流式构建的(internal/backup/gmail/planner.go),因此全量邮箱备份不会把所有原始邮件常驻内存。--gmail-refresh-cache强制重新抓取;缓存是本地明文数据,若你希望机器上不保留加密备份/导出之外的本地邮件副本,请清理该目录。
对于启用缓存的长时间抓取,--gmail-checkpoints(默认开启)会把不完整的加密检查点快照推入备份 Git 仓库:检查点分片与清单位于checkpoints/gmail/<account-hash>/<run-id>/,使用与普通分片相同的 age 接收者加密,提交信息形如checkpoint: gmail backup 20000/359635,清单带"incomplete": true标记(见 internal/backup/backup.go 的CheckpointManifest)。status、verify、cat、export始终以根manifest.json为权威完成态,不会把部分数据当作成品快照。
检查点提交经由单一有序的后台队列推送(internal/backup/async_push.go):gogcli 记录确切提交 SHA、继续缓存抓取、逐个推送排队的 SHA。瞬时推送失败会重试(最多 3 次、指数退避,见 async_push.go);GitHub 硬性拒绝(如GH001、Large files detected、pre-receive hook declined,见 async_push.go)会终止后续检查点,因为后续提交会继承被拒对象。最终完成的备份会等待队列排空,然后把已完成的检查点消息分片提升进根清单,而不是把整个邮箱再加密成第二个数 GB 的最终推送。检查点复用通过精确的有序消息 ID 指纹判定,并要求清单运行、服务、账户、行数与加密接收者保持兼容。
调节提交节奏的参数:--gmail-checkpoint-rows(默认 10000)/--gmail-checkpoint-interval(默认 30m),置 0 禁用对应触发条件;--no-gmail-checkpoints完全禁用检查点推送。Gmail 专用变体gog backup gmail push使用--checkpoint-rows/--checkpoint-interval。
安全边界与信任模型
加密分片保护的是 Google 内容本身:邮件正文、主题、发件人、收件人、原始 MIME 载荷、标签、Drive 文件名、联系人、事件标题等。当前信任模型(见 docs/backup.md):
- 机密性:只要
~/.gog/age.key保持私密,对私有 GitHub 备份仓库而言是可靠的; - 对随机损坏的完整性:age 认证、gzip 解码、明文 SHA-256 与行数校验可捕获损坏分片(
verify的实现在 backup.go:逐片解密、比对哈希、比对 JSONL 行数); - 对仓库写入方的完整性:有限。任何有推送权限的人都可能用公共接收者加密不同数据来替换备份内容,因此应限制仓库写权限并审查异常提交;
- 密钥泄露:若
AGE-SECRET-KEY-...泄露,Git 历史中的历史分片可能被解密。应轮换接收者、重新加密,并把旧 Git 历史视为已暴露(除非重写历史并清除所有副本)。
已知的加固方向包括:清单只存密文哈希、把明文哈希移入加密分片元数据;用本地签名密钥签名清单或提交,让verify能证明备份的创建者;以及为在意尺寸侧信道的部署场景增加分片填充或禁用 gzip。另外,加密分片头部被限制为 2 MiB 与 1024 个接收者 stanza,读取方会拒绝超限分片。
干跑、输出与配套命令
gog backup push --dry-run只校验选项并打印预期备份计划,不会认证、接触 Google、访问仓库、创建缓存或检查点、也不会写任何文件(实现见 internal/cmd/backup.go,输出服务、仓库、远程、身份、接收者、推送开关与 Gmail 相关参数);gog backup gmail push --dry-run行为一致。backup init/status/verify/cat/export的--dry-run同理只打印解析后的仓库/拉取计划。--no-push让 push 只提交到本地仓库而不推远程(对应backup.Options.Push,见 internal/cmd/backup.go)。-j/--json输出机器可读结果(repo、changed、encrypted、shards、按服务聚合的count.*),便于脚本与 CI;-p/--plain输出稳定 TSV。长 Gmail 运行的 list、fetch、shard-build 计数器写入 stderr,stdout 保持可解析。- 推送完成后可用
gog backup status检查明文清单元数据、gog backup verify解密每个分片并校验哈希与行数、gog backup cat解密单个分片、gog backup export生成未加密的本地可读副本(如--gmail-format markdown导出带 YAML 元数据的message.md与attachments/目录)。status/verify/cat/export会先拉取或克隆配置的远程;--no-pull直接读取本地状态。所有读命令在仓库缺失或克隆失败时都不会新建 Git 仓库;配合--no-input时,Git 操作会禁用凭据/UI 提示与 SSH 密码提示。
推荐的落地实践
- 先小后大:首次使用
--services gmail --query 'newer_than:7d' --max 25做有界冒烟测试,确认认证、加密、推送链路全部正常后再--services all全量; - 控制本地缓存:默认 Gmail 缓存与检查点是明文本地数据,明确机器上允许保留邮件副本,否则用
--no-gmail-cache --no-gmail-checkpoints; - 限制推送内容体积:为控制仓库体积,可用
--drive-content-max-bytes跳过超大单文件、用--no-drive-binary-contents(默认)不收录非 Google 二进制字节、用--no-drive-collaboration跳过每文件协作元数据; - CI 化之前先干跑:
--dry-run+--no-input可在不触碰任何远程资源的前提下验证参数组合与备份计划; - 密钥管理:
age1...公共接收者可以安全写进~/.gog/backup.json与manifest.json,AGE-SECRET-KEY-...私钥必须留在本地或密码管理器中;可重复使用--recipient为多个接收者加密同一份备份。
更多细节可参阅备份总览 docs/backup.md、父命令 gog backup 与完整命令索引 docs/commands/README.md。
【免费下载链接】gogcliGoogle Workspace in your terminal.项目地址: https://gitcode.com/GitHub_Trending/gogcl/gogcli
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考