跳转到内容

备份与恢复

本指南涵盖人们实际用备份做的五件事:创建备份、取回副本、迁移工作区、恢复备份,以及把副本保存在机器之外。关于每种产物和每项操作的确切形态,请参阅 备份参考。

本节所有内容都位于设置 → 服务器 → 备份与恢复。

  • 一个完整客户端——桌面应用或 Web 应用。已配对的手机按设计无法触发其中任何操作。
  • 要创建、列出、下载或删除安装快照:需要该安装的所有者。
  • 针对单个工作区的操作:导出需要该工作区的管理员,导入或删除需要所有者。
  • 下载和上传:需要与服务器的直接连接。中转中继承载的是 RPC 帧,而不是文件传输;当你处于中继连接时,传输控件会自动禁用并显示一条说明。

这两种产物都只包含数据库:

  • 安装快照是一个带时间戳的目录:manifest.json、global.db,以及每个工作区一个 <workspaceId>/workspace.db。
  • 工作区导出就是那单个 workspace.db 文件。

两者都不包含数据目录的其余部分:secrets.json(配对密钥、提供方 凭据、SSO)、工作区的 blobs/(粘贴到消息中的图片)、skills/、 agents/、chat_credentials/、录制的会议音频或机台镜像。其中有些 可以舍弃,有些则不能—— 完整表格见参考, 而涵盖这些内容正是机器之外一节的目的。

  1. 打开设置 → 服务器 → 备份与恢复。
  2. 在安装快照下,点击立即备份。
  3. 提示条会显示在服务器主机上写入的目录。新快照会出现在列表顶部。

整个过程服务器始终保持运行。每个文件都用 VACUUM INTO 写入,它对运行中的数据库 是一致的,因此无需维护窗口,也不必停止智能体。

列表中的每一行都会显示时间戳、磁盘上的大小、捕获了多少个工作区,以及该快照是 完成还是未完成。未完成意味着清单缺失,或引用了不存在的文件—— 备份被崩溃或磁盘写满中断。这些仍然会被特意列出:看不见的快照,就是你以为自己 拥有的快照。未完成的快照无法恢复整个安装,但它确实包含的工作区文件仍可逐个采用。

某一行也可能显示 n 个工作区未捕获。这表示该工作区已注册但从未写入 (还没有文件),或其副本复制失败——请检查服务器日志。

打开该工作区的设置 → 流水线 → 流水线模板,找到 Workspace backup。其已启用的计划在每周日 03:00 UTC 运行: Back up workspace,接着是 Delete backups older than(默认 30 天)。第二个节点仅在备份成功后运行。你可以修改节点上的保留天数,或停用 该计划。如果服务器在计划时间处于离线状态,它恢复后会补跑一次,而不会把 错过的每一周都重放一遍。

工作区备份存放在服务器上的 backups/workspace-backups/<workspaceId>/<timestamp>/workspace.db。保留 节点只删除此工作区的旧备份;它绝不会删除安装快照或其他工作区的备份。这些 文件只包含数据库。若要在机器之外保留,请单独复制它们。

这些备份与安装快照列表相互独立。要恢复其中之一, 请使用工作区数据 → 导入,并填入该备份在服务器端的 workspace.db 路径。导入会替换该工作区当前的数据库,因此如果之后可能需要撤销恢复,请先将其 导出。

在安装快照下,展开该快照(包括未完成的快照), 并使用危险区域中的删除快照。确认其名称。整个 快照目录会从服务器上永久移除;如果需要保留副本,请先下载。工作区备份 流水线绝不会删除这些快照。

页面上显示的路径位于运行 cc_server 的机器上。如果那不是你正在使用的机器, 请使用下载按钮:

  • 在工作区数据下每个工作区旁的下载,用于获取一个 .db 文件。
  • 在安装快照下每个快照旁的下载,用于获取整个快照的 .zip。

在桌面端,你可以选择文件的保存位置,提示条会显示该位置;在 Web 端,它会进入 浏览器的下载目录。两种方式都会以字节为单位报告进度,因为这两类负载都可能达到 数 GB。

两者都会在按下按钮的那一刻生成一份全新副本,流式传输,并在之后删除服务器上的 副本——下载并不是“取回导出按钮先前生成的文件”。

解压快照归档会精确还原快照的目录结构,正因如此,恢复它就只是把内容复制回去。

一个工作区就是一个数据库文件,因此移交它就是一次文件操作。

  1. 在源服务器上,进入设置 → 服务器 → 备份与恢复 → 工作区数据,展开该工作区并点击下载。
  2. 在目标服务器上,创建(或选择)接收它的工作区。
  3. 展开该工作区,在从此设备恢复下点击选择文件并上传。选择你下载的 .db 文件。

如果两台服务器都是你正在使用的这台机器,保存到服务器加 导入 → 选择文件也能达到相同效果,且无需往返传输;导入 对话框中的路径在服务器主机上解析。

有两种情况会被允许并记录日志,而不是被拒绝:导入的文件所记录的 workspace id 与目标不同(这正是复制工作区或以新 id 恢复它的方式),以及导入 来自另一个安装的文件。在后一种情况下,该文件已配对的设备与用户 id 属于它 来源的那个安装,无法在这个安装上解析——工作区自身的数据完好无损,但采用之后请 重新检查成员关系。

聊天机器人令牌存放在数据库旁边,而不是其中,因此你交给别人的工作区不携带任何 有效凭据。接收方的安装会重新连接自己的凭据。

  1. 在安装快照下,展开你想要的那个快照。
  2. 找到该工作区所在的行,点击恢复。
  3. 确认。该工作区自拍摄快照以来的所有操作都会丢失。

这与导入是同一项操作,只是指向快照中该工作区文件的副本——这是有意为之,这样 就不会有第二套机制对同一个文件做出不同处理。

某一行可能显示已不在此服务器上,且恢复被禁用:该快照 包含一个此安装已不再拥有的工作区。请手动把它恢复回来——创建一个工作区, 然后在工作区数据下从 <snapshot path>/<old workspace id>/workspace.db 导入到其中。展开的快照会在 一个可复制的字段中显示它自己的服务器上的路径,而该行的标题就是旧的 工作区 id,因此该路径的两半都在你眼前。

对此没有按钮,也不应该有:它会替换正在运行的服务器所持有的数据库。

  1. 停止 cc_server。 如果你运行的是带内嵌服务器的桌面应用,请退出该应用。

  2. 将快照的内容复制到数据目录之上。快照的目录结构与实时目录一致,因此这就是一次普通复制:

    终端窗口
    # macOS default; see the CLI reference for other platforms
    DATA_DIR="$HOME/Library/Application Support/control-center"
    SNAPSHOT="$DATA_DIR/backups/2026-07-28T09-12-33-000Z"
    cp "$SNAPSHOT/global.db" "$DATA_DIR/global.db"
    for d in "$SNAPSHOT"/*/; do
    id=$(basename "$d")
    mkdir -p "$DATA_DIR/$id"
    cp "$d/workspace.db" "$DATA_DIR/$id/workspace.db"
    done
  3. 删除任何紧挨着你所替换数据库的 -wal 和 -shm 文件。它们属于旧文件,与恢复后的数据库放在一起的过期文件会带来损坏风险。

  4. 再次启动服务器。

快照不包含 secrets.json,因此恢复到全新主机的安装会保留数据,但不保留 其凭据:已配对的设备、提供方令牌和 SSO 设置都必须重新建立,或从你保存该文件的 地方恢复。恢复到同一主机时,secrets.json 从未丢失,一切都会保留。

与所复制的数据库位于同一块磁盘上的快照,能让你免受一次糟糕导入的影响,却挡不住 磁盘故障。Control Center 不会把副本发送到任何地方,所以这部分得靠你自己。

快照一旦写入便不可变,并以时间戳命名,因此任何同步工具都能很好地处理它们。 排除 transfer/,它是进行中下载和上传的工作台:

终端窗口
DATA_DIR="$HOME/Library/Application Support/control-center"
# To another host over ssh
rsync -a --delete --exclude 'transfer/' \
"$DATA_DIR/backups/" backup-host:/srv/control-center-backups/
# To object storage
aws s3 sync --exclude 'transfer/*' \
"$DATA_DIR/backups/" s3://my-bucket/control-center/backups/
# Or with deduplication, encryption and its own retention
restic backup --exclude 'transfer' "$DATA_DIR/backups"

--delete 会把你在本地的清理镜像到远端。如果你希望远端比主机保留更长时间的快照, 就去掉它。

为了能够重建整个安装而不只是它的数据,也要复制以下内容。它们是 普通文件,在服务器运行时复制是安全的:

终端窗口
rsync -a \
"$DATA_DIR/secrets.json" \
backup-host:/srv/control-center-backups/config/
rsync -a --relative \
"$DATA_DIR"/./*/chat_credentials \
"$DATA_DIR"/./*/blobs \
"$DATA_DIR"/./*/skills \
"$DATA_DIR"/./*/agents \
backup-host:/srv/control-center-backups/workspace-files/

secrets.json 的权限是 0600,保存着该安装上的每一个配对密钥、提供方凭据和 SSO 设置。它落到哪里,哪里就必须至少与服务器主机同样受保护—— 静态加密,而且不是任何他人都能读取的存储桶。

跳过 spaces/(写时复制工作树,会从你的仓库重新预配)、pr_clones/ (缓存)、models/(会重新下载)、media_cache/ 和 rigs/(机器状态, 且体积大)。如果你保留会议,meetings/ 下录制的会议音频值得一并纳入。

内置流水线只备份一个工作区。对于无人值守的整个安装快照, 没有 CLI 子命令,而且快照 RPC 需要一个配对且为该安装所有者的完整 客户端。主机侧的定时器可以对实时数据库使用 VACUUM INTO:

#!/usr/bin/env bash
set -euo pipefail
DATA_DIR="${CC_SERVER_DATA_DIR:-$HOME/.local/share/control-center}"
DEST="/srv/control-center-snapshots/$(date -u +%Y-%m-%dT%H-%M-%SZ)"
mkdir -p "$DEST"
sqlite3 "$DATA_DIR/global.db" "VACUUM INTO '$DEST/global.db'"
for db in "$DATA_DIR"/*/workspace.db; do
id=$(basename "$(dirname "$db")")
mkdir -p "$DEST/$id"
sqlite3 "$db" "VACUUM INTO '$DEST/$id/workspace.db'"
done

以拥有数据目录的同一用户身份,通过 cron 或 systemd 定时器运行它,之后把 DEST 同步到主机之外。VACUUM INTO 需要 SQLite 3.27 或更高版本。

把它写到 <dataDir>/backups/ 的外部。那里的手工目录没有 manifest.json,因此应用会把它列为未完成的快照,列表也就不再是服务器 自身产物的如实记录。

你可以在应用中删除单个安装快照。对于主机侧的保留 策略,请让工作区备份目录与安装快照保持分离:

终端窗口
find "$DATA_DIR/backups" -mindepth 1 -maxdepth 1 -type d \
! -name exports ! -name transfer ! -name workspace-backups \
-mtime +30 -exec rm -rf {} +

在加上 -exec 之前,先检查一次 -print 运行的输出。保留不止一份:你 要防范的故障往往是“最近一次备份也存在同样的问题”。

一份从未被恢复过的备份只是一个假设。

低成本检查——文件能打开,且其页面完好:

终端窗口
sqlite3 "$SNAPSHOT/global.db" 'PRAGMA integrity_check;' # expects: ok

真正的检查——采用它。在一个非生产安装上创建一个临时工作区,把一份 工作区文件导入其中,然后看看你期望的空间、工单和消息是否都在那里。这会走一遍 真实恢复所走的同一条路径,包括 FTS 重建, 而它是唯一能告诉你备份可恢复、而不只是可读取的检查。

在配置备份时做一次,之后每当更改它们的存储位置时再做一次。

现象 原因与修复
下载和上传控件被禁用,并显示一条关于中继的说明 你正通过中继连接到服务器,而中继不承载文件传输。请改为直接连接
“服务器拒绝了” 角色问题。创建或列出安装快照需要该安装的运营者。下载工作区需要管理员,恢复工作区需要所有者,获取整个快照 zip 需要该安装的运营者
“此服务器没有备份接口” 该主机未接上备份端口——这是一个演示服务器。这些操作是缺席的,而不是被拒绝
“文件大于服务器接受的上限” 上传上限为 8 GiB。请把文件放到服务器主机上,改用导入 → 选择文件
导入被拒绝:不是 Control Center 工作区数据库 该文件没有 workspace_meta 行——它不是工作区导出,或者已被截断。没有任何内容被替换
快照被列为未完成 其清单缺失或引用了不存在的文件。请重新创建一份;在此期间可以从中逐个采用工作区文件
一份快照提示有工作区未被捕获 那些工作区从未被写入,或其复制失败了。请检查服务器日志
恢复后的安装没有代码托管或 SSO 凭据 secrets.json 不在快照中。请从你保存它的地方恢复它,或重新连接提供方
恢复后的工作区缺少粘贴的图片 Blob 位于数据库旁边,而不是其中。请一并复制 <workspaceId>/blobs/