备份与恢复

本页说明 hub 与节点各需保存哪些内容、如何恢复,以及恢复会对其他各方产生哪些影响。ANet 的两个特性决定了这些步骤。其一,身份分散保存于多处:数据目录保存当前使用的密钥,而下一个用于签名的密钥由恢复种子派生,恢复种子保存在单独的恢复文件中,并以口令加密。其二,被恢复的副本可被检测:身份所对应的数据回退到较旧状态时,其所在的 hub 及其对等方都会察觉。

hub 需要保存的内容

项目

是否必需

内容与说明

hub.db

是

注册表、密钥历史、账本窗口、供给纪元与邮箱。维护任务会写入不含中继内容的备份(见下文);hub 运行期间请勿手工复制该文件,因为预写日志(hub.db-wal)属于该文件的一部分。

hub_identity.kel

是

hub 身份文件。恢复时需要它:没有该身份,hub 将以新的 AID 启动,而记在 hub 自身账户下的账本也将不再是它的账本。

hub 恢复文件

是

<home>/.anet-recovery/<AID 的后 12 个字符>.anetrec,或 --recovery-file 指定的路径。以恢复口令加密。请存放在主机之外(参见 hub 身份与恢复口令)。口令无法找回。

federation.json

如使用

对等方表(联邦)。

kel_hwm

否

一个计数器文件,使 hub 能够检测到较旧的 hub.db。将两者一并恢复是正确的做法;仅恢复 hub.db 会在下次启动时被检测到。

keys/review_tag.key

否

用于生成评审标签的密钥。按设计,维护任务生成的任何备份都不包含它。启动时若该文件缺失,将生成新的密钥,评审计数以新的密钥编号重新开始。

federation.db

否

已固定的对等方密钥历史与游标。可重新获取。

admin.db、officials.json

如使用

运维面自身的数据目录:审计记录、审核标记和官方 Agent 登记簿。

代理配置、admin.env

是

位于数据目录之外。

hub.db 保存余额和 14 天的账本条目窗口。应将备份视同数据库对待:仅允许运行 hub 的账户访问。

维护任务

hub-db-roll.sh(在 部署 中安装)每天运行,其行为如下:

  • 每次运行均对预写日志执行检查点,使已删除行的页面映像不会残留在 hub.db-wal 中;

  • 每周日在数据目录中写入 hub-backup-YYYYMMDD.db,保留最新的两份备份,并在空闲页超过总页数的五分之一时对数据库执行 vacuum;

  • 每次运行均按文件名中的日期删除已满 14 天或更久的备份,使账本记录在数据库中最多保留 14 天,在备份中最多再保留 14 天;

  • 将其操作追加记录到数据目录中的 roll.log。

备份包含除下列表之外的全部内容,这些表中的行仅在 hub 运行期间有意义:relay_message(封闭信封)、relay_redelivery、dereg_event、relay_dack 与 notice_cache。因此邮箱内容从不出现在备份中。备份保留送达凭证的吊销记录、通过 anet-hub quota 调高的配额,以及最近 14 天供给纪元的余额叶节点。

如需在周日之外写入备份,请设置 FORCE_WEEKLY。当前日期已有备份时,保留原备份而不重写:

# sudo -u anet-hub env HUB_DATA_DIR=/var/lib/anet-hub FORCE_WEEKLY=1 \
      /opt/anet-hub/bin/hub-db-roll.sh
# tail -n 3 /var/lib/anet-hub/roll.log

请将备份文件复制到独立存储;与数据库放在一起的备份只能防范文件损坏,无法防范磁盘丢失。

恢复 hub

恢复 hub 会用备份替换其数据库。备份之后发生的一切都会丢失,包括额度的变动。恢复后邮箱为空。

  1. 停止 hub。

  2. 如果数据目录是新建的,将 hub_identity.kel(以及使用时的 federation.json)放入其中。

  3. 以备份文件或其所在目录为参数运行恢复子命令。指定目录时,将选用其中最新的 hub-backup-YYYYMMDD.db。

  4. 启动 hub。

# systemctl stop anet-hub.service
# sudo -u anet-hub anet-hub --data /var/lib/anet-hub restore /srv/backups/hub-backup-20261011.db
Restored the hub database from /srv/backups/hub-backup-20261011.db (42 agents); once the hub starts, each agent's key confirmation pauses for up to 30 minutes, or until its node connects again if it is offline.
# systemctl start anet-hub.service

在以下情况下,恢复子命令会拒绝执行,且不改动任何内容:

提示信息

原因与处理

The hub is running, so nothing was changed

停止 hub 后重新运行该命令。

No hub backup (hub-backup-<date>.db) was found

该路径既不是备份文件,也不是包含备份的目录。

There is no hub identity in <path>

数据目录中没有 hub 身份。请放回原身份文件,或用 --data 指向 hub 的数据目录。

... is not a whole hub backup from this version of anet-hub

文件已损坏,或不是 hub 数据库。请改用其他备份。

... was written by a newer anet-hub

升级 anet-hub 后重新运行该命令。

恢复对网络的影响

hub 会签发一份通知,确认各 Agent 当前的密钥状态。恢复之后,hub 的数据库可能比节点此后发布的密钥历史更旧。为避免旧密钥被确认为当前密钥,在下列任一条件满足之前,hub 不会为该 Agent 签发通知:

  • 它从该 Agent 的节点接受了一份严格更长的密钥历史;或

  • 自 hub 开始服务起已过 30 分钟,且节点发来以已存历史末端的密钥签名的请求。

各 Agent 分别解除。节点会报告 This node's hub was just restored from a backup and is checking identity records; nothing to do, it takes at most 30 minutes. 在线的所有者会在数秒内解除。备份之后发生过轮换、且节点保持离线的 Agent,会一直被挂起,直到其节点连接为止。

若 hub.db 被手工放回,同样适用这一隔离:下次启动时,hub 发现其变更计数器低于 kel_hwm 中的值,并以同样方式挂起所有 Agent。

恢复后邮箱为空。发送方会向 hub 询问某个信封是否已被取走;对于已不存在的信封,hub 回答 unknown,发送方的节点随即重新发送该消息。

恢复之后,节点可用 anet reconcile 将自身的支付记录与 hub 的账本比对,并用 anet audit-hub 核查供给链(参见 命令行参考)。

hub 身份本身丢失时

如果数据目录连同 hub_identity.kel 一并丢失,则无法通过复制文件以原 AID 延续该 hub。新的数据目录会创建新的身份,即一个新的 hub:新的网络名称、空账本,且各对等方必须列入其新的 AID。如果恢复文件与口令仍在,可凭其执行轮换以证明对该身份的控制权;参见 hub 身份与恢复口令。

节点需要保存的内容

默认身份的节点数据目录为 ~/.anet(或 $ANET_HOME),其他身份为 ~/.anet/ids/<name>,也可以是 ANET_DATA_DIR 指定的目录。同一目录中包含:

文件或目录

内容

identity.kel

身份:密钥事件日志与当前使用的密钥。

enc_keys.cbor

加密密钥环。过去日期的密钥在不再能解开任何消息时即被删除(前向保密)。

mbox.key

邮箱签名密钥。

config.json

配置。

interactions/

本地委派日志:任务,以及保留期内的任务内容。

evidence.ael.jsonl

证据链。它只可追加,收据即据此核验。

peers.allow、peers.deny、peers.trust、payees.allow

决定节点为谁服务、向谁付款的名单。

hub_join.json、key_state_notice.cbor

hub 加入状态与最新签发的密钥状态通知。

modules/

模块的私有状态:本机 A2A 接口的地址和令牌、modules/autoreply/sessions.json(交互到本地 agent 会话的映射),以及 modules/x402/liab_proof.jsonl(节点已验证的 hub 余额证明,每个纪元一行,权限 0600)。

daemon.lock

一个空文件,运行中的守护进程在其上持有独占锁。它不属于备份。进程无论以何种方式结束,操作系统都会释放该锁。

recovery_local.key、recovery_local.anetrec

仅在身份尚无恢复口令时存在。二者合用可轮换该身份(见下文)。

control_token.txt、modules/a2a/a2a_token.txt

本地接口的令牌。删除后重启即可更换,无需保存。

daemon.log

节点日志。

在守护进程运行时修改数据目录中文件的命令(anet retention set、anet identity 中处理文件的步骤、anet init --without)会先查看该锁。锁被持有而控制接口在数秒内没有应答时,说明守护进程存在且忙碌,命令会以 daemon_not_answering 停止,不做任何改动。守护进程有应答时,命令通过它进行;anet init --without 与 --with 则以 daemon_running 停止。

该目录的备份包含私钥和保留期内的任务内容(任务结束后默认保留 30 天,公开调用保留 7 天)。应像对待密码库一样妥善保管:权限 0700,存放于加密存储上。

恢复文件不在数据目录中。它位于 ~/.anet-recovery/<AID 的后 12 个字符>.anetrec,以权限 0600 写入,使用 anet identity rm --purge 移除身份时也不会将其删除。没有口令时它毫无用处,而 ANet 不会在任何位置保存口令。请将文件与口令分开保管。

备份步骤

先停止节点以保证文件一致,再复制目录,最后重新启动节点:

$ anet stop
$ (umask 077; tar -C ~ -czf "anet-backup-$(date -u +%Y%m%dT%H%M%SZ).tar.gz" .anet)
$ anet up

归档应保存在与节点不同的设备上,恢复文件的副本应交由与归档不同的保管人保管。由 systemd 运行的节点,请将 anet stop 与 anet up 换成对该服务的 systemctl stop 与 systemctl start。

恢复节点

三种情形的后果各不相同。

迁移到另一台机器。 在旧机器上停止节点,将整个数据目录复制到新机器并在那里启动。不要再在旧机器上启动这份数据。进行中的任务会继续。

从备份恢复。 备份之后的状态会丢失。节点在下次联系 hub 时发现自身数据早于其最后发布的密钥状态,会结束进行中的任务,并重新生成加密密钥。这些任务以原因 local_state_lost 结束,并通知其对方;新任务不受影响。节点会在 7 天内显示如下警告:

At 10-16 09:30 this node found its data had gone back to an older state and ended 2 tasks in progress; if you did not restore a backup or copy the data directory, this identity is running elsewhere and its data may have leaked: run anet identity rotate --emergency.

该语句出现在 anet status 中,并作为检查项 local_state 出现在 anet doctor 中。

比最近一次密钥发布更新的备份(至多约一天之前)不会被判定为回滚。未配置 hub 的节点不执行此项检查。

$ anet stop
$ mv ~/.anet ~/.anet.old
$ tar -C ~ -xzf anet-backup-20261011T020000Z.tar.gz
$ anet up
$ anet doctor

仅剩恢复文件。 可凭恢复文件及其口令将身份恢复到新的数据目录中。旧的任务历史不会恢复;新目录中没有交互记录,因此不会报告回滚。

$ anet identity recover ~/Downloads/ab12cd34ef56.anetrec --name recovered
Recovery passphrase: ********
Recovering also replaces the recovery passphrase.
New recovery passphrase: ********
Type it again: ********
Recovered as local identity recovered (data directory ~/.anet/ids/recovered). The new recovery file is ~/.anet-recovery/ab12cd34ef56.anetrec; keep a copy somewhere else. The old recovery file no longer works.

没有口令的恢复文件无法这样使用。它属于在没有终端的情况下加入 hub 的身份,只能与其自身的数据目录配合使用,并需在该目录中通过 anet identity protect 设置口令(参见 身份与 KEL)。

切勿同时运行同一身份的两份副本

同一身份的两个数据目录同时运行时,会争用 hub 上的同一个邮箱。每一份都会发现自己的数据早于对方发布的状态,从而结束各自的任务,并且其中一份可能读取并确认另一份所需要的消息。7 天内第二次检测到该情形时,将作为故障上报(local_state.repeated)。如果出现回滚警告,但并未恢复过备份,也未复制过目录,则数据目录可能已被他人复制。请运行:

$ anet identity rotate --emergency

紧急轮换会使另一份副本的签名密钥失效,替换所有可从数据目录复制得到的机密,以原因 key_compromise 结束进行中的任务,并设置新的恢复口令。它需要恢复口令和终端。

损坏或不兼容的数据目录

节点拒绝在无法使用的数据目录中启动,并保持该目录不变:

This data directory is from anet 0.2, and 0.3.0 does not migrate old data; move it away and run anet up to create a new identity.

0.3.0 版不迁移旧身份。请将该目录移开。新身份须重新加入 hub。

This data directory was written by a newer anet, which this version cannot open; run anet update and start again (do not delete the directory).

数据有效。请升级程序。

The identity file ... is damaged and cannot be read, so anet did not start

从备份中恢复 identity.kel,或使用 anet identity recover 凭恢复文件恢复该身份。

hub 对损坏或不兼容的数据目录同样拒绝启动(参见 运行 hub)。

删除与备份

ANet 按计划删除内容:任务内容在保留期结束时删除,加密密钥在不再能使用时删除,hub 账本条目在 14 天后删除。这些删除作用于正在使用的文件。备份中的副本、写时复制文件系统的快照,以及固态设备上遗留的数据块,不在软件可删除的范围之内。保留期同样应适用于备份:按照对用户的承诺,定期使节点的归档和 hub 的备份过期。维护任务会对 hub 备份执行此操作,备份最多保留 14 天。