Skip to content

Configuration

The nestor binary is configured by one TOML file passed as --config or NESTOR_CONFIG. Every key has a default except origin.endpoint, and every key can be set from the environment as NESTOR_SECTION__KEY, which wins over the file. Unknown keys are rejected.

bash
nestor check --config nestor.toml    # parse, validate, resolve credentials, exit
nestor serve --config nestor.toml
NESTOR_CACHE__MEMORY='"2 GiB"' NESTOR_SERVER__LISTEN='"0.0.0.0:9000"' nestor serve

Environment values are parsed as TOML values, quoting strings is always safe. Nested keys merge with the file, so a file can hold credentials = { source = "static" } and the environment the keys under it. Sizes accept MiB, GiB and friends, durations accept 50ms, 2s, 10m.

The reference file with every default is nestor-cli/nestor.toml. The sections below follow it.

[server]

KeyDefaultPurpose
listen127.0.0.1:9000The S3 listener.
metricsunsetPrometheus listener serving /metrics. Unset disables it.
tlsunset{ cert = "...", key = "..." } in PEM. Terminates TLS on listen.
addressing{ style = "path" }Or { style = "virtual_hosted", domain = "s3.internal" } to take the bucket from the Host header.

Serving anonymous plaintext on a non-loopback address is allowed and logs a warning at startup. Anyone who can reach the socket can then read any object the origin credentials can.

[origin]

KeyDefaultPurpose
endpointhttps://s3.us-east-1.amazonaws.comAny S3-compatible endpoint.
regionus-east-1Used in the SigV4 scope of forwarded and fetched requests.
virtual_hostedfalseAddress the origin as bucket.endpoint instead of endpoint/bucket.
credentials{ source = "default" }How Nestor authenticates to the origin.

Credential sources:

  • default resolves the AWS chain: environment variables, shared profile, ECS or IMDS role, IRSA. Requires an AWS-style environment and is the only AWS-specific setting in the file.
  • static takes access_key, secret_key and an optional session_token. The usual choice for MinIO, RustFS and other compatible stores.
  • anonymous sends unsigned requests, for public buckets.

[auth]

KeyDefaultPurpose
modeanonymousanonymous accepts everything, static verifies SigV4 against one key pair.
access_key, secret_keyRequired with static. What clients sign with.

Client credentials and origin credentials are independent. A deployment usually hands clients a dedicated key pair that exists nowhere but in this file, and keeps the origin's credentials on the Nestor host only.

[cache]

KeyDefaultPurpose
memory256 MiBRAM tier size.
shardsderivedTwo per core, capped so each shard holds at least 32 MiB.
meta_entries100000Objects whose size and ETag are remembered.
origin_concurrency64Foreground origin GETs in flight.
readahead_concurrency16Background origin GETs in flight.
hedge_concurrency16Hedge requests in flight.
retry{ attempts = 3, base = "50ms", max = "2s" }Backoff for I/O errors and short reads.

[cache.disk]

Absent by default. Present enables the disk tier.

KeyDefaultPurpose
path/var/lib/nestorDirectory foyer owns. Must be writable, existing regions are recovered.
capacity8 GiBDisk tier size.
region_size64 MiBAppend and reclaim unit.
direct_iotrueO_DIRECT on Linux. Ignored elsewhere.
compressionnonelz4 or zstd.
recoverquietnone, quiet or strict.

[buckets]

The caching policy every bucket gets as a namespace.

KeyDefaultPurpose
block_size1 MiBPower of two from 64 KiB to 16 MiB.
fetch_window8Blocks per origin GET on a miss.
read_window16Blocks in flight per stream.
consistency{ mode = "etag", ttl = "60s" }Or { mode = "immutable" }.
readahead8Blocks prefetched on sequential access. 0 disables.
hedge{ factor = 3.0, min = "50ms", max = "2s" }Tail hedging against the origin. Omit the key to disable.
populate_max16 MiBLargest PUT body inserted into the cache on the way through.

[cluster]

Absent by default. Present turns this binary into a gateway that reads from a cluster of nodes instead of the origin. Exactly one of nodes and dns must be set.

KeyDefaultPurpose
nodesStatic list of host:port.
dnsA name resolved to the node set, host:port.
refresh10sHow often dns is re-resolved.
block_size1 MiBRouting unit. Must be a multiple of buckets.block_size.
read_window16Cluster blocks in flight per read.
load_limit256In-flight requests per node before spilling to the next choice.
down_for5sHow long a node is skipped after a connection failure.
hedge{ factor = 3.0, min = "50ms", max = "2s" }Hedging across nodes.
tlsfalseUse https toward nodes.
credentialsunset{ access_key, secret_key } matching the nodes' [auth].
warm_on_writefalseAfter a PUT, fetch each block on its owning node.

A node in the cluster is a plain nestor binary with [origin] and no [cluster]. The gateway and the nodes should agree on buckets.block_size, and the gateway's cluster.block_size is normally the same value.

Logging

Logs go to stderr through tracing and are filtered by RUST_LOG, info by default. Startup, shutdown, membership changes and configuration warnings are logged. Per-request behaviour is not, it is exposed as metrics instead.