| name | vss-deploy-profile |
| description | Use when the user asks to select, configure, deploy, verify, debug, or tear down a VSS profile (base, search, lvs, warehouse, edge). Not for standalone microservices — use the vss-deploy-* skill. |
| license | Apache-2.0 |
| metadata | {"version":"3.2.1","author":"NVIDIA Video Search and Summarization team","github-url":"https://github.com/NVIDIA-AI-Blueprints/video-search-and-summarization","tags":"nvidia blueprint deployment"} |
VSS Deploy
Do not use this skill for:
- Standalone microservice deployment outside a compose profile — use the matching skill:
vss-deploy-dense-captioning, vss-deploy-detection-tracking-2d, vss-deploy-detection-tracking-3d, or vss-deploy-video-embedding.
- Summarizing or querying a video once
lvs is deployed — use vss-summarize-video.
- NGC CLI install/configure in isolation — see
references/ngc.md, or vss-deploy-profile will run it as part of the credential gate.
Available Scripts
| Script | Purpose | Arguments |
|---|
scripts/normalize_resolved_yml.py | Strip optional depends_on entries for services filtered out of resolved.yml before deploy. | Path to resolved.yml |
scripts/probe_remote_models.sh | Probe an OpenAI-compatible remote LLM/VLM endpoint and verify the selected model id. | Base URL, optional expected model id |
scripts/check_credentials.sh | Probe NGC_CLI_API_KEY/NGC_API_KEY, NVIDIA_API_KEY, and HF_TOKEN against their services; see references/credentials.md. | None (reads env vars) |
Profile Routing
Match the user's request to a profile, then load that profile's reference for sizing, services, env recipes, and debugging.
Edge hardware routing (DGX Spark, AGX/IGX Thor): see references/edge.md. All three edge platforms run the blueprint default nemotron-3.5-lightning-30b-a3b NIM on port 30081 as vss-llm-nim; each ships its own hw-*.env sizing pair. Nothing rewrites the LLM on edge any more. nvidia-nemotron-nano-9b-v2-fp8 remains reachable via an explicit --llm.
Each profile's reference owns its sizing table. Don't pick a deployment shape from this file — open the profile reference and check minimum GPU count for the host's hardware against the (mode × platform) matrix there.
Instructions
The deployment flow is always: copy overrides.env to generated.env, apply overrides, dry-run compose into resolved.yml with both env layers, review, normalize, deploy with the same env layers, then wait for readiness.
.env is the read-only checked-in stable-default layer. overrides.env is the read-only checked-in profile override layer for values the deploy scripts may modify per host/profile. generated.env is the per-deploy working copy created from overrides.env. Step 1c covers this in full.
Prerequisites
- Repo path — auto-detect
video-search-and-summarization/ before
asking the user. Use the detected path as $REPO for all subsequent
commands.
- Credential gates — see
references/credentials.md: NGC_CLI_API_KEY for local/local_shared NIM pulls, NVIDIA_API_KEY for remote NIM endpoints, and HF_TOKEN for edge recipes that use gated HF models.
- System prerequisites (GPU driver, Docker, NVIDIA Container Toolkit, kernel sysctls, and — if
ufw is active — the Docker-bridge→host firewall allow so bridge NIMs can fetch clips from host-mode VST) — full checks in references/prerequisites.md. Canonical hardware/driver matrix is the VSS prerequisites page.
The auto-detect snippet (git-root, then a common-path probe gated on
deploy/docker/compose.yml + dev-profile.sh + skills/deployment/vss-deploy-profile)
lives in references/prerequisites.md.
Export the resolved $REPO; if detection fails, ask the user for the checkout path.
Pre-flight check
Run before every deploy. The full system checklist and remediation steps live
in references/prerequisites.md.
For DGX Spark / IGX Thor / AGX Thor, also run the cache-cleaner check in
references/edge.md.
Detect sudo mode first. Several pre-flight remediations and the
edge cache-cleaner installer call sudo. If the host requires a
sudo password, those steps will silently no-op under sudo -n and
leave the deploy in a half-prepared state.
if sudo -n true 2>/dev/null; then
echo "passwordless sudo — pre-flight will auto-install missing pieces"
else
echo "sudo requires password — pre-flight will NOT auto-install; hand commands to the user"
fi
When sudo needs a password, the skill must not run privileged
installers itself. Surface the copy-pasteable command block from
references/prerequisites.md to the user with a "run this once and
confirm" handoff, then resume after the user replies.
Minimum smoke test (must succeed):
nvidia-smi --query-gpu=index,name --format=csv,noheader
docker info 2>/dev/null | grep -qi runtimes \
&& docker run --rm --gpus all ubuntu:22.04 nvidia-smi >/dev/null 2>&1 \
&& echo "nvidia runtime OK"
If the smoke test fails, do not proceed; open
references/prerequisites.md
for the remediation tree.
Model Selection
$LLM_REMOTE_URL / $VLM_REMOTE_URL if the user asks for remote
$NGC_CLI_API_KEY (local NIMs) or $NVIDIA_API_KEY (remote)
Endpoint intent gate. Don't infer remote placement from stray env vars
(LLM_ENDPOINT_URL, VLM_ENDPOINT_URL, LLM_BASE_URL, VLM_BASE_URL may be
leftovers). Use remote LLM/VLM only when (1) the user asked for / supplied a
remote endpoint, (2) local sizing can't fit the selected models and the user
agrees, or (3) an edge recipe needs a standalone local service VSS treats as
remote (e.g. an external OpenAI-compatible endpoint per edge.md
on localhost:30081). If an endpoint var is set but the user didn't ask
for remote, surface it in Step 1 and ask — never silently deploy remote
because a var happened to exist.
If no combination on this host satisfies the profile's sizing requirements, stop and report the blocker — don't silently pick another shape.
Edge shared mode is platform-specific. Full recipes are in references/edge.md.
Deployment Flow
Always follow this sequence. Never skip the dry-run.
Step 0 — Tear down any existing deployment + clear data volumes
If a deployment already exists, tear it down AND clear stale data volumes before redeploying.
Full procedure lives in references/teardown.md.
Step 0a — Credentials gate (run before any env mutation)
Validate every credential and selected remote endpoint the chosen profile
needs before Step 1c copies overrides.env to generated.env. A 401 here is a
30-second failure; the same 401 inside a NIM cold-start is a 10–20 min
failure. Run the discovery and probe flow in
references/credentials.md, including
scripts/probe_remote_models.sh for any LLM/VLM endpoint you plan to write
into generated.env. Map the result against the chosen mode: missing
or invalid required credentials/endpoints are blockers, optional credentials
are not.
Step 1 — Gather context
Before building env overrides, confirm:
| Value | How to determine |
|---|
| Profile | Match user intent to the routing table above. Default: base |
| Repo path | Use the $REPO value auto-detected in prerequisites. If auto-detect failed, ask the user for the checkout path before continuing. |
| Hardware | nvidia-smi --query-gpu=name,memory.total --format=csv,noheader |
| LLM/VLM placement | Explicitly decide local / local_shared / remote. Cross-reference available GPUs against the chosen profile's Minimum GPU count table. If endpoint env vars are present but the user did not request remote, ask whether to use or ignore them. |
| API keys | NGC_CLI_API_KEY for local NIMs, NVIDIA_API_KEY for remote |
HOST_IP | In-cluster dial address: ip route get 1.1.1.1 src (like dev-profile.sh; correct on LAN + cloud). If that interface is a VPN/tunnel, fall back to the LAN IP and prompt the user — Network addressing. |
EXTERNAL_IP | Browser-facing address; defaults to ${HOST_IP}. Override when the browser path differs — cloud public IP, Brev secure-link (Step 1d), or tunnel; ask the user where they browse from if unsure. Network addressing. |
HAPROXY_HOST_PORT | Browser-facing ingress host port. Default 7777; change it in generated.env if the host port conflicts. |
HAPROXY_PORT | HAProxy container listen port. Default 7777; leave it unchanged unless a platform-specific path, such as Brev, requires it. |
Before docker compose up, verify EXTERNAL_IP, HAPROXY_HOST_PORT, VSS_PUBLIC_HOST, and VSS_PUBLIC_PORT are populated with browser-reachable values. Otherwise the stack may appear healthy while UI/API/VST links 404 or loop through Cloudflare Access.
Step 1b — Prepare the data directory
Layout (asset paths, ownership, mount points, profile-specific subdirs) is documented in references/data-directory.md. Read that file before deploying for the first time on a host or when changing profiles.
Step 1c — Initialize generated.env
The skill's per-deploy working copy. Always start from a fresh copy of overrides.env, never mutate .env or overrides.env.
PROFILE=base
ENV_SRC=$REPO/deploy/docker/developer-profiles/dev-profile-$PROFILE/.env
ENV_POST=$REPO/deploy/docker/developer-profiles/dev-profile-$PROFILE/overrides.env
ENV_GEN=$REPO/deploy/docker/developer-profiles/dev-profile-$PROFILE/generated.env
cp "$ENV_POST" "$ENV_GEN"
All subsequent writes (Brev EXTERNAL_IP, the env_overrides dict from Step 2) go to $ENV_GEN. $ENV_SRC and $ENV_POST are read-only from here on, and Compose must receive $ENV_SRC before $ENV_GEN.
Step 1d — Brev only: detect first, then set EXTERNAL_IP to the secure-link domain
Detect Brev before anything else — a Brev-provisioned instance sets BREV_ENV_ID in /etc/environment; nothing else does:
grep -qE '^BREV_ENV_ID=' /etc/environment && echo "on Brev" || echo "not Brev"
- not Brev → skip the rest of this step and do not read
references/brev.md; keep the normal ${HOST_IP}-based EXTERNAL_IP.
- on Brev → apply the Brev secure-link overrides from
references/brev.md § Setup flow to generated.env (NOT .env). Those set EXTERNAL_IP / VSS_PUBLIC_HOST to the secure-link domain and VSS_PUBLIC_HTTP_PROTOCOL=https / VSS_PUBLIC_WS_PROTOCOL=wss / VSS_PUBLIC_PORT=443 — setting EXTERNAL_IP alone leaves http://…:7777 UI/API/WS links that the browser blocks as mixed content.
Step 2 — Build env_overrides
Produce an env_overrides dict from the user request and the gathered
context: explicitly choose remote/local LLM/VLM, set credentials, point at
endpoints, set platform-specific flags. Do not let existing shell env vars
silently pick placement; write the selected LLM_MODE / VLM_MODE and
matching endpoint/model fields into generated.env. The full mapping (every
override key, when it applies, defaults, profile-specific differences) lives
in references/env-overrides.md. Each profile
reference has worked examples for that profile's common scenarios.
Step 3 — Apply overrides + dry-run
Working env files: <repo>/deploy/docker/developer-profiles/dev-profile-<profile>/.env plus <repo>/deploy/docker/developer-profiles/dev-profile-<profile>/generated.env (created in Step 1c from overrides.env).
Reminder (see Step 1c): apply all overrides (Step 2 dict + Brev EXTERNAL_IP) to generated.env; Compose gets .env first and generated.env second, and post-deploy verifiers read generated.env for the actually-deployed override values.
cd $REPO/deploy/docker
docker compose --env-file $ENV_SRC --env-file $ENV_GEN config > resolved.yml
The resolved YAML is saved to <repo>/deploy/docker/resolved.yml.
Step 3b — Verify resolved.yml has no unexpanded ${...} tokens
Unexpanded ${VAR} tokens in resolved.yml mean compose did not see those env values. Diagnostic procedure and common culprits live in references/troubleshooting.md.
Step 3c — Verify access to selected NGC artifacts
After resolved.yml exists and before Compose starts, follow
references/credentials.md § Artifact Entitlement Probes.
Verify every selected container image, NGC model/resource path, and
profile-staged artifact. Authentication alone does not prove repository
entitlement. Any access failure is a blocker; do not start Compose.