Secure AI Agents with OpenShell
Isolate OpenClaw with kernel-level policies and route inference to a local model
Confirm your environment
Verify the OS, GPU, Docker, and Python are available before installing anything.
head -n 2 /etc/os-release
nvidia-smi
docker info --format '{{.ServerVersion}}'
python3 --version
Expected output should show Ubuntu 24.04 (or compatible DGX OS), a detected GPU, a Docker server version, and Python 3.12+. If you access the hardware remotely, ensure port 18789 is available for the OpenClaw dashboard.
Docker configuration
Verify that the local user has Docker permissions:
docker ps
If you get a permission denied error (permission denied while trying to connect to the docker API at unix:///var/run/docker.sock), add your user to the Docker group:
sudo usermod -aG docker $USER
newgrp docker
Reboot (or log out and back in) so the group membership applies to all sessions.
Configure Docker to use the NVIDIA Container Runtime:
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
Verify GPU access inside a container:
docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smi
Install the OpenShell CLI
Install OpenShell with the official installer, which installs the openshell CLI and registers the openshell-gateway systemd user service:
curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | sh
Open a new shell (or source ~/.bashrc) so openshell is on your PATH, then verify:
openshell --help
Expected output should show the openshell command tree with subcommands like gateway, sandbox, provider, and inference.
NOTE
Alternative install: uv venv openshell-env && source openshell-env/bin/activate && uv pip install openshell. If you use this path, activate the virtual environment in every new terminal before running openshell commands, and use openshell gateway start in Step 4 (the systemd unit is provided by the official installer).
Verify the OpenShell gateway
The official installer manages the gateway as a systemd user service. Confirm the service is running and the CLI can reach it:
systemctl --user status --no-pager openshell-gateway
openshell status
openshell status should report the gateway as Connected. If the service is not running, start it:
systemctl --user start openshell-gateway
To keep the gateway available after you log out:
sudo loginctl enable-linger $USER
Follow gateway logs in real time (press Ctrl+C to exit):
journalctl --user -u openshell-gateway -f
If you installed via uv (or the systemd unit is not present), start the gateway with the CLI instead:
openshell gateway start
openshell status
The first run may take a few minutes while Docker pulls images and the internal k3s cluster bootstraps.
TIP
To manage a gateway on remote hardware from a separate workstation, ensure passwordless SSH works first, then use openshell gateway start --remote <username>@<hostname> (or register an existing gateway per the OpenShell gateway docs).
Serve a model with vLLM
Serve an OpenAI-compatible API for local inference. Use the recommended model for your hardware platform from the Agent-ready Models tab.
Launch the matching recipe in a separate terminal, keeping --host 0.0.0.0 and port 8000 so the OpenShell gateway (inside Docker) can reach the server.
Once the server reports Application startup complete, verify it is reachable:
curl -s http://0.0.0.0:8000/v1/models
Expected: a JSON "data" array listing your model handle. Note the exact id — you will reuse it in Steps 6–7 and the OpenClaw wizard.
IMPORTANT
Do not bind the server to localhost only. The OpenShell gateway cannot reach host services via 127.0.0.1 from inside its container network.
Create an inference provider
Create an OpenShell provider that points to your local vLLM server.
Find the IP address of your hardware:
hostname -I | awk '{print $1}'
Create the provider, replacing {Machine_IP} with that address. vLLM does not require an API key, so any non-empty placeholder works:
openshell provider create \
--name local-vllm \
--type openai \
--credential OPENAI_API_KEY=not-needed \
--config OPENAI_BASE_URL=http://{Machine_IP}:8000/v1
IMPORTANT
Do not use localhost or 127.0.0.1 here. Use the machine's actual IP address. On some Linux Docker setups, http://host.docker.internal:8000/v1 is an equivalent alternative if that hostname resolves inside the gateway container.
Verify:
openshell provider list
Configure inference routing
Point the inference.local endpoint (available inside every sandbox) at your model. The model name must match the handle served in Step 5:
openshell inference set \
--provider local-vllm \
--model <MODEL_HANDLE>
Replace <MODEL_HANDLE> with the HuggingFace handle from the Agent-ready Models tab (for example nvidia/Qwen3.6-35B-A3B-NVFP4 or nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4).
NOTE
If you see failed to verify inference endpoint or failed to connect, confirm the server is healthy and warm up with one chat completion request. You can add --no-verify to skip endpoint verification after confirming reachability from the host.
Verify:
openshell inference get
Expected output should show provider: local-vllm and your chosen model.
Deploy the OpenShell sandbox
Create a sandbox using the pre-built OpenClaw community sandbox:
export SANDBOX_NAME=openshell-demo
openshell sandbox create \
--keep \
--forward 18789 \
--name "$SANDBOX_NAME" \
--from openclaw \
-- openclaw-start
NOTE
Do not pass --policy with a local file path when using --from openclaw. The policy is bundled with the community sandbox; a local file path can cause "file not found."
The --keep flag keeps the sandbox running after the initial process exits. To terminate when the initial process exits, use --no-keep instead.
The CLI will:
- Resolve
openclawagainst the community catalog - Pull and build the container image
- Apply the bundled sandbox policy
- Launch OpenClaw inside the sandbox
--forward 18789 registers the port-forward intent. Activate it explicitly:
openshell forward start --background 18789 "$SANDBOX_NAME"
openshell forward list
You should see your sandbox name with port 18789.
Configure OpenClaw within the sandbox
The OpenClaw onboarding wizard launches automatically in your terminal.
IMPORTANT
The onboarding wizard is fully interactive — it requires arrow-key navigation and Enter to select options. It cannot be completed from a non-interactive session. You must run openshell sandbox create from a terminal with full TTY support.
If the wizard did not complete during sandbox creation, reconnect:
openshell sandbox connect "$SANDBOX_NAME"
NOTE
If openshell sandbox get shows Phase: Unspecified, that is expected until the interactive wizard finishes. The sandbox container can still be healthy while the phase shows Unspecified. Confirm with supervisor logs if needed:
docker logs $(docker ps --filter name=openshell-"$SANDBOX_NAME" --format '{{.Names}}') --tail 20
Look for OpenShell Sandbox Supervisor success and Applying Landlock filesystem sandbox.
Use the arrow keys and Enter to complete onboarding:
- If you understand and agree, select Yes and press Enter.
- Quickstart vs Manual: select Quickstart.
- Model/auth Provider: select Custom Provider.
- API Base URL:
https://inference.local/v1 - How do you want to provide this API key?: Paste API key for now.
- API key: enter any non-empty placeholder (for example
vllmornot-needed). - Endpoint compatibility: select OpenAI-compatible.
- Model ID: enter the same handle you set in Step 7.
- Endpoint ID: leave the default.
- Alias: optional; you can reuse the model name.
- Channel: Skip for now.
- Search provider: Skip for now.
- Skills: No for now.
- Enable hooks: Skip for now / No, then press Enter.
After 1–2 minutes you should see a URL with a token:
OpenClaw gateway starting in background.
Logs: /tmp/gateway.log
UI: http://127.0.0.1:18789/?token=<unique-token>
Verify the sandbox:
openshell sandbox get "$SANDBOX_NAME"
Access the dashboard
On the hardware itself: open the UI URL from the wizard output in a local browser (right-click → Open Link when available).
From a remote workstation: ensure port forwarding is active (openshell forward list), then open:
http://127.0.0.1:18789/#token=<your-token>
If you manage the gateway from a remote machine, register it with hostname openshell (not the raw LAN IP) so TLS certificate validation succeeds — see the OpenShell gateway docs. Map openshell to the hardware IP in /etc/hosts on the workstation, then:
openshell gateway add https://openshell:8080 --remote <user>@<hardware-ip>
openshell forward start --background 18789 "$SANDBOX_NAME"
If the dashboard URL is only reachable inside the sandbox and the host forward is not active, you can also tunnel with the OpenShell SSH proxy (replace sandbox id, token, and gateway URL from your environment):
ssh -o ProxyCommand='openshell ssh-proxy --gateway https://127.0.0.1:17670/connect/ssh --sandbox-id <sandbox-id> --token <token> --gateway-name openshell' \
-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR \
-N -L 18789:127.0.0.1:18789 sandbox
Then open http://127.0.0.1:18789/?token=<your-token> in your local browser.
From the dashboard you can Chat with your OpenClaw agent inside the OpenShell sandbox.
Test inference inside the sandbox
Connect to the sandbox terminal:
openshell sandbox connect "$SANDBOX_NAME"
Test connectivity to the local model:
curl https://inference.local/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "<MODEL_HANDLE>",
"messages": [{"role": "user", "content": "Hello!"}]
}'
Replace <MODEL_HANDLE> with the same handle from Step 7.
Verify sandbox isolation
Open a second terminal and check live status and logs:
openshell term
The terminal dashboard shows:
- Sandbox status — name, phase, image, providers, and port forwards
- Live log stream — outbound connections, policy decisions (
allow,deny,inspect_for_inference), and inference interceptions
Verify that the agent can reach inference.local and that unauthorized outbound traffic is denied.
TIP
Press f to follow live output, s to filter by source, and q to quit.
Reconnect and transfer files
Reconnect at any time:
openshell sandbox connect "$SANDBOX_NAME"
NOTE
openshell sandbox connect is interactive-only. Use upload/download for file transfers, or openshell sandbox ssh-config for scripted SSH.
openshell sandbox upload "$SANDBOX_NAME" ./local-file /sandbox/destination
openshell sandbox download "$SANDBOX_NAME" /sandbox/file ./local-destination
Cleanup
Run gateway-dependent cleanup first, while the gateway is still reachable:
openshell sandbox delete "$SANDBOX_NAME"
openshell provider delete local-vllm
If you use the systemd user service (official installer):
systemctl --user stop openshell-gateway
systemctl --user disable openshell-gateway
sudo loginctl disable-linger $USER
If you started the gateway with the CLI instead:
openshell gateway stop
WARNING
The following command permanently removes the gateway cluster and all its data.
openshell gateway destroy
Stop and remove the vLLM container if you started one for this playbook (replace the name/image filter to match your launch):
docker stop vllm-server 2>/dev/null; docker rm vllm-server 2>/dev/null
Next steps
- Add more providers: Attach GitHub tokens, GitLab tokens, or cloud API keys with
openshell provider create, then pass--provider <name>when creating a sandbox. - Try other community sandboxes:
openshell sandbox create --from baseor--from sdg. - Connect VS Code: Use
openshell sandbox ssh-config <sandbox-name>and append the output to~/.ssh/config. - Monitor and audit: Use
openshell logs <sandbox-name> --tailoropenshell termto monitor agent activity and policy decisions.