Expand description
The gunnar git server: everything that used to live behind gunnar-cli’s
--features server, now its own crate.
Nothing in here may reach gunnar-client except the client-gated
[mirror] module (replication’s send-pack). That edge is what would drag
gix’s worktree, status and index machinery into an appliance image, and it
is asserted absent from a resolved dependency graph in
gunnar-cli/tests/feature_split.rs.
Re-exports§
pub use storage::encrypted_quarantine;pub use attest::AttestationLog;pub use attest::ATTESTATION_LOG;pub use control_plane::CoreControlPlane;pub use grpc_gate::activity_ledger;pub use grpc_gate::control_audit_ledger;pub use grpc_gate::control_transfer_gate;pub use serve::GrpcTls;pub use serve::ServeConfig;pub use serve::Server;pub use stores::ServerStores;pub use stores::CONTROL_DB;pub use stores::CONTROL_DIR;pub use transport::WireConfig;pub use transport::WireTransport;
Modules§
- account_
audit_ sweep - The account audit logs’ retention sweep (2026-10-05). The account audit logs’ retention sweep (2026-10-05): every few hours, each account’s log drops the days past its retention (a year by default), so an account nothing happens in for a while does not keep entries the promise says are gone. An append does the same for its own account first; this is the rest. Never on a twin: its control store is a replica, and the primary’s sweep reaches it as transactions.
- account_
purge - What emptying an account means, in one place: the four classes of bytes a user owns and the walk that reclaims them. What emptying an account actually means, in one place.
- admin
- The administrative verbs: namespaces, repositories, principals, keys,
grants, and
gc. - attest
- The attestation log, on the server’s own store.
- blame
- Whole-file blame:
verify’s line→commit link 1, done once for every line of a file. Reusesverify’s tree/blob and parent readers and thediffengine (one implementation).gunnar blame— who wrote each line, walked backwards. - boot
- Gunnar’s end of PID 1. The jobs an operating system used to do for the
server (signals, reaping, the network, DHCP, the stop and the power-off)
are edda’s
appliance-pid1, shared with Holger; this is what Gunnar says about itself to it (GUNNAR_NET, the host name, the narration tap, GN-99). Gunnar’s end of PID 1. Everything an OS-less PID 1 owes the kernel — the signals, the reaper, the netlink writer, the DHCPv4 client and its renewal, the resolver file, the stop sources and the power-off, the install record, the graphics-console mirror, the boot narration’s secret door, the panic as a fault — is edda’sappliance-pid1(0.1.5, lanes G4 and G6), the one PID 1 Gunnar and Holger both run. Gunnar’s ownpid1.rsanddhcp.rswere moved there whole and deleted here (lane L10). - budget
- The declared budgets — concurrent transfers, open repository handles and
the git memory budget — derived from cores +
RLIMIT_NOFILE+MemAvailableand named in one INFO row at start. The replacement for the three emergent ceilings of 2026-08-29 (19,25,256). The declared budgets: how many git transfers may be in flight, how many repository handles may be open, and how much memory the two of them may hold — every one of them derived from the box and said out loud at start. - capacity
Admin.Capacity: “if a tenant’s cap rose to N bytes, could you serve it?” — the question monetize must ask before it buys a disk. Answers with a verdict measured off the SAMEstatvfsthe push door refuses under, and, independently, whether this data set can ever grow at all: the appliance is SEALED (an md set laid once at install, no runtime growth path, PID 1 with no shell), so a disk bought for it is billed and invisible. “If a tenant’s cap rose to N bytes, could you serve it?” —Admin.Capacity.- clock
- The fourth of those jobs, added 2026-09-14: the wall clock. The appliance
booted two hours fast and refused every genuine credential and every Stripe
webhook for it; UDP/123 is closed on that network, so “now” arrives in the
Dateheader of an HTTPS response, from three sources that must agree. The appliance’s wall clock: glue between PID 1 and eddaestate-clock. - control_
plane gunnar-grpc’sControlPlaneseam, overgunnar-coreandgunnar-store: the adapter its module docs asked for.- dashboard
- The VGA-console status screen the appliance draws as PID 1 (header band +
rolling events off the log tap).
The console dashboard: what a human sees on the appliance’s VGA screen
(
/dev/tty0) when the box is otherwise dark — a Talos-style status band and a rolling list of what the server is doing. - diff
- The tree diff
Refs.Diffserves (the event stream). - disktest
- The start-up disk test: what /data can actually do, said once on the screen.
- durable
- The start-up disk test the appliance runs on /data (seq write/read, 4 KiB
fsync ops) — one
disktestrow on the screen. One place that writes a small control file durably. - feed
- The estate values the installer’s door feeds (monetize key, clock key and peer), taken instead of the medium’s — see the module. The estate values the installer’s door FEEDS, taken instead of the medium’s — so one medium serves any estate.
- first_
commit - A repository’s first commit, written by the server (
Repos.Create{readme}). A repository’s first commit, written by the server (the owner, 2026-10-08: a sold private Gunnar is handed over with ONE welcome repository whose README thanks the buyer and says how to start — with no git client anywhere in the sale). - gc_
queue - One gc at a time, for the whole box — the queue behind
Repos.Gc. One gc at a time, for the whole box. - glance
- The machine at a glance (
StorageReality.glance, 2026-10-04): the Machine card’s lines, decided here. The machine at a glance (StorageReality.glance, owner 2026-10-04): the four lines the console’s Machine card shows —/data’s shape, the off-stripe copies on/serialdat, the free space, the disk speed — each with gunnar’s own verdict. - grow
- The runtime data-set growth (
DATA-SET-GROWTH-FLOW.md§3): the phase machine over aWorldseam, the go-ahead, and — withgrow-runtime— the appliance world that links edda’s engine. The runtime data-set growth —/datagrows WITHOUT a restart (private-gunnar-ops/DATA-SET-GROWTH-FLOW.md§0 ruling 1, §3; the torture test’s T1, T2, T6, T9, T11 are binding). - grpc_
gate - The control plane’s one transfer, on the same gate as git — one implementation, not a second gate.
- identity
- The identity core’s Gunnar host, built at the start (IDENTITY-HOST).
The identity core, built at the start (IDENTITY-HOST, 2026-10-27):
edda’s
nornir_identity::Identityovergunnar_grpc::identity::GunnarHost. Its own records (sessions and invites as hashes, the floors, the sign-up state) live in<data root>/identity.json, written atomically and framed in the transaction log like every other document, so a twin holds them too. Mail: none (airgap) — an invite’s link is handed over, and a sold estate’s first-login link is the shop’s to mail. - import_
room - An import’s memory against the memory this server may really use (IMPORT-2):
the box’s
MemTotalor the cgroup’smemory.max, a named refusal before an index that would not fit, and the cgroup’s memory in the shape the indexer’s guard reads. An import’s memory, against the memory this server may really use (IMPORT-2, 2026-10-27). - job_
queue - One worker, one job at a time, FIFO, deduplicated by subject — the
runner
gc_queueandpurge_queueare two kinds on, and the hook a third kind plugs into without editing it. One worker, one job at a time, FIFO, deduplicated by subject — for any kind of job the box has to do slowly. - layout_
config - The layout config (
/boot/korp/layout.conf): what the installer decided, written down and sealed by the thing that did the deciding. gunnar is TOLD where its storage is and obeys; it never surveys disks, an absent config is answered as absent rather than inferred, and an unsigned one is never presented as verified. The layout config: gunnar is TOLD where its data lives, and obeys. - limits
- The descriptor limit: raised once (PID 1 to a million, anyone else to its
hard limit), and the open-repository handle cache sized to fit under it.
The fix for the rig’s “202nd repository”
EMFILE(2026-08-29). The descriptor limit: raised once, read once, and the handle cache sized to fit under it. - live_
update - Live update (owner 2026-10-12): what this box runs, a new app staged, the graceful
re-exec, the confirm — generic primitives over korp-installer’s
live. Live update, gunnar’s side (owner 2026-10-12, TURNAROUND §8) — generic primitives only; the decisions are korp-installer’s (korp_installer::live), the wire is nordisk-pairing’s (nordisk_pairing::live, the installer’s log door, its own certificate only): - mirror_
fetch - What a mirror sync does: one
gunnar-wirefetch_packover one of two transports, and one compare-and-swap that moves the references. WhatMirror.Syncactually does: one fetch from an upstream, into this box’s own storage engine, and one compare-and-swap that moves the references. - mirror_
queue - One mirror sync at a time, for the whole box — the third kind on the one
runner, and the queue behind
Mirror.Sync. One mirror sync at a time, for the whole box. - narrate
- The fifth of those jobs, added 2026-09-23: saying where the boot is.
boot::ship_boot_narrationends atend of hand-offand the estate’s twin died in the silence after it; this is the narrator that speaks from there on — a stage line at every boundary, a tick a minute, and a fatal fault that sends a stable code, waits to be heard and then powers the box off cleanly. The app’s half of the boot narration: stages, ticks and fault codes. - oci
- The artifact registry and the OCI images it holds. The artifact registry, and the images it holds (roadmap phase 4).
- purge_
queue - One account purge at a time, and the lockout always comes off. The
Accounts.Purgequeue; see its module docs for why it is its own line and not the gc one. One account purge at a time, and the lockout always comes off. - push_
space - The receive path’s half of space admission (
gunnar_ssh::space): the reader a pushed (or mirrored) pack is read through, which asks the data set’s ledger before every chunk it hands on, and the sweep of spool files a crash left behind. - readiness
- The boot window: whether the stores have finished their post-crash work,
and the retryable
startinganswer a client gets until they have. The 0.6-0.7 s ofthe repository is unavailable; try againafter a power cut. Is this server ready to serve git? — one flag, set once, and the honest answer while it is clear. - registry
- The registry’s one rule: no artifact without valid, logged provenance. The registry’s one rule (roadmap phase 4).
- replication_
view - What replication looks like from outside it — the one shape the console
band,
Admin.Statsand the log all read. - runner
- The build runner: checkout, sandbox, artifacts, signed provenance. The build runner (roadmap phase 3).
- sandbox
- The build sandbox: a network namespace of the build’s own, unprivileged. The build sandbox: no network, by construction (roadmap phase 3).
- scrape
- The counters over HTTP. Opt-in; binds nothing by default.
The counters, over HTTP: one opt-in read-only listener that
answers “is it slow or is it stuck” without
perfand without a restart. - search
- Latest-revision literal code search: walk the tree at a ref, scan text
blobs. Bounded by a file-size and a match ceiling; not a persistent index.
gunnar search— a literal string, across one revision’s files. - serve
gunnar servestarts its listeners together and stops them together. They share nothing but the control plane behind them.- slow
- The slow disk (
/serialdat): the other spindle, and the other failure domain. One code path whatever is underneath it, and a three-valued claim — off-stripe, same-device, unverified — over the three copies that are supposed to outlive losing a data disk. Where each kind of data goes, and what gunnar may claim about it. - sso_
import_ queue - The directory import on its own jera lane (A34-17). The directory import, one per account at a time, on its own jera lane (A34-17).
- stop_
record - The last stop, kept where it survives the stop (2026-10-01, the real test2 run 9:
vm1 stopped cleanly, but its power-off steps were lost — the narration and the disk log
die with the read-only remount of /data — and UpCloud reported
stopped46 s after the soft stop, so nobody could tell the guest’s power-off from the provider’s reporting). After the quiesce and just before the power goes, ONE line is written on the ESP (its own filesystem, flipped read-write for that write); the next boot says it at INFO and removes it. - storage
- The znippy cold tier, wired where objects enter the server. Which storage engine this binary carries, and which one it is running.
- stores
- Where the server’s state lives on this box, and the one place a repository is turned into a pair of stores.
- tls_
preflight - Can this control plane be moved onto mutual TLS, and who does it cost?
The one preflight
gunnar serve --grpc-tls-selfrefuses on andgunnar issuer readinessasks in advance. Moving a control plane onto mutual TLS, after it has been enrolled. - topology
Admin.Topology’s facts from this server: the pairing feed, the front’s principals, the plugin registration (2026-10-04).Admin.Topology’s facts from this server (2026-10-04): what onlygunnar-serverholds — the installer’s pairing feed (joined.toml) with the ESTATE RECORD it carries (theestate.*keys: every box as the kit laid it), which principals run on the front, the plugin registration, this box’s own data volume. The assembly and every verdict aregunnar_grpc::topology’s; this module only reads.- transport
- The join.
gunnar-ssh’sGitTransportseam, implemented overgunnar-wire’s state machines, withgunnar-wire’sPushGateseam implemented overgunnar-policy’s engine. - tunnel_
addr - Where the WireGuard tunnel is, for the listeners that follow it (owner’s
ruling 2026-09-22, amended 2026-09-24): the mutual replication listener
(
:50052) answers on the outer address (eth1) for the process lifetime and, once the tunnel is up, ALSO onwg0’s address (replication_extra).:50051does not move. - twin
- The twin: follows the primary’s transaction log, applies it, restores from it.
The twin: the box that holds every transaction the primary was told, in
order, durably, and is never promoted.
.nornir/twin-transaction-log.md§“The twin’s loop”. - twin_
tls - The twin’s mutual-TLS credential: minted at pairing, never on the medium. The twin’s mutual-TLS credential, minted at PAIRING and never on the medium.
- txlog_
lfs - The LFS tee: an object is a transaction-log frame before it is published.
The LFS tee: an LFS object is a frame in the transaction log before
the store publishes it. The fourth decorator of
.nornir/twin-transaction-log.md; the other three live ingunnar_core::txlog::tee, and this one is here because the server is the crate that seesgunnar-lfs. - usage_
ledger - The usage ledger (2026-10-06): every namespace’s stock meters, re-measured
only where something changed — what
UsageBatch.ReadManyanswers from. The usage ledger: every namespace’s stock meters, kept current by re-measuring only what changed (2026-10-06). - verify
gunnar verify— the unbroken chain, walked backwards from a line of source.gunnar verify— the unbroken chain, walked backwards.
Constants§
- SERVER_
ALLOCATOR - The value to declare. See
ServerAllocator.
Functions§
- functional_
status - Record one functional-status row for the nornir test matrix.
- run
- Dispatch a server verb. The one entry point both this crate’s binary and
gunnar-cli’srun()route server commands through, so the wiring lives exactly once (one implementation).
Type Aliases§
- Server
Allocator - The allocator every gunnar that serves is built on.