Module options
Generated from the module declarations by nix build .#options-doc; do not edit by hand. CI fails when this file differs from a fresh build, so regenerate it in the same commit as any option change:
cp "$(nix build .#options-doc --print-out-paths)" docs/module-options.md
The prose about how the modules fit together lives in architecture.md.
services.holochain-bootstrap.enable
Whether to enable the Kitsune2 bootstrap and relay server (kitsune2-bootstrap-srv).
One process serves peer discovery at /bootstrap/{space} and an iroh
relay at /relay on the same port. Point conductors at it with
services.holochain-edgenode.bootstrapUrl = "http(s)://<host>:<port>"
and relayUrl = "http(s)://<host>:<port>/relay".
The relay is open: it has no authentication by default, so anyone who can reach the port can relay traffic through it. Keep it on a LAN or behind a firewall unless that is what you want. Its state is ephemeral and cannot be shared between instances, so run one server per network, not several behind a load balancer .
Type: boolean
Default:
false
Example:
true
Declared by:
services.holochain-bootstrap.package
The kitsune2-bootstrap-srv package. The flake’s module defaults it to
the holonix main-0.6 build (kitsune2 0.4.1), the line the Sensorica
fleet runs. A 0.7 network takes nixos-holochain.packages.${system}.bootstrap-srv
instead (kitsune2 0.5.0): keep the server on the same line as the
conductors that use it.
Type: package
Default:
nixos-holochain.packages.${system}.bootstrap-srv-0_6
Declared by:
services.holochain-bootstrap.extraArgs
Further kitsune2-bootstrap-srv flags, appended as given.
Type: list of string
Default:
[ ]
Example:
[
"--max-entries-per-space"
"64"
"--allowed-origins"
"https://example.org"
]
Declared by:
services.holochain-bootstrap.listenAddresses
Addresses the HTTP server binds, each on port. IPv6 addresses go in
brackets. The default [::] is dual-stack on Linux and accepts IPv4
as well; on a host with IPv6 disabled, use 0.0.0.0.
Do not list both 0.0.0.0 and [::], although that is the server’s
own production default. On Linux the second bind fails with “address
in use”, and the 0.4.1 server does not exit on a failed bind: it logs
nothing, listens on nothing and stays up, so systemd reports the unit
active. Seen in this repository’s VM test, not guessed.
Type: list of string
Default:
[
"[::]"
]
Example:
[
"192.168.1.10"
]
Declared by:
services.holochain-bootstrap.logLevel
RUST_LOG filter for the server. Its built-in default is debug,
which logs every request to the journal.
Type: string
Default:
"info"
Example:
"info,kitsune2_bootstrap_srv=debug"
Declared by:
services.holochain-bootstrap.openFirewall
Open port on TCP and quicPort on UDP. Conductors on other machines
cannot reach the server without this or an equivalent firewall rule.
Type: boolean
Default:
false
Declared by:
services.holochain-bootstrap.port
TCP port for bootstrap and relay, over HTTPS when a certificate is
configured and plain HTTP otherwise. The unit holds
CAP_NET_BIND_SERVICE so a port below 1024 works without root.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
443
Declared by:
services.holochain-bootstrap.quicAddress
Address the QUIC address discovery (QAD) endpoint binds, which lets
iroh clients learn their public address. On Linux [::] also accepts
IPv4.
Type: string
Default:
"[::]"
Declared by:
services.holochain-bootstrap.quicPort
UDP port for QUIC address discovery; 7842 is iroh’s default.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
7842
Declared by:
services.holochain-bootstrap.tlsCertFile
PEM certificate for HTTPS and for QUIC. A path as a string, read at
service start through systemd’s LoadCredential, so it never enters
the Nix store and may be readable by root only. Set it together with
tlsKeyFile.
Without it the server speaks plain HTTP, and QUIC uses a self-signed
certificate it generates at start. That is enough for a LAN of
edgenodes, which then need
services.holochain-edgenode.relayAllowPlainText = true. It is not
enough for a packaged Moss desktop: Moss enables plain-text relays only
in development builds, so a laptop running stock Moss needs this server
on HTTPS with a certificate it trusts.
The certificate is read once, at start: restart the unit after a renewal.
Type: null or string
Default:
null
Example:
"/var/lib/acme/bootstrap.example.org/fullchain.pem"
Declared by:
services.holochain-bootstrap.tlsKeyFile
PEM private key matching tlsCertFile, loaded the same way.
Type: null or string
Default:
null
Example:
"/var/lib/acme/bootstrap.example.org/key.pem"
Declared by:
services.holochain-bootstrap.workerThreads
Worker threads for the HTTP server. null keeps the server’s
production default, four per CPU. The workers block on file IO, which
is why the default exceeds the core count.
Type: null or (positive integer, meaning >0)
Default:
null
Declared by:
services.holochain-edgenode.enable
Whether to enable Holochain edgenode (conductor + lair + hApp installer).
Type: boolean
Default:
false
Example:
true
Declared by:
services.holochain-edgenode.package
Holochain conductor package. Its version selects the config schema the
module renders: below 0.7 the network section carries bootstrap_url,
signal_url and relay_url; from 0.7 it carries bootstrap_url and
relay_url, because signal_url was removed from the schema.
Type: package
Default:
inputs.holonix.packages.${pkgs.stdenv.hostPlatform.system}.holochain
Declared by:
services.holochain-edgenode.adminAllowedOrigins
Allowed origins for the admin WebSocket interface. The default is the
Origin header hc sends when given no --origin, which is what the
hApp installer and the metrics timer use, and which no browser sends:
with * any web page open in a browser on the node could drive the
admin API over ws://localhost. Widen it only for an admin UI you
trust.
Type: string
Default:
"holochain_websocket"
Declared by:
services.holochain-edgenode.adminPort
WebSocket port for the conductor admin interface (bound to localhost).
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
4444
Declared by:
services.holochain-edgenode.allowedOrigins
Allowed origins for the app WebSocket interface the installer attaches:
*, a single origin, or a comma-separated list.
Type: string
Default:
"*"
Declared by:
services.holochain-edgenode.appPort
WebSocket port the hApp installer attaches as the app interface.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
8888
Declared by:
services.holochain-edgenode.binaryCache.enable
Declare the Holochain Foundation’s binary cache
(https://holochain-ci.cachix.org) in the host’s nix.settings, so
holochain and hc are downloaded prebuilt instead of compiled from
source. A flake’s own nixConfig does not reach a downstream flake
that imports this module, and without the cache a first
nixos-rebuild switch compiles the whole Holochain workspace
(seen on a homelab rehearsal, 2026-09-26).
The setting lands in nix.conf only once a switch has activated it,
so the very first switch that brings it still builds from source
unless it is run with
--option extra-substituters https://holochain-ci.cachix.org --option extra-trusted-public-keys <key>; see docs/deployment.md.
Type: boolean
Default:
true
Declared by:
services.holochain-edgenode.bootstrapUrl
Kitsune2 bootstrap server used for WAN peer discovery. null selects the
default for the configured line: https://dev-test-bootstrap2.holochain.org
below 0.7 (Holo-Host/edgenode’s 0.6.1 template) and the same URL with a
trailing slash from 0.7 (what holochain --create-config writes). No
production bootstrap URL is documented for either line, so point this at
your own infrastructure for a real deployment.
Type: null or string
Default:
null
Declared by:
services.holochain-edgenode.conductorMetrics.enable
Whether to enable a timer that exports the conductor’s own network stats as
holochain_* series through node_exporter’s textfile collector.
This is the fleet dashboard’s Holochain data source. It calls
dump-network-stats on the admin interface, which answers with
Kitsune2’s TransportStats on both the 0.6 and 0.7 lines, and derives
connection gauges and byte and message counters from it; it also
counts installed apps by status from list-apps. The counters are
running totals kept in conductor-metrics-counters.json under
dataDir, so a peer disconnecting does not pull them down. It also
calls dump-network-metrics --include-dht-summary and writes one
holochain_dht_* series set per DHT the conductor is in (peers, ops
held here and by the best peer, pending fetches, seconds since the
last gossip, completed rounds and timeouts), labelled app_id,
role and dna, and names every app and DHT in holochain_app_info
and holochain_dht_info from displayName and roleNames. Every
line carries conductor, from name. Requires
metricsExporter.enable
.
Type: boolean
Default:
false
Example:
true
Declared by:
services.holochain-edgenode.conductorMetrics.interval
How often the timer writes the textfile, as a systemd time span. The floor is what the dashboard’s resolution is worth: Prometheus scrapes node_exporter on its own schedule and simply re-reads whatever the file last said, so a value far above the scrape interval shows as a staircase rather than a curve.
Type: string
Default:
"30s"
Example:
"1min"
Declared by:
services.holochain-edgenode.conductorMetrics.name
The conductor label on every holochain_* series this node
writes, and the name dashboards show for the conductor. It keeps
two conductors on one machine apart (this one and a Moss node, say),
so give each its own.
Type: string
Default:
"Holochain"
Example:
"Workshop"
Declared by:
services.holochain-edgenode.dataDir
Persistent state directory for the conductor database, the lair keystore
and the generated passphrase. Created as the unit’s StateDirectory with
mode 0700.
Keep it short. The keystore’s unix socket is ${dataDir}/ks/socket and
unix socket paths are capped at 108 bytes (SUN_LEN); a deeper path makes
the conductor exit at startup with path must be shorter than SUN_LEN.
Type: absolute path
Default:
"/var/lib/holochain"
Declared by:
services.holochain-edgenode.dbSyncLevel
db_sync_level, the SQLite synchronous level, from 0.7 only (0.6 has
db_sync_strategy instead, which this module does not set). null
leaves the conductor default, Normal. Off trades crash safety for
speed. Ignored with a warning below 0.7.
Type: null or one of “Full”, “Normal”, “Off”
Default:
null
Declared by:
services.holochain-edgenode.happs
hApps to install and keep enabled, keyed by installed app id.
Type: attribute set of (submodule)
Default:
{ }
Example:
{
dino-adventure = {
src = pkgs.fetchurl {
url = "https://github.com/holochain/dino-adventure/releases/download/v0.3.0/dino-adventure-v0.3.0.happ";
sha256 = "...";
};
networkSeed = "workshop-2026";
};
}
Declared by:
services.holochain-edgenode.happs.<name>.displayName
What dashboards call this app, as app_name on the
holochain_app_info and holochain_dht_info series. null
falls back to the bundle’s own name from list-apps, with
underscores and dashes read as spaces and the first letter
capitalised (requests_and_offers reads “Requests and
offers”).
Type: null or string
Default:
null
Example:
"Requests & Offers"
Declared by:
services.holochain-edgenode.happs.<name>.installed
Whether to install this hApp when absent and keep it enabled. Setting it to false (or removing the entry) stops managing the app; it does not disable or uninstall an app already installed.
Type: boolean
Default:
true
Declared by:
services.holochain-edgenode.happs.<name>.networkSeed
Network seed override for every DNA in this app.
Type: null or string
Default:
null
Declared by:
services.holochain-edgenode.happs.<name>.roleNames
What dashboards call each part of this app, keyed by DNA role,
as part_name on holochain_dht_info. A role left out reads
as nothing when the app has one role, so its network is shown
by the app’s name alone, and otherwise as the role id with a
one-letter prefix dropped and underscores read as spaces
(rFiles reads “Files”).
Type: attribute set of string
Default:
{ }
Example:
{
hrea = "Accounting";
requests_and_offers = "Listings";
}
Declared by:
services.holochain-edgenode.happs.<name>.src
Path to the .happ bundle. Fetch it by hash; never commit one (ADR-012).
Type: absolute path
Declared by:
services.holochain-edgenode.hcPackage
Holochain CLI package used by the hApp installer. Keep it on the same
line as package: the admin subcommand is hc client call from 0.7 and
hc sandbox call below it.
Type: package
Default:
inputs.holonix.packages.${pkgs.stdenv.hostPlatform.system}.hc
Declared by:
services.holochain-edgenode.installerTimeout
Seconds the hApp installer allows each of its waits: the admin interface answering at all, then, per hApp, the install and the enable settling. The conductor needs about 80 seconds to open the port on an unaccelerated VM, so leave room. The unit itself has no start timeout, so raising this is enough.
Type: signed integer
Default:
300
Declared by:
services.holochain-edgenode.metricsExporter.enable
Whether to enable Prometheus node_exporter for fleet observability.
Type: boolean
Default:
false
Example:
true
Declared by:
services.holochain-edgenode.metricsExporter.port
Port to expose node metrics on.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
9100
Declared by:
services.holochain-edgenode.metricsExporter.textfileDirectory
Directory node_exporter’s textfile collector reads. Every *.prom
file in it is appended to /metrics verbatim, which is how metrics
that no exporter produces on its own reach Prometheus.
The directory is created 0755 and owned by user, so the conductor
metrics timer can write into it while node_exporter, which runs as
its own user, can read it.
Type: absolute path
Default:
"/var/lib/prometheus-node-exporter-text-files"
Declared by:
services.holochain-edgenode.openFirewall
Open firewall ports for the app and metrics interfaces. The admin port
is never opened. The conductor binds its websockets to localhost, so in
practice this matters for the metrics exporter, and for the app port
only if danger_bind_addr is configured by hand.
Type: boolean
Default:
false
Declared by:
services.holochain-edgenode.passphraseFileName
Name of the lair passphrase file inside dataDir. Generated with mode
0600 on first boot if absent and reused on every boot after that, which
is what lets the keystore open again after a reboot with nobody present.
Type: string
Default:
"lair-passphrase"
Declared by:
services.holochain-edgenode.relayAllowPlainText
Let the iroh transport use a plain-HTTP relay, by rendering
network.advanced.irohTransport.relayAllowPlainText: true. Kitsune2
refuses an http:// relay URL without it, so the conductor would not
start. Needed for a LAN services.holochain-bootstrap server without
TLS; leave it off for an https:// relay. Works on both lines.
Type: boolean
Default:
false
Declared by:
services.holochain-edgenode.relayUrl
Iroh relay used when a direct connection cannot be established. Required
by the conductor on both lines; null selects
https://use1-1.relay.n0.iroh-canary.iroh.link./, the default both
0.6.3 and 0.7.0 write for themselves.
For a services.holochain-bootstrap server this is
http(s)://<host>:<port>/relay: the same server as bootstrapUrl,
on the /relay path. A plain http:// relay also needs
relayAllowPlainText.
Type: null or string
Default:
null
Declared by:
services.holochain-edgenode.requestTimeoutS
network.request_timeout_s: seconds before a request and its response
time out. null leaves the conductor default, 60. Same key on both
lines.
Type: null or (positive integer, meaning >0)
Default:
null
Example:
90
Declared by:
services.holochain-edgenode.signalUrl
WebRTC signal server. Used only below 0.7, where null selects
wss://dev-test-bootstrap2.holochain.org. network.signal_url was
removed from the 0.7 config schema, so from 0.7 this option is ignored
and setting it raises a warning; use relayUrl instead.
Type: null or string
Default:
null
Declared by:
services.holochain-edgenode.useSystemdNotify
Run the conductor as Type = "notify", so the unit becomes active only
once the conductor has signalled readiness rather than as soon as the
process exists. Set to false to fall back to Type = "simple".
Type: boolean
Default:
true
Declared by:
services.holochain-edgenode.user
System user the conductor runs as.
Type: string
Default:
"holochain"
Declared by:
services.holochain-edgenode.wasmBackend
wasm_backend, from 0.7 only: which compiler runs zomes when the
Holochain binary was built with more than one. The conductor refuses a
backend it was not built with. null uses whichever is available.
Ignored with a warning below 0.7.
Type: null or one of “cranelift”, “LLVM”, “wasmi”
Default:
null
Declared by:
services.holochain-grafana.enable
Whether to enable Prometheus + Grafana observability for Holochain fleet.
Type: boolean
Default:
false
Example:
true
Declared by:
services.holochain-grafana.adminPassword
Grafana administrator password. The default is the workshop’s shared password, kept as a default so a fleet works out of the box on a lab network.
It ends up world-readable in the Nix store, so it is a lab convenience
and not a secret, and nixpkgs warns about it on every evaluation. On
anything reachable from outside the lab use adminPasswordFile, which
takes precedence over this option.
Type: string
Default:
"workshop2026"
Declared by:
services.holochain-grafana.adminPasswordFile
Path on the target machine to a file holding the Grafana administrator
password. When set it takes precedence over adminPassword, and the
password never enters the Nix store: systemd hands the file to Grafana
as a credential (LoadCredential), and Grafana reads it through a
$__file{...} reference.
Because systemd reads it, the file can stay owned by root with mode 0400, and it can be created before Grafana (or its user) exists. Create it on the node before the first deploy, for example:
sudo install -d -m 0700 /var/lib/secrets
sudo install -m 0400 /dev/null /var/lib/secrets/grafana-admin-password
printf '%s' 'the-password' | sudo tee /var/lib/secrets/grafana-admin-password > /dev/null
If the file is missing, grafana.service fails to start and its journal names the path.
The path must survive a reboot, so /run is the wrong place for it
unless a secrets manager repopulates it at boot.
Type: null or absolute path not in the Nix store
Default:
null
Example:
"/var/lib/secrets/grafana-admin-password"
Declared by:
services.holochain-grafana.adminUser
Grafana administrator account.
Type: string
Default:
"admin"
Declared by:
services.holochain-grafana.dashboards
Directory of Grafana dashboard JSON files to provision. Everything in
it is loaded at startup and re-read every 30 seconds. The module ships
five, each titled with the question it answers and all tagged
holochain: holochain-home (“What is this machine running?”),
Grafana’s home page, with each service’s state and version, each
conductor’s Holochain version and each app’s state; holochain-now
(“Is the Holochain network working?”), the room screen;
holochain-fleet (“Which Holochain node needs attention?”), for
whoever runs the fleet;
holochain-node (“Is this node working, app by app?”), one machine;
and holochain-network (“Is this app in step on every node?”), one
app network across every machine. They read the recording rules of
holochain-rules.nix, so they agree on every state.
For a directory in the Nix store, the module sets Grafana’s home page
(services.grafana.settings.dashboards.default_home_dashboard_path,
at default priority, so a definition of your own wins): its
holochain-home.json when it has one, with its node variable
defaulting to this machine (the name of the scrape target on a
loopback address, or at this machine’s host name or FQDN, else
networking.hostName), else its
holochain-now.json, otherwise a copy of Grafana’s own home page.
The choice is made while building, so a directory inside a package is
not built during evaluation.
A directory in the Nix store (a path in your flake, or a directory
inside a flake input or package such as "${inputs.x}/dashboards")
has every dashboard’s units textbox variable set from
overviewUnits on its way in, every field override matched by name
to name given the units’ names as value mappings, and the
room_app, room_part and room_label constants set from room
when that is set. Every threshold step that names a states option
in its fromOption key takes that option’s value, and the sentences
that quote a state’s threshold quote the value given, so the colours
and the words agree with the state the rules compute. A directory
outside the store, or a
store path written as a bare string that carries no Nix string
context, is provisioned as it is.
Type: absolute path
Default:
./dashboards
Declared by:
services.holochain-grafana.grafanaPort
Port Grafana listens on.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
3000
Declared by:
services.holochain-grafana.openFirewall
Open firewall ports for Grafana, Prometheus, and node_exporter.
Type: boolean
Default:
false
Declared by:
services.holochain-grafana.overviewUnits
systemd units to watch on every node on top of the ones each node lists itself, each with the name a person reads for it. The keys are units, the values their names; a unit whose name is null, or an entry of a plain list of units, is shown by its unit name.
Every node lists its own services in
services.holochain-services.units, filled from the modules enabled
on it (the conductor, the HTTP gateway, the local bootstrap and relay,
the Wind Tunnel runner, Prometheus, Grafana, and the services beside
them), and publishes that list through node_exporter. This option is
for what a node does not list: a machine that does not run these
modules, or a unit of your own on every machine. Its default is empty,
so what is watched follows each node’s configuration.
Each key is a regular expression Prometheus matches against the whole
unit name, suffix included, so restic-backups-.* works, and its name
is given to every unit it matches. A unit is watched on each node that
runs it, and a node that does not run it has no row for it, so one set
serves a fleet whose machines run different things. A unit a node
lists itself keeps the name the node gives it.
The watched units reach the recording rules (holochain:service_watched
and holochain:service_state), which the node page’s “Is each
service on this machine running?”, the fleet page’s “Which services
are not running?” and the room screen’s machine tiles read. For a dashboard of your own, the
keys are also joined with | into the default of any units textbox
variable, and every field override matched by name to name (the
unit label of node_systemd_unit_state) gets one regex value mapping
per named unit.
The holochain:node_problem rule, which the problem lists read, gives
every failed unit on the node a sentence of its own whether it is
watched or not, except device, scope and slice units, which the
node_exporter flags these modules set leave out, naming it by its
watched name or, when it has none, by its unit name.
Type: (attribute set of (null or string)) or (list of string) convertible to it
Default:
{ }
Example:
{
"caddy.service" = "Web server";
"restic-backups-.*" = "Backups";
}
Declared by:
services.holochain-grafana.prometheusPort
Port Prometheus listens on.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
9090
Declared by:
services.holochain-grafana.room
The one app part a room screen follows writes in. Rendered into the
constant variables room_app, room_part and room_label of every
provisioned dashboard that declares them; when null, those variables
keep the defaults their dashboard gives them.
An app installed by hand in Moss is not a good choice: its id changes
with every installation and holds $, which Grafana reads as a
variable.
Type: null or (submodule)
Default:
null
Declared by:
services.holochain-grafana.room.app
The installed_app_id of an app this module’s fleet installs from Nix.
Type: string
Example:
"requests-and-offers"
Declared by:
services.holochain-grafana.room.label
The name the room screen gives that app.
Type: string
Example:
"Requests & Offers"
Declared by:
services.holochain-grafana.room.part
The role of the app whose writes the room follows.
Type: string
Example:
"requests_and_offers"
Declared by:
services.holochain-grafana.scrapeInterval
How often Prometheus scrapes its targets. Prometheus itself defaults to
one minute, which for a lab fleet of a handful of nodes draws a
fifteen-minute window as about fifteen points, and makes rate() over
a short range flat or empty. The conductor metrics timer writes every
30 s by default, so this is deliberately below it.
Type: string
Default:
"15s"
Declared by:
services.holochain-grafana.scrapeTargets
The node_exporter of every node Prometheus scrapes, and the name each
node goes by on the dashboards. Prometheus attaches the name to every
series from the target as the node label, so a node that is down is
still shown by its name.
As an attribute set, each key is the node’s name, and the value gives
its address (host:port) and, optionally, its site, which becomes a
site label. As a list of host:port strings, each node is named after
the host part of its address, except that a loopback address
(127.0.0.1, localhost, ::1) takes this machine’s
networking.hostName. A list entry given by an IP address therefore
goes by that address on every dashboard, and evaluation warns about
it: give such a node a name with the attribute set form.
No two targets may go by the same name: the dashboards aggregate by
node, so two targets named alike would read as one machine. Two
list entries on one host (two ports of a loopback, say) need the
attribute set form.
Type: (list of string) or attribute set of (submodule)
Default:
[ ]
Example:
{
lab-1 = { address = "sensorica-holoport-01:9100"; site = "Sensorica lab"; };
lab-2 = { address = "sensorica-holoport-02:9100"; site = "Sensorica lab"; };
homelab.address = "100.64.0.7:9100";
}
Declared by:
services.holochain-grafana.secretKeyFile
Path on the target machine to a file holding Grafana’s
security.secret_key, the key it encrypts data source secrets with.
Since NixOS 26.05 Grafana has no default key and refuses to evaluate
without one.
When null, the module generates a random key once, at first boot, in
${services.grafana.dataDir}/secret_key (mode 0400, owned by
grafana) and keeps it across rebuilds, so the key never enters the
Nix store. Set this only to share one key between machines or to
restore one from a backup; like adminPasswordFile, it is handed over
by systemd and can stay root-owned.
Type: null or absolute path not in the Nix store
Default:
null
Example:
"/var/lib/secrets/grafana-secret-key"
Declared by:
services.holochain-grafana.states.historyWindow
How far back, as a Prometheus duration, a DHT with no peer is remembered to have had one. Within it the DHT reads “Lost contact”; a DHT that had nobody in all of it, on a DNA no other node of the fleet runs, reads “No one else yet”, which is normal for a node that is alone.
Type: string matching the pattern [0-9]+(ms|s|m|h|d|w|y)
Default:
"24h"
Declared by:
services.holochain-grafana.states.inStepShare
The share of its best peer’s data a connected DHT must hold, on
average over shareWindow, to read “In step” rather than “Catching
up”. A healthy DHT rarely holds everything its best peer does, since
new data is always on its way, so 1 would read a working network as
behind for good; 0.95 is what the Sensorica Moss node’s DHTs held on
2026-09-27.
Type: integer or floating point number between 0 and 1 (both inclusive)
Default:
0.95
Declared by:
services.holochain-grafana.states.shareWindow
The window, as a Prometheus duration, the held share is averaged over, so a DHT does not flap between “In step” and “Catching up” at every write.
Type: string matching the pattern [0-9]+(ms|s|m|h|d|w|y)
Default:
"10m"
Declared by:
services.holochain-grafana.states.silentAfterSeconds
How long a DHT that knows peers may go without gossiping with any of them before it reads “Lost contact”.
Type: positive integer, meaning >0
Default:
600
Declared by:
services.holochain-grafana.states.staleAfterSeconds
How old a conductor’s readings may get before every DHT of it reads
“No fresh readings” and its conductor state reads stale. The default
covers the metrics timer’s 30 s interval plus the 15 s scrape, with
margin; raise it with conductorMetrics.interval.
Type: positive integer, meaning >0
Default:
90
Declared by:
services.holochain-http-gateway.enable
Whether to enable the Holochain HTTP gateway in front of the local conductor.
Type: boolean
Default:
false
Example:
true
Declared by:
services.holochain-http-gateway.package
The hc-http-gw package to run. The default is built from the tagged
upstream source for the Holochain line the conductor runs, so it does
not have to be set by hand when the conductor’s line changes.
Type: package
Default:
the hc-http-gw release matching services.holochain-edgenode.package.version: 0.4.x for Holochain 0.7, 0.3.x for 0.6
Declared by:
services.holochain-http-gateway.address
Address the gateway binds to, passed as --address (HC_GW_ADDRESS).
The default keeps it on loopback; set it to 0.0.0.0 and turn on
services.holochain-http-gateway.openFirewall to serve a LAN.
Type: string
Default:
"127.0.0.1"
Declared by:
services.holochain-http-gateway.adminPort
Admin websocket port of the conductor the gateway drives. It becomes
HC_GW_ADMIN_WS_URL=ws://127.0.0.1:<adminPort>, which the binary
requires: without it the process exits immediately.
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
config.services.holochain-edgenode.adminPort
Declared by:
services.holochain-http-gateway.allowedAppIds
Installed app ids the gateway is allowed to reach, joined into
HC_GW_ALLOWED_APP_IDS. Empty, the default, exposes nothing: the
gateway runs and refuses every zome-call path. Each id listed here
needs a matching entry in
services.holochain-http-gateway.allowedFns.
Type: list of string
Default:
[ ]
Example:
[
"dino-adventure"
]
Declared by:
services.holochain-http-gateway.allowedFns
Per app id, the zome functions the gateway may call, written
zome_name/fn_name. Each entry becomes
HC_GW_ALLOWED_FNS_<app-id>, a comma separated list.
The single-element list ["*"] allows every function in every zome of
that app, which the binary accepts but which also exposes the app’s
writes, since the gateway does nothing else to tell a read from a
write. Using it raises an evaluation warning. * cannot be mixed with
named functions; the binary would fail to parse the value.
Type: attribute set of list of string
Default:
{ }
Example:
{
dino-adventure = ["dino_adventure/get_all_dinos_local"];
my-app = ["*"];
}
Declared by:
services.holochain-http-gateway.maxAppConnections
How many app websocket connections the gateway keeps open at once, one
per allowed app, as HC_GW_MAX_APP_CONNECTIONS. Older connections are
closed when the limit is reached.
Type: unsigned integer, meaning >=0
Default:
50
Declared by:
services.holochain-http-gateway.openFirewall
Open services.holochain-http-gateway.port in the firewall.
Leave it off unless the gateway is meant to be reachable from other
machines; the conductor’s admin interface is reachable through
anything the gateway is allowed to call.
Type: boolean
Default:
false
Declared by:
services.holochain-http-gateway.payloadLimitBytes
Largest accepted payload query parameter, in bytes, as
HC_GW_PAYLOAD_LIMIT_BYTES. Measured on the base64 text before it is
decoded, so it is really a cap on the URL length the gateway will
process. Upstream’s own default is the same 10 KiB.
Type: unsigned integer, meaning >=0
Default:
10240
Declared by:
services.holochain-http-gateway.port
Port the gateway listens on, passed as --port (HC_GW_PORT).
Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)
Default:
8090
Declared by:
services.holochain-http-gateway.zomeCallTimeoutMs
Deadline for a single zome call, in milliseconds, as
HC_GW_ZOME_CALL_TIMEOUT_MS. A call that outruns it answers 500.
Type: unsigned integer, meaning >=0
Default:
10000
Declared by:
services.holochain-services.healthChecks
Health checks, keyed by the unit they check, which should also be in
units. A timer runs every one every 30 seconds and writes
holochain_service_healthy (1 or 0) and
holochain_service_health_timestamp_seconds to
holochain-service-health.prom in textfileDirectory. A service
whose unit is active reads Not answering on the dashboards when its
check fails, and No fresh readings when the last check is older than
services.holochain-grafana.states.staleAfterSeconds. The bootstrap
module adds its /health here.
Type: attribute set of (submodule)
Default:
{ }
Declared by:
services.holochain-services.healthChecks.<name>.insecure
Accept any TLS certificate. For a check that reaches a service by its loopback address while its certificate names the host.
Type: boolean
Default:
false
Declared by:
services.holochain-services.healthChecks.<name>.timeoutSeconds
How long the check waits for an answer before it reads the service as not answering.
Type: positive integer, meaning >0
Default:
5
Declared by:
services.holochain-services.healthChecks.<name>.url
A URL that answers with a success status while the service works.
Type: string
Example:
"http://127.0.0.1:443/health"
Declared by:
services.holochain-services.textfileDirectory
The directory node_exporter’s textfile collector reads on this
machine, where the list of services and the health readings are
written. Set by services.holochain-edgenode when its
metricsExporter is on, and by services.holochain-grafana on a
monitor; on another machine that runs node_exporter with a textfile
collector of its own (a machine that only runs the bootstrap server,
say), set it to that collector’s directory. Null writes nothing, and
that machine’s services are then missing from the dashboards.
Type: null or string
Default:
null
Example:
"/var/lib/prometheus-node-exporter-text-files"
Declared by:
services.holochain-services.units
The systemd units this node runs that the Holochain dashboards watch,
each with the name a person reads for it; a value is that name, or
{ name; conductor; version; holochainVersion; }, where version is
the version of the package the unit runs and the last two are for a
unit that runs a conductor.
Filled from the configuration: every nixos-holochain module that is
enabled adds the units it creates (the conductor, the app installer
when there are apps, the conductor readings timer when
conductorMetrics is on, the HTTP gateway, the local bootstrap and
relay, the Wind Tunnel runner, and on a monitor Prometheus and
Grafana), and, on a machine where any of them is enabled, the
services beside them that are enabled here: node_exporter, sshd,
Tailscale and the Nix daemon’s socket. Each module also gives the
version of the package it runs the unit from, so the home page can
say what runs, in which version, without asking the machine. Add a
unit of your own the way any attribute set option merges; override a
name with lib.mkForce on that one attribute.
Published as holochain_service_info through node_exporter’s textfile
collector when textfileDirectory is set. The home page’s “Is each
service running, and in which version?” lists each of them with its
state and version, the node page’s “Is each service on this machine
running?” with its state,
the fleet page lists the ones that are not running, and the room
screen’s machine tile reads “A service is down” while one has failed,
keeps failing and restarting, has stopped or does not answer. A unit
systemd does not run has no row; evaluation warns about a listed unit
this configuration does not define.
services.holochain-grafana.overviewUnits, on the monitor, adds units
to watch on every node on top of these.
Type: attribute set of ((submodule) or string convertible to it)
Default:
{ }
Example:
{
"caddy.service" = "Web server";
"moss-node-metrics.timer" = "Moss readings (timer)";
}
Declared by:
services.holochain-services.units.<name>.conductor
For a unit that runs a Holochain conductor, the conductor label
its readings carry (services.holochain-edgenode.conductorMetrics.name
for an edgenode). The service then reads Not answering when the
conductor does not answer its admin interface, and No fresh
readings when its readings are old, although systemd says the
unit is active. A conductor that no listed unit claims is shown
as a service of its own, “Holochain conductor (<conductor>)”, as
the edgenode names the unit that runs a conductor under a name
other than the default: a Moss node whose readings carry
conductor="Moss" reads “Holochain conductor (Moss)”.
Type: null or string
Default:
null
Example:
"Workshop"
Declared by:
services.holochain-services.units.<name>.holochainVersion
For a unit that runs a Holochain conductor, the Holochain version
that conductor is, published as the holochain_version label.
It differs from version when the unit runs another program
that brings its own Holochain, as a Moss node does.
Type: string
Default:
""
Example:
"0.6.1"
Declared by:
services.holochain-services.units.<name>.name
The name a person reads for the unit on the dashboards.
Type: string
Example:
"Local bootstrap and relay"
Declared by:
services.holochain-services.units.<name>.version
The version of what the unit runs, from the package the module
runs it from, never guessed at runtime; published as the
version label. Empty when the unit has none worth naming (a
readings timer, a container pulled by digest), which the home
page shows as a dash.
Type: string
Default:
""
Example:
"0.6.3"
Declared by:
services.holochain-windtunnel.enable
Donate this machine to the Holochain Foundation’s Wind Tunnel test network.
The container runs its own Holochain conductor and reports to the
Foundation’s Nomad cluster at nomad-server-01.holochain.org; the
runner’s own README calls these machines “designed to be for internal
use only” and warns that the image “requires extensive permissions on
the host machine that are effectively root access” and “should only be
run on a dedicated machine”.
Enabling this donates the machine. It does not feed the fleet
dashboard: the holochain_* series come from
services.holochain-edgenode.conductorMetrics, and nothing in this
module exposes a Prometheus endpoint. Off by default, deliberately.
Type: boolean
Default:
false
Example:
true
Declared by:
services.holochain-windtunnel.autoStart
Start the container at boot. Set to false to keep the unit generated but idle, which is what the VM test does: the test sandbox has no network, so the image cannot be pulled there.
Type: boolean
Default:
true
Declared by:
services.holochain-windtunnel.backend
OCI backend used to run the container. Podman is the default: it needs no daemon and the NixOS module wires the unit to it directly. The runner’s README documents Docker, and the image is indifferent to which one starts it.
Type: one of “podman”, “docker”
Default:
"podman"
Declared by:
services.holochain-windtunnel.extraOptions
Flags passed to podman run / docker run. The default is the set the
runner’s README requires: host networking, privileged, and the host
cgroup namespace, so the Nomad agent inside can schedule and supervise
its own workloads. Removing any of them stops the runner from working;
they are an option only so that a host with a conflicting device or
network setup can adjust them knowingly.
Type: list of string
Default:
[
"--net=host"
"--privileged"
"--cgroupns=host"
]
Declared by:
services.holochain-windtunnel.hostname
Hostname the container reports to the Nomad cluster, passed as
--hostname. The runner’s README asks for a unique, recognisable
nomad-client-<user> style name, since it is how the machine is
identified in the Nomad and Tailscale dashboards.
Type: string
Default:
"nomad-client-${config.networking.hostName}"
Declared by:
services.holochain-windtunnel.image
Runner image, pinned by digest.
ghcr.io/holochain/wind-tunnel-runner publishes only the moving tags
latest, latest-amd64 and latest-arm64, so a tag pin would silently
change what a fleet runs. The default is the multi-architecture index
digest that latest resolved to on 2026-08-28, which keeps amd64 and
arm64 hosts on the same pin. Re-pin with
skopeo inspect docker://ghcr.io/holochain/wind-tunnel-runner:latest
Type: string
Default:
"ghcr.io/holochain/wind-tunnel-runner@sha256:650c91806275681bc1961e0e55e85fa7fbf31bebe0c8665fc0a6af71ac330fa2"
Declared by: