Inventory & multi-device fan-out
Running a command against one switch is useful. Running the same command across every spine and leaf in your fabric — concurrently, with one line — is what makes nxstate valuable at scale. This guide covers the inventory file, how settings are inherited, how to target devices, and what the concurrent fan-out output looks like.
The inventory file
Section titled “The inventory file”nxstate looks for a Nornir-flavored YAML file at:
~/.config/nxstate/inventory.yamlYou can override that location with a flag or an environment variable:
# flag — takes effect for this one runnxstate --inventory /etc/nxstate/prod.yaml interface list --all
# environment variable — applies to every run in this shell sessionexport NXSTATE_INVENTORY=/etc/nxstate/prod.yamlnxstate interface list --allIf the file does not exist when you use --device, --group, or --all, nxstate exits immediately with code 10 (config_error) and tells you where it looked.
The file has three top-level sections: defaults, groups, and hosts. Passwords are never stored here — they come from the environment, the OS keyring, or --password-stdin at connection time. See Authentication for the full credential resolution order.
A complete example
Section titled “A complete example”## No secrets here. Passwords come from NXSTATE_PASSWORD / the OS keyring# (nxstate auth login) / --password-stdin.
defaults: username: netops transport: auto # auto | ssh | nxapi
groups: datacenter: transport: nxapi insecure: true # self-signed NX-API TLS certs are common in labs edge: {}
hosts: leaf1: host: 10.1.1.11 groups: [datacenter] leaf2: host: 10.1.1.12 groups: [datacenter] edge1: host: edge1.example.net groups: [edge] username: edge-ro # host-level override: different account on this switchInheritable keys
Section titled “Inheritable keys”The following keys can appear in defaults, a groups entry, or a hosts entry:
| Key | Description |
|---|---|
host | Hostname or IP to connect to (defaults to the inventory name if omitted) |
username | Login username |
transport | auto, ssh, or nxapi |
port | Transport port (nxstate picks the right default per transport) |
insecure | Skip TLS verification for NX-API self-signed certs (true/false) |
timeout | Per-command timeout in seconds (default 30) |
How settings are inherited
Section titled “How settings are inherited”Resolution follows a simple three-level merge: defaults is the base, then each group listed in groups: for that host is applied in order, and finally the host’s own keys win. The rule is defaults ← groups ← host (host wins).
Working through the example above for leaf1:
- Start with defaults:
{username: netops, transport: auto} - Apply the
datacentergroup:{username: netops, transport: nxapi, insecure: true} - Apply
leaf1’s own keys:{host: "10.1.1.11", username: netops, transport: nxapi, insecure: true}
For edge1, the host-level username: edge-ro overrides the default netops:
- Start with defaults:
{username: netops, transport: auto} - Apply the
edgegroup (empty{}): no change - Apply
edge1’s own keys:{host: "edge1.example.net", username: edge-ro, transport: auto}
A CLI flag always wins over everything else. So --username admin --device edge1 would use admin even though the inventory says edge-ro.
Targeting devices
Section titled “Targeting devices”All targeting flags are global — they can go anywhere in the command line, before or after the subcommand.
By name (with glob support)
Section titled “By name (with glob support)”--device matches inventory host names. Pass it once per name, or use a shell glob:
# single device by exact namenxstate --device leaf1 interface list
# two devices explicitlynxstate --device leaf1 --device leaf2 vlan list
# all hosts whose name starts with "leaf"nxstate --device 'leaf*' vlan list
# mix glob and explicit name — results are de-duplicatednxstate --device 'leaf*' --device edge1 system versionIf a pattern matches no inventory host, nxstate exits with code 5 (not_found) before connecting to anything.
By group
Section titled “By group”--group selects all members of a named group. Repeatable:
# all datacenter hostsnxstate --group datacenter bgp summary
# union of two groupsnxstate --group datacenter --group edge system versionIf the group name does not exist in the inventory, nxstate exits with code 5 (not_found).
All hosts
Section titled “All hosts”--all targets every host in the inventory:
nxstate --all system versionMixing targeting flags
Section titled “Mixing targeting flags”You can combine --device, --group, and --all freely. Results are merged and de-duplicated, then sorted by inventory name before the run begins.
Ad-hoc without an inventory
Section titled “Ad-hoc without an inventory”If you just want to hit one switch without setting up a file, use --host directly:
nxstate --host 10.1.1.11 --username netops system version--host and the inventory targeting flags (--device/--group/--all) serve different purposes: --host selects an ad-hoc target without any inventory file, while --device/--group/--all resolve targets from the inventory. When inventory targeting flags are present, the inventory path is used; --host is not meaningful in that context and should be omitted.
Single-device output
Section titled “Single-device output”When exactly one target resolves, nxstate writes clean structured output to stdout — identical to what you get with --host:
$ nxstate --device leaf1 system version{ "nxos_ver_str": "10.3(8)", "hostname": "leaf1", ...}Multi-device fan-out
Section titled “Multi-device fan-out”When more than one target resolves, nxstate runs all devices concurrently (using a thread pool) and streams one JSON object to stdout per device as each completes. This is newline-delimited JSON (NDJSON) — one complete JSON object per line, in completion order (not inventory order).
$ nxstate --group datacenter system version{"device":"leaf1","host":"10.1.1.11","ok":true,"data":{"nxos_ver_str":"10.3(8)","hostname":"leaf1",...}}{"device":"leaf2","host":"10.1.1.12","ok":true,"data":{"nxos_ver_str":"10.3(8)","hostname":"leaf2",...}}Each line is a self-contained envelope:
{ "device": "leaf1", "host": "10.1.1.11", "ok": true, "data": { ... }}On error, the envelope carries "ok": false and a structured error object instead of data:
{ "device": "leaf2", "host": "10.1.1.12", "ok": false, "error": { "code": "UNREACHABLE", "message": "10.1.1.12 is not reachable: connection timed out", "remediation": "check connectivity, --transport, --port, and credentials" }}Per-device error isolation
Section titled “Per-device error isolation”A failure on one device never interrupts the others. All remaining devices continue to run and emit their results. You always get output for every device that succeeds, regardless of what other devices do.
Exit code 15 — PARTIAL
Section titled “Exit code 15 — PARTIAL”After all devices have completed, nxstate exits 0 if every device succeeded, or 15 (partial) if at least one device returned an error. This makes it straightforward to detect partial failures in scripts:
nxstate --all interface listEXIT=$?
if [ $EXIT -eq 0 ]; then echo "All devices OK"elif [ $EXIT -eq 15 ]; then echo "Some devices failed — check the NDJSON output for ok:false lines"else echo "Hard error: $EXIT"fiSee Exit codes for the full table.
Controlling concurrency
Section titled “Controlling concurrency”The default thread-pool size is 10 concurrent devices. Increase or decrease it with --workers:
# run up to 30 devices at oncenxstate --all --workers 30 vlan list
# slow it down for a congested out-of-band networknxstate --all --workers 2 vlan listThere is no enforced upper limit, but practical limits depend on your management network and CPU. For very large fleets, start with the default and increase once you observe stable results.
Processing NDJSON output
Section titled “Processing NDJSON output”Because each line is valid JSON, standard tools work cleanly:
# pretty-print with jq, one device at a timenxstate --all system version | jq .
# extract just the hostname from each device's datanxstate --all system version | jq -r '.data.hostname // .device + " (failed)"'
# filter to failures onlynxstate --group datacenter interface list | jq 'select(.ok == false)'
# collect all results into a JSON arraynxstate --all system version | jq -s '.'Running doctor across a fleet
Section titled “Running doctor across a fleet”nxstate doctor also fans out across multiple targets, emitting per-device NDJSON. This is the fastest way to confirm that every switch in your inventory is reachable with valid credentials before a bulk operation:
nxstate --all doctorIf any device fails the reachability check, the overall exit code is 9 (unreachable). The individual check objects in each envelope tell you exactly which step failed — host present, credentials present, or connectivity.
Related pages
Section titled “Related pages”- Global flags —
--device,--group,--all,--inventory,--workersand every other flag - Authentication — password resolution order, keyring setup,
--password-stdin - Output & filtering —
--format,--select,--limitall apply per-device in fan-out mode - Exit codes — full table including exit 15 (
partial) - Inventory schema — exhaustive YAML field reference
- Troubleshooting — debugging connectivity and credential issues