How to Self-Host Open-Weight Models With NVIDIA's Model-Free NIM Container (One Image, Any Supported Architecture)
NVIDIA's model-free NIM container serves any architecture its bundled backend supports - Kimi, MiniMax, DeepSeek, Qwen3, gpt-oss - from a single image, with the model passed at runtime. Here are the exact Docker commands, the VRAM sizing math, the Kubernetes wrapper, and the self-host vs hosted-API break-even formula.
A model-free NIM container is one NVIDIA image with no weights inside. You pass the model at start time with NIM_MODEL_PATH (for example hf://openai/gpt-oss-20b, an s3:// bucket or a local directory). NVIDIA publishes two of them: vllm-model-free-nim and sglang-model-free-nim (NVIDIA NIM docs).
"Any model" means "any architecture the bundled engine supports". NIM 2.1.5 ships vLLM 0.31.0 and SGLang 0.5.21 (NIM release notes). Read the architectures field in the checkpoint's config.json, then check it against that engine version before you rent a GPU.
Kimi-K3 and MiniMax-M3 are on NVIDIA's validated list today. Each has a dedicated tag of the same model-free image (2.1.4-kimi-k3, 2.1.4-minimax-m3) (NIM support matrix). Kimi K3.1 Pro, released three days ago, is not on the list yet.
Size memory from total parameters, not active ones. Weights = total params x bytes per param (2 at BF16, 1 at FP8, about 0.5 at FP4). Add KV cache and 10-20% overhead on top. Kimi-K3 has 2.8T total parameters but activates 104B per token, and NVIDIA's smallest validated layout is one 8x B300 node.
Self-hosting only beats a token API at high sustained utilization. $/M tokens = hourly node price / (tokens per second x 0.0036). On a $55.04/hour AWS p5.48xlarge at SGLang's published 22,282 output tokens/s per node, that is $0.69/M at 100% use and $6.86/M at 10%.
The economics hold up only when the GPUs sit in your own cloud account. That is where your Savings Plans, committed-use discounts, capacity reservations and data residency apply. Qovery deploys and operates the workload in your own AWS, GCP, Azure or Scaleway account, or on your existing Kubernetes cluster, and auto-stops idle environments.
A new open-weight model drops on a Friday. Your team wants it in staging by Monday. Until recently, NIM users had to wait for NVIDIA to publish a per-model image on NGC, or give up on NIM and wire vLLM themselves.
The model-free NIM container removes that wait for any model whose architecture the bundled engine already understands. I've spent the last few weeks reading the docs, the support matrix and the model cards to work out what that means in practice.
This guide covers how to self-host open-weight models with it end to end: the support check, the VRAM math, the Docker commands, the Kubernetes wrapper and the cost break-even.
What is NVIDIA's model-free NIM container, and how is it different from a per-model NIM image?
A model-free NIM container is a single NVIDIA NIM image that ships the inference engine (vLLM or SGLang), NVIDIA's profile-selection logic and an OpenAI-compatible API server, with no model weights inside. You point it at a model at start time with NIM_MODEL_PATH, and NIM generates a runtime manifest, picks a profile and serves the model (NVIDIA NIM docs).
The limit, in NVIDIA's own words: "if its architecture is unsupported by the inference backend in your container (vLLM or SGLang), it is also unsupported by NIM." So the NVIDIA NIM model-free container serves any model whose architecture the bundled engine version supports. It does not serve every model on Hugging Face.
The classic packaging model: one container per model, versioned with that model, published on NGC (for example nvcr.io/nim/meta/llama-3.1-8b-instruct:2.1.5). The manifest, curated weights and optimized profiles are baked in. That works well for models NVIDIA has already packaged, and it blocks you the week a new one ships.
The model-free approach:
One image per engine: nvcr.io/nim/nvidia/vllm-model-free-nim:2.1.5 or nvcr.io/nim/nvidia/sglang-model-free-nim:2.1.5 (NIM installation).
Weights come from hf://, ngc://, s3://, gs://, modelscope:// or an absolute local path.
Tensor and pipeline parallelism are runtime settings (NIM_TENSOR_PARALLEL_SIZE, NIM_PIPELINE_PARALLEL_SIZE).
Profiles are generated per model in the form vllm-tp2-pp1-<hash>. NIM still auto-selects one based on the GPUs it detects.
What stays the same as per-model NIM:
The OpenAI-compatible routes: /v1/chat/completions, /v1/completions, /v1/responses, /v1/models.
The health endpoints /v1/health/live and /v1/health/ready.
The maintenance argument is the one I care about most. Ten models used to mean ten images to mirror into your private registry, scan, patch and upgrade. With model-free NIM you run one image per engine, with one CVE-patching surface and one upgrade path. That is also how NVIDIA pitches it: "One container image can pass security review and serve any supported model."
Licensing, read before production:
NVIDIA's NIM FAQ says the free NVIDIA Developer Program covers self-hosted NIM "for research, application development, and experimentation on up to 16 GPUs" (NVIDIA NIM FAQ).
The current docs split NIM into two offerings, and NIM Certified Production Branch "requires an active NVIDIA AI Enterprise subscription" (NIM offerings).
Every container exposes GET /v1/license. Read it, and get your legal team to read it too.
Runtime
How the model is supplied
Time to serve a brand-new open-weight architecture
Images to maintain
Optimization profiles
OpenAI-compatible API
Registry and licence
Multi-GPU / tensor parallel
Best fit
Per-model NIM image
Baked into the image
When NVIDIA publishes the image. The fast-track NIM offering targets "about 72 hours" after upstream availability (NVIDIA)
One per model
Prebuilt and tuned per GPU
Yes
NGC; NVIDIA licence, AI Enterprise for production
Yes, via profiles
Teams standardizing on NVIDIA-supported models
Model-free NIM container
NIM_MODEL_PATH at start (hf://, s3://, gs://, local)
As soon as the bundled vLLM/SGLang version supports the architecture
One per engine
Generated at start, auto-selected; some models ship tuned recipes
Yes
NGC; same NVIDIA licence terms
Yes, NIM_TENSOR_PARALLEL_SIZE, multi-node
NIM ergonomics on fast-moving open models
vLLM
CLI argument (HF repo or path)
Often day 0 (gpt-oss, MiniMax M3, Kimi K3.1 Pro on the vLLM blog)
One (upstream or your build)
You tune flags yourself
Yes
Docker Hub / PyPI; Apache 2.0
Yes, TP/PP/EP
Newest architectures, full control
SGLang
CLI argument (HF repo or path)
Often day 0 or close
One
You tune flags yourself
Yes
Docker Hub / PyPI; Apache 2.0
Yes, TP/EP, prefill-decode disaggregation
Large MoE at scale, DeepSeek-style serving
Hugging Face TGI
--model-id at start
Depends on TGI's model support
One
You tune flags yourself
Yes (Messages API)
Docker / GHCR; Apache 2.0
Yes, sharding
Teams already on HF Inference Endpoints
Ollama
ollama pull (GGUF library)
When a GGUF build exists
One
None (llama.cpp quantization)
Yes (compat endpoint)
ollama.com; MIT
Limited
Laptops and single-GPU dev boxes
Which open-weight models can you actually serve, and how do you check in 60 seconds?
To check whether the model-free NIM container can serve a model, open the checkpoint's config.json on Hugging Face and read the architectures field. Then confirm that the vLLM or SGLang version bundled in your NIM image supports that exact class name and the checkpoint's quantization format. NIM 2.1.5 bundles vLLM 0.31.0 and SGLang 0.5.21.
The 60-second check:
Fetch the config: curl -s https://huggingface.co/<org>/<model>/raw/main/config.json | jq .architectures.
Look for that string on NVIDIA's Model-Free NIM support matrix. If it is listed, use the exact image tag NVIDIA gives you.
Confirm the precision: BF16, FP8, MXFP4, NVFP4, GPTQ or AWQ. It must match a kernel your GPU generation has. NVFP4 needs Blackwell.
Check the context length (max_position_embeddings) and whether the repo ships a standard tokenizer and chat template.
Run list-model-profiles with the same NIM_MODEL_PATH you plan to deploy. If NIM lists no runnable profiles for your GPUs, stop there.
A real example from this week: Moonshot AI published Kimi K3.1 Pro on Hugging Face on November 2, 2026. Its architecture is KimiK31ForConditionalGeneration. That class is not in vLLM 0.31.0's registry, so model-free NIM 2.1.5 cannot serve it yet. vLLM shipped a day-0 image on November 4. Community engines usually get there first, because model-free NIM can only be as new as the engine it bundles. Use upstream vLLM or SGLang for that gap and move to NIM once NVIDIA ships a new tag.
The licence check is separate from the technical one. Apache 2.0 (gpt-oss, Qwen3-235B), MIT (DeepSeek) and bespoke licences (Kimi-K3, MiniMax-M3, both marked other on Hugging Face) differ on commercial use, attribution and redistribution. Check each model, not each family.
Gated repos: none of the checkpoints below are gated today. For those that are, Hugging Face says you must request access "from your browser" while logged in, and scripts must "provide a user token" (Hugging Face gated models). A 401 at download time almost always means the token's account never got access.
Pin the revision. NIM accepts hf://{org}/{model}:{revision} (NIM model download), and Hugging Face requires "the full-length hash" for commits (huggingface_hub docs). Write hf://openai/gpt-oss-120b:b5c939de8f754692c1647ca79fbf85e8c1e70f8a, not just the repo name. If the upstream repo is re-uploaded, your production model stays the same.
The chat-template trap: a mismatched chat template still returns HTTP 200, with quietly worse answers. Tool calls break, reasoning tags leak into the output, and the model ignores the system prompt. Use the template that ships with the checkpoint, and override it only through NIM's custom parsers and templates when the model card tells you to.
Parameter counts come from each model card. The Hugging Face file browser shows wrong totals for 4-bit checkpoints, because packed integer tensors get counted as single parameters.
How much GPU memory and what node shape do you need to self-host these models?
Estimate GPU memory as total parameters x bytes per parameter (2 at BF16, 1 at FP8, about 0.5 at FP4), plus the KV cache, plus 10-20% runtime overhead. For Mixture-of-Experts models, all experts must sit in GPU memory even though only a few run per token. That is why large MoE checkpoints need 8-GPU nodes or multi-node serving.
Step 1, weights: NVIDIA's memory guide uses the same arithmetic: Llama 3.3 70B at FP8 is "70 billion x 1 byte / 2 GPUs" = 35 GB per GPU (NIM memory troubleshooting).
Step 2, KV cache: 2 x layers x kv_heads x head_dim x bytes per element x context length x concurrent sequences.
Qwen3-235B uses GQA with 94 layers, 4 KV heads and head_dim 128 (config.json).
At BF16 that is about 192 KB per token: 6.3 GB for one 32K-token sequence, and 101 GB for 16 of them.
GQA, MLA (DeepSeek, Kimi K2) and the hybrid linear-attention designs in Kimi-K3 and MiniMax-M3 shrink this a lot compared with full multi-head attention. Read the model card before you assume the worst case.
Step 3, overhead: add 10-20% for activations, CUDA graphs and communication buffers. If startup fails during KV allocation, NVIDIA's fix is to cut NIM_MAX_MODEL_LEN before you buy more GPUs.
The MoE rule: active parameters set compute cost, total parameters set memory cost. So how much VRAM does a 100B MoE model need? Budget for 100B, not for the 5-10B it activates. gpt-oss-120b activates 5.1B parameters, yet its card says it fits "into a single 80GB GPU (like NVIDIA H100 or AMD MI300X)" only because its MoE weights ship in MXFP4 (gpt-oss-120b model card).
Check your arithmetic against an official layout:
Kimi-K3: 2.8T params x 0.5 byte is about 1.4 TB of weights before any KV cache. One 8x B200 node holds 1,440 GB in total (NVIDIA DGX B200), so NVIDIA's validated B200 layout uses two nodes, and B300 fits on one 8-GPU node (NIM support matrix).
MiniMax-M3 NVFP4: about 250 GB of weights. NVIDIA validates it at TP4 on H200 (4 x 141 GB) and TP8 on H100 80GB. BF16 needs TP8 on B200.
Tensor parallelism has two hard constraints:
TP must divide the GPUs you have (1, 2, 4, 8).
TP must divide the attention-head count. vLLM refuses to start otherwise: "Total number of attention heads (...) must be divisible by tensor parallel size" (vLLM source).
MiniMax-M3 and gpt-oss have 64 heads, so TP=6 on a six-GPU box fails. Once you go past one GPU, NVLink/NVSwitch matters: PCIe-only nodes lose a lot of throughput on large models, and NVIDIA states that MiniMax-M3 is not supported in VMs with PCIe GPU passthrough in 2.1.4.
GPU driver 580 or later, CUDA 12.9 or later, Docker 24.0 or later.
NVIDIA Container Toolkit 1.14.0 or later, configured with sudo nvidia-ctk runtime configure --runtime=docker (Container Toolkit install guide). On Kubernetes the GPU Operator installs it for you.
--shm-size raised well above Docker's 64 MB default. NVIDIA calls that default "too small for multi-GPU vLLM" and asks for 16 GB on most MiniMax-M3 profiles.
An HF_TOKEN. An NGC API key is only needed for Production Branch images, NIMs older than 2.0.10, or private artifacts.
Size the cache disk above the checkpoint. Kimi-K3 is about 1.6 TB per checkpoint, and NVIDIA warns the first download and load "can take several hours".
How do you run a model-free NIM container with Docker, step by step?
Five steps take you from a bare GPU host to an OpenAI-compatible endpoint: create a persistent cache directory, export HF_TOKEN, optionally log in to nvcr.io, run the model-free image with NIM_MODEL_PATH set, then poll /v1/health/ready and call /v1/chat/completions. Every command below is copied from the NIM 2.1.5 docs.
Step 1: create the weight cache. This is the most common mistake: without a mounted cache, every restart downloads the whole model again.
BASH
export LOCAL_NIM_CACHE=~/.cache/nim
mkdir -p "$LOCAL_NIM_CACHE"
# The NIM container runs as a non-root user with GID 0
sudo chgrp -R 0 "$LOCAL_NIM_CACHE"
sudo chmod -R g+rwX "$LOCAL_NIM_CACHE"
Use one cache directory per model and per image. NVIDIA recommends this for air-gapped redeploys too.
Step 2: export your Hugging Face token from a secret store, not a pasted literal in shell history:
BASH
export HF_TOKEN="$(cat ~/.secrets/hf_token)"
Step 3 (only if required): log in to nvcr.io. Public model-free images pull without a login. You only need it for Production Branch, gated or older images. The username is the literal string $oauthtoken:
Tensor parallel size: set -e NIM_TENSOR_PARALLEL_SIZE=8, or pass --tensor-parallel-size 8 after the model path. Better still, run list-model-profiles first and set NIM_MODEL_PROFILE to an ID from its output.
Served model name: without NIM_SERVED_MODEL_NAME, clients must send the derived name (the URI minus hf:// and the :revision). Set it explicitly so your clients keep the same model ID when you change precision or revision.
For MiniMax-M3 or Kimi-K3, use NVIDIA's tags (vllm-model-free-nim:2.1.4-minimax-m3, vllm-model-free-nim:2.1.4-kimi-k3) and the checkpoints listed in the support matrix.
Step 5: wait for ready, then call it.
BASH
until curl -sf http://localhost:8000/v1/health/ready > /dev/null; do sleep 10; done
curl -s http://localhost:8000/v1/models
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-oss-20b",
"messages": [{"role": "user", "content": "Hello! How are you?"}],
"max_tokens": 100
}'
A trimmed response looks like {"object":"chat.completion","model":"openai/gpt-oss-20b","choices":[{"message":{"role":"assistant","content":"..."},"finish_reason":"stop"}],"usage":{...}}.
Cold start: the first boot downloads the weights, generates the manifest and selects a profile. Later starts read from the cache. For a 14 GB model that takes minutes. For a 1.6 TB checkpoint NVIDIA says hours.
Serving local weights instead: mount the directory and point NIM_MODEL_PATH at it, for example -v /mnt/models:/mnt/models -e NIM_MODEL_PATH=/mnt/models/my-120b-model. NIM then generates the manifest with "no network access or credentials", which is the air-gapped, regulated and low-bandwidth pattern (NIM air-gap deployment).
Symptom
Likely cause
Fix
Fails at load with an unsupported architecture error
The architectures class is not in the bundled vLLM/SGLang version
Use a newer NIM tag, or upstream vLLM/SGLang until NVIDIA ships one
torch.OutOfMemoryError during weight loading
Total params x bytes exceeds per-GPU memory at your TP size
Raise TP, use an FP8/FP4 checkpoint, or move to bigger GPUs
OOM after weights load, during KV cache allocation
Native context (e.g. 128K-1M tokens) needs more KV cache than fits
Lower NIM_MAX_MODEL_LEN (NVIDIA's documented fix)
"Total number of attention heads must be divisible by tensor parallel size"
TP does not divide the head count
Use TP 2, 4 or 8 for 64-head models
HTTP 401/403 downloading from Hugging Face
Token missing, or its account never accepted the gated terms
Request access in the browser, then re-issue HF_TOKEN
PermissionError writing to /opt/nim/.cache
Cache dir not writable by GID 0
chgrp -R 0 + chmod -R g+rwX, run with -u $(id -u):0
No space left on device mid-download
Cache disk smaller than the checkpoint
Size the volume above on-disk weights (250 GB to 1.6 TB for the models above)
could not select device driver "" with capabilities: [[gpu]]
NVIDIA Container Toolkit missing or Docker not configured
Qovery deploys and operates GPU workloads inside your own AWS, GCP, Azure, or Scaleway account - or your existing Kubernetes cluster. The bill, the weights, and the prompt data stay yours.
How do you run NIM on Kubernetes so it survives restarts, scales, and does not burn GPU hours idle?
To run NIM on Kubernetes, wrap the same container in a Deployment that requests nvidia.com/gpu in its limits and mounts a persistent volume at /opt/nim/.cache. Give it a startup probe on /v1/health/ready long enough to cover the first model download. Schedule it onto a tainted GPU node pool that scales to zero when nobody calls the model.
GPU scheduling: the cluster needs the vendor device plugin. After that it "exposes a custom schedulable resource such as nvidia.com/gpu", and GPUs "are only supposed to be specified in the limits section" (Kubernetes docs). The NVIDIA GPU Operator installs the driver, the container toolkit, the device plugin and DCGM monitoring in one go. Taint the GPU nodes so CPU pods never land on a $55/hour machine.
The weight cache is again the biggest practical problem. If every new pod downloads 250 GB, scale-up takes forever and you pay the egress each time. You have three options:
A ReadWriteOnce PVC per replica.
Node-local NVMe that you pre-warm.
A ReadWriteMany volume shared across replicas. NVIDIA's minimal Helm values use persistence.accessMode: ReadWriteMany (NIM Helm deployment).
A minimal manifest for MiniMax-M3 NVFP4 on an 8x H100 node:
Why startupProbe and not just a long initialDelaySeconds: with a short liveness check, the kubelet kills the pod mid-download, and you end up in a crash loop that never finishes. The startup probe holds liveness off until the model is ready.
KEDA scales workloads "all the way to zero", though not on CPU or memory triggers. The KEDA HTTP add-on does request-driven scaling and is still beta.
On dev and evaluation environments, scale-to-zero makes the biggest difference to your bill.
Observability:/v1/metrics passes through the engine's native Prometheus metrics with a vllm: or sglang: prefix (NIM observability). Set SLOs on time-to-first-token, inter-token latency and tokens per second per GPU. CPU utilization tells you nothing here. Add DCGM exporter for DCGM_FI_DEV_GPU_UTIL and DCGM_FI_DEV_FB_USED.
Concern
What to configure
What breaks if you skip it
GPU scheduling
GPU Operator or device plugin, nvidia.com/gpu in limits, taints + tolerations
Pods stay Pending, or CPU pods occupy GPU nodes
Weight cache
PVC (RWO per replica or RWX shared) or pre-warmed NVMe at /opt/nim/.cache, writable by GID 0
Every restart re-downloads 14 GB to 1.6 TB
Startup and readiness
startupProbe on /v1/health/ready with a long failureThreshold, liveness on /v1/health/live
Kubelet kills the pod during first download: crash loop
Shared memory
emptyDir with medium: Memory at /dev/shm (16Gi+)
NCCL and multi-GPU worker crashes
Autoscaling and scale-to-zero
Karpenter or Cluster Autoscaler on the GPU pool, KEDA for request-driven replicas
Idle GPU nodes billed 24/7
Image supply chain
Mirror the NIM image to your private registry, pin the tag
Upstream tag changes or registry outage break deploys
Observability
Scrape /v1/metrics and DCGM exporter
You find latency regressions from users
Licence governance
Pin model revision SHA, record provenance, review each model's licence
Silent model changes, licence breach in production
Is self-hosting an open-weight model actually cheaper than a hosted inference API?
Self-hosting is cheaper than a hosted API only when your GPUs stay busy. Effective $/M tokens = node hourly price / (sustained tokens per second x 0.0036). Compare that with the provider's published price per million tokens. An idle GPU node costs exactly as much as a saturated one, so self-hosting wins above a utilization threshold and loses badly below it.
The formula:
Self-hosted $/M tokens = hourly price / (tokens per second x 0.0036). 3,600 seconds per hour, divided by 1,000,000 tokens.
At utilization U, divide that result by U.
Break-even utilization = (self-hosted $/M at 100%) / (API $/M).
A worked example, sourced, as of November 5, 2026:
Throughput: SGLang's team measured 22,282 output tokens/s per decode node for DeepSeek-V3 on 8x H100 at 2K-token inputs. The setup used prefill-decode disaggregation and expert parallelism across 12 nodes (96 GPUs) (LMSYS). Treat it as an upper bound for a heavily tuned deployment.
Result: $55.04 / (22,282 x 0.0036) = $0.69 per million output tokens at 100% utilization. Prefill nodes come on top.
Same node elsewhere: Google Cloud a3-highgpu-8g in Iowa costs $88.49/hour (Google Cloud), or $1.10/M. Azure ND96isr_H100_v5 in East US costs $98.32/hour (Azure retail prices), or $1.23/M.
Hosted APIs for the same architecture: DeepSeek V3.1 lists at $0.58 input / $1.68 output per M on Amazon Bedrock (Bedrock pricing) and $0.25 / $0.95 on OpenRouter (OpenRouter).
Break-even on AWS on-demand: 0.69 / 1.68 = 41% sustained utilization against Bedrock, and 0.69 / 0.95 = 72% against OpenRouter.
Utilization is the number that matters most. At 10% utilization the same p5 node costs $6.86/M output tokens, four times Bedrock's price. Continuous batching, scale-to-zero and auto-stop on non-production move your effective price more than switching from H100 to H200.
Reasons to self-host that have nothing to do with price:
Prompts, outputs and weights never leave your VPC.
Data residency for regulated workloads, which is usually what decides it.
Fine-tuned or proprietary checkpoints that no API will host.
No third-party rate limits, more predictable tail latency, and no forced model deprecations.
Reasons not to self-host:
You take on the operations: driver and CUDA drift, GPU quota approvals and regional capacity shortages.
Bursty, low-volume traffic will never pay for a reserved node. For that workload, a hosted API is the right answer.
What model-free NIM changes: trying the newest open-weight model in production becomes a config change (NIM_MODEL_PATH) instead of a packaging project. That makes owning the serving layer more valuable.
Discounts belong to the account that buys them:
AWS EC2 Instance Savings Plans go "up to 72%" (AWS). EC2 Capacity Blocks for ML reserve 1 to 64 GPU instances up to eight weeks ahead, for up to 182 days.
Google Cloud's published A3 resource-based commitments price a3-highgpu-8g at $61.38/hour (1 year) and $38.86/hour (3 years), about 31% and 56% off on-demand.
Each of these is tied to your account, organization or project.
Option
Where prompts and weights live
Time to serve a brand-new open-weight architecture
Cost model
Ops burden
Control over quantization and TP
Who owns discounts and reservations
Best fit
Self-hosted NIM in your own cloud account
Your VPC
When the bundled engine supports it; days with model-free NIM
Per GPU-hour ($55.04/hour for 8x H100 on AWS on-demand)
Per token (gpt-oss-120b $0.15 / $0.60 per M on Together AI and Fireworks AI)
None
None or limited
Provider
Bursty or low-volume traffic, prototypes
Managed cloud model endpoints (Amazon Bedrock, Google Vertex AI, Azure AI Foundry)
Cloud provider's managed service
When the provider adds the model to its catalog
Per token (gpt-oss-120b $0.15 / $0.60 per M on Bedrock)
Low
None
Provider sets the per-token price
Teams that want one cloud bill and no GPUs
GPU-rental platforms (Modal, RunPod)
Platform's infrastructure
As fast as you can run vLLM/SGLang there
Per GPU-second or GPU-hour
Medium
Full
Platform
Experiments and burst capacity
How do you keep the GPU bill, the weights, and the prompt data inside your own cloud account?
Run the GPU nodes in your own cloud account. Your committed-use discounts, Savings Plans, GPU quotas and capacity reservations belong to that account, and a third-party platform cannot use them for you. Prompts and fine-tuned checkpoints are also the most sensitive things an AI team handles, so they should stay in your VPC.
Bring your own cloud (BYOC), applied to inference, means all of this stays in your name:
The cloud bill.
The capacity blocks and reservations.
The GPU quotas.
The VPC.
The prompt logs.
The model weights.
GPU commitments run for months or years and cost six or seven figures. A leaked prompt log or fine-tuned checkpoint is a far worse incident than a leaked static asset. I wrote more about the BYOC trade-offs here.
This is where Qovery fits. Qovery deploys and operates workloads inside your own AWS, GCP, Azure or Scaleway account, or on your existing Kubernetes cluster. You get Kubernetes without managing Kubernetes directly, and you ship without a dedicated DevOps engineer. What it gives you:
Git-push deployments for the NIM container and the apps that call it.
Preview environments per pull request, useful for A/B testing a prompt or model swap before it reaches production (how preview environments help teams).
Environment auto-stop on a schedule, so the evaluation GPU node is off at 7 PM and back at 8 AM (deployment rules).
Per-environment RBAC, so the person who can redeploy staging cannot touch production.
Managed cluster upgrades, and databases backed by your cloud's managed services.
What the GPU pattern looks like:
On Qovery-managed AWS EKS clusters, you enable a dedicated GPU node pool (Karpenter) and pick the instance types (Qovery EKS docs, GPU workloads on EKS).
On GCP, Azure or Scaleway, you connect an existing cluster that already has GPU nodes (bring your own Kubernetes).
The NIM container then runs as a Qovery container service with a GPU allocation and persistent storage mounted at /opt/nim/.cache. Qovery persistent storage cannot be shared between replicas, so give each replica its own cache.
Auto-stop keeps the eval environment from running overnight.
Be fair to the alternatives:
If you want zero infrastructure, use a hosted API.
If you are running a one-off experiment, vLLM on a single rented GPU is enough.
Qovery does not make GPUs cheaper. It runs them in your account, on your discounts, and switches them off when nobody uses them.
How do I deploy this with Qovery from Claude Code or Cursor?
Install the Qovery Agent Skills with one curl command, then ask your coding agent in plain language to deploy the NIM container into your own cloud account. The agent proposes the service, the GPU allocation and the persistent volume, and you approve each step before anything runs.
curl -fsSL https://skill.qovery.com/install.sh | bash
# Or scope the install to the current project only
curl -fsSL https://skill.qovery.com/install.sh | bash -s -- --project
# Add the Qovery MCP Server to Claude Code over OAuth (read-only by default)
claude mcp add --transport http qovery https://mcp.qovery.com/mcp --callback-port 4242
# Write access, only when you explicitly want it (also enable it in the Qovery Console)
claude mcp add --transport http qovery "https://mcp.qovery.com/mcp?read_write=true" --callback-port 4242
The skills deploy new services, and the MCP Server operates what already exists:
Skill
What it does
qovery-onboard
Connects your cloud account or cluster
qovery-deploy
Ships a service
qovery-troubleshoot
Diagnoses failing deployments
qovery-optimize
Finds cost savings, such as idle environments
qovery-speedup
Shortens build and deploy times
qovery-preview
Sets up per-PR environments
qovery-terraform
Works with the Qovery Terraform provider
Then a prompt like: "deploy the vllm-model-free-nim container to my AWS cluster's GPU node pool with NIM_MODEL_PATH=hf://openai/gpt-oss-120b, mount a 200 GB persistent volume at /opt/nim/.cache, and auto-stop the staging environment at night."
Can NVIDIA's model-free NIM container serve any open-weight model from Hugging Face?
It serves any model whose architecture the bundled engine supports, not every repo on Hugging Face. NIM 2.1.5 bundles vLLM 0.31.0 and SGLang 0.5.21, and NVIDIA states that an architecture unsupported by that engine "is also unsupported by NIM". You pass the model with NIM_MODEL_PATH=hf://<org>/<model>, and the source can also be S3, GCS, NGC or a local path.
How do I check whether a brand-new model like a Kimi or MiniMax release is supported before I rent a GPU?
Read the architectures field in the model's config.json. Check it against NVIDIA's model-free NIM support matrix, then against the model registry of the vLLM or SGLang version in your image. For example, Kimi-K3 (KimiK3ForConditionalGeneration) and MiniMax-M3 are validated with tags 2.1.4-kimi-k3 and 2.1.4-minimax-m3. Kimi K3.1 Pro (KimiK31ForConditionalGeneration) is not in vLLM 0.31.0's registry yet. Running list-model-profiles with the same NIM_MODEL_PATH confirms it on your own hardware.
How much GPU memory do I need to self-host a large open-weight MoE model like DeepSeek, Kimi or MiniMax?
Multiply total parameters, not active ones, by bytes per parameter: 2 at BF16, 1 at FP8, about 0.5 at FP4. Then add KV cache and 10-20% overhead. MiniMax-M3 (~428B total) needs about 250 GB at NVFP4, and NVIDIA validates it on 4x H200 or 8x H100. Kimi-K3 (2.8T total) needs about 1.4 TB at 4-bit, which means one 8x B300 node or two 8x B200 nodes.
Is a model-free NIM container faster or slower than running vLLM or SGLang directly?
The model-free NIM container runs vLLM or SGLang inside, so for the same version and flags you should expect similar throughput. The difference comes from NVIDIA's tuned profiles and recipes for validated models. NVIDIA's own 2024 benchmark claimed 6,372 vs 2,679 tokens/s for Llama 3.1 8B on one H100 with NIM optimizations on and off (NVIDIA, vendor-published). Benchmark your own model with your own traffic before you trust either number.
Do I need an NVIDIA AI Enterprise licence to run NIM in production?
NVIDIA's NIM FAQ limits the free Developer Program licence to "research, application development, and experimentation on up to 16 GPUs". For production, NVIDIA directs you to NVIDIA AI Enterprise, which has a free 90-day trial. NIM Certified Production Branch images explicitly require an AI Enterprise subscription. Check GET /v1/license on your container and NVIDIA's current terms before you go live.
How do I serve model weights from local storage instead of downloading them from Hugging Face?
Mount the weights directory into the container and set NIM_MODEL_PATH to the absolute path, for example -v /mnt/models:/mnt/models -e NIM_MODEL_PATH=/mnt/models/my-120b-model. NIM generates the manifest from the local directory with no network access or credentials. That is NVIDIA's documented pattern for air-gapped and regulated environments.
Is self-hosting an open-weight model cheaper than calling a hosted inference API?
Only at high sustained utilization. Use $/M tokens = hourly node price / (tokens per second x 0.0036). An AWS p5.48xlarge at $55.04/hour serving 22,282 output tokens/s costs $0.69/M at 100% use and $6.86/M at 10%, against $1.68/M output for DeepSeek V3.1 on Amazon Bedrock. Bursty, low-volume traffic is cheaper on a hosted API.
Romaric founded Qovery to make Kubernetes accessible to every engineering team. He writes about platform strategy, developer experience, and the future of cloud infrastructure.
Next step
Run your own models on your own cloud account.
Qovery deploys and operates GPU workloads inside your own AWS, GCP, Azure, or Scaleway account - or your existing Kubernetes cluster. The bill, the weights, and the prompt data stay yours.