Configuration

Dugite reads a JSON configuration file that controls network settings, genesis file paths, P2P parameters, and tracing options. The format is compatible with the cardano-node configuration format.

Configuration File Format

The configuration file uses PascalCase keys (matching the cardano-node convention). This is config/preview/config.json as shipped in the repository:

{
  "Network": "Testnet",
  "NetworkMagic": 2,
  "DiffusionMode": "InitiatorAndResponder",
  "ByronGenesisFile": "byron-genesis.json",
  "ByronGenesisHash": "81cf23542e33d64c541699926c2b5e6e9c286583f0c8a3fb5f22ea7b352dd174",
  "ShelleyGenesisFile": "shelley-genesis.json",
  "ShelleyGenesisHash": "363498d1024f84bb39d3fa9593ce391483cb40d479b87233f868d6e57c3a400d",
  "AlonzoGenesisFile": "alonzo-genesis.json",
  "ConwayGenesisFile": "conway-genesis.json",
  "TargetNumberOfRootPeers": 60,
  "TargetNumberOfActivePeers": 15,
  "TargetNumberOfEstablishedPeers": 30,
  "TargetNumberOfKnownPeers": 85,
  "TargetNumberOfActiveBigLedgerPeers": 5,
  "TargetNumberOfEstablishedBigLedgerPeers": 10,
  "TargetNumberOfKnownBigLedgerPeers": 15,
  "MinSeverity": "Info",
  "LogDirective": "info",
  "MetricsPort": 12796,
  "ExperimentalHardForksEnabled": true
}

Unknown keys are ignored. The node's deserializer does not reject fields it does not recognise, so a typo in a key name silently leaves the default in force with no warning. Run dugite-config validate <file> to have unknown keys reported — see Configuration Editor.

Fields Reference

Network Settings

FieldTypeDefaultDescription
Networkstring"Mainnet"Network identifier: "Mainnet" or "Testnet"
NetworkMagicintegerautoNetwork magic number. If omitted, derived from Network (764824073 for mainnet)
DiffusionModestring"InitiatorAndResponder"Controls inbound connection acceptance. "InitiatorAndResponder" (default): relay mode, accepts inbound N2N connections. "InitiatorOnly": block producer mode, outbound only (no listening port opened)
PeerSharingboolean/nullnullEnable the peer sharing mini-protocol. When null (default), peer sharing is automatically disabled for block producers (when --shelley-kes-key is provided) and enabled for relays. Set explicitly to override
ConsensusModestring"Praos""Praos" (default) or "Genesis" (trustless bulk sync). "PraosMode" / "GenesisMode" are accepted legacy aliases. The --consensus-mode CLI flag, taking praos or genesis, overrides this field
ExperimentalHardForksEnabledbooleanfalseAdvertise readiness for the next major protocol version. false → the node signals ProtVer 11 0 in forged headers and rejects headers whose on-chain protocol version exceeds 11; true → signals ProtVer 12 0 (Dijkstra) and accepts up to 12. Must stay false on mainnet. The shipped config/preview/config.json sets it true

EnableP2P is not a Dugite config key. Dugite is always P2P; there is no non-P2P path to switch off. If your config file carries EnableP2P (from a cardano-node 8.x config) the node ignores it silently.

Protocol

FieldTypeDefaultDescription
Protocolstring/objectabsentAccepts either a bare string (e.g. "Cardano", which is ignored) or an object carrying RequiresNetworkMagic
Protocol.RequiresNetworkMagicstring"RequiresMagic"Whether network magic is required in the handshake
RequiresNetworkMagicstringnoneThe same setting at the top level, for guild-style and newer cardano-node configs

These three are inert. They are parsed so a cardano-node config file drops in without error, but nothing in the workspace reads them — Dugite always sends the network magic in the N2N handshake. NetworkMagic is the field that actually decides which network you join.

Genesis Files

Genesis file paths are resolved relative to the directory containing the configuration file. For example, if your config is at /opt/cardano/config.json and specifies "ShelleyGenesisFile": "shelley-genesis.json", Dugite will look for /opt/cardano/shelley-genesis.json.

FieldTypeDefaultDescription
ByronGenesisFilestringnonePath to Byron genesis JSON
ShelleyGenesisFilestringnonePath to Shelley genesis JSON
AlonzoGenesisFilestringnonePath to Alonzo genesis JSON
ConwayGenesisFilestringnonePath to Conway genesis JSON
DijkstraGenesisFilestringnonePath to Dijkstra genesis JSON (post-Conway HFC). Parsed at startup but not yet applied to runtime ledger rules. Overridden by the --dijkstra-genesis CLI flag
ByronGenesisHashstringnoneExpected Blake2b-256 of the Byron genesis file, as 64 hex characters
ShelleyGenesisHashstringnoneExpected Blake2b-256 of the Shelley genesis file
AlonzoGenesisHashstringnoneExpected Blake2b-256 of the Alonzo genesis file
ConwayGenesisHashstringnoneExpected Blake2b-256 of the Conway genesis file
DijkstraGenesisHashstringnoneExpected Blake2b-256 of the Dijkstra genesis file

At startup the node checks that every configured genesis file exists (resolved against the config file's directory) and that every configured hash is exactly 64 hex characters. Either check failing is a fatal startup error naming the era.

Tip: Genesis files for each network can be downloaded from the Cardano Operations Book.

P2P Parameters

These parameters control the P2P peer governor's target counts, matching the cardano-node defaults. The governor continuously works to maintain these targets by promoting/demoting peers and discovering new ones.

FieldTypeDefaultDescription
TargetNumberOfRootPeersinteger60Target number of root peers (bootstrap + local + public roots)
TargetNumberOfActivePeersinteger20Target number of active (hot) peers — fully syncing with ChainSync + BlockFetch
TargetNumberOfEstablishedPeersinteger30Target number of established (warm) peers — TCP connected, keepalive running
TargetNumberOfKnownPeersinteger150Target number of known (cold) peers in the peer table
TargetNumberOfActiveBigLedgerPeersinteger5Target number of active big ledger peers (high-stake SPOs, prioritised during sync)
TargetNumberOfEstablishedBigLedgerPeersinteger10Target number of established big ledger peers
TargetNumberOfKnownBigLedgerPeersinteger15Target number of known big ledger peers

Two of these are advisory in Dugite rather than direct policy levers: TargetNumberOfRootPeers is validated and exported as a Prometheus gauge, but root-peer connectivity is actually driven per-group by the topology's hotValency / warmValency; and TargetNumberOfKnownBigLedgerPeers is not enforced as a separate cap, because the known set as a whole is bounded by TargetNumberOfKnownPeers and selectively forgetting scarce big ledger peers would hurt Genesis sync.

Genesis-mode sync targets

A second target set applies while the node is in Genesis-mode bulk sync. It is parsed and validated unconditionally, but only takes effect when ConsensusMode is "Genesis".

FieldTypeDefaultDescription
SyncTargetNumberOfActivePeersinteger5Active peers during Genesis bulk sync
SyncTargetNumberOfEstablishedPeersinteger10Established peers during Genesis bulk sync
SyncTargetNumberOfKnownPeersinteger150Known peers during Genesis bulk sync
SyncTargetNumberOfRootPeersinteger0Root peers during Genesis bulk sync
SyncTargetNumberOfActiveBigLedgerPeersinteger30Active big ledger peers during Genesis bulk sync
SyncTargetNumberOfEstablishedBigLedgerPeersinteger40Established big ledger peers during Genesis bulk sync
SyncTargetNumberOfKnownBigLedgerPeersinteger100Known big ledger peers during Genesis bulk sync
MinBigLedgerPeersForTrustedStateinteger5Pause sync if active big ledger peers drop below this

Startup validation

Both target sets are checked at startup against the same predicates as Haskell's sanePeerSelectionTargets, and a violation is a fatal startup error naming the set ([deadline] or [sync]):

  • active <= established <= known, and root <= known
  • activeBigLedger <= establishedBigLedger <= knownBigLedger
  • active <= 100, established <= 1000, known <= 10000 (and the same three ceilings for the big-ledger-peer counts)

Churn

FieldTypeDefaultDescription
ChurnIntervalNormalSecsinteger3300Governor churn interval while caught up (55 min, matching cardano-node)
ChurnIntervalSyncSecsinteger900Governor churn interval while syncing (15 min)

Ouroboros Genesis Tuning

LowLevelGenesisOptions mirrors cardano-node's object of the same name and is only consulted when ConsensusMode is "Genesis". Omit the whole object to get the upstream defaults.

"LowLevelGenesisOptions": {
  "EnableCSJ": true,
  "EnableLoEAndGDD": true,
  "EnableLoP": true,
  "BlockFetchGracePeriod": 10,
  "BucketCapacity": 100000,
  "BucketRate": 500,
  "CSJJumpSize": 4320,
  "GDDRateLimit": 1.0
}
FieldTypeDefaultDescription
EnableCSJbooleantrueEnable ChainSync Jumping
EnableLoEAndGDDbooleantrueEnable Limit on Eagerness + Genesis Density Disconnection
EnableLoPbooleantrueEnable the Limit on Patience leaky bucket
BlockFetchGracePeriodfloat10Seconds before rotating a starving bulk-sync peer
BucketCapacityinteger100000LoP bucket capacity, in tokens
BucketRateinteger500LoP bucket leak rate, in tokens/second
CSJJumpSizeinteger4320CSJ jump size in slots (2 × 2160, the Byron forecast range)
GDDRateLimitfloat1.0Minimum seconds between GDD evaluations
SnapshotMinIntervalBulkSyncfloat1800Dugite-specific (not a cardano-node key). Minimum wall-clock seconds between epoch-boundary ledger snapshots during bulk sync. Raising it cuts snapshot I/O; lowering it shrinks the rollback blast radius on an unexpected stop

Checkpoints

FieldTypeDefaultDescription
CheckpointsFilestringnonePath to a lightweight-checkpoints JSON file ({"checkpoints":[{"blockNo":N,"hash":"<hex>"},...]}), resolved relative to the config file's directory. Checkpoints are enforced for every header in both consensus modes
CheckpointsFileHashstringnoneBlake2b-256 hex of the checkpoints file bytes. A mismatch is a fatal startup error

Connection Management

FieldTypeDefaultDescription
AcceptedConnectionsLimit.hardLimitinteger512Refuse new inbound connections beyond this count
AcceptedConnectionsLimit.softLimitinteger384Start delaying new inbound connections at this count
AcceptedConnectionsLimit.delayfloat5.0Maximum delay in seconds applied above the soft limit
PerIpRateLimitN2ninteger5Maximum concurrent N2N inbound connections per source IP. 0 disables per-IP limiting (not recommended)
MaxN2cConnectionsinteger16Maximum concurrent N2C (Unix socket) connections
BlockFetchMaxRangeintegermaxMaximum blocks pulled by a single BlockFetch MsgRequestRange. Clamped to [64, 2000] at use; omitted means the 2000-block network cap. The DUGITE_BLOCKFETCH_MAX_RANGE env var overrides this field

AcceptedConnectionsLimit also accepts the older long key names (acceptedConnectionsHardLimit, acceptedConnectionsSoftLimit, acceptedConnectionsDelay) as aliases.

The following four keys are parsed for cardano-node config-file compatibility but not currently enforced. Setting them changes nothing; they are reserved so that a cardano-node config drops in without a parse error.

FieldTypeDefaultWhy it is inert
ProtocolIdleTimeoutfloat5.0Dugite prunes idle connections via the connection manager's own 300 s INBOUND_IDLE_TIMEOUT
TimeWaitTimeoutfloat60.0Dugite relies on the OS TCP TIME_WAIT
EgressPollIntervalfloat0.0The governor runs on a fixed, tuned 2 s tick
ChainSyncIdleTimeoutfloatnoneDugite randomises the timeout between Haskell's minChainSyncTimeout / maxChainSyncTimeout bounds; a fixed override would defeat that

Metrics, RPC, and Storage

FieldTypeDefaultDescription
MetricsPortinteger12796Prometheus metrics port. 0 disables the server. Dugite's default is deliberately offset from cardano-node's 12798 so both can run on one host
TurnOnLogMetricsbooleantrueMaster switch for the metrics endpoint, matching cardano-node. false disables the server regardless of MetricsPort
RpcobjectnoneUTxO RPC (gRPC) server block: Enabled, ListenAddr, Port, MaxConcurrentStreams, StreamBufferSize, ReflectionEnabled, WebEnabled, AlphaEnabled, Tls: {CertPath, KeyPath}. See UTxO RPC
StorageobjectnoneStorage overrides layered on top of --storage-profile (index type, UTxO backend, LSM memtable/cache/bloom sizing)

Effective metrics port, highest precedence first: --no-metrics0; --metrics-port <PORT>; TurnOnLogMetrics: false0; MetricsPort; otherwise 12796. Note that an explicit --metrics-port wins even over TurnOnLogMetrics: false.

Tracing

FieldTypeDefaultDescription
MinSeveritystring"Info"Minimum log severity, in cardano-node's syslog vocabulary: Debug, Info, Notice, Warning, Error, Critical, Alert, Emergency. Mapped onto tracing levels — Noticeinfo, and Critical/Alert/Emergencyerror. Anything unrecognised falls back to info
LogDirectivestringnoneRUST_LOG-style filter directive (e.g. "info,dugite_network=trace"). Applied at startup and on SIGHUP, and takes precedence over MinSeverity
TraceOptions.TraceBlockFetchClientbooleanfalseTrace block fetch client activity
TraceOptions.TraceBlockFetchServerbooleanfalseTrace block fetch server activity
TraceOptions.TraceChainDbbooleanfalseTrace ChainDB operations
TraceOptions.TraceChainSyncClientbooleanfalseTrace chain sync client activity
TraceOptions.TraceChainSyncServerbooleanfalseTrace chain sync server activity
TraceOptions.TraceForgebooleanfalseTrace block forging
TraceOptions.TraceMempoolbooleanfalseTrace mempool activity

Log Level Control

Verbosity is resolved with this precedence, highest first:

  1. RUST_LOG environment variable
  2. --log-level CLI flag
  3. LogDirective config field
  4. MinSeverity config field
# Via CLI flag
dugite-node run --log-level debug ...

# Via environment variable (takes priority over --log-level)
RUST_LOG=info dugite-node run ...

# Debug only for specific crates
RUST_LOG=dugite_network=debug,dugite_consensus=debug dugite-node run ...

Because the config file is read after the tracing subscriber is constructed, the config-file values are applied via a live filter reload immediately after startup — but only when neither RUST_LOG nor --log-level is set, so an explicit operator override is never clobbered by the file.

That guard applies at startup only. A later SIGHUP applies LogDirective / MinSeverity unconditionally, so a reload will override a level you set on the command line or in the environment.

Dugite supports multiple log output targets (stdout, file, journald) and file rotation. See Logging for full details on output configuration.

Live Reload (SIGHUP)

Sending SIGHUP re-reads both the config file and the topology file. Changed fields are partitioned into those that can be applied live and those that need a restart; restart-required changes are logged as warnings and the reloadable ones are still applied.

Hot-reloadable: all seven TargetNumberOf* deadline targets, ChurnIntervalNormalSecs, ChurnIntervalSyncSecs, LogDirective, MinSeverity.

Restart required: Network, NetworkMagic, every genesis file path and hash, MetricsPort, TurnOnLogMetrics, DiffusionMode, ExperimentalHardForksEnabled, ConsensusMode — plus everything set on the command line (database and socket paths, listen address and port, KES/VRF/OpCert paths).

kill -HUP $(pgrep -x dugite-node)

Stopping the Node

Always stop the node with SIGTERM (or SIGINT / Ctrl-C), never SIGKILL.

kill -TERM $(pgrep -x dugite-node)     # correct
kill -9    $(pgrep -x dugite-node)     # do not do this

On SIGTERM the node demotes its peers, flushes storage, and writes a final ledger snapshot. A hard kill skips all of that and risks damaging the active ImmutableDB chunk's secondary index. Since v2.4.0 the node reconciles that damage at open — verifying the tail chunk by CRC, truncating to the verified prefix, and quarantining an index-less tail chunk as .chunk.orphaned — but recovery still costs the un-flushed blocks, and damage below the tail chunk is a hard InconsistentChunk error rather than something the node repairs.

A second SIGINT/SIGTERM during shutdown forces an immediate exit, matching cardano-node's behaviour, so you never need kill -9 to get out of a wedged shutdown.

ChainDB::open takes an exclusive advisory flock on <database-path>/lock, so a second process pointed at the same directory fails fast and names the pid already holding it, instead of two nodes silently interleaving writes.

Minimal Configuration

The smallest viable configuration file specifies only the network:

{
  "Network": "Testnet",
  "NetworkMagic": 2
}

All other fields use the defaults tabulated above. Note that with no genesis files specified the node falls back to built-in default protocol parameters, which will not match a real network — for anything beyond a smoke test, point at the genesis files for the network you are joining.

Format Support

The parser picks its format from the file extension: .json is parsed as cardano-node-compatible JSON, and anything else is parsed as TOML. If the path does not exist at all, the node starts on built-in defaults rather than failing — so a typo in --config produces a mainnet-default node, not an error.

Editing Configuration Interactively

dugite-config is a standalone TUI for browsing and editing these files with per-field type validation, tuning hints, a diff view, and a save-and-SIGHUP live reload. See Configuration Editor (dugite-config).