Install NemoClaw / OpenClaw on DGX Spark Behind a Proxy
A practical step-by-step installation guide for DGX Spark users running Docker, OpenShell, NemoClaw, OpenClaw, local Ollama models, GPU passthrough, and a proxy such as Clash Verge.
<DGX_IP>, <SSH_USER>, and <MODEL_NAME> with your own values.
0. Replace placeholders
Use your own values before running commands.
export DGX_IP="<DGX_IP>"
export PROXY_PORT="<PROXY_PORT>"
export PROXY="http://${DGX_IP}:${PROXY_PORT}"
export SSH_USER="<SSH_USER>"
export OPENCLAW_GATEWAY_IMAGE="ghcr.io/nvidia/openshell/cluster:0.0.36"
export AIRGAP_IMAGE="localhost:5000/openshell-cluster-airgap:0.0.36"
export OLLAMA_MODEL="<MODEL_NAME>"
Example model names may include locally available Ollama models such as nemotron-3-super:120b, but use the model actually installed on your machine.
1. Check basic system status
hostname -I
node -v
npm -v
docker --version
nvidia-smi
Check Docker can see the NVIDIA GPU:
docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smi
If Docker cannot pull ubuntu, fix Docker proxy first.
2. Configure shell proxy and Git proxy
If your proxy runs on the DGX Spark host, make sure the proxy allows LAN access and use the host IP instead of 127.0.0.1 when containers need to reach it.
export http_proxy="${PROXY}"
export https_proxy="${PROXY}"
export HTTP_PROXY="${PROXY}"
export HTTPS_PROXY="${PROXY}"
export no_proxy="localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,100.64.0.0/10"
export NO_PROXY="$no_proxy"
Configure Git:
git config --global http.proxy "${PROXY}"
git config --global https.proxy "${PROXY}"
git config --global http.version HTTP/1.1
Test connectivity:
curl -x "${PROXY}" -I https://github.com --max-time 20
curl -x "${PROXY}" -I https://ghcr.io/v2/ --max-time 20
curl -x "${PROXY}" -I https://registry-1.docker.io/v2/ --max-time 20
git ls-remote https://github.com/NVIDIA/NemoClaw.git | head
For Docker Hub, HTTP/2 401 is normal. It means the registry is reachable but unauthenticated.
3. Configure Docker daemon proxy
Docker daemon does not automatically inherit shell proxy variables.
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf > /dev/null <<EOF
[Service]
Environment="HTTP_PROXY=${PROXY}"
Environment="HTTPS_PROXY=${PROXY}"
Environment="NO_PROXY=localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,100.64.0.0/10"
Environment="http_proxy=${PROXY}"
Environment="https_proxy=${PROXY}"
Environment="no_proxy=localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,100.64.0.0/10"
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
Verify without entering a pager:
systemctl --no-pager show --property=Environment docker
docker info | grep -i -E "proxy|http|https" || true
Test image pulls:
for i in 1 2 3; do
echo "=== test $i ==="
docker pull ghcr.io/nvidia/openshell/cluster:0.0.36
docker pull docker.io/rancher/mirrored-pause:3.6
done
4. Configure Docker container proxy
This makes newly created containers receive proxy environment variables.
mkdir -p ~/.docker
cat > ~/.docker/config.json <<EOF
{
"proxies": {
"default": {
"httpProxy": "${PROXY}",
"httpsProxy": "${PROXY}",
"noProxy": "localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,100.64.0.0/10"
}
}
}
EOF
Test:
docker run --rm --entrypoint env ghcr.io/nvidia/openshell/cluster:0.0.36 | grep -i proxy
Expected output should include HTTP_PROXY and HTTPS_PROXY.
5. Install NemoClaw CLI
curl -fsSL --retry 5 --retry-all-errors -L \
https://www.nvidia.com/nemoclaw.sh \
-o /tmp/nemoclaw_install.sh
ls -lh /tmp/nemoclaw_install.sh
head -n 20 /tmp/nemoclaw_install.sh
bash /tmp/nemoclaw_install.sh
Check installation:
source ~/.bashrc
which nemoclaw
nemoclaw --version
openshell --version
If GitHub cloning fails with TLS errors, repeat the proxy tests and confirm:
git ls-remote https://github.com/NVIDIA/NemoClaw.git | head
A Python externally-managed-environment warning may appear during model-router installation. In the tested workflow, it did not block the core NemoClaw CLI installation.
6. Why a custom airgap gateway image is needed
The OpenShell gateway is a Docker container that starts an embedded k3s cluster. Even when Docker daemon proxy is correct, the k3s/containerd inside the gateway may fail to pull required images.
Common failing images include:
rancher/mirrored-pause:3.6
rancher/mirrored-metrics-server:v0.8.1
rancher/local-path-provisioner:v0.0.35
rancher/klipper-helm:v0.9.14-build20260309
rancher/mirrored-coredns-coredns:1.14.2
registry.k8s.io/agent-sandbox/agent-sandbox-controller:v0.1.0
Typical errors include:
ImagePullBackOff
ErrImagePull
failed to pull
TLS handshake timeout
connection reset by peer
EOF
The robust fix is to preload these images into /var/lib/rancher/k3s/agent/images/ inside a custom OpenShell cluster image.
7. Pull all required k3s images
IMAGES=(
docker.io/rancher/mirrored-pause:3.6
docker.io/rancher/mirrored-metrics-server:v0.8.1
docker.io/rancher/local-path-provisioner:v0.0.35
docker.io/rancher/klipper-helm:v0.9.14-build20260309
docker.io/rancher/mirrored-coredns-coredns:1.14.2
registry.k8s.io/agent-sandbox/agent-sandbox-controller:v0.1.0
)
for img in "${IMAGES[@]}"; do
echo "=== pulling $img ==="
for i in 1 2 3 4 5; do
docker pull "$img" && break
echo "retry $i failed: $img"
sleep 5
done
done
Save them into one airgap tarball:
docker save \
docker.io/rancher/mirrored-pause:3.6 \
docker.io/rancher/mirrored-metrics-server:v0.8.1 \
docker.io/rancher/local-path-provisioner:v0.0.35 \
docker.io/rancher/klipper-helm:v0.9.14-build20260309 \
docker.io/rancher/mirrored-coredns-coredns:1.14.2 \
registry.k8s.io/agent-sandbox/agent-sandbox-controller:v0.1.0 \
-o /tmp/openshell-k3s-images-airgap.tar
ls -lh /tmp/openshell-k3s-images-airgap.tar
8. Build the custom OpenShell airgap image
mkdir -p /tmp/openshell-cluster-airgap
cp /tmp/openshell-k3s-images-airgap.tar /tmp/openshell-cluster-airgap/
cat > /tmp/openshell-cluster-airgap/Dockerfile <<EOF
FROM ghcr.io/nvidia/openshell/cluster:0.0.36
USER root
RUN mkdir -p /var/lib/rancher/k3s/agent/images
COPY openshell-k3s-images-airgap.tar \
/var/lib/rancher/k3s/agent/images/openshell-k3s-images-airgap.tar
ENV HTTP_PROXY=${PROXY}
ENV HTTPS_PROXY=${PROXY}
ENV http_proxy=${PROXY}
ENV https_proxy=${PROXY}
ENV NO_PROXY=localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,100.64.0.0/10
ENV no_proxy=localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,100.64.0.0/10
EOF
docker build \
-t local/openshell-cluster-airgap:0.0.36 \
-t localhost:5000/openshell-cluster-airgap:0.0.36 \
/tmp/openshell-cluster-airgap
Test the image:
docker run --rm --entrypoint sh local/openshell-cluster-airgap:0.0.36 -lc '
env | grep -i proxy
ls -lh /var/lib/rancher/k3s/agent/images/
'
9. Start a local Docker registry
OpenShell may try to docker pull the image. A pure local tag may be treated as a remote repository. Use a local registry instead.
docker rm -f local-registry 2>/dev/null || true
docker run -d \
--name local-registry \
--restart unless-stopped \
-p 5000:5000 \
registry:2
Check:
docker ps | grep local-registry
Push the airgap image:
docker push localhost:5000/openshell-cluster-airgap:0.0.36
docker pull localhost:5000/openshell-cluster-airgap:0.0.36
10. Start OpenShell gateway with GPU
Clean old state:
openshell gateway destroy --name nemoclaw || true
openshell gateway destroy -g nemoclaw || true
docker rm -f openshell-cluster-nemoclaw 2>/dev/null || true
docker volume ls -q --filter "name=openshell-cluster-nemoclaw" | xargs -r docker volume rm
Start gateway using the local registry image:
OPENSHELL_CLUSTER_IMAGE=localhost:5000/openshell-cluster-airgap:0.0.36 \
openshell gateway start --name nemoclaw --gpu
Expected success:
✓ Checking Docker
✓ Downloading gateway
✓ Initializing environment
✓ Starting gateway
✓ Gateway ready
Name: nemoclaw
Endpoint: https://127.0.0.1:8080
✓ Active gateway set to 'nemoclaw'
Verify image and health:
docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}" | grep openshell
docker inspect --format '{{.State.Health.Status}}' openshell-cluster-nemoclaw
Verify GPU passthrough:
docker inspect openshell-cluster-nemoclaw \
--format 'Image={{.Config.Image}} DeviceRequests={{json .HostConfig.DeviceRequests}}'
Inside logs, a good sign is:
Got registration request from device plugin with resourceName="nvidia.com/gpu"
11. Run NemoClaw onboarding
nemoclaw onboard --gpu
Recommended choices
Choose N at first. Enable it later after the core system works.
Skip Telegram, Discord, and Slack initially. Add them later when you have tokens ready.
Use Balanced, keep npm, pypi, huggingface, brew, brave, and local-inference.
Enable github if you want the sandbox to work with source repositories.
12. Access the OpenClaw UI
At the end of onboarding, NemoClaw should show something like:
OpenClaw UI
Dashboard: http://127.0.0.1:18789/
Token: nemoclaw my-assistant gateway-token --quiet
Get token:
nemoclaw my-assistant gateway-token --quiet
If your browser is on the DGX Spark machine, open:
http://127.0.0.1:18789/
If you are connecting from another computer, use SSH port forwarding from your local computer:
ssh -L 18789:127.0.0.1:18789 <SSH_USER>@<DGX_IP>
Then open locally:
http://127.0.0.1:18789/
If the browser asks for auth, append:
http://127.0.0.1:18789/#token=<your-token>
Do not publish your token.
13. Useful status commands
nemoclaw list
openshell gateway status
docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"
docker logs --tail=300 openshell-cluster-nemoclaw | \
grep -Ei "ImagePull|ErrImage|BackOff|failed to pull|EOF|error|failed|nvidia|gpu|openshell"
14. Troubleshooting
Problem: curl: SSL_ERROR_SYSCALL
curl -x "${PROXY}" -I https://registry-1.docker.io/v2/ --max-time 20
If Docker Hub returns 401, it is reachable.
Problem: git clone fails with gnutls_handshake()
git config --global http.proxy "${PROXY}"
git config --global https.proxy "${PROXY}"
git config --global http.version HTTP/1.1
Problem: Docker pull fails but curl works
Docker daemon needs its own proxy. Repeat Step 3.
Problem: New containers do not have proxy variables
docker run --rm --entrypoint env ghcr.io/nvidia/openshell/cluster:0.0.36 | grep -i proxy
Problem: OpenShell gateway uses default GHCR image instead of airgap image
docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}" | grep openshell
The image should be:
localhost:5000/openshell-cluster-airgap:0.0.36
Problem: pull access denied for local/openshell-cluster-airgap
Do not use a pure local image tag as OPENSHELL_CLUSTER_IMAGE. Use the local registry image:
localhost:5000/openshell-cluster-airgap:0.0.36
Problem: ImagePullBackOff inside gateway
Find the missing image:
docker logs --tail=300 openshell-cluster-nemoclaw | \
grep -Ei "ImagePull|ErrImage|BackOff|failed to pull|EOF|manifest"
Pull it on the host, add it to the docker save command in Step 7, rebuild the airgap image, push it to the local registry, and restart gateway.
Problem: Existing gateway was started without GPU passthrough
openshell gateway destroy --name nemoclaw || true
docker rm -f openshell-cluster-nemoclaw 2>/dev/null || true
docker volume ls -q --filter "name=openshell-cluster-nemoclaw" | xargs -r docker volume rm
OPENSHELL_CLUSTER_IMAGE=localhost:5000/openshell-cluster-airgap:0.0.36 \
openshell gateway start --name nemoclaw --gpu
nemoclaw onboard --gpu
Problem: Ollama reachability warning during onboarding
You may see a warning that local Ollama is responding on 127.0.0.1 but Docker container reachability failed. If NemoClaw still creates the provider and sets the inference route, continue and test inference after onboarding.
15. Final expected result
NemoClaw CLI installed
OpenShell gateway ready
GPU passthrough enabled
Ollama local inference provider configured
OpenClaw launched inside sandbox
OpenClaw UI available at http://127.0.0.1:18789/
Core commands for daily use:
openshell gateway status
nemoclaw list
nemoclaw my-assistant gateway-token --quiet