Back openDesk Edu for a sovereign, open-source education β every vote counts.
Vote nowIn 2024, running a 685-billion-parameter model locally meant a rack of A100s, a six-figure power bill, and a PhD in distributed systems. In 2026, it means two desktop workstations, a direct-attach cable, and a single command. The sovereignty equation has inverted β and the hardware is finally ready.
This is the story of what sovereign AI looks like when it fits under your desk.
Sovereign AI is not anti-cloud. It's about owning the decision: choosing when your data stays local, when your models run in your jurisdiction, and when you don't pay per-token rent for capabilities you can host yourself.
The practical sovereignty threshold in 2026 is frontier-grade inference β models that can reason, use tools, and handle 200K-token contexts. DeepSeek-V4-Flash crosses that threshold. It's a Mixture-of-Experts architecture with 685B total parameters (37B active per token), tool calling, multi-step reasoning, and a quality ceiling that sits firmly in the GPT-4 class. And it runs on two NVIDIA DGX Sparks β locally, with no data leaving your network.
The sovereignty argument isn't theoretical. Germany's Digital Sovereignty Act, the EU AI Act, and the EU Data Act all create regulatory pressure toward local inference. Companies processing sensitive data β legal documents, medical records, financial models, source code β face escalating compliance costs when sending prompts to cloud APIs. Self-hosted inference eliminates the data residency question entirely.

NVIDIA's DGX Spark (GB10) packs a Grace Blackwell Superchip into a desktop form factor: 128 GB of unified memory, a 20-core ARM Grace CPU (80-core SoC with 20 performance + 60 efficiency cores), and a Blackwell GPU on a single package connected via NVLink-C2C. Unified memory means GPU and CPU share a single address space β no discrete HBM, no PCIe DMA bottleneck β which simplifies deployment but introduces constraints we'll get to.
The real magic is the interconnect. Each DGX Spark ships with a Mellanox ConnectX-7 NIC (two ports, 200 Gbps each). Our cluster bonds two of these ports per node into a bond0 interface using Linux bonding mode 2 (balance-xmit) with layer3+4 hash policy, creating a 400 Gbps direct-attach link between the two nodes.
| Node | Hostname | GB10 Memory | Role | Interconnect |
|---|---|---|---|---|
| ai1 | 192.168.0.27 | 121 GB | Head (API server + EngineCore) | bond0: 10.10.10.1/30 |
| ai2 | 192.168.0.176 | 119 GB | Worker (TP2 shard) | bond0: 10.10.10.2/30 |
Physical cabling: Two QSFP56 direct-attach cables run between ai1 and ai2 β one per ConnectX port. No switch, no router, no intermediate hop. RoCE (RDMA over Converged Ethernet) handles NCCL's communication pattern natively.
Network bonding: Mode 2 (balance-xmit) with layer3+4 hash policy and MTU 9000 (jumbo frames). Note: mode 2 is round-robin transmit, not 802.3ad/LACP (that's mode 4). The Mellanox virtual MAC conflict (where bond0's MAC collides with the physical port's permanent address) is resolved with an explicit mac: assignment in NetworkManager.
# Simplified topology
βββββββββββββββββββββββββββ βββββββββββββββββββββββββββ
β ai1 (DGX Spark #1) β β ai2 (DGX Spark #2) β
β 121 GB unified memory β β 119 GB unified memory β
β 192.168.0.27 (LAN) β β 192.168.0.176 (WiFi) β
β 10.10.10.1 (bond0) βββββββββββΊβ 10.10.10.2 (bond0) β
β enp1s0f0 ββ cable βββΊ β β enp1s0f0 ββ cable βββΊ β
β enp1s0f1 ββ cable βββΊ β β enp1s0f1 ββ cable βββΊ β
βββββββββββββββββββββββββββ βββββββββββββββββββββββββββ
2 Γ 200 Gbps = 400 Gbps aggregate
The head node (ai1) runs the OpenAI-compatible API server on port 8000. The worker (ai2) connects via NCCL and runs headless β all inference traffic flows through ai1's public interface.
DeepSeek-V4-Flash is the sweet spot for sovereign inference. It's open-weight (DeepSeek license), an MoE architecture designed for efficiency:
| Property | Value |
|---|---|
| Architecture | Mixture-of-Experts (MoE) |
| Total parameters | 685B |
| Active parameters per token | ~37B (MoE, top-1 routing) |
| Context window | Up to 1M tokens; 128Kβ204K practical on dual Spark (204K production) |
| Speculative decoding | Native MTP (Multi-Token Prediction) |
| Tool calling | Built-in (deepseek_v4 parser) |
| Reasoning | Chain-of-thought with thinking/thought blocks |
| Model size (FP8) | ~149 GB across 46 shards |
The model uses a custom tokenizer (deepseek_v4), MLA (Multi-head Latent Attention) for efficient KV caching, and natively supports tool calling with --enable-auto-tool-choice. For agentic workloads β the real sovereignty use case β this means the model can call tools, reason about results, and execute multi-step plans without any cloud dependency.
After two months of production tuning (since May 2026), our cluster delivers these numbers on the official FP8 model with vLLM 0.21.1rc1 V0 engine, PIECEWISE cudagraph, and MTP speculation:
| Scenario | Tokens/Second |
|---|---|
| Single stream, short prompt | 12β20 tok/s (sustained ~15, peak ~20) |
| Concurrent Γ2, short prompts | ~25β35 tok/s aggregate |
| MTP speculation gain | ~60% effective throughput at 68% acceptance |
| Prompt Size | Tokens/Second |
|---|---|
| 2,048 tokens | ~1,100 tok/s |
| 8,192 tokens | ~770 tok/s |
| 32,768 tokens | ~320 tok/s |
| 65,535 tokens | ~176 tok/s |
Sourced from arthurdroz's llama-benchy benchmarks (eugr/spark-vllm-docker PR #219), measured at 128K context with FP8 KV cache.
| Prompt Size | TTFT |
|---|---|
| Short (prefix-cached) | ~2 s |
| 32K tokens | ~53 s |
| 128K tokens | ~250 s |
| Scenario | Throughput | Speedup |
|---|---|---|
| Cold (first request) | 2.8 tok/s | 1.0Γ |
| Same prompt (cached) | 6.0 tok/s | 2.1Γ |
| Similar prompt (deep cached) | 12.4 tok/s | 4.4Γ |
For agentic workloads β where every request shares a system prompt and conversation history β the prefix cache is transformative. A multi-turn coding session with persistent system instructions runs 4Γ faster after the first request.
| Metric | 1Γ Spark (IQ2XXS + DSpark) | 2Γ Spark (FP8 + MTP) |
|---|---|---|
| Precision | ~2-bit quant | FP8 (official) |
| Decode throughput | ~20 tok/s | 15β20 tok/s |
| Context window | 32K max | 200K+ |
| Concurrent requests | 1 practical | 2β3 at 200K ctx |
| Model quality | Tool-eval: 83/100 | Higher (FP8 ceiling) |
| Community reports (V1, c=8) | N/A | ~96 tok/s aggregate |
The scaling from 1β2 Sparks delivers a 1.7β1.9Γ speedup per user (CosmicRaisins, NVIDIA Forum). The main gains aren't raw throughput β they're precision (FP8 vs 2-bit), context length (200K vs 32K), and concurrency (2β3 simultaneous requests). For sovereign AI, these matter more than peak tok/s.
Note: Community benchmarks from tonyd615 (44 tok/s) and serapis (35 tok/s) use the V1 engine with FULL_AND_PIECEWISE cudagraph β higher throughput than our V0 PIECEWISE config, which trades peak speed for stability on GB10 unified memory.
This is the exact deepseek-v4-flash-wrapper.sh running in production β Ansible-deployed, systemd-managed, with full OOM safeguards:
#!/bin/bash
# DeepSeek V4 Flash TP2 Cluster β Production Config
# Ansible-deployed via vllm_cluster role
# Proven stable since May 2026, no crashes
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
export VLLM_SKIP_INIT_MEMORY_CHECK=1
export VLLM_TRITON_MLA_SPARSE=1
export VLLM_ALLOW_LONG_MAX_MODEL_LEN=1
export VLLM_USE_FLASHINFER_SAMPLER=1
export TORCH_CUDA_ARCH_LIST=12.1a
export OMP_NUM_THREADS=8
# Reserve 1.5 GiB for system (prevents OOM freeze on GB10)
echo 1572864 | sudo tee /proc/sys/vm/min_free_kbytes >/dev/null 2>&1
ssh -n weiss@192.168.0.176 \
"echo 1572864 | sudo tee /proc/sys/vm/min_free_kbytes >/dev/null 2>&1" || true
vllm serve deepseek-ai/DeepSeek-V4-Flash \
--served-model-name deepseek-v4-flash \
--host 0.0.0.0 --port 8000 \
--trust-remote-code \
--tensor-parallel-size 2 \
--pipeline-parallel-size 1 \
--enable-expert-parallel \
--kv-cache-dtype fp8 \
--block-size 256 \
--enable-prefix-caching \
--max-model-len 204800 \
--max-num-seqs 2 \
--max-num-batched-tokens 8192 \
--gpu-memory-utilization 0.78 \
--compilation-config '{"cudagraph_mode":"PIECEWISE"}' \
--speculative-config '{"method":"deepseek_mtp","num_speculative_tokens":2}' \
--tokenizer-mode deepseek_v4 \
--tool-call-parser deepseek_v4 \
--enable-auto-tool-choice \
--reasoning-parser deepseek_v4 \
--reasoning-config '{"reasoning_parser":"deepseek_v4","reasoning_start_str":"thinking","reasoning_end_str":"thought"}' \
--default-chat-template-kwargs '{"thinking":true}' \
--load-format safetensors \
--disable-custom-all-reduce \
"$@"
Note: This wrapper is invoked by
launch-cluster.sh --launch-script deepseek-v4-flash-wrapper.sh --no-ray, which automatically adds--nnodes 2,--node-rank N,--master-addr, and--master-portarguments for distributed execution. The wrapper itself is the vLLM serve configuration β it's not the complete launch command.
Key decisions in this configuration:
gpu-memory-utilization 0.78 β The GB10's unified memory means GPU and CPU share 128 GB. At 0.78, the model loads ~75 GB, leaving headroom for the KV cache, MTP drafter, and system processes. Going higher (0.82+) causes OOM.PIECEWISE cudagraph β Avoids TileLang's custom_ops: ["all"] compilation path, which needs ~3 GB of system RAM during JIT and bricks the machine when it's not available. PIECEWISE mode compiles only essential graphs (attention, MLP) for a 10β20% ITL improvement without the OOM risk.V0 engine (no VLLM_USE_V1) β The V1 engine's Gloo-based distributed init registers 127.0.0.1 even with --network host, breaking cross-node TP2. V0 uses NCCL directly and works reliably.--no-ray distributed executor β PyTorch native distributed (mp backend) is more reliable than Ray for small clusters. No world-size issues, no Ray dependency overhead.--disable-custom-all-reduce β Necessary on GB10 to avoid custom communication kernels that may not optimize for the unified memory architecture.The GB10's unified memory is the most important constraint β and the one most people get wrong. Unlike discrete GPUs with separate HBM and system RAM, the GB10's GPU and CPU share a single 128 GB pool. When memory runs out, there's no graceful CUDA error. The entire machine freezes β SSH hangs, no ping, no recovery. Hard power cycle required.
Our production environment applies seven OOM mitigations to both nodes via Ansible:
| Mitigation | Setting | Purpose |
|---|---|---|
| Disable swap | swapoff -a | Swap on UMA causes death spiral |
| Disable overcommit | vm.overcommit_memory=0 | malloc fails immediately |
| Minimize swappiness | vm.swappiness=1 | Belt-and-suspenders |
| Docker memory limit | --memory=100G | Process killed before kernel freezes |
| Reserve free memory | vm.min_free_kbytes=1572864 | 1.5 GiB system reserve |
| Drop page cache | echo 3 > /proc/sys/vm/drop_caches | Before model load |
| Lower readahead | blockdev --setra 16 | Faster model load from NVMe |
The startup script drops page cache and temporarily reduces NVMe readahead to 8 KB (restored after 180 seconds). Model weights load from NVMe in ~152 seconds; CUDA graph capture takes ~7 seconds; warmup and FlashInfer autotune complete in ~2 minutes. Total cold start: ~7 minutes.
The entire cluster is managed as code β network bonding, vLLM service lifecycle, OOM safety sysctl, IB health monitoring, and Prometheus/Loki metric shipping are all Ansible-driven.
Everything is version-controlled, reproducible, and auditable. Changing a gpu-memory-utilization value means editing one file, running one playbook, and letting systemd handle the restart.
| Deployment | Year 1 Cost | Ongoing/Year | Notes |
|---|---|---|---|
| 2Γ DGX Spark (on-prem) | ~$5,000β6,000 | Power (~$200) | One-time hardware + electricity |
| Cloud API (GPT-4 class) | $0 | $15,000β50,000+ | Per-token pricing scales with usage |
| Cloud GPU (A100 rental) | $0 | $12,000β24,000 | Reserved instances, no data residency control |
The break-even on two DGX Sparks against cloud API pricing is typically 2β4 months for a team of 5β10 developers. For regulated industries where data residency is non-negotiable, the calculation isn't financial β it's compliance.
| Capability | Cloud API | On-Prem Dual Spark |
|---|---|---|
| Data residency | β Data leaves your network | β Never leaves your network |
| Model selection | β Vendor-controlled | β Any open-weight model |
| Cost predictability | β Per-token pricing | β Fixed hardware cost |
| Regulatory compliance | β οΈ Shared responsibility | β Full control |
| Custom fine-tuning | β οΈ Limited or expensive | β Full LoRA/QLoRA support |
| Context window | β οΈ API-dependent | β 200K+ tokens |
| Tool calling privacy | β Tool calls logged by vendor | β All calls stay local |
| Offline operation | β Requires internet | β Air-gappable |
The real value of sovereign AI isn't single-prompt chat. It's agentic systems β multi-step tool-using workflows where data sovereignty matters at every step.
Consider a code review agent that:
Every step involves sensitive data. Sending this through a cloud API means your proprietary code, your architecture decisions, and your security findings all leave your network. Running locally on dual Sparks means nothing leaves.
With the prefix cache enabled, the agent's system prompt (~2K tokens) gets cached after the first request. Subsequent tool calls with the same system prompt execute at 4.4Γ the initial speed β critical for multi-turn agentic workflows that may make 10β20 tool calls per session.
The NVIDIA Developer Forums' DGX Spark community has validated this architecture extensively:
FULL_AND_PIECEWISE cudagraph β higher than our V0 PIECEWISE config but using a different engine modeOur V0 PIECEWISE production config prioritizes stability over peak throughput β a deliberate choice after the V1 engine's Gloo bug and the TileLang custom_ops OOM freeze. The configuration is reproducible: CosmicRaisins independently confirmed similar scaling efficiency.
For some workloads, a single DGX Spark is sufficient:
| Use Case | 1Γ Spark | 2Γ Spark |
|---|---|---|
| Small models (<70B) | β Excellent | Overkill |
| Coding assistant (single user) | β Good (IQ2XXS: ~20 tok/s) | Better (FP8 + 200K ctx) |
| Multi-turn chat | β Good | β Better (prefix cache) |
| Production multi-user | β Bottlenecked | β Handles concurrency |
| 200K+ context | β Doesn't fit | β Fits (FP8) |
| Sensitive data processing | β Works | β Works (both local) |
| Tool-calling agents | β Functional | β Full FP8 quality |
The Single DGX Spark Recipe: Qwen3.8-27B covers the one-node deployment path β the same Ansible-managed approach, tuned for 128 GB unified memory without the TP2 complexity.
Our cluster roadmap addresses the known limitations:
max-num-seqs to 4β8 β KV cache utilization sits at ~52% with 2 sequences; there's headroom for more concurrencycustom_ops: ["all"] for maximum fusion performance without first-run OOM riskSovereign AI in 2026 is not a compromise β it's an engineering decision with clear cost, compliance, and control advantages. Two DGX Sparks, a direct-attach cable, and a well-tuned vLLM configuration deliver frontier-grade inference that never sends your data through anyone else's server.
The configuration isn't perfect β 200K context at ~15 tok/s won't match a cloud provider's A100 cluster at concurrency=64. But for the sovereign AI use case β sensitive data, regulated industries, agentic workflows, air-gapped environments β it doesn't need to. It needs to be good enough, fully local, and production-stable.
Two months in, our cluster hasn't crashed once since we applied the OOM safeguards and settled on the PIECEWISE cudagraph + MTP configuration. It processes agentic coding workflows, knowledge graph queries, and multi-turn reasoning chains β all behind our firewall, all under our control.
That's what sovereign AI looks like when it fits under your desk.
Related resources on graphwiz.ai:
Enjoyed this article? Subscribe to get notified about new sovereign AI and infrastructure deep-dives.