Automating NVUE: REST API, config templates and Ansible
S5·E4The first question is not technical · Customer engineering office, Wednesday, thirty-two leaves on the whiteboard
Before you read: what do you already know?
3 quick questions. Wrong answers are fine and expected; trying first makes the lesson stick.
After this lesson you can
- Query and modify switch configuration through the NVUE REST API with the correct path shape, revision and authentication.
- Create a reusable leaf template from a working configuration using `nv config show -o commands`, `verify` and `replace`.
- Build an Ansible play against the `nvidia.nvue` collection that configures RoCE and a VLAN and reports drift.
- Judge when a snippet is the right escape hatch and what it costs at the next upgrade.
Episode 4 — The first question is not technical
Two days left, and the network lead has stopped asking about drops. Her question now is whether any of this is supported, because the change board asks her that tomorrow and she will not guess. The Dell SE has the promise spreadsheet open beside her; the row that matters says thirty-two leaves, identically configured, by Thursday night.
You can give her most of the answer immediately. The NVUE object model is defined with the OpenAPI Specification v3.0.2, and the CLI and the REST API are equivalent in functionality — there is no automation-only feature set and no CLI-only one.[2] The API is enabled by default on port 8765 with basic authentication against switch credentials, and after an upgrade to 5.6 or later an unchanged cumulus password returns 403 on every call, which reads as a fleet-wide outage and is authentication.[1]
That equivalence is why the model exists: one schema, three revisions, every client — a human typing, a curl, a play — staging into the same pending configuration.
Then the night operator says his scripts will just push /etc/frr/frr.conf the way they do everywhere else. NVUE commands replace the configuration in files such as /etc/network/interfaces and /etc/frr/frr.conf, so that edit is transient by design.[3] On the speakerphone the NVIDIA PM answers the roadmap version with “not announced”, the honest answer and nobody’s favourite.
If the CLI can say it, the API can say it — and whatever you hand-edit underneath, the model will say it again.
Start with the model, and with the CLI as only one of its clients.
1The API is the model, and the CLI is a client of it
NVUE’s object model is defined with the OpenAPI Specification v3.0.2, and “The CLI and the REST API are equivalent in functionality”.[2] That single sentence is the licence for everything in this lesson: there is no automation-only feature set and no CLI-only feature set. The nvued service is installed and enabled by default.[2][1]
The REST API is enabled by default on port 8765; disable it with nv set system api state disabled and move it with nv set system api port <port-number>.[1] Authentication is HTTP basic with switch credentials — and after upgrading to 5.6 or later you must change the password for the cumulus user, “otherwise you see 403 responses”.[1] On a customer call, a fleet-wide 403 reads like an outage and is a password.
curl -u 'cumulus:cumulus' --insecure https://127.0.0.1:8765/nvue_v1/interface
curl -u 'cumulus:cumulus' --insecure https://127.0.0.1:8765/nvue_v1/?rev=applied
curl -u 'cumulus:cumulus' -H 'Content-Type: application/json' -X PATCH \
https://127.0.0.1:8765/nvue_v1/interface/lo/ip/address?rev=2 -d '{"99.99.99.99/32": {}}'[1] Paths follow /nvue_v1/<resource>/<path>, with top-level objects including acl, bridge, interface, router, vrf, service and system; the full endpoint listing lives in the NVUE API browser tool at https://api-prod.nvidia.com/openapi-browser.[1] Note the ?rev= on both the read and the write: the API works on the same pending, applied and startup revisions the CLI does, so an automation run stages into a revision and then applies it, exactly like a human.[1][3]
- nothing run yet — start with `nv set`.
Pending revision
- Where `nv set` and `nv unset` land. Nothing is running yet — the switch behaves exactly as it did before.
- Read it with `nv show --pending`. Before every apply, read `nv config diff startup pending`.
- `nv config detach` throws away every pending change made since the last apply.
Blocked destinations: /bin, /sbin, /boot, /root, /sys, /proc, /dev. One snippet per file, set/unset only, 1 MB cap on flexible snippets.
nv action generate system tech-support # or: sudo cl-support nv config apply nv config save # writes /etc/nvue.d/startup.yaml nv config show -o commands > backup.config scp cumulus@leaf01:/etc/nvue.d/startup.yaml . nv config diff startup applied # must be empty before the reboot
Destructive ONIE install keeps the config only with -t /etc/nvue.d/startup.yaml. 5.18.0 adds automatic snapshots in /var/lib/config-backup/ (512 MB cap) restored with nv action restore system config backup <path>.
Upgrading Cumulus Linux · DGX SuperPOD switch update guide · 5.18 What's New · NVUE object model
2Templates out of the config verbs
A template is not a new tool; it is a disciplined use of nv config.[4]
| Command | What it does | Introduced |
|---|---|---|
nv config show |
current applied configuration as YAML; --all includes defaults; -r <rev-id> for a revision |
5.0.0 |
nv config patch <file> |
merges a YAML or command-text file into pending | 5.0.0 |
nv config replace <file> |
replaces the whole pending configuration — the file must include everything you want kept | 5.0.0 |
nv config diff <base> <target> |
compares two configurations | 5.0.0 |
nv config translate revision <rev-id> or filename <file> |
converts a revision or YAML file into NVUE commands | 5.12.0 |
nv config verify [filename <file> or revision <rev>] |
validates without applying | 5.17.0 |
nv config lookup <search-path> |
retrieves configuration by space- or slash-separated path | 5.18.0 |
nv config revision / history / attach / delete |
revision list, apply history, attach and remove | 5.5.0 / 5.0.0 / 5.12.0 |
[4] The template workflow follows directly: build one leaf by hand, export it with nv config show -o commands > leaf.config, parameterize the lines that differ per device, validate the rendered file with nv config verify filename <file>, load it with nv config replace <file>, and commit with nv config apply --confirm <time> so a switch that loses its management path rolls back on its own.[3][4]
Two properties of that chain matter more than the syntax. First, replace is destructive by design: anything not in the file is gone from pending, which is what makes it a template verb and also what makes an un-diffed replace dangerous on a switch someone customised.[4] Second, keep both forms. NVIDIA’s documented restore procedure saves startup.yaml, copies it off-box, and — if required — converts it to the running release’s format with nv config translate before nv config replace.[3] The same page warns that NVUE syntax can change between releases, so review the What’s New before restoring across releases; that warning applies to the command form too.[3] Keep the -o commands export because it is reviewable in a change record and re-appliable by hand, not because NVIDIA documents it as more durable.
Auto-save is on by default from Cumulus Linux 5.9 onward, so nv config apply also writes startup; before 5.9 nv config save was mandatory.[4] Do not let that make you casual: nv config diff startup applied before a reboot is a two-second check that resolves half of all “the config disappeared” tickets.[3]
3Snippets: the escape hatch and its bill
NVUE renders the Linux configuration files from its model, so “NVUE commands replace the configuration in files such as /etc/network/interfaces and /etc/frr/frr.conf”.[3] A hand edit to those files is transient by design, and this is the single most common self-inflicted outage on a newly automated fabric.
Snippets are the sanctioned way to carry configuration NVUE does not model. Documented destinations are /etc/network/interfaces, /etc/frr/frr.conf, /etc/frr/daemons, /etc/cumulus/switchd.conf, /etc/cumulus/datapath/traffic.conf and /etc/ssh/sshd_config.[5] The rules: “You can only set or unset a snippet; you cannot modify, partially update, or change a snippet”; one snippet per configuration file; flexible snippets cap at 1 MB.[5] The YAML shape, applied with nv config patch <file>.yaml and then nv config apply:
- set:
system:
config:
snippet:
frr.conf: |
<raw FRR config>[5] “NVUE does not validate the snippet text but does ensure that the destination conforms to NVUE policy during apply”, and writes to /bin, /sbin, /boot, /root, /sys, /proc and /dev are blocked.[5] The bill arrives at upgrade time: “Before upgrading Cumulus Linux, remove snippets for features now supported natively by NVUE.”[5] A snippet written in 5.14 for something 5.18 models natively is a latent upgrade failure, so a fabric with snippets needs a snippet inventory in its upgrade runbook.
4Ansible: the nvidia.nvue collection
NVIDIA publishes an Ansible collection named nvidia.nvue.[6] Install it from Galaxy, from a requirements file, or from git, and verify:
ansible-galaxy collection install nvidia.nvue
ansible-galaxy collection install -r requirements.yml
ansible-galaxy collection install git+https://gitlab.com/nvidia-networking/systems-engineering/nvue.git
ansible-galaxy collection list[7] Requirements as stated on the deployment page: ansible-core 2.11 or later, Python 3.6 and later, Cumulus Linux 5.4 and above; the automation page describes the modules as “developed and validated using Ansible 2.11 and Python 3.6” and “supported on Cumulus Linux 5.x”.[7][6]
Two high-level modules and a set of object modules:[6]
nvidia.nvue.command— “A wrapper around the NVUE command line tool with added templating and automated dialog prompting.”nvidia.nvue.api— “A wrapper around the NVUE REST API to send and retrieve NVUE configuration.” Use it “For REST API endpoints that are not covered by the object-specific modules or for sub-paths within the object specific modules”.- Object modules:
acl,bridge,config,evpn,interface,mlag,router,service,system,vrf,vxlan.
The support statement belongs in your first conversation with any customer who wants to build a pipeline on this: “The NVUE Ansible modules are community supported and not validated by NVIDIA. Support for these modules are on a ‘Best-Effort’ basis.”[6] That does not mean do not use them; it means the customer’s escalation path for a module bug is not the same as their escalation path for a switch bug, and their runbook should be able to fall back to nv config replace over SSH.
The two pages fetched for this lesson do not document the inventory variables or the connection method the modules use, so build the inventory from the collection’s own documentation after installing it, and remember the API side of the equation: port 8765, basic auth, and a cumulus password that must not still be the default.[6][7][1]
Goal: one template, applied to leaf01 and leaf02, that enables RoCE and creates VLAN 10, with drift reporting.
-
Build leaf01 by hand and confirm it:
nv set qos roce,nv set bridge domain br_default vlan 10,nv config apply, thennv show qos roce.[9] -
Export the command form:
nv config show -o commands > leaf01.config.[4] Read the file; it is the whole applied configuration, not a fragment. -
Parameterize. Replace the device-specific lines with placeholders and keep everything else:
nv set system hostname {{ inventory_hostname }} nv set router bgp autonomous-system {{ bgp_asn }} nv set interface lo ip address {{ loopback }} nv set qos roce nv set bridge domain br_default vlan 10 -
Render per host into
build/leaf01.configandbuild/leaf02.configwith any templating engine, includingnvidia.nvue.command’s own templating.[6] -
Validate before touching hardware: copy each rendered file to its switch and run
nv config verify filename <file>. A failure here fails the pipeline while both switches still run the old configuration.[4] -
Diff before replacing, because
replaceremoves anything not in the file:nv config replace <file>thennv config diff applied pendingand read it.[4] -
Apply with rollback protection:
nv config apply --confirm 5, confirm only if the switch is still reachable and healthy.[3] -
Prove it rather than trusting the return code: read state back with
nv show qos roceandnv show bridge domain br_default vlan, or through the API withcurl -u '<user>:<pw>' --insecure https://<leaf>:8765/nvue_v1/qos/roce?rev=applied, and fail the run on any difference.[1][9] -
Record the two support facts in the runbook header: the API and config verbs are product features; the Ansible collection is community supported, best-effort.[1][6]
- Export the template:
nv config show -o ____ > leaf01.config. - Validate a rendered file without applying:
nv config ____ filename build/leaf02.config— available since ____. - Load it:
nv config ____ build/leaf02.config, which removes anything ____. - Commit safely on a remote leaf:
nv config apply ____ 5. - Read back through the API:
curl -u '<user>:<pw>' --insecure https://<leaf>:____/nvue_v1/qos/roce?rev=____. - Support statement to put in the runbook header: the Ansible collection is ____ and ____ by NVIDIA.
Design a pipeline for 32 leaves in a Spectrum-X pod. Requirements: RoCE lossless on every leaf, one VLAN per tenant with a per-leaf list, adaptive routing enabled globally and on uplinks only, and one leaf (leaf17) that carries a snippet for a feature NVUE does not model.
Produce: (a) the rendering and validation stages with the exact commands at each; (b) the rule that stops the pipeline from destroying leaf17’s snippet, naming which verb would have removed it; (c) a drift-detection stage that reads state back and defines pass or fail; (d) the two sentences you would put in the customer’s change record about support ownership; and (e) the rollback for a leaf that applies cleanly but loses BGP afterwards. Acceptance: (b) names nv config replace and a snippet inventory, (c) reads state rather than checking exit codes, and (e) uses a mechanism that works when you can no longer reach the switch.
What the network lead took to her change board
The artefact of her pipeline is not a play, it is a rendered NVUE command file: validated with nv config verify while all 32 leaves still run the old configuration, loaded with nv config replace, committed with nv config apply --confirm so a leaf that loses its management path rolls itself back.[4][3]
What she tells the board: the API and the config verbs are product features; the Ansible collection is community supported and not NVIDIA validated, best-effort.[1][6] So Ansible renders and ships the file, and anyone with SSH can apply it during an incident.
Thursday morning the read-back is uniform — and finds the one thing a template cannot make uniform. Twenty-eight leaves on one release, four on another, and Friday’s acceptance criteria name a build.
Lab
No switch in the Dell lab, so apply the same discipline to the host side of the fabric: idempotent configuration plus a read-back that fails on drift.
Pre-flight inventory, all hosts: ethtool -i <ifname>, sudo mst start && flint -d /dev/mst/<dev> q, mlxconfig -d /dev/mst/<dev> q > mlxconfig-before.txt, and mlxreg -d /dev/mst/<dev> --reg_name QPTS --get > qpts-before.txt plus the same for PFCC. These files are the rollback reference for every step.
- Read-only first. Read the current trust mode and PFC state from the NIC and record them:
mlxreg -d /dev/mst/<dev> --reg_name QPTS --getandmlxreg -d /dev/mst/<dev> --reg_name PFCC --get. - Mutating. Write an idempotent script that sets the host RoCE state you want (trust
dscp, PFC on priority 3, the ToS your fabric expects) usingmlxreg --set, and that re-reads each register afterwards and exits non-zero if the read-back does not match the intent. Idempotent means running it twice changes nothing the second time — prove that by running it twice and diffing the read-backs. Rollback: re-apply the values captured inqpts-before.txtand the PFCC equivalent withmlxreg --set, then re-read to confirm. - Wrap it as an Ansible role with two tasks: apply, and verify. The verify task must read state and fail the play on drift, not check the exit code of the apply. This is the same rule as step 8 of the Worked example, moved to the host.
- Run the play against both lab hosts and then deliberately change one register by hand on one host and re-run only the verify task. Expected: the play fails on that host and names the register. That failure is the deliverable.
- Optional: if HBN is running on the BlueField-3 it exposes
nvverbs; check which subset withnv --helpandnv config show -o commandson the Arm side, and document exactly which of this lesson’s verbs exist there before you rely on any of them. Read-only. Treat anything you cannot confirm on the box as unverified rather than assuming parity with a switch. - Write the one-page comparison: what the switch pipeline does (render, verify, replace, apply –confirm, read back) and what the host pipeline does (apply registers, read back, fail on drift), and where the two must be sequenced together during a fabric change.[4]
Work against a DSX Air Cumulus node. Everything here changes configuration on a simulated switch, which is the safe place to make these mistakes.
-
Pre-flight:
nv show system version, thennv config show -o commands > baseline.configand keep it. This is your rollback for every later step.[4] -
API read. From the node itself (or from another node in the simulation):
curl -u 'cumulus:<pw>' --insecure https://127.0.0.1:8765/nvue_v1/interface curl -u 'cumulus:<pw>' --insecure https://127.0.0.1:8765/nvue_v1/?rev=appliedExpected: JSON for the interface tree and the applied revision.[1] If you get 403: the
cumuluspassword is still the default — change it and retry, and write that symptom down.[1] -
API write. PATCH a loopback address, then apply and confirm through the CLI:
curl -u 'cumulus:<pw>' -H 'Content-Type: application/json' -X PATCH \ https://127.0.0.1:8765/nvue_v1/interface/lo/ip/address?rev=<rev> -d '{"99.99.99.99/32": {}}' nv config diff applied pending nv config apply --confirm 2Expected: the diff shows exactly the loopback change; if you do nothing for the confirm window the switch rolls back.[1][3] Rollback:
nv config replace baseline.configthennv config apply. -
Template. Build a small working configuration by hand (hostname, loopback,
nv set qos roce, one VLAN), export withnv config show -o commands > leaf.config, parameterize hostname and loopback, render a second version, and apply it to a second node withnv config verify filename,nv config replace,nv config apply --confirm 5.[4][9] Expected: the second node ends up with the same RoCE and VLAN state;nv show qos roceon both matches. Rollback: each node’s ownbaseline.configthroughnv config replace. -
Snippet. Apply an FRR snippet through
nv config patch snippet.yaml, apply, and prove the raw text landed withcat /etc/frr/frr.conf.[5] Then hand-edit that file, runnv config applyagain, and re-read it: the hand edit is gone and the snippet is not. That contrast is the whole lesson. Rollback:nv unset system config snippet frr.conf(set or unset only) thennv config apply.[5] -
Ansible. Install the collection with
ansible-galaxy collection install nvidia.nvueand confirm withansible-galaxy collection list.[7] Write a play that usesnvidia.nvue.commandto enable RoCE and create a VLAN on both nodes, and a second task usingnvidia.nvue.apifor a path with no object module.[6] Build the inventory from the collection’s own documentation after installing it — the deployment pages fetched for this lesson do not specify the connection variables. Expected: a green run and a state read-back that matches. If the collection will not install: record the ansible-core and Python versions you have against the stated requirements (ansible-core 2.11+, Python 3.6+).[7] -
Deliverable: the runbook header stating who supports which layer — Cumulus API and config verbs versus a community-supported collection.[1][6]
Retrieval check
10 questions from memory. Answer before looking anything up; misses become flashcards.
Explain it to a Dell SE
Explain to a Dell automation engineer, in five sentences, how you would push the same RoCE configuration to 32 leaves without logging into any of them, and what protects you when the 17th one is different.
Sources
Facts in this lesson were checked against NVUE Automation with Ansible and Deploying Ansible Modules pages fetched 2026-09-07 (new sources for this lesson); NVUE API, Object Model, CLI, Snippets and Config Commands reference — research fetched 2026-09-07. Dates are when each page was fetched.
- NVUE API | Cumulus Linux 5.18 · fetched 2026-09-07
- NVUE Object Model | Cumulus Linux 5.18 · fetched 2026-09-07
- NVUE CLI | Cumulus Linux 5.18 · fetched 2026-09-07
- NVUE Reference - Config Commands · fetched 2026-09-07
- NVUE Snippets | Cumulus Linux 5.18 · fetched 2026-09-07
- NVUE Automation with Ansible | Data Center Network Automation Ansible Deployment Guide · fetched 2026-09-07
- Deploying Ansible Modules | Data Center Network Automation Ansible Deployment Guide · fetched 2026-09-07
- What's New | Cumulus Linux 5.18 · fetched 2026-09-07
- RDMA over Converged Ethernet - RoCE | Cumulus Linux 5.18 · fetched 2026-09-07
The same idea elsewhere
Other lessons that cover this ground, sometimes from another course's angle.
- The NVUE object model, revisions and snippetsElsewhere in this course · Same ground: snippets, NVUE snippet and api
- The switch half: Cumulus NVUE and Dell Enterprise SONiCRoCE course · Same ground: ansible, NVUE and correct
- Version matrices, upgrades and heterogeneous clustersK8sNet course · Same ground: upgrade, fae and versions