Copy NVIDIA NIM Images to Internal Quay Reg...
Pull NIM container images from nvcr.io and push to an internal Quay registry. Covers authentication, tagging, air-gapped workflows, and curl token issues.
π‘ Quick Answer: Use
podman pullfromnvcr.io, retag for your internal Quay, thenpodman push. For API token endpoints, ensure your JSON has no escaped backslashes inside single quotes and use the correct field capitalization (GrantTypenotgrantType).
The Problem
You need to deploy NVIDIA NIM containers (like DeepSeek-R1) on an OpenShift cluster that cannot pull directly from nvcr.io. Your organization uses an internal Quay registry, and all images must be promoted through a controlled pipeline. Along the way, you hit authentication issues with the platform API token endpoint and shell escaping problems with curl.
flowchart LR
NGC["nvcr.io<br/>(NVIDIA NGC)"] -->|podman pull| WS["Workstation"]
WS -->|podman tag| WS
WS -->|podman push| QUAY["Internal Quay<br/>Registry"]
QUAY -->|ImageStream| OCP["OpenShift<br/>Cluster"]The Solution
Step 1: Authenticate to NVIDIA NGC
# Login to NVIDIA NGC registry
# Username is always $oauthtoken
# Password is your NGC API key from https://ngc.nvidia.com/setup
podman login nvcr.io
# Username: $oauthtoken
# Password: <your-ngc-api-key>
# Login SucceededStep 2: Authenticate to Internal Quay
# Login to your internal Quay registry
podman login quay-int.registry.example.com
# Username: your-username (or robot account)
# Password: <your-token>
# Login SucceededStep 3: Pull the NIM Image
# Pull the specific NIM image
podman pull nvcr.io/nim/deepseek-ai/deepseek-r1:latest
# Verify the image is present
podman images | grep deepseek
# nvcr.io/nim/deepseek-ai/deepseek-r1 latest abc123... 11.5GBβ οΈ Pin by version, not
latestβ for production, always use a specific tag like1.7.3to avoid unexpected changes.
# Better: pull a pinned version
podman pull nvcr.io/nim/deepseek-ai/deepseek-r1:1.7.3Step 4: Retag for Internal Registry
# Tag for your internal Quay repository
podman tag \
nvcr.io/nim/deepseek-ai/deepseek-r1:1.7.3 \
quay-int.registry.example.com/ai-models/deepseek-r1:1.7.3Step 5: Push to Internal Quay
# Push to internal registry
podman push quay-int.registry.example.com/ai-models/deepseek-r1:1.7.3
# Verify in Quay UI or via API
podman search quay-int.registry.example.com/ai-models/deepseek-r1Step 6: Create OpenShift ImageStream (Optional)
apiVersion: image.openshift.io/v1
kind: ImageStream
metadata:
name: deepseek-r1
namespace: ai-workloads
spec:
lookupPolicy:
local: true
tags:
- name: "1.7.3"
from:
kind: DockerImage
name: quay-int.registry.example.com/ai-models/deepseek-r1:1.7.3
importPolicy:
scheduled: false
referencePolicy:
type: Localoc apply -f imagestream-deepseek.yaml
oc get is deepseek-r1 -n ai-workloadsBonus: Pin by Digest for Immutable References
# Get the exact digest
podman inspect nvcr.io/nim/deepseek-ai/deepseek-r1:1.7.3 \
--format '{{.Digest}}'
# sha256:a1b2c3d4e5f6...
# Tag with digest-based version
podman tag \
nvcr.io/nim/deepseek-ai/deepseek-r1@sha256:a1b2c3d4e5f6... \
quay-int.registry.example.com/ai-models/deepseek-r1:1.7.3
podman push quay-int.registry.example.com/ai-models/deepseek-r1:1.7.3Fixing curl Token Endpoint Issues
When authenticating to platform APIs (like Run:AI or other ML platforms), a common pattern is requesting an OAuth token via curl. Here are the most frequent pitfalls:
Problem 1: Trailing Spaces After Backslash
# β WRONG β trailing space after backslash breaks line continuation
curl -X POST 'https://api.platform.example.com/api/v1/token' \Β·
--header 'Content-Type: application/json' \Β·
--data-raw '{"grantType":"client_credentials"}'
# bash: --header: command not foundThe backslash (\) must be the very last character on the line β no trailing spaces.
# β
CORRECT β no spaces after backslash
curl -X POST 'https://api.platform.example.com/api/v1/token' \
-H 'Content-Type: application/json' \
-d '{"GrantType":"client_credentials","clientId":"my-client","clientSecret":"my-secret"}'Problem 2: Backslashes Inside Single-Quoted JSON
# β WRONG β backslashes inside single quotes become literal
curl -X POST 'https://api.platform.example.com/api/v1/token' \
-d '{ \
"GrantType":"client_credentials" \
}'
# Error: invalid character '\\' looking for beginning of object key stringSingle quotes in bash already protect everything β never add backslashes inside them:
# β
CORRECT β clean JSON inside single quotes
curl -X POST 'https://api.platform.example.com/api/v1/token' \
-H 'Content-Type: application/json' \
-d '{
"GrantType": "client_credentials",
"clientId": "my-client",
"clientSecret": "my-secret"
}'Problem 3: Case-Sensitive Field Names
Many OAuth endpoints are case-sensitive. grantType β GrantType:
# β May fail β wrong case
-d '{"grantType": "client_credentials"}'
# β
Check API docs for exact casing
-d '{"GrantType": "client_credentials"}'Debug Tip: Verbose Mode
# Add -v to see exactly what curl sends
curl -v -X POST 'https://api.platform.example.com/api/v1/token' \
-H 'Content-Type: application/json' \
-d '{"GrantType":"client_credentials","clientId":"my-client","clientSecret":"my-secret"}'
# Look for:
# > Content-Type: application/json
# > {"GrantType":"client_credentials",...}
# If you see backslashes in the body β your JSON is malformedAutomation Script: Bulk NIM Image Mirror
#!/bin/bash
# mirror-nim-images.sh β Pull NIM images from NGC and push to internal Quay
set -euo pipefail
INTERNAL_REGISTRY="quay-int.registry.example.com"
INTERNAL_ORG="ai-models"
# List of NIM images to mirror
IMAGES=(
"nvcr.io/nim/deepseek-ai/deepseek-r1:1.7.3"
"nvcr.io/nim/meta/llama-3.1-405b-instruct:1.5.2"
"nvcr.io/nim/meta/llama-3.1-70b-instruct:1.5.2"
)
for IMAGE in "${IMAGES[@]}"; do
# Extract name and tag
NAME=$(echo "$IMAGE" | awk -F'/' '{print $NF}' | cut -d: -f1)
TAG=$(echo "$IMAGE" | awk -F: '{print $NF}')
TARGET="${INTERNAL_REGISTRY}/${INTERNAL_ORG}/${NAME}:${TAG}"
echo "=== Mirroring ${IMAGE} β ${TARGET} ==="
# Pull
podman pull "$IMAGE"
# Tag
podman tag "$IMAGE" "$TARGET"
# Push
podman push "$TARGET"
echo "β
${NAME}:${TAG} mirrored successfully"
done
echo "=== All images mirrored ==="Common Issues
| Issue | Cause | Fix |
|---|---|---|
denied: requested access on push | Missing Quay permissions | Create repo first or grant robot account write access |
manifest unknown on pull | Tag doesnβt exist | List available tags: podman search --list-tags nvcr.io/nim/... |
x509: certificate signed by unknown authority | Internal Quay uses custom CA | Add CA to /etc/pki/ca-trust/ and run update-ca-trust |
invalid character '\\' in curl | Backslashes inside single-quoted JSON | Remove all \ from inside '...' blocks |
unsupported value '' for field 'GrantType' | Broken line continuation or wrong case | Fix trailing spaces after \, check field capitalization |
| Image too large for single pull | Multi-GB NIM images (10GB+) | Use --retry 3 flag, ensure sufficient disk space |
Best Practices
- Pin versions β never use
latestin production; pin to specific tags like1.7.3 - Pin by digest β for immutable references, use
@sha256:...notation - Use robot accounts β create dedicated Quay robot accounts for CI/CD image mirroring
- Mirror on schedule β automate with CronJobs or Tekton pipelines to keep images current
- Verify after push β always check the Quay UI or use
skopeo inspectto confirm - Use skopeo for air-gapped β
skopeo copycan transfer between registries without pulling locally - Clean up local images β remove pulled images after push to save disk:
podman rmi $IMAGE
Key Takeaways
- Pull NIM images from
nvcr.iowith your NGC API key, retag, and push to internal Quay - Always pin image versions for production deployments
- When using
curlfor API tokens: no trailing spaces after\, no backslashes inside single quotes, and check field name casing - Use
skopeo copyfor direct registry-to-registry transfer without local storage - Create OpenShift ImageStreams to reference internal registry images cleanly

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
