Milestone 5: metered awareness, DSCP, systemd, man pages, packaging

Metered detection polls NetworkManager's Metered property over D-Bus
(feature "metered", default on; builds without D-Bus via
no-default-features). While metered the daemon closes incoming blob
connections and defers every fetch; VARDE_FORCE_METERED=true forces the
state as a kill switch and test hook. Endpoint UDP sockets get DSCP CS1
best-effort by matching bound ports to /proc/net/udp inodes (iroh hides
its fds). systemd socket activation adopts LISTEN_FDS fd 3, readiness
is a hand-rolled sd_notify READY=1 (abstract + path sockets), and
standalone binding still works unchanged. dist/ ships hardened system
and user units (DynamicUser, ProtectSystem=strict, StateDirectory,
RestrictAddressFamilies), a commented config example, scdoc man pages
validated with scdoc, and an untested PKGBUILD skeleton.

Tests: activation-socket round trip via a real fd-3 handoff, READY=1
received on a NOTIFY_SOCKET, metered daemons neither serve nor fetch.

Dependencies: zbus (optional, feature-gated D-Bus client for the
NetworkManager metered flag).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-15 08:07:24 +02:00
parent 20bdf56668
commit 871280553e
19 changed files with 1031 additions and 5 deletions
+49
View File
@@ -0,0 +1,49 @@
# Maintainer: you
#
# UNTESTED SKELETON — best-effort Arch packaging for varde. Review before
# building; in particular pkgver/source must point at a real release.
pkgname=varde
pkgver=0.1.0
pkgrel=1
pkgdesc="Content-addressed blob mirror daemon on iroh"
arch=('x86_64' 'aarch64')
url="https://github.com/bendiklh/varde"
license=('MIT OR Apache-2.0')
depends=('gcc-libs')
optdepends=('networkmanager: metered-connection detection')
makedepends=('cargo' 'scdoc')
source=("$pkgname-$pkgver.tar.gz::$url/archive/v$pkgver.tar.gz")
sha256sums=('SKIP')
build() {
cd "$pkgname-$pkgver"
export RUSTUP_TOOLCHAIN=stable
export CARGO_TARGET_DIR=target
cargo build --release --locked
scdoc < dist/varde.8.scd > varde.8
scdoc < dist/varde-ctl.1.scd > varde-ctl.1
}
check() {
cd "$pkgname-$pkgver"
# Integration tests spawn daemons and use the network; keep package
# builds to the fast unit tests.
cargo test --release --locked --lib -p varde-proto -p varde-daemon
}
package() {
cd "$pkgname-$pkgver"
install -Dm755 target/release/varde-daemon "$pkgdir/usr/bin/varde-daemon"
install -Dm755 target/release/varde-ctl "$pkgdir/usr/bin/varde-ctl"
install -Dm644 dist/varde.service "$pkgdir/usr/lib/systemd/system/varde.service"
install -Dm644 dist/varde.socket "$pkgdir/usr/lib/systemd/system/varde.socket"
install -Dm644 dist/user/varde.service "$pkgdir/usr/lib/systemd/user/varde.service"
install -Dm644 dist/user/varde.socket "$pkgdir/usr/lib/systemd/user/varde.socket"
install -Dm644 dist/config.toml "$pkgdir/etc/varde/config.toml"
install -Dm644 varde.8 "$pkgdir/usr/share/man/man8/varde.8"
install -Dm644 varde-ctl.1 "$pkgdir/usr/share/man/man1/varde-ctl.1"
}
+28
View File
@@ -0,0 +1,28 @@
# varde example configuration — /etc/varde/config.toml (system) or
# $XDG_CONFIG_HOME/varde/config.toml (user).
#
# Every key is optional; the daemon runs with an empty (or absent)
# config. Values shown are the defaults. Precedence:
# CLI flags > VARDE_* environment > this file > defaults.
# Directory holding the blob store, metadata and endpoint secret key.
# Default: /var/lib/varde (system) or $XDG_DATA_HOME/varde (user).
#store_dir = "/var/lib/varde"
# Unix socket serving the JSON-lines API.
# Default: /run/varde/varde.sock (system) or $XDG_RUNTIME_DIR/varde.sock.
#socket_path = "/run/varde/varde.sock"
# Upload cap in bytes/sec. 0 disables serving entirely.
#max_upload_bytes_per_sec = 10485760 # 10 MiB/s
# Download cap in bytes/sec. 0 means unlimited.
#max_download_bytes_per_sec = 0
# LAN peer discovery (mDNS). Discovery is the open tier: being visible
# costs nothing; serving is still gated on trust and per-pin policy.
#discovery = true
# Permit WAN traffic (enables the iroh relay for NAT traversal). Off by
# default: LAN-only posture, zero WAN upload.
#wan_upload = false
+15
View File
@@ -0,0 +1,15 @@
# varde per-user service (systemctl --user). Pairs with the user
# varde.socket; stores under $XDG_DATA_HOME/varde.
[Unit]
Description=varde content-addressed blob mirror daemon (user)
Documentation=man:varde(8)
Requires=varde.socket
[Service]
Type=notify
ExecStart=/usr/bin/varde-daemon --user
Restart=on-failure
NoNewPrivileges=yes
[Install]
WantedBy=default.target
+9
View File
@@ -0,0 +1,9 @@
# Socket activation for the per-user varde daemon.
[Unit]
Description=varde API socket (user)
[Socket]
ListenStream=%t/varde.sock
[Install]
WantedBy=sockets.target
+84
View File
@@ -0,0 +1,84 @@
varde-ctl(1)
# NAME
varde-ctl - control the varde blob mirror daemon
# SYNOPSIS
*varde-ctl* [*--socket* _PATH_] [*--json*] _COMMAND_ [_ARGS_]
# DESCRIPTION
Command-line client for *varde*(8), speaking the JSON Lines socket
protocol. Doubles as the protocol's reference implementation: every
subcommand maps 1:1 onto a request.
# GLOBAL OPTIONS
*--socket* _PATH_
Daemon socket (env: *VARDE_SOCKET*). Default:
_/run/varde/varde.sock_ as root, _$XDG_RUNTIME_DIR/varde.sock_
otherwise.
*--json*
Print the raw JSON response envelope instead of human output.
# COMMANDS
*add* [-r|--recursive] _PATH_
Import a file (or, with *-r*, a directory tree) into the store.
Prints the root hash. Content is not pinned by adding — pin it to
protect it from *gc*.
*pin* [--open-lan] _HASH_
Standing intent: keep this content, fetch it if absent, serve it to
trusted peers. *--open-lan* serves it to any LAN peer.
*unpin* _HASH_
Remove the intent. Data stays until *gc*.
*materialize* [--mode reflink-or-copy|copy] _HASH_ _DEST_
Export content to a path. The default mode reflinks when the
filesystem supports it and falls back to copying.
*status* [_HASH_]
Daemon status, or presence/completeness of one hash.
*list*
All pins with policy and completeness.
*ticket export* _HASH_
Print an iroh ticket for out-of-band sharing. Note: exporting
grants standing consent to serve that content to anyone (the
ticket holder is not on the allowlist).
*ticket import* [--open-lan] _TICKET_
Pin the ticket's content and fetch it from the embedded provider.
*peer trust* _NODE-ID_
Add a peer to the allowlist. Content is served to and auto-fetched
from trusted peers only. Applies to connections made after the
change.
*peer untrust* _NODE-ID_
Remove a peer from the allowlist.
*peer list*
Trusted peers and whether they are currently present on the LAN.
*gc*
Drop all blobs not reachable from a pin. Never runs implicitly.
*subscribe*
Stream daemon events (transfer progress, peer presence, pin
completion) as JSON lines until interrupted.
# EXIT STATUS
0 on success; nonzero with a structured error (code and message) on
stderr otherwise.
# SEE ALSO
*varde*(8)
+77
View File
@@ -0,0 +1,77 @@
varde(8)
# NAME
varde-daemon - content-addressed blob mirror daemon on iroh
# SYNOPSIS
*varde-daemon* [_OPTIONS_]
# DESCRIPTION
varde owns a content-addressed blob store and mirrors content between
consenting peers. Applications talk to it over a unix socket speaking
JSON Lines (one request per line, one response per line); *varde-ctl*(1)
is the reference client.
Discovery is open; replication is explicit. The daemon advertises itself
via mDNS on the local network (identifiable, never camouflaged), but
content is only served to peers on the trust allowlist, plus content
deliberately published per-pin (*open-lan*) or via ticket export. All
fetched data is BLAKE3-verified regardless of source.
Default traffic posture: LAN only (no relay), upload capped at 10 MiB/s,
UDP sockets marked DSCP CS1 (best effort), and all transfers stop while
NetworkManager reports the connection as metered.
# OPTIONS
*--config* _PATH_
Config file. Default: _/etc/varde/config.toml_ in system mode,
_$XDG_CONFIG_HOME/varde/config.toml_ in user mode. The default file
may be absent; an explicitly named one must exist.
*--store* _PATH_
Store directory override.
*--socket* _PATH_
API socket path override.
*--system*, *--user*
Force system-mode or user-mode default paths. Default: system when
running as root, user otherwise.
*--version*, *--help*
Print version or usage and exit.
# CONFIGURATION
See the commented example at _/etc/varde/config.toml_. Precedence:
flags > *VARDE_\** environment variables (*VARDE_CONFIG*, *VARDE_STORE*,
*VARDE_SOCKET*, *VARDE_MAX_UPLOAD*, *VARDE_MAX_DOWNLOAD*,
*VARDE_DISCOVERY*, *VARDE_WAN_UPLOAD*) > config file > defaults.
# FILES
_/var/lib/varde_ (system), _$XDG_DATA_HOME/varde_ (user)
Store directory: iroh-blobs store under _blobs/_, pins and trust in
_meta.json_, endpoint key in _secret.key_ (mode 0600).
_/run/varde/varde.sock_ (system), _$XDG_RUNTIME_DIR/varde.sock_ (user)
API socket. systemd socket activation (LISTEN_FDS) is supported;
without it the daemon binds the socket itself.
# NOTES
Materialization attempts a reflink (FICLONE) before falling back to a
byte copy; store directory and materialization targets must share a
filesystem (btrfs/XFS) for reflinks to work. Store files are immutable
and never hardlinked out.
DSCP marking may require CAP_NET_ADMIN on some systems and is silently
skipped where unavailable.
# SEE ALSO
*varde-ctl*(1)
+38
View File
@@ -0,0 +1,38 @@
# varde system service. Pairs with varde.socket for socket activation;
# also runs standalone (the daemon binds its own socket when not
# activated).
[Unit]
Description=varde content-addressed blob mirror daemon
Documentation=man:varde(8)
After=network.target
Requires=varde.socket
[Service]
Type=notify
ExecStart=/usr/bin/varde-daemon --system
Restart=on-failure
# Hardening
DynamicUser=yes
StateDirectory=varde
RuntimeDirectory=varde
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
SystemCallArchitectures=native
SystemCallFilter=@system-service
CapabilityBoundingSet=
[Install]
WantedBy=multi-user.target
+10
View File
@@ -0,0 +1,10 @@
# Socket activation for the varde system daemon.
[Unit]
Description=varde API socket
[Socket]
ListenStream=/run/varde/varde.sock
SocketMode=0666
[Install]
WantedBy=sockets.target