Skip to content

Configuration Reference ​

Kurrent has two authoritative declarations: control-plane configuration and node configuration. Both use kurrent.io/v1 and are validated by Pydantic models inside the components; the validation image the CLI invokes uses the same schema as runtime loading.

  • Control plane: control_plane/kurrent.yaml, kind: ControlPlaneConfiguration
  • Node: storager/kurrent.yaml, kind: NodeConfiguration

Templates come from kurrent config print init-defaults and kurrent config print node-defaults, generated from the same source as the .example files in the repository. Runtime files are not committed.

Validation semantics ​

SemanticsBehavior
Unknown fieldsRejected; typos are never silently ignored
Required fieldsMissing means failure
DefaultsInjected at validation time; config show displays the effective form
Cross-field constraintsSubnet, TTL bounds, and certificate days are checked in the same model
Protocol constantsnonce TTL, timeouts, and similar values stay in code, not in the declaration
Deployment factsContainer paths, listen addresses, and credential files are not part of the declaration

Validation happens before anything is written. Declaration errors surface at kurrent init / kurrent join, not when a container starts.

Control-plane configuration ​

Root fields ​

FieldTypeRequiredMeaning
apiVersionstringyesFixed kurrent.io/v1
kindstringyesFixed ControlPlaneConfiguration
metadata.namestringyesControl-plane name, 1–63 chars, lowercase letters, digits, dot or dash
specobjectyesSee below

spec.networking (required) ​

PXE deployment network declaration and the sole authority for dnsmasq.conf.

FieldTypeRequiredConstraintMeaning
interfacestringyes1–15 chars, no whitespaceNIC dnsmasq binds to
subnetstringyesIPv4 CIDRService subnet
dhcpRangestringyesstart,end, both inside the subnet, excluding network/broadcastDHCP pool
gatewaystringyesIPv4 inside the subnetDHCP option 3
dnsstringyesIPv4DHCP option 6

spec.pki ​

FieldDefaultRangeMeaning
bootstrapTokenTtlMinutes601–1440Default bootstrap token TTL
bootstrapTokenMaxTtlMinutes14401–1440Maximum issuable TTL; not below the default
bootstrapTokenMaxUses1001–1000Maximum uses per token
componentCertDays901–3650Component certificate lifetime
renewThreshold0.2(0, 1]Renewal trigger as a fraction of remaining lifetime
crlRefreshHours121–167Component CRL re-sign interval; keep below the CRL nextUpdate

spec.serverCert ​

The nginx 443 self-signed server certificate used by the TOFU boot chain.

FieldDefaultRangeMeaning
sanIP:127.0.0.1,DNS:localhostAt least one entry, no duplicatesComma-separated IP: / DNS: entries
days36501–36500Certificate lifetime
rotateOnChangefalse—Re-sign automatically when the declaration changes; changes the TOFU fingerprint

SAN or lifetime changes are reported as drift only; re-signing requires rotateOnChange: true. Devices already in the pool must pin the new server fingerprint.

spec.boot ​

FieldDefaultRangeMeaning
defaultArchx86_64Letters, digits, underscoreDefault boot architecture
menuTimeoutMs5000≥ 0Menu auto-select timeout in milliseconds
autoBootTimeoutMs1≥ 0Reboot wait timeout when no default disk exists, in milliseconds

spec.auth ​

FieldDefaultRangeMeaning
sessionTtlHours121–168Management session lifetime
adminCertDays3651–3650Default admin certificate lifetime; not above userCertDaysMax
userCertDaysMax36501–36500Maximum user certificate lifetime
tokenTtlHours241–8760Default management token TTL; not above tokenMaxTtlHours
tokenMaxTtlHours7201–8760Maximum management token TTL

spec.registration ​

FieldDefaultRangeMeaning
windowMaxTtlMinutes601–1440Maximum duration of one registration window
windowMaxDevices10001–100000Maximum devices admitted in one window

The window itself is runtime state, opened only briefly during deployment; the declaration only bounds it.

spec.credentials ​

FieldDefaultRangeMeaning
rotationDays900–3650DHHC-1 rotation period; 0 disables
reconcileIntervalSeconds600–86400Credential push reconciliation period; 0 disables

spec.agentTimeoutSec ​

FieldDefaultRangeMeaning
agentTimeoutSec10(0, 600]Control-plane call timeout to storage Agents, in seconds

Complete example ​

yaml
apiVersion: kurrent.io/v1
kind: ControlPlaneConfiguration
metadata:
  name: kurrent-cp
spec:
  networking:
    interface: enp3s0
    subnet: 192.168.80.0/24
    dhcpRange: 192.168.80.50,192.168.80.100
    gateway: 192.168.80.2
    dns: 223.5.5.5
  pki:
    bootstrapTokenTtlMinutes: 60
    bootstrapTokenMaxTtlMinutes: 1440
    bootstrapTokenMaxUses: 100
    componentCertDays: 90
    renewThreshold: 0.2
    crlRefreshHours: 12
  serverCert:
    san: "IP:127.0.0.1,DNS:localhost"
    days: 3650
    rotateOnChange: false
  boot:
    defaultArch: x86_64
    menuTimeoutMs: 5000
    autoBootTimeoutMs: 1
  auth:
    sessionTtlHours: 12
    adminCertDays: 365
    userCertDaysMax: 3650
    tokenTtlHours: 24
    tokenMaxTtlHours: 720
  registration:
    windowMaxTtlMinutes: 60
    windowMaxDevices: 1000
  credentials:
    rotationDays: 90
    reconcileIntervalSeconds: 60
  agentTimeoutSec: 10

Node configuration ​

Root fields ​

FieldTypeRequiredMeaning
apiVersionstringyesFixed kurrent.io/v1
kindstringyesFixed NodeConfiguration
metadata.namestringyesNode identity (agent_id): 12 lowercase hex characters, same form as the disk os_tag
metadata.remarkstringnoHuman-readable note (the only place for a descriptive name), defaults to empty
specobjectyesSee below

metadata.name is both the control-plane registry key and the component certificate CN, bound by the bootstrap token. After kurrent join writes it, it should not be edited by hand. Descriptive names belong in metadata.remark, never in the identity field.

spec.agent ​

FieldTypeRequiredConstraintMeaning
backendstringnonvmet / stgt / lio, default nvmetData-plane backend
advertiseUrlstringnohttp(s) URL, may be emptyAgent address reachable from the control plane, used for registration and renewal
diskDirstringyesAbsolute host pathDisk image directory; also the compose mount source
nqnBasestringyesnqn.<yyyy-mm>.<reverse-domain>Namespace for Host NQN and disk NQNs

spec.controlPlane ​

FieldTypeRequiredConstraintMeaning
urlstringyeshttp(s) URLmTLS target for component enroll / renew

Complete example ​

yaml
apiVersion: kurrent.io/v1
kind: NodeConfiguration
metadata:
  name: 3f2a9c1d8b7e
  remark: Production storage
spec:
  agent:
    backend: nvmet
    advertiseUrl: https://192.168.80.10:4840
    diskDir: /storager_img
    nqnBase: nqn.2026-07.com.kurrent
  controlPlane:
    url: https://192.168.80.1

Apply and verify ​

Control plane ​

bash
kurrent config print init-defaults > control_plane/kurrent.yaml
$EDITOR control_plane/kurrent.yaml
kurrent config validate
kurrent config show          # effective form with defaults injected
kurrent init                 # validate, apply, start, wait for health
kurrent config status        # configHash, derived files, certificate drift

init is idempotent: rerun it after editing the declaration. A validation failure writes nothing; a startup failure rolls back to the previous declaration and restores service with a non-zero exit.

Node ​

bash
kurrent config print node-defaults > storager/kurrent.yaml
$EDITOR storager/kurrent.yaml
kurrent config validate --node
kurrent join https://<control-plane> --token <token> --agent-id <agent_id>

join generates the declaration from the template when missing and merges the control-plane address when it exists. Node declaration errors fail before writing, not at container startup.

configHash and drift ​

The control-plane configHash is the SHA-256 of the effective declaration (defaults injected) serialized as canonical JSON (sorted keys, compact separators). It confirms which declaration is loaded at runtime and excludes runtime settings.

Derived objects and drift:

ObjectSourceDrift handling
dnsmasq.confspec.networkingRegenerated at startup; config status reports differences
Server certificatespec.serverCertReport-only by default; re-signed when rotateOnChange is on
Component PKIspec.pkiChecked at startup; missing or damaged material fails health

Runtime settings such as the registration window and signature enforcement live in state/settings.json; they are not part of the declaration or configHash.

Environment variables ​

VariableEffectScope
KURRENT_CONFIG_FILEOverrides the declaration path the process readsControl plane and node; for test injection
KURRENT_CP_INSECUREDevelopment mode allowing all requestsLocal development only, never production
KURRENT_CP_OPENAPIEnables the OpenAPI document endpointsOff by default
KURRENT_CP_ALARM_WEBHOOKAlarm delivery URLOptional
KURRENT_CP_CREDENTIAL_ROTATION_DAYSTemporary override of the rotation periodOperations and tests
KURRENT_CP_CREDENTIAL_RECONCILE_INTERVALTemporary override of the reconciliation periodOperations and tests
KURRENT_CP_CRL_REFRESH_INTERVALTemporary override of the CRL re-sign periodOperations and tests

The declaration is the default source for policy; the two background-task variables are temporary overrides. Container paths and listen addresses are fixed by compose and are not part of the declaration.