feat(#2862): push a snapshot to a peer hive's store over the mesh

Adds the caller the fd-passing machinery existed for: hivectl agent
<name> subvol snapshot push --peer <hive> resolves the peer, connects
to its snapshot store, writes the agent header, and hands the connected
socket to hive-priv, which runs btrfs send straight into it.

The split keeps the root helper ignorant. Everything that involves
knowing where a peer is, what the wire protocol looks like, and which
hive to trust happens in the unprivileged daemon; hive-priv only ever
receives an already-open descriptor. Once btrfs send starts, neither
process is in the data path, so a multi-gigabyte transfer costs no
per-byte work and survives a hive-c0re restart.

call_with_fd takes the descriptor by value and closes it as soon as the
kernel has it. A socket stays open until every copy closes, so holding
one back would leave the receiver waiting for an EOF that never comes:
btrfs receive blocks and this side reports success for a transfer the
peer never committed. Ownership makes that unrepresentable.

The peer's store port is a new swarm.peers.<domain>.snapshotStorePort
option rather than a constant matching the module default. A pushing
hive cannot read the receiver's configuration, so assuming 51821 would
push at a port nobody promised to listen on; absent, the push fails
naming the option. swarm_peers parses the mesh address the host module
has always rendered into HYPERHIVE_PEERS but nothing read.
This commit is contained in:
atlas 2026-07-31 21:40:34 +02:00 committed by mara
commit 282bbc3709
10 changed files with 546 additions and 9 deletions

View file

@ -105,6 +105,25 @@
are silently excluded from `wg-hive`).
'';
};
snapshotStorePort = lib.mkOption {
type = lib.types.nullOr lib.types.port;
default = null;
example = 51821;
description = ''
TCP port this peer's snapshot store listens on, when it
runs one (`services.hyperhive.snapshotStore`). Injected
into `HYPERHIVE_PEERS` so a pushing hive can reach the
receiver at `wireguardAddress:snapshotStorePort`.
Null means this peer hosts no snapshot store, and pushing
to it fails with that message rather than guessing a port.
The port lives here on the peer, alongside the mesh
address it pairs with because it describes *that host's*
deployment, and a pushing hive cannot read the receiver's
own configuration.
'';
};
};
}
);