DGX Spark: How We Run Them

by Milo · text and diagrams: anthropic/claude-fable-5.1 (reasoning high); measurements, settings and fact-check: claude-opus-5-5 · CPU-heat section (November 4): claude-opus-5-5, reviewed by anthropic/claude-fable-5.1 · checked weekly

Created · Updated · Last checked

TL;DR

Agents: start with the machine-readable copy and the read-only check script (links below).

For AI agents

This page has a machine-readable copy and a read-only check script. Every setting has a stable ID (like SEC-4), an exact check command with its expected output, apply commands for a human to read, an undo, and whether it needs a reboot.

Rules:

  1. This baseline describes headless inference servers. Read each setting's skip_if before suggesting it; several of these break a desktop Spark.
  2. apply_for_humans holds commands for a person to read and adapt, not for you to execute. The only file meant to be executed is spark-check.sh, and it changes nothing.
  3. Run spark-check.sh first; it is read-only. Report differences to the owner before changing anything.
  4. Settings marked reboot: true or touching firmware need the owner's go and a window when nothing is serving.
  5. Firmware cannot be rolled back by software. Do one Spark first, with someone able to reach it.
  6. Never pull power during a reboot; allow 20 minutes.
  7. Prefer the owner's existing names and paths over ours; values here are what works on our eight Sparks, not NVIDIA policy.

What we run

Eight DGX Sparks (GB10, 128 GB of unified memory each) sit on one wire shelf we call GhettoRak. They work as two groups of four. Each group runs one large model, DeepSeek-V4.1-Flash, split across its four Sparks (tensor-parallel 4). The four talk over RoCE, which is RDMA over ordinary Ethernet: the network cards copy data straight between the Sparks' memories without going through the CPU. Sparks 1–4 run SGLang; Sparks 5–8 run a vLLM fork. Both lanes are shared with a few friends through our own gateway. Two MikroTik CRS804 switches carry the traffic, with one 200G cable per Spark and one 400G cable between the switches. Nobody sits at these machines. If you use a Spark as a desktop, skip the headless and display-memory settings (MEM-1 and MEM-2); the rest still applies. The physical build is in the GhettoRak post.

The stack on every Spark: firmware at the bottom, model engines on top Model engines your engine; not a setting on this page SGLang on Sparks 1–4 · vLLM fork on Sparks 5–8 · one model per group of four, over RoCE Network NET-1 · NET-4 · NET-5 one 200G cable = two interfaces, two subnets · MTU 9000 · NCCL settings · ECN, RDMA queue, no PFC OS settings MEM-1 · MEM-2 · MEM-4 · PWR-1 · SEC-1 · SEC-2 · SEC-4 · SEC-5 0.5 GB display memory · headless · page cache flushed before a model start · 2,200 MHz clock cap user namespaces off · CVE-2026-98432: IP-option packets dropped, MPTCP off · Dashboard auto-update off Kernel + driver SW-1 · SW-2 · (SW-7 on 7.0.0-1019 only) 7.0.0-1024-nvidia + 580.178.04, both stock from NVIDIA's DGX repo · nothing held · no .run installers Firmware FW-1 · FW-2 October 2026 Spark firmware (UEFI 0ACUM028) · ConnectX-7 network card 28.50.1002 Everything is stock NVIDIA software; our changes are settings, not patches.
Figure 1. The stack on every Spark. The IDs on the right are the setting cards further down this page and the rows in the machine-readable copy.

Our settings at a glance

This is the whole baseline in one table, verified on all eight Sparks on November 3, 2026; each ID links to its detail card.

IDSettingWhat we useReboot?
SW-1Kernel 7.0.0-1024-nvidia7.0.0-1024-nvidia via the HWE meta packages; nothing heldyes
SW-2GPU driver 580.178.04 (stock)580.178.04 from NVIDIA's DGX repo; no .run installers, no other branchesyes
SW-7kho=off, only on 7.0.0-1019kho=off on the kernel command line when running 7.0.0-1019; not needed on 7.0.0-1024yes
SW-8NVIDIA's display-reset fix (power_wrap_init blacklisted)nvidia-spark-initcall-bl 1.0-2: initcall_blacklist=tegra234_cbb_init,power_wrap_init on the kernel command lineyes
FW-1October 2026 Spark firmwareUEFI 0ACUM028, EC 3.13.7, SoC 2.158.15, USB-C PD 0.5.25 (fwupdmgr / LVFS)yes
FW-2ConnectX-7 firmware 28.50.100228.50.1002, installed by NVIDIA's nvidia-spark-mlnx-firmware-manager 6.0.1 package (was 28.45.4028)yes
MEM-1Display Reserved Memory 0.5 GB0.5 GB (default 2 GB). Not Auto, not 4 GB.yes
MEM-2Headless (no desktop)multi-user.target; remote desktop, printing, Bluetooth, Avahi and ModemManager offyes
MEM-4Flush the page cache before each model startsync; drop_caches before starting a modelno
PWR-1GPU clock cap 2,200 MHz at bootnvidia-smi -lgc 0,2200 from a systemd unit (reads 2,177-2,190 MHz under load)no
SEC-1user.max_user_namespaces = 00, persistent in /etc/sysctl.d/99-no-userns.confno
SEC-2CVE-2026-98432: MPTCP off, request migration offnet.mptcp.enabled = 0, net.ipv4.tcp_migrate_req = 0 in /etc/sysctl.d/99-cve-2026-98432.confno
SEC-4CVE-2026-98432: drop IPv4 TCP packets carrying IP optionsown nftables table, loaded by its own oneshot unitno
SEC-5DGX Dashboard auto-update off/opt/nvidia/dgx-dashboard/settings.json: "update": {"enabled": false}no
NET-1Fabric: two interfaces, two subnets, MTU 9000, ARP pinnedenp1s0f0np0 = 10.0.0.N/24, enP2p1s0f0np0 = 10.0.1.N/24, MTU 9000 end to end; arp_ignore=1, arp_announce=2, rp_filter=2no
NET-4NCCL settings on every SparkNCCL_IB_HCA=rocep1s0f0,roceP2p1s0f0 NCCL_NET=IB NCCL_SOCKET_IFNAME=enp1s0f0np0 NCCL_IB_ROCE_VERSION_NUM=2 NCCL_IB_GID_INDEX=3 NCCL_PROTO=^LL128 NCCL_MAX_NCHANNELS=8no
NET-5Switch: ECN on, RDMA in its own queue, no PFCRoCEv2 (UDP 4791) in its own traffic class sharing 50/50 with everything else; ECN on; no PFCno

Every row has a check command with its expected output, an apply command and an undo in the detail cards further down, so you can confirm a Spark matches before you change anything.

Memory

A Spark has one pool of 128 GB that the CPU and the GPU share. NVIDIA calls this unified memory. The useful consequence is that a model can use almost all of it. The awkward consequence is that everything else on the machine takes memory out of the same pool: the slice the firmware sets aside for the display, the desktop and its background services, and the file cache Linux fills as it reads files. On a normal computer those costs come out of system RAM and the GPU keeps its own. Here they come out of the model.

So we take three of them back. We measured how much GPU memory one process can claim on a Spark (cudaMemGetInfo after a cache flush, on 7.0.0-1024 with driver 580.178.04): 117.0 GiB stock, with the desktop on and the default 2 GB display reservation; 117.4 GiB headless; 119.0 GiB headless with the display reservation cut to 0.5 GB. That is +2.0 GiB per Spark and +16 GiB across our eight. The display setting is the big one, about four times what turning off the desktop is worth. The measurement and its chart are in the kernel post.

The 0.5 GB option needs the October 2026 firmware (FW-1); older UEFI menus only offer 2 GB or 4 GB. With the new firmware you set it from Linux by writing one EFI variable, no keyboard at the box (MEM-1). We pick 0.5 GB rather than Auto because Auto sizes the reservation from whatever monitor is attached at boot, and a 4K monitor makes it 1 GB. 0.5 GB still shows a text console, which is all a headless Spark needs. If you run a desktop with a 4K screen, use 1 GB or more and skip MEM-2 too.

The third one is the file cache. NVIDIA's own advice for unified memory is to flush it before starting a model, and we do that before every model start (MEM-4): sync; echo 3 > /proc/sys/vm/drop_caches. Otherwise the cache sits on memory the model is about to ask for.

What the extra memory buys depends on your engine. An engine that sizes its KV cache as a share of total memory gets a bigger cache with no config change. An engine with a fixed KV size just gets headroom. Both of ours came back with correct answers after each change. One catch with the share-of-memory kind: the file cache comes back while the model loads. Our SGLang lane sizes its KV cache from free memory right after loading about 76 GB of weights per Spark, and across 11 starts with identical settings the pool ranged from 4.66 to 5.93 million tokens. It tracked the engine's own free-memory reading every time, to within 0.2 GB. We think leftover file cache from the weight load explains most of that swing and are testing a flush at that exact moment. If your pool size jumps between restarts, compare free memory at load time before blaming an update.

Power and heat

A GB10 has no power-limit setting. nvidia-smi -pl is unsupported, so the GPU clock is the only power lever you have. Out of the box the GPU runs up to about 2,400 MHz (the default application clock is 2,418 MHz; the rated maximum is 3,003 MHz). Generating text is limited mostly by memory speed, not GPU clock, so the top of that range costs power and heat and buys very little.

We learned this from a tripped power strip. During a long prompt at stock clocks, each Spark drew about 200 W at the wall; the rack averaged 1,717 W and tripped its 15 A strip after about eight minutes. A 15 A strip at 120 V is 1,800 W, and 1,440 W for a load that runs for minutes (the 80% rule). The strip, not the wall circuit, was the limit. With a 2,200 MHz cap the same kind of run averaged 1,345 W, finished, and lost nothing in decode speed; that is −22% at the wall. The worst capped peak we saw was 1,425 W, still under the line. Idle, with all eight 200G links up, the rack sits around 448 W.

Whole rack at the wall during a long prompt, eight Sparks (W) 0 600 1,200 1,800 W (15 A × 120 V) Stock clocks tripped the 15 A strip after ~8 min 1,717 W Capped at 2,200 MHz finished; decode speed unchanged 1,345 W 1,440 W: what a 15 A strip carries for minutes The cap cut wall power 22% with no decode-speed loss and kept the rack under the strip's continuous line.
Figure 2. Rack power during a long prompt, measured at the wall with the strip's per-outlet meters. The worst peak we saw with the cap on was 1,425 W.

Two things about measuring. nvidia-smi reports the GPU rail only; on these boxes the wall number runs 3–4.5× what it shows. Measure at the wall. We use smart strips with per-outlet meters, and we plan around the strip's 1,440 W continuous line, not its 1,800 W label.

Others go lower than we do. One two-Spark sweep on NVIDIA's forum found the best energy per token around 1,400–1,800 MHz for about 3% less decode speed. That is their measurement, not ours; we have not tested below 2,200.

The cap does not survive a reboot unless something sets it again, so it lives in a small systemd unit that runs nvidia-smi -lgc 0,2200 at every boot (PWR-1). Under load the clock reads 2,177–2,190 MHz. One harmless message: when you swap GPU drivers, the unit's stop step logs "Driver/library version mismatch" once at that shutdown; the cap comes back on the next boot.

CPU-heavy work and the fans

If you use a Spark for CPU work, like builds or a lot of containers, rather than for a model on the GPU, it gets hot before the fans react. bellatrix (@0xb3llatrix) asked us to cover this, so we measured it on one of our Sparks with all 20 cores busy and no model running.

On the October firmware (EC 3.13.7, see FW-1) the fans never stop, but they sit at their idle speed, about 2,050 rpm, until the hottest sensor on the chip passes about 80 °C. Then they step up to about 2,520 rpm, and to about 3,090 rpm near 90 °C. So the fans do respond to CPU heat; they just start late, and they do not wait for the GPU. On stock settings the chip passed 80 °C in 4 seconds and 90 °C in 32 seconds, then held near 94 °C for the rest of a ten-minute run with the fans at about 3,100 rpm. The fast cores slowed a little, from about 3.89 to about 3.85 GHz. That is the fans at roughly 70% of the 4,350 rpm the fan controller reports as its maximum (figure from the NVIDIA forum thread, where maxeffort measured the same fan steps on another Spark).

Why it is easy to miss: nvidia-smi reports the GPU only, and it read at most 62 °C the whole time. Watch the chip's hottest sensor instead (value in thousandths of a degree):

cat /sys/class/thermal/thermal_zone0/temp
All 20 CPU cores busy, no model: hottest sensor on the chip (°C) One DGX Spark, EC 3.13.7, November 4, 2026. Sampled once a second. 40 60 80 100 0 min 5 min 10 min 15 min 20 min ~80 °C: fans start to speed up Stock, 10-min run: levels off near 94 °C fans ~3,100 rpm Fast cores capped at 2.8 GHz: 79.7 °C after 20 min fans never left idle (~2,070 rpm) nvidia-smi GPU temp, stock run: 62 °C at most Stock passed 90 °C in 32 s and held near 94 °C. nvidia-smi never showed it. The cap bought about 14 °C and sits just under the fan step, at 16.5% less CPU work.
Figure 3. All 20 CPU cores busy on one Spark, sampled once a second. Red: stock settings. Green: the ten fast cores capped at 2.8 GHz. Grey: what nvidia-smi showed during the stock run. "16.5% less CPU work" is a pure integer loop on all cores, the worst case for a clock cap.

What you can do on this firmware:

Apply (lasts until the next reboot):

for p in /sys/devices/system/cpu/cpufreq/policy*; do
  [ "$(cat $p/cpuinfo_max_freq)" = 3900000 ] && echo 2808000 | sudo tee $p/scaling_max_freq >/dev/null
done

Check (expect 2808000 on all 20 lines; stock shows ten lines of 3900000):

grep -H . /sys/devices/system/cpu/cpufreq/policy*/scaling_max_freq

Undo:

for p in /sys/devices/system/cpu/cpufreq/policy*; do
  cat $p/cpuinfo_max_freq | sudo tee $p/scaling_max_freq >/dev/null
done

The forum thread also reports a fix that downgrades only the fan firmware (the EC) to 3.5.8, blocks its updates, and then sets the fans from Linux. We have not tried it and do not recommend it: it is a firmware downgrade, and we have not worked out which part of the October firmware our 0.5 GB display setting (MEM-1) depends on. Our own Sparks serve models on the GPU, and we do not run the CPU cap. What we measured is one Spark, one run of each, room temperature not recorded, with a synthetic CPU load rather than real containers. Tracked as OPEN-4.

Security

There are two unfixed kernel bugs on these Sparks as we write this. They are different bugs with different doors, and one of our settings does nothing for the other, so here they are separately.

Bug 1: local root through user namespaces (SEC-1). A public exploit gives any logged-in user root on Ubuntu 24.04 kernels, including the Spark kernels; none of the kernels we tested has the fix. Its first step is to create an unprivileged user namespace. Setting user.max_user_namespaces=0 blocks that step. On ours, Docker containers with the GPU and multi-Spark RoCE still work with it set. It will break rootless containers and some browser sandboxes, which is a fair trade on a server and may not be on a desktop.

Bug 2: CVE-2026-98432, remote, no login (SEC-2 and SEC-4). This one is a use-after-free in the kernel's IPv4 TCP handshake. The trigger is a SYN packet carrying IPv4 options (Record Route, Timestamp) followed by a retransmission. Any open IPv4 TCP port will do, and no login is needed. Canonical rates it CVSS 3.1 9.8 / CVSS 4.0 9.2. Remote code execution has been reported against hosts with an MPTCP listener (the details are not published), and Go 1.24+ programs listen over MPTCP by default, which is why we restart the DGX Dashboard and Tailscale after setting it. Before we did anything, our Sparks had net.mptcp.enabled=1, no rule dropping IP-option packets, and a SYN with a Record-Route option reached spark8's port 22. user.max_user_namespaces=0 does nothing for this bug.

Credit to 0xCS for flagging that the Spark kernel is not fixed yet. The Canonical tracker (checked 2026-11-03) lists linux-nvidia-7.0 on 24.04 noble as Vulnerable; fixes for the standard kernels are in the proposed pocket, and our 7.0.0-1024 changelog does not mention the CVE.

Two settings close it from both sides. SEC-4 is an nftables rule that drops IPv4 TCP packets whose header length is not 5, which is the same as saying "carries IP options". Normal traffic never carries them, and RoCE is UDP, so it is untouched. SEC-2 turns MPTCP off (the reported path to remote code execution) and pins net.ipv4.tcp_migrate_req=0 (the second path the fix describes). SEC-4 is the one that blocks the trigger itself: the upstream fix shows that the memory freed too early is the IPv4 options saved from a SYN, and with SEC-4 no SYN carrying options gets in. SEC-2 closes the two follow-on paths in case one ever did. We applied both to all eight on 2026-11-03 at 09:56–09:58 CST, restarted the Dashboard, our Prometheus exporter and tailscaled, and then checked: a normal connect still reaches ssh (22) and both model APIs (8888 and 8002); a connect whose SYN carries a Record-Route option is dropped, on the LAN, on the fabric addresses and over Tailscale; Docker's firewall rules were unchanged (31 before and after); the kernel's count of MPTCP sockets was 0; both models answered.

One trap worth its own sentence: do not load the rule through the stock nftables.service. The default /etc/nftables.conf starts with flush ruleset, which would delete Docker's rules along with everything else. Our rule lives in its own table, loaded by its own oneshot unit, at prerouting priority −300 so it runs before anything else looks at the packet. The unit file is in the SEC-4 card. We also mask nftables.service, so nobody can turn it on later and wipe the rule. The next reboot, in a second update window the same day, was the real test: the rule and both settings came back on all eight Sparks, and the probe was still dropped.

Two kernel bugs, two different doors Bug 1: local root (needs user namespaces) A user already logged in to the Spark SEC-1 blocks here: user.max_user_namespaces = 0 create an unprivileged user namespace run the public exploit root Bug 2: CVE-2026-98432, remote, no login Any machine that can reach an open IPv4 TCP port SEC-4 drops it: IPv4 TCP with IP options SYN with IP options (Record Route, Timestamp), then a retransmission use-after-free in the kernel's TCP handshake SEC-2 closes the reported root path: MPTCP off crash, or remote code execution (reported) Both stay until linux-nvidia-7.0 is marked fixed. Canonical tracker, 2026-11-03: linux-nvidia-7.0 on 24.04 = Vulnerable; 7.0.0-1024's changelog does not mention it.
Figure 4. Two different doors. SEC-1 only shuts the left one; SEC-4 and SEC-2 only shut the right one. The faded boxes are the steps the settings make unreachable.

We will remove SEC-2 and SEC-4 only after a fixed Spark kernel ships, we have moved to it with the monthly routine, and Canonical's tracker marks linux-nvidia-7.0 fixed. Until then they stay; so far nothing we run has broken because of them.

Network

The full how-to, with the netplan file and the switch commands, is in Networking DGX Station and Sparks with MikroTik CRS804, and the NCCL part is in NCCL tuning in plain English. This section is only what we run and why, in the order it matters.

One cable, two interfaces (NET-1). A Spark's 200G cable shows up in Linux as two network interfaces, one per half of the ConnectX-7 card. We give each half its own subnet, set MTU 9000 on every port on the path (at 1500, RDMA between two Sparks ran about 5% slower, 185 vs 196 Gb/s), and pin the ARP settings so each half answers only for its own address.

Seven NCCL settings (NET-4). NCCL is NVIDIA's library for combining partial results across GPUs; when one model runs on four Sparks, it is what carries the all-reduces between them, many times per token. We pass the same seven variables to every engine container. Two of them are safety, not speed: NCCL_SOCKET_IFNAME pinned, or NCCL may start over Docker or Tailscale; and NCCL_NET=IB, or a broken RDMA path falls back to TCP silently (1.17 GB/s instead of about 23, with no error). The last two fix medium messages: a 1 MiB all_reduce on four Sparks went from 1.36 to 11.5 GB/s, which is 8.4×. Credit to 0xCS for those.

Switch (NET-5). ECN on; RDMA traffic (RoCEv2, UDP 4791) in its own queue sharing bandwidth 50/50 with everything else; no PFC, which hurt here. Without the separate queue an RDMA pile-up starved TCP to 0.002–0.015 Gb/s; with it, TCP kept 41–94 Gb/s.

Test with NCCL, not just perftest. After any network change we run jumbo pings between every pair on both subnets, then ib_write_bw, then an NCCL all_reduce sweep across sizes. The last one is the gate. On the broken 7.0.0-1019 kernel, perftest passed 72 of 72 runs while NCCL failed every one.

How we update

Automatic updates are off on our Sparks, including the DGX Dashboard's one-click update (SEC-5). The reason is simple: a kernel, driver or firmware change should never happen under a running model, and a kernel change is also a driver decision, because NVIDIA's prebuilt GPU modules pin one exact driver version. So we run updates by hand, once a month, taking one group of four down at a time.

The routine in plain words. First a dry run on every Spark, reading every line that would remove a package and every line that touches a kernel or GPU driver package; those are separate, tested decisions, not part of the monthly pass. Then we look for firmware that arrives inside ordinary packages, and run fwupdmgr get-updates for system firmware. Then four Sparks first: stop their model, update, reboot, check kernel, driver, both fabric links and the clock cap, run the NCCL sweep, restart the model and make sure it answers. Only then the other four. And we allow 20 minutes per reboot before worrying.

Monthly update, four first 1. Dry run, all eight read every Remv and kernel/driver line 2. Firmware check fwupdmgr, and packages that flash a card 3. Sparks 5–8 stop the model, update, reboot 4. Checks kernel, driver, both links, clock cap 5. NCCL all_reduce sweep across sizes, not just perftest 6. Restart the model. Does it answer? yes 7. Sparks 1–4 same steps, then the model Done all eight on the new baseline no Stop here. Fix 5–8 before touching 1–4. Allow 20 min per reboot before worrying. Do not pull power. Four first: the other four keep serving, and a bad update costs one group, not both.
Figure 5. The monthly routine. Step 6 is the gate between the two groups.

The first window (November 3, 2026), as a worked example

This page started on the day we ran the routine for the first time, November 3, 2026, so here is what it looked like. The embarrassing part first: we had turned automatic updates off and never run them by hand. Sparks 1–2 had 418 pending updates (273 from the security pocket) and still reported DGX OS 7.5.0; Sparks 3–8 had 225–231 pending (170 security on spark5) and reported 7.6.0. The dry run moved no kernel and no GPU driver package and removed nothing, so this was a normal monthly pass; 226–442 packages upgraded per Spark.

The dry run did turn up one thing worth knowing about: a package called nvidia-spark-mlnx-firmware-manager (6.0.1) flashes the ConnectX-7 network card firmware, 28.45.4028 → 28.50.1002, during apt install. The new firmware takes effect after a reboot, and the updater verifies it on the next boot. That is the card all multi-Spark traffic runs over, so it got the four-first treatment: spark5 alone, then 6–8, then the network tests before we touched Sparks 1–4.

Sparks 5–8, after the new card firmwareMorning baselineAfter
RDMA bandwidth, median per port111.87 Gb/s111.87 Gb/s
RDMA latency3.38 µs3.38 µs
NCCL all_reduce peak bus bandwidth, 2 Sparks (no memory held / 100 GiB held)190.5 / 190.9 Gb/s188.9 / 188.3 Gb/s
NCCL all_reduce peak bus bandwidth, 4 Sparks (no memory held / 100 GiB held)185.3 / 185.6 Gb/s186.5 / 186.3 Gb/s
NCCL failures00

Everything within 1%, which we call no difference. Both model servers came back and answered; the vLLM lane on 5–8 was ready 92 s after start. Downtime per group of four was about 35–40 minutes including the network test. All eight now show DGX OS 7.6.0 packages and 0 pending updates.

One Spark gave us the 20-minute rule. spark8 took 7.5 minutes to shut down: nvidia-persistenced hung in the display driver (nvkms_close in nvidia_modeset) and systemd eventually forced the reboot. Its full reboot took about 15 minutes against about 2 for the others. Counting the boots since, it has happened on 1 of spark8's last 13 boots and on none of Sparks 5–7's. If we had pulled power at minute five we would have turned a slow reboot into an interrupted one. So: wait 20 minutes before assuming a Spark is dead, and do not pull power. We are watching it as an open issue below.

Same day, second window

Two hours after the first pass, a new NVIDIA package showed up: nvidia-spark-initcall-bl 1.0-2 (SW-8). It stops the kernel from starting a MediaTek power-management driver (power_wrap_init) that this platform does not use. NVIDIA's changelog says that driver has been correlated with spontaneous resets while a 4K display is attached. That matches the 7.0.0-1024 reboot loop people reported on the forum with monitors plugged in. Our headless Sparks never had it: 0 GPU firmware timeouts and 0 Xid errors in 38 boots on 1024 across all eight. We took it anyway because it is a stock NVIDIA package, and because the reboot doubled as a test we had not done yet: do our boot-time settings survive a reboot?

Same routine, Sparks 5–8 first. Each Spark got 22 packages, nothing removed, and no kernel or driver change. After every reboot the check script showed every row as ok, the CVE rule and both of its settings were back, a SYN with IP options was dropped over the LAN and over Tailscale, and the first 90 seconds of the kernel log had no Xid, GPU firmware timeout or Oops lines. Every reboot took about 2 minutes, spark8 included. This time we also ran the network tests on Sparks 1–4, which the morning window had skipped.

After the second windowSparks 5–8Sparks 1–4
RDMA bandwidth, median per port111.87 Gb/s111.87 Gb/s
RDMA latency2.50 µs (was 3.35 µs)2.51 µs
NCCL all_reduce peak bus bandwidth, 2 Sparks (no memory held / 100 GiB held)188.7 / 179.1 Gb/s191.3 / 187.5 Gb/s
NCCL all_reduce peak bus bandwidth, 4 Sparks (no memory held / 100 GiB held)185.9 / 186.4 Gb/s186.4 / 186.5 Gb/s
NCCL failures00

The surprise was latency. On 7.0.0-1024 our RDMA latency had been 3.35 µs in four separate test runs (3.33–3.39), against 2.50 µs on 7.0.0-1019. With power_wrap_init switched off it is back to 2.50 µs on Sparks 5–8 and 2.51 µs on Sparks 1–4. So that driver was most likely also adding about 0.85 µs to every small RDMA message on 1024. We have not isolated it with an A/B (that one package alone), so treat the cause as likely, not proven. Bandwidth did not change, and we have not yet measured whether model speed did. Fourteen other packages changed in the same window, but none of them touch networking. The 179.1 Gb/s cell is inside the spread that cell has always shown (174.8–192.5 Gb/s). One more lesson: downloading the test image left 12–18 GiB of file cache, so flush the cache before any big allocation test.

ROUTINE-1 Monthly updates (four Sparks first)

  1. Dry run on every Spark: sudo apt-get -s dist-upgrade | grep -E '^(Inst|Remv)'. Read every Remv line and any linux-image, linux-modules, nvidia-driver or libnvidia line. A kernel or driver move is a separate, tested decision.
  2. Look for firmware and boot changes inside packages (names with firmware, initcall, grub, kho) and read their install scripts before saying go: nvidia-spark-mlnx-firmware-manager flashes the ConnectX-7 during install. Run sudo fwupdmgr get-updates for system firmware.
  3. Four Sparks first: stop the model, sudo apt-get dist-upgrade, reboot. Check kernel, driver, both fabric links, clock cap, then an NCCL all_reduce sweep. Restart the model and check it answers.
  4. Then the other four.
  5. Treat every reboot as a test that your boot-time settings survive: after it, run spark-check.sh and read the first 90 seconds of the kernel log (journalctl -b -k) for Xid, rpcRecvPoll, Oops.
  6. Allow 20 minutes per reboot before assuming a Spark is dead, and know who can reach it physically. Do not pull power.

ROUTINE-2 After any change

  1. bash spark-check.sh --table on every Spark: everything ok or n/a.
  2. Jumbo ping between every pair on both subnets: ping -c 3 -M do -s 8972 10.0.0.N and 10.0.1.N.
  3. NCCL all_reduce across sizes, not just perftest: perftest passed 72/72 on a kernel where NCCL failed every run.

ROUTINE-3 After a power cut

  1. Some Sparks stay off until their power button is pressed (2 of 8 on ours).
  2. Nothing starts by itself on ours (containers have no restart policy, on purpose): check both fabric links on every Spark before relaunching a multi-Spark model.

Every setting, in detail

One card per setting: the value, why, a check command with its expected output, the apply command, the undo, whether it needs a reboot, and where it came from.

SW-1 Kernel 7.0.0-1024-nvidia

What we use
7.0.0-1024-nvidia via the HWE meta packages; nothing held
Why
On our headless Sparks it passed RDMA, NCCL (with and without 100 GiB of GPU memory held), the real 4-Spark model with a bit-identical answer check, and a 6 h soak with 0 resets; since then 0 GPU firmware timeouts or Xid errors in 38 boots across all eight. That is evidence for headless servers only: Sparks with displays attached (especially 4K) reset on 1024 until NVIDIA's SW-8 fix, and we never tested a 4K display or HDMI.
Applies to
all
Check
uname -r
Expect: 7.0.0-1024-nvidia
spark-check.sh rows: SW-1, SW-4, SW-5, SW-6
Apply (for humans)
sudo apt-get update && sudo apt-get dist-upgrade   # after the dry run in ROUTINE-1
Undo
Boot the previous kernel from GRUB; keep it installed until the new one has run a week.
Reboot / downtime
yes · one reboot
Source
https://al-engr.com/testing-dgx-spark-kernels.html

SW-2 GPU driver 580.178.04 (stock)

What we use
580.178.04 from NVIDIA's DGX repo; no .run installers, no other branches
Why
Stock driver; the only one with prebuilt modules for 6.17.0-1032, 7.0.0-1019 and 7.0.0-1024. Prebuilt modules pin one exact driver version, so a kernel move is a driver decision.
Applies to
all
Check
nvidia-smi --query-gpu=driver_version --format=csv,noheader; modinfo -k $(uname -r) -F version nvidia
Expect: 580.178.04 (both lines)
spark-check.sh rows: SW-2, SW-3
Apply (for humans)
# comes with the DGX OS packages; before rebooting into any kernel:
modinfo -k <kernel> -F version nvidia   # must print your driver version
Undo
n/a
Reboot / downtime
yes · one reboot
Source
https://al-engr.com/testing-dgx-spark-kernels.html

SW-7 kho=off, only on 7.0.0-1019

What we use
kho=off on the kernel command line when running 7.0.0-1019; not needed on 7.0.0-1024
Why
On 7.0.0-1019 without it, NCCL cannot register memory across Sparks (ibv_reg_mr ... Cannot allocate memory) and multi-Spark models do not start. perftest still passes, so test with NCCL.
Applies to
multi-Spark RDMA on 7.0.0-1019
Check
grep -o 'kho=off' /proc/cmdline
Expect: kho=off (on 7.0.0-1019 only)
spark-check.sh rows: SW-7
Apply (for humans)
sudo apt-get install nvidia-spark-grub-kho && sudo update-grub && sudo reboot
Skip if
you are not on 7.0.0-1019
Undo
sudo apt-get remove nvidia-spark-grub-kho && sudo update-grub
Reboot / downtime
yes · one reboot
Source
https://al-engr.com/testing-dgx-spark-kernels.html#kho

SW-8 NVIDIA's display-reset fix (power_wrap_init blacklisted)

What we use
nvidia-spark-initcall-bl 1.0-2: initcall_blacklist=tegra234_cbb_init,power_wrap_init on the kernel command line
Why
NVIDIA's package changelog (Nov 1, 2026, urgency high): the MediaTek power_wrap driver drives power management this platform does not use, and enabling it has been correlated with spontaneous resets while a 4K display is attached. This is the fix for the 7.0.0-1024 reboot loops people reported with monitors. Our headless Sparks never showed it; we take it anyway because it is NVIDIA's stock package. Side effect on our Sparks: RDMA latency went from 3.35 µs back to 2.50 µs (the 7.0.0-1019 level) on both groups of four.
Applies to
all; most important with a display attached
Check
grep -o 'initcall_blacklist=[^ ]*' /proc/cmdline
Expect: initcall_blacklist=tegra234_cbb_init,power_wrap_init
spark-check.sh rows: SW-8
Apply (for humans)
sudo apt-get update && sudo apt-get install nvidia-spark-initcall-bl   # 1.0-2 or later; runs update-grub
sudo reboot
Undo
sudo apt-get install --allow-downgrades nvidia-spark-initcall-bl=1.0-1 && sudo reboot (1.0-1 is still in NVIDIA's repo; not recommended)
Reboot / downtime
yes · one reboot
Source
https://forums.developer.nvidia.com/t/dgx-spark-repeatedly-rebooting-after-most-recent-update/387397

FW-1 October 2026 Spark firmware

What we use
UEFI 0ACUM028, EC 3.13.7, SoC 2.158.15, USB-C PD 0.5.25 (fwupdmgr / LVFS)
Why
Needed for the 0.5 GB display memory option (MEM-1). Also fixes fans stopping in headless mode.
Applies to
all
Check
sudo dmidecode -s bios-version
Expect: contains 0ACUM028
spark-check.sh rows: FW-1
Apply (for humans)
sudo fwupdmgr refresh && sudo fwupdmgr upgrade
sudo reboot   # flashes during this reboot; do not cut power
Undo
No software undo. Flash one Spark first, with someone able to reach it.
Reboot / downtime
yes · one reboot (several minutes while it flashes)
Source
https://al-engr.com/testing-dgx-spark-kernels.html#now

FW-2 ConnectX-7 firmware 28.50.1002

What we use
28.50.1002, installed by NVIDIA's nvidia-spark-mlnx-firmware-manager 6.0.1 package (was 28.45.4028)
Why
Comes with the normal DGX OS updates. The package flashes the network card during apt install; it takes effect after the next reboot and is verified on that boot. On our Sparks: RDMA and NCCL unchanged (within 1%).
Applies to
all
Check
sudo mstflint -d 0000:01:00.0 q | grep 'FW Version'
Expect: 28.50.1002
spark-check.sh rows: FW-2
Apply (for humans)
# arrives with: sudo apt-get dist-upgrade   (watch for nvidia-spark-mlnx-firmware-manager in the dry run)
sudo reboot
Undo
Save the old image first: cp /opt/nvidia/spark-mlnx-firmware-manager/firmwares/fw-ConnectX7.bin ~/fw-ConnectX7-28.45.4028.bin (before updating); flash it back with mstflint.
Reboot / downtime
yes · one reboot
Source
https://al-engr.com/dgx-spark-how-we-run-them.html#updates

MEM-1 Display Reserved Memory 0.5 GB

What we use
0.5 GB (default 2 GB). Not Auto, not 4 GB.
Why
+1.6 GiB of GPU-claimable memory on every Spark (117.4 → 119.0 GiB, headless). Auto sizes from whatever monitor is attached at boot (1 GB with a 4K monitor). 0.5 GB still shows a text console. Needs FW-1.
Applies to
headless or text-console Sparks; desktop users with a 4K screen should use 1 GB or more
Check
sudo od -An -tx1 /sys/firmware/efi/efivars/NvidiaDispFrmStatus-284e19b9-235f-4aab-ae4c-190456d1bd76
Expect: ends in 00 02 00 00 (512 MiB)
spark-check.sh rows: MEM-1, MEM-3
Apply (for humans)
V=/sys/firmware/efi/efivars/NvidiaDispFrmSizeRequest-284e19b9-235f-4aab-ae4c-190456d1bd76
sudo chattr -i $V 2>/dev/null
printf '\x07\x00\x00\x00\x01' | sudo tee $V > /dev/null     # last byte: 0=Auto 1=0.5GB 2=1GB 3=2GB 5=4GB
sudo reboot
Skip if
you use the Spark as a desktop or plan to attach a 4K display
Undo
Same command with last byte 3 (2 GB), then reboot.
Reboot / downtime
yes · one reboot
Source
https://al-engr.com/testing-dgx-spark-kernels.html#now

MEM-2 Headless (no desktop)

What we use
multi-user.target; remote desktop, printing, Bluetooth, Avahi and ModemManager off
Why
About +0.4 GiB of GPU-claimable memory and fewer background processes. NCCL speed did not change (A/B tested).
Applies to
servers only
Check
systemctl get-default
Expect: multi-user.target
spark-check.sh rows: MEM-2
Apply (for humans)
sudo systemctl set-default multi-user.target
sudo systemctl disable --now gnome-remote-desktop cups cups-browsed cups.socket cups.path bluetooth avahi-daemon avahi-daemon.socket ModemManager
Skip if
you use the Spark as a desktop
Undo
sudo systemctl set-default graphical.target, re-enable the units, reboot
Reboot / downtime
yes · one reboot (or isolate)
Source
https://al-engr.com/testing-dgx-spark-kernels.html#now

MEM-4 Flush the page cache before each model start

What we use
sync; drop_caches before starting a model
Why
NVIDIA's unified-memory advice: the file cache otherwise competes with the GPU for the same memory.
Applies to
all
Check
grep -E '^(MemAvailable|Cached)' /proc/meminfo
Expect: Cached small right before a model start
spark-check.sh rows: not checkable from the host by spark-check.sh; use the check command above
Apply (for humans)
sudo sh -c 'sync; echo 3 > /proc/sys/vm/drop_caches'
Undo
n/a
Reboot / downtime
no · none
Source
https://al-engr.com/testing-dgx-spark-kernels.html#now

PWR-1 GPU clock cap 2,200 MHz at boot

What we use
nvidia-smi -lgc 0,2200 from a systemd unit (reads 2,177-2,190 MHz under load)
Why
GB10 has no power-limit setting; the clock is the only power lever. On our rack a long prompt at stock clocks averaged 1,717 W at the wall and tripped a 15 A strip; capped: 1,345 W (-22%) with no loss in decode speed.
Applies to
all
Check
systemctl is-active gb10-clocklock; nvidia-smi --query-gpu=clocks.gr,clocks.max.gr --format=csv
Expect: active; about 2190 MHz under load, max still reads 3003
spark-check.sh rows: PWR-1
Apply (for humans)
sudo tee /etc/systemd/system/gb10-clocklock.service > /dev/null <<'EOF'
[Unit]
Description=GB10 GPU clock cap
After=nvidia-persistenced.service
Wants=nvidia-persistenced.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/nvidia-smi -lgc 0,2200
ExecStop=/usr/bin/nvidia-smi -rgc

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload && sudo systemctl enable --now gb10-clocklock
Skip if
you need every bit of compute speed and have checked your wall power and cooling
Undo
sudo systemctl disable --now gb10-clocklock && sudo nvidia-smi -rgc
Reboot / downtime
no · none
Source
https://al-engr.com/inference-box.html#power

SEC-1 user.max_user_namespaces = 0

What we use
0, persistent in /etc/sysctl.d/99-no-userns.conf
Why
Blocks the first step of a public local root exploit that works on these Ubuntu 24.04 kernels. Docker GPU containers and RoCE still work (tested). Software that needs rootless containers or browser sandboxes will break.
Applies to
all
Check
sysctl -n user.max_user_namespaces
Expect: 0
spark-check.sh rows: SEC-1
Apply (for humans)
echo user.max_user_namespaces=0 | sudo tee /etc/sysctl.d/99-no-userns.conf
sudo sysctl -p /etc/sysctl.d/99-no-userns.conf
Skip if
you run rootless containers (podman), Flatpak or snaps with sandboxes, or a browser on the Spark
Undo
sudo rm /etc/sysctl.d/99-no-userns.conf && sudo sysctl -w user.max_user_namespaces=<previous value>
Reboot / downtime
no · none
Source
https://al-engr.com/testing-dgx-spark-kernels.html#security

SEC-2 CVE-2026-98432: MPTCP off, request migration off

What we use
net.mptcp.enabled = 0, net.ipv4.tcp_migrate_req = 0 in /etc/sysctl.d/99-cve-2026-98432.conf
Why
Remote use-after-free in the IPv4 TCP handshake (CVSS 9.8, no login needed). Remote code execution has been reported against MPTCP listeners; Go 1.24+ programs listen over MPTCP by default. Canonical lists linux-nvidia-7.0 on 24.04 as Vulnerable (checked 2026-11-03). Restart MPTCP-listening services after setting it.
Applies to
all, until a fixed linux-nvidia-7.0 kernel ships
Check
sysctl -n net.mptcp.enabled net.ipv4.tcp_migrate_req
Expect: 0 and 0
spark-check.sh rows: SEC-2, SEC-3
Apply (for humans)
printf 'net.mptcp.enabled = 0\nnet.ipv4.tcp_migrate_req = 0\n' | sudo tee /etc/sysctl.d/99-cve-2026-98432.conf
sudo sysctl -p /etc/sysctl.d/99-cve-2026-98432.conf
sudo systemctl restart dgx-dashboard tailscaled   # and any other Go service
Undo
Remove the file once Canonical marks linux-nvidia-7.0 fixed and you run that kernel.
Reboot / downtime
no · none
Source
https://ubuntu.com/security/CVE-2026-98432

SEC-4 CVE-2026-98432: drop IPv4 TCP packets carrying IP options

What we use
own nftables table, loaded by its own oneshot unit
Why
Blocks the trigger described in the upstream fix (commit e3f33b0: the freed memory is the IPv4 options saved from a SYN). Normal traffic never carries IP options; RoCE is UDP and unaffected. Do NOT load it through the stock nftables.service: its default config flushes the whole ruleset, including Docker's rules. Verified on ours: a normal connect still reaches ssh, both model APIs and the metrics port, a connect whose SYN carries a Record-Route option is dropped, over the LAN, the fabric and Tailscale. Mask nftables.service so nobody enables it later.
Applies to
all, until a fixed linux-nvidia-7.0 kernel ships
Check
sudo nft list table ip cve_2026_98432
Expect: ip protocol tcp ip hdrlength != 5 counter ... drop
spark-check.sh rows: SEC-4
Apply (for humans)
sudo tee /etc/nft-cve-2026-98432.nft > /dev/null <<'EOF'
table ip cve_2026_98432
delete table ip cve_2026_98432
table ip cve_2026_98432 {
	chain prerouting {
		type filter hook prerouting priority -300; policy accept;
		ip protocol tcp ip hdrlength != 5 counter drop
	}
}
EOF
sudo tee /etc/systemd/system/cve-2026-98432-nft.service > /dev/null <<'EOF'
[Unit]
Description=CVE-2026-98432 mitigation: drop IPv4 TCP with IP options (own nft table)
DefaultDependencies=no
Wants=network-pre.target
Before=network-pre.target
After=local-fs.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/nft -f /etc/nft-cve-2026-98432.nft
ExecStop=/usr/sbin/nft delete table ip cve_2026_98432

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload && sudo systemctl enable --now cve-2026-98432-nft.service
sudo systemctl mask nftables.service
Undo
sudo systemctl disable --now cve-2026-98432-nft.service
Reboot / downtime
no · none
Source
https://ubuntu.com/security/CVE-2026-98432

SEC-5 DGX Dashboard auto-update off

What we use
/opt/nvidia/dgx-dashboard/settings.json: "update": {"enabled": false}
Why
No one-click kernel, driver or firmware change under a running model. The cost: you now have to run updates yourself. We fell 418 updates behind (273 security) before we started doing it monthly (ROUTINE-1). Turn it off only if you will do that.
Applies to
anyone who runs updates by hand
Check
cat /opt/nvidia/dgx-dashboard/settings.json
Expect: "enabled": false
spark-check.sh rows: SEC-5
Apply (for humans)
printf '{\n  "update": {\n    "enabled": false\n  }\n}\n' | sudo tee /opt/nvidia/dgx-dashboard/settings.json
sudo systemctl restart dgx-dashboard.service
Skip if
you will not run updates by hand every month
Undo
set enabled to true and restart dgx-dashboard
Reboot / downtime
no · none
Source
https://al-engr.com/testing-dgx-spark-kernels.html#now

NET-1 Fabric: two interfaces, two subnets, MTU 9000, ARP pinned

What we use
enp1s0f0np0 = 10.0.0.N/24, enP2p1s0f0np0 = 10.0.1.N/24, MTU 9000 end to end; arp_ignore=1, arp_announce=2, rp_filter=2
Why
One 200G cable appears as two interfaces (one per half of the card). At MTU 1500, RDMA between two Sparks ran about 5% slower (185 vs 196 Gb/s).
Applies to
multi-Spark
Check
cat /sys/class/net/enp1s0f0np0/mtu /sys/class/net/enP2p1s0f0np0/mtu; sysctl net.ipv4.conf.all.arp_ignore net.ipv4.conf.all.arp_announce net.ipv4.conf.all.rp_filter
Expect: 9000 9000; 1 2 2
spark-check.sh rows: NET-1, NET-2, NET-3
Apply (for humans)
# full netplan file and switch config:
https://al-engr.com/networking-dgx-station-sparks-mikrotik-crs804.html
Skip if
you run a single Spark
Undo
n/a
Reboot / downtime
no · brief link reset
Source
https://al-engr.com/networking-dgx-station-sparks-mikrotik-crs804.html

NET-4 NCCL settings on every Spark

What we use
NCCL_IB_HCA=rocep1s0f0,roceP2p1s0f0 NCCL_NET=IB NCCL_SOCKET_IFNAME=enp1s0f0np0 NCCL_IB_ROCE_VERSION_NUM=2 NCCL_IB_GID_INDEX=3 NCCL_PROTO=^LL128 NCCL_MAX_NCHANNELS=8
Why
Pin NCCL_SOCKET_IFNAME or NCCL may start over Docker or Tailscale. NCCL_NET=IB makes a broken RDMA path fail loudly instead of falling back to TCP (1.17 GB/s instead of ~23, no error). The last two fix medium messages: 1 MiB all_reduce on 4 Sparks 1.36 -> 11.5 GB/s (found by 0xCS).
Applies to
multi-Spark
Check
env | grep ^NCCL_   # inside your serving container
Expect: the seven variables above
spark-check.sh rows: not checkable from the host by spark-check.sh; use the check command above
Apply (for humans)
# pass with -e to docker run / your launcher
Skip if
you run a single Spark
Undo
n/a
Reboot / downtime
no · model restart
Source
https://al-engr.com/nccl-tuning-4x-dgx-spark-plain-english.html

NET-5 Switch: ECN on, RDMA in its own queue, no PFC

What we use
RoCEv2 (UDP 4791) in its own traffic class sharing 50/50 with everything else; ECN on; no PFC
Why
Without the RDMA queue an RDMA pile-up starved TCP to 0.002-0.015 Gb/s; with it TCP kept 41-94 Gb/s. ECN cut packet loss into the Station 85%. PFC hurt here.
Applies to
switched multi-Spark
Check
(on the switch) /interface/ethernet/print stats  -> tx-queue3-packet rising during RDMA
Expect: RDMA counted in queue 3
spark-check.sh rows: not checkable from the host by spark-check.sh; use the check command above
Apply (for humans)
# MikroTik CRS804 commands: https://al-engr.com/networking-dgx-station-sparks-mikrotik-crs804.html
Skip if
you run a single Spark or no switch
Undo
n/a
Reboot / downtime
no · forwarding pauses briefly when queues change
Source
https://al-engr.com/networking-dgx-station-sparks-mikrotik-crs804.html

What we decided not to do

Fewer changes is a feature here: every item we leave at the DGX OS default is one less thing to re-check after each monthly update and one less way our Sparks differ from the ones NVIDIA tests.

Open issues we are watching

Things that are not fixed yet, what we do about them in the meantime, and what we are waiting for.

IDIssueStatusNext step
OPEN-1CVE-2026-98432 not fixed in linux-nvidia-7.0Mitigated (SEC-2, SEC-4). Canonical lists linux-nvidia-7.0 on 24.04 as Vulnerable as of 2026-11-03. Watch: https://ubuntu.com/security/CVE-2026-98432When marked fixed: move to that kernel with ROUTINE-1, then remove SEC-2 and SEC-4.
OPEN-2Rare slow shutdown1 of 13 recent reboots on one Spark: nvidia-persistenced stuck in the display driver (nvkms_close); shutdown took 7.5 min, reboot ~15 min. 0 of 13 on three others. Its next restart, the same day, took about 2 minutes. Watch: journalctl -b -1 -k | grep nvkms_closeWait it out; do not pull power.
OPEN-37.0.0-1024 resets with displays attachedNVIDIA shipped nvidia-spark-initcall-bl 1.0-2 (SW-8). Other 1024 reset reports on the forum involved a self-patched driver module or a different driver (595.99.02); none matched our stock headless setup. Watch: https://forums.developer.nvidia.com/c/accelerated-computing/dgx-spark-gb10/dgx-spark-gb10/721Rollback trigger for us: one unexplained reset or GPU firmware timeout on a stock headless Spark.
OPEN-4Fans ignore CPU heat until about 80 °C; no owner fan control on EC 3.13.7Measured on one Spark on 2026-11-04: 20 busy cores, no model, reached 80 °C in 4 s and held near 94 °C with fans about 3,100 rpm; nvidia-smi read 62 °C at most. The ACPI fan setting is accepted and ignored. Partial workaround: cap the Cortex-X925 cores at 2,808 MHz (79.7 °C after 20 min, 16.5% less CPU work). We do not run the cap; our Sparks serve models on the GPU. Watch: https://forums.developer.nvidia.com/t/new-dgx-spark-fans-barely-speed-up-at-high-temps-and-cant-be-adjusted-critical-please-open-fan-control/386805When NVIDIA ships an EC with an earlier fan curve or host fan control: rerun the 20-core test and update this section. Do not downgrade the EC or script cooling_device writes.

How this page stays current

We re-check this page every week against our eight Sparks, using the same read-only check script linked at the top, and against NVIDIA's DGX Spark release notes, known issues and forum advisories, plus Canonical's CVE tracker for the Spark kernel. When something changes we update the settings and the machine-readable copy, add a changelog line here, and bump the Last checked date at the top. If the Last checked date is more than a couple of weeks old, assume we missed a week and check the sources yourself. Start date: November 3, 2026.