config.toml

Every key of a host's configuration file, from its JSON Schema.

The file nibrunnerd install writes and every nibrunnerd start reads, at /etc/nibrunner/config.toml unless NIBRUNNER_CONFIG names another. Configuration is the guide to it; this is the file key by key. Nothing here has a default, so a key its section declares is required unless the table says otherwise, and a key no section declares is refused.

An editor that reads TOML schemas — Even Better TOML in VS Code, taplo — completes and checks the file when its first line names the schema:

#:schema https://raw.githubusercontent.com/ilbertt/nibrunner/main/deploy/config.schema.json

Schema: config.schema.json

HostConfig

A host's config.toml. No key has a default: a key its section declares and the file omits is refused by name, and so is a key no section declares. What may be absent is a whole section — [proxy], [metrics], [volumes.zerofs] — and one that is present is filled in completely.

NameTypeDescription
max_appsinteger, 1 to 5567How many apps this host is laid out for. Everything that counts slots follows from it: the slot ring, the loopback ports reserved from 21000, the nbd minors on a zerofs host, the kernel's conntrack table at 1024 entries an app, what the metrics page calls the total. install measures what this machine holds and writes the least of memory, disk and ports; start says the three against what is set.
pathspathsWhere this host keeps what is its own.
artifactsartifactsWhere the layers a document names come from.
volumesvolumesWhere volumes live, and how.
exportsexportsWhere a checkpoint goes when the document asks for it as a bundle.
networknetworkWhat a guest is denied, by name.
logs optionallogsAbsent keeps the newest 256 MiB of each app's output.
metrics optionalmetricsAbsent is a host that scrapes nothing.
proxy optionalproxyAbsent serves nothing: no hostname, no raw port.

paths

Every one an absolute path, and every one this host's alone.

NameTypeDescription
state_dirstring, matching ^/Everything this host keeps, state.db included.
runtime_dirstring, matching ^/Sockets and pidfiles that outlive the daemon.
snapshot_dirstring, matching ^/Where a sleeping app's memory goes. On a zerofs host it shares its disk with the cache.
guest_image_dirstring, matching ^/vmlinux, rootfs.ext4 and manifest.json, put there by install.
desired_state_filestring, matching ^/The document this host watches and converges on.
api_socketstring, matching ^/The daemon's own socket.
versions_filestring, matching ^/What install stamped what it laid down into, read back into reported.json.

artifacts

One store, in S3 or on this disk.

NameTypeDescription
store_urlstring, matching ^(s3://[^/]+|/)s3://bucket[/prefix], or an absolute path.

volumes

The backend, and the prefix every volume on this host is under.

NameTypeDescription
backend"local-file" | "zerofs"local-file is sparse files under paths.state_dir, and no export. zerofs is blocks in an object store, reached from the guest over NBD.
storage_prefixstring, 1 to 512 characters, matching ^(?!\.\.?(/|$))[^/]+(/(?!\.\.?(/|$))[^/]+)*$Where this host's volumes live under the store: 1 to 512 bytes, no leading or trailing /, no empty, . or .. segment. One host, not one app: every tenant here shares it, and deleting it destroys all of them.
zerofs optionalvolumes.zerofsRequired by the zerofs backend, refused by local-file.

exports

The store a bundle is put in, and the disk it is assembled on first.

NameTypeDescription
store_urlstring, matching ^(s3://[^/]+|/)s3://bucket[/prefix], or an absolute path.
staging_dirstring, matching ^/A bundle is assembled here and removed after.

network

The ranges a guest is denied by name, on top of the blanket rules: public addresses that are still yours, and that a tenant must not reach. Both may be empty; both must be there.

NameTypeDescription
denied_egress_addresses_v4array of string, matching ^[0-9]{1,3}(\.[0-9]{1,3}){3}/[0-9]{1,2}$Each a.b.c.d/n, n at most 32.
denied_egress_addresses_v6array of string, matching ^[0-9A-Fa-f.]*:[0-9A-Fa-f:.]*/[0-9]{1,3}$Each addr/n, n at most 128.

logs

How much of each app's output stays on disk, under paths.state_dir/logs. Nothing on the host reads it back: it is there to be tailed.

NameTypeDescription
keep_mib_per_appinteger, at least 1Whole mebibytes, more than 0. The newest this many of an app's output, in two files: <appId>.log becomes <appId>.log.1 when it passes this, over the one before it, so an app holds between one and two of these on disk however fast it writes. 256 is weeks of an app that logs a line per request, and about a minute of one that floods.

metrics

A Prometheus page, rendered from the same builder that writes reported.json. Nothing here is an input.

NameTypeDescription
portinteger, 1 to 65535A free port, outside the range the slots take from 21000, other than proxy.http.port, and not 9091 on a zerofs host, which ZeroFS holds.
listen_addressstringAn IP address to bind.

proxy

Every way in. Each section under here is absent or complete, and each binds an address of its own, because each faces a different machine.

NameTypeDescription
http optionalproxy.httpThe one HTTP listener. Absent, a document naming a hostname is refused.
raw optionalproxy.rawPorts carried to a guest unread. Absent carries nothing raw.

volumes.zerofs

Everything install needs to lay ZeroFS down and everything the daemon needs to reach it once systemd has it running. Its two configuration files are rendered from here.

NameTypeDescription
binarystring, matching ^/Where install puts ZeroFS.
config_filestring, matching ^/Rendered by install.
mount_pathstring, matching ^/This host's own view of the filesystem.
nbd_socket_pathstring, matching ^/Where ZeroFS serves NBD, which is what a guest's disk is.
ninep_socket_pathstring, matching ^/Where ZeroFS serves 9P, which is how the host reaches the filesystem itself.
rpc_socket_pathstring, matching ^/Where ZeroFS answers RPC.
storage_urlstring, matching ^(s3://[^/]+|/)s3://bucket/prefix, or an absolute path.
cache_dirstring, matching ^/The disk cache of the object store.
cache_disk_gibinteger, at least 1Whole gibibytes, more than 0. Size it against the disk it is on, which it shares with paths.snapshot_dir: a full one breaks the filesystem every app on the host runs from.
cache_memory_gibinteger, at least 1Whole gibibytes, more than 0. Held back from what any guest may be promised.
checkpoint_runtime_dirstring, matching ^/Where the checkpoint reader an export starts keeps its socket.
checkpoint_config_filestring, matching ^/Rendered by install.
checkpoint_cache_dirstring, matching ^/The checkpoint reader's own cache.

proxy.http

The one HTTP listener, where the edge reaches it. One per host: nothing here redirects, so a plain port beside a TLS one would serve every app both ways forever.

NameTypeDescription
listen_addressstringAn IP address to bind.
portinteger, 1 to 65535A free port, outside the range the slots take from 21000. Not 0.
tls optionalproxy.http.tlsServe the port encrypted. Absent is plain HTTP, which is what a host behind an edge that terminates TLS wants.

proxy.raw

Ports carried to a guest unread — ssh, DNS, WireGuard — reached at a port of their own, tcp or udp, where the relay that publishes them reaches this host.

NameTypeDescription
listen_addressstringAn IP address to bind: a private one the relay can see, never the world's.
max_ports_per_guestinteger, 1 to 7How many raw ports an app may name: 1 to 7, what a slot reserves past its HTTP port.

proxy.http.tls

One certificate for the whole host — there is no SNI selection, so a wildcard in practice — read once, at startup. Obtaining and renewing it is certbot's or the edge's.

NameTypeDescription
certificatestring, matching ^/PEM.
keystring, matching ^/PEM.
client_ca optionalproxy.http.tls.client_caMakes a caller's own certificate the price of the handshake, which on an origin whose IP is discoverable is what keeps it reachable only through the edge.

proxy.http.tls.client_ca

The certificates a caller may present, as a PEM trust pool.

NameTypeDescription
certificatestring, matching ^/PEM, holding every certificate the pool trusts.

On this page