diff --git a/pr-preview/pr-677/about/architecture.json b/pr-preview/pr-677/about/architecture.json index 5fbc53b8e..374fb09d2 100644 --- a/pr-preview/pr-677/about/architecture.json +++ b/pr-preview/pr-677/about/architecture.json @@ -1 +1 @@ -{"id":"about/architecture","title":"How OpenShell Works","url":"about/architecture.html","last_modified":"2026-03-30T18:03:24.369520+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"OpenShell architecture overview covering the gateway, sandbox, policy engine, and privacy router.","tags":["AI Agents","Sandboxing","Security","Architecture"],"topics":["Generative AI","Cybersecurity"],"content_type":"concept","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"How OpenShell Works OpenShell runs inside a Docker container. Each sandbox is an isolated environment managed through the gateway. Four components work together to keep agents secure. Components The following table describes each component and its role in the system: Component Role Gateway Control-plane API that coordinates sandbox lifecycle and state, acts as the auth boundary, and brokers requests across the platform. Sandbox Isolated runtime that includes container supervision and policy-enforced egress routing. Policy Engine Policy definition and enforcement layer for filesystem, network, and process constraints. Defense in depth enforces policies from the application layer down to infrastructure and kernel layers. Privacy Router Privacy-aware LLM routing layer that keeps sensitive context on sandbox compute and routes based on cost and privacy policy. How a Request Flows Every outbound connection from agent code passes through the same decision path: The agent process opens an outbound connection (API call, package install, git clone, and so on). The proxy inside the sandbox intercepts the connection and identifies which binary opened it. If the target is https://inference.local , the proxy handles it as managed inference before policy evaluation. OpenShell strips sandbox-supplied credentials, injects the configured backend credentials, and forwards the request to the managed model endpoint. For every other destination, the proxy queries the policy engine with the destination, port, and calling binary. The policy engine returns one of two decisions: Allow - the destination and binary match a policy block. Traffic flows directly to the external service. Deny - no policy block matched. The connection is blocked and logged. For REST endpoints with TLS termination enabled, the proxy also decrypts TLS and checks each HTTP request against per-method, per-path rules before allowing it through. Deployment Modes OpenShell can run locally, on a remote host, or behind a cloud proxy. The architecture is identical in all cases — only the Docker container location and authentication mode change. Mode Description Command Local The gateway runs inside Docker on your workstation. The CLI provisions it automatically on first use. openshell gateway start Remote The gateway runs on a remote host via SSH. Only Docker is required on the remote machine. openshell gateway start --remote user@host Cloud A gateway already running behind a reverse proxy (e.g. Cloudflare Access). Register and authenticate via browser. openshell gateway add https://gateway.example.com You can register multiple gateways and switch between them with openshell gateway select . For the full deployment and management workflow, refer to the Gateways section. Next Steps Continue with one of the following: To deploy or register a gateway, refer to Gateways . To create your first sandbox, refer to the Quickstart . To learn how OpenShell enforces isolation across all protection layers, refer to Sandboxes","format":"text","summary":"OpenShell runs inside a Docker container. Each sandbox is an isolated environment managed through the gateway. Four components work together to keep agents secure.","headings":[{"text":"How OpenShell Works","level":1},{"text":"Components","level":2},{"text":"How a Request Flows","level":2},{"text":"Deployment Modes","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file +{"id":"about/architecture","title":"How OpenShell Works","url":"about/architecture.html","last_modified":"2026-03-30T18:08:14.776034+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"OpenShell architecture overview covering the gateway, sandbox, policy engine, and privacy router.","tags":["AI Agents","Sandboxing","Security","Architecture"],"topics":["Generative AI","Cybersecurity"],"content_type":"concept","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"How OpenShell Works OpenShell runs inside a Docker container. Each sandbox is an isolated environment managed through the gateway. Four components work together to keep agents secure. Components The following table describes each component and its role in the system: Component Role Gateway Control-plane API that coordinates sandbox lifecycle and state, acts as the auth boundary, and brokers requests across the platform. Sandbox Isolated runtime that includes container supervision and policy-enforced egress routing. Policy Engine Policy definition and enforcement layer for filesystem, network, and process constraints. Defense in depth enforces policies from the application layer down to infrastructure and kernel layers. Privacy Router Privacy-aware LLM routing layer that keeps sensitive context on sandbox compute and routes based on cost and privacy policy. How a Request Flows Every outbound connection from agent code passes through the same decision path: The agent process opens an outbound connection (API call, package install, git clone, and so on). The proxy inside the sandbox intercepts the connection and identifies which binary opened it. If the target is https://inference.local , the proxy handles it as managed inference before policy evaluation. OpenShell strips sandbox-supplied credentials, injects the configured backend credentials, and forwards the request to the managed model endpoint. For every other destination, the proxy queries the policy engine with the destination, port, and calling binary. The policy engine returns one of two decisions: Allow - the destination and binary match a policy block. Traffic flows directly to the external service. Deny - no policy block matched. The connection is blocked and logged. For REST endpoints with TLS termination enabled, the proxy also decrypts TLS and checks each HTTP request against per-method, per-path rules before allowing it through. Deployment Modes OpenShell can run locally, on a remote host, or behind a cloud proxy. The architecture is identical in all cases — only the Docker container location and authentication mode change. Mode Description Command Local The gateway runs inside Docker on your workstation. The CLI provisions it automatically on first use. openshell gateway start Remote The gateway runs on a remote host via SSH. Only Docker is required on the remote machine. openshell gateway start --remote user@host Cloud A gateway already running behind a reverse proxy (e.g. Cloudflare Access). Register and authenticate via browser. openshell gateway add https://gateway.example.com You can register multiple gateways and switch between them with openshell gateway select . For the full deployment and management workflow, refer to the Gateways section. Next Steps Continue with one of the following: To deploy or register a gateway, refer to Gateways . To create your first sandbox, refer to the Quickstart . To learn how OpenShell enforces isolation across all protection layers, refer to Sandboxes","format":"text","summary":"OpenShell runs inside a Docker container. Each sandbox is an isolated environment managed through the gateway. Four components work together to keep agents secure.","headings":[{"text":"How OpenShell Works","level":1},{"text":"Components","level":2},{"text":"How a Request Flows","level":2},{"text":"Deployment Modes","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file diff --git a/pr-preview/pr-677/about/overview.json b/pr-preview/pr-677/about/overview.json index 8d025ef8b..72a336363 100644 --- a/pr-preview/pr-677/about/overview.json +++ b/pr-preview/pr-677/about/overview.json @@ -1 +1 @@ -{"id":"about/overview","title":"Overview of NVIDIA OpenShell","url":"about/overview.html","last_modified":"2026-03-30T18:03:24.379390+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"OpenShell is the safe, private runtime for autonomous AI agents. Run agents in sandboxed environments that protect your data, credentials, and infrastructure.","tags":["AI Agents","Sandboxing","Security","Privacy","Inference Routing"],"topics":["Generative AI","Cybersecurity"],"content_type":"concept","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Overview of NVIDIA OpenShell NVIDIA OpenShell is an open-source runtime for executing autonomous AI agents in sandboxed environments with kernel-level isolation. It combines sandbox runtime controls and a declarative YAML policy so teams can run agents without giving them unrestricted access to local files, credentials, and external networks. Why OpenShell Exists AI agents are most useful when they can read files, install packages, call APIs, and use credentials. That same access can create material risk. OpenShell is designed for this tradeoff: preserve agent capability while enforcing explicit controls over what the agent can access. Common Risks and Controls The table below summarizes common failure modes and how OpenShell mitigates them. Threat Without controls With OpenShell Data exfiltration Agent uploads source code or internal files to unauthorized endpoints. Network policies allow only approved destinations; other outbound traffic is denied. Credential theft Agent reads local secrets such as SSH keys or cloud credentials. Filesystem restrictions (Landlock) confine access to declared paths only. Unauthorized API usage Agent sends prompts or data to unapproved model providers. Privacy routing and network policies control where inference traffic can go. Privilege escalation Agent attempts sudo , setuid paths, or dangerous syscall behavior. Unprivileged process identity and seccomp restrictions block escalation paths. Protection Layers at a Glance OpenShell applies defense in depth across the following policy domains. Layer What it protects When it applies Filesystem Prevents reads/writes outside allowed paths. Locked at sandbox creation. Network Blocks unauthorized outbound connections. Hot-reloadable at runtime. Process Blocks privilege escalation and dangerous syscalls. Locked at sandbox creation. Inference Reroutes model API calls to controlled backends. Hot-reloadable at runtime. For details, refer to Sandbox Policies and Customize Sandbox Policies . Common Use Cases OpenShell supports a range of agent deployment patterns. Use Case Description Secure coding agents Run Claude Code, OpenCode, or OpenClaw with constrained file and network access. Private enterprise development Route inference to self-hosted or private backends while keeping sensitive context under your control. Compliance and audit Treat policy YAML as version-controlled security controls that can be reviewed and audited. Reusable environments Use community sandbox images or bring your own containerized runtime. Next Steps Explore these topics to go deeper: To understand the components that make up the OpenShell runtime, refer to the Architecture Overview . To install the CLI and create your first sandbox, refer to the Quickstart . To learn how OpenShell enforces isolation across all protection layers, refer to Sandboxes","format":"text","summary":"NVIDIA OpenShell is an open-source runtime for executing autonomous AI agents in sandboxed environments with kernel-level isolation. It combines sandbox runtime controls and a declarative YAML policy so teams can run agents without giving them unrestricted access to local files, credentials, and ...","headings":[{"text":"Overview of NVIDIA OpenShell","level":1},{"text":"Why OpenShell Exists","level":2},{"text":"Common Risks and Controls","level":2},{"text":"Protection Layers at a Glance","level":2},{"text":"Common Use Cases","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file +{"id":"about/overview","title":"Overview of NVIDIA OpenShell","url":"about/overview.html","last_modified":"2026-03-30T18:08:14.783524+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"OpenShell is the safe, private runtime for autonomous AI agents. Run agents in sandboxed environments that protect your data, credentials, and infrastructure.","tags":["AI Agents","Sandboxing","Security","Privacy","Inference Routing"],"topics":["Generative AI","Cybersecurity"],"content_type":"concept","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Overview of NVIDIA OpenShell NVIDIA OpenShell is an open-source runtime for executing autonomous AI agents in sandboxed environments with kernel-level isolation. It combines sandbox runtime controls and a declarative YAML policy so teams can run agents without giving them unrestricted access to local files, credentials, and external networks. Why OpenShell Exists AI agents are most useful when they can read files, install packages, call APIs, and use credentials. That same access can create material risk. OpenShell is designed for this tradeoff: preserve agent capability while enforcing explicit controls over what the agent can access. Common Risks and Controls The table below summarizes common failure modes and how OpenShell mitigates them. Threat Without controls With OpenShell Data exfiltration Agent uploads source code or internal files to unauthorized endpoints. Network policies allow only approved destinations; other outbound traffic is denied. Credential theft Agent reads local secrets such as SSH keys or cloud credentials. Filesystem restrictions (Landlock) confine access to declared paths only. Unauthorized API usage Agent sends prompts or data to unapproved model providers. Privacy routing and network policies control where inference traffic can go. Privilege escalation Agent attempts sudo , setuid paths, or dangerous syscall behavior. Unprivileged process identity and seccomp restrictions block escalation paths. Protection Layers at a Glance OpenShell applies defense in depth across the following policy domains. Layer What it protects When it applies Filesystem Prevents reads/writes outside allowed paths. Locked at sandbox creation. Network Blocks unauthorized outbound connections. Hot-reloadable at runtime. Process Blocks privilege escalation and dangerous syscalls. Locked at sandbox creation. Inference Reroutes model API calls to controlled backends. Hot-reloadable at runtime. For details, refer to Sandbox Policies and Customize Sandbox Policies . Common Use Cases OpenShell supports a range of agent deployment patterns. Use Case Description Secure coding agents Run Claude Code, OpenCode, or OpenClaw with constrained file and network access. Private enterprise development Route inference to self-hosted or private backends while keeping sensitive context under your control. Compliance and audit Treat policy YAML as version-controlled security controls that can be reviewed and audited. Reusable environments Use community sandbox images or bring your own containerized runtime. Next Steps Explore these topics to go deeper: To understand the components that make up the OpenShell runtime, refer to the Architecture Overview . To install the CLI and create your first sandbox, refer to the Quickstart . To learn how OpenShell enforces isolation across all protection layers, refer to Sandboxes","format":"text","summary":"NVIDIA OpenShell is an open-source runtime for executing autonomous AI agents in sandboxed environments with kernel-level isolation. It combines sandbox runtime controls and a declarative YAML policy so teams can run agents without giving them unrestricted access to local files, credentials, and ...","headings":[{"text":"Overview of NVIDIA OpenShell","level":1},{"text":"Why OpenShell Exists","level":2},{"text":"Common Risks and Controls","level":2},{"text":"Protection Layers at a Glance","level":2},{"text":"Common Use Cases","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file diff --git a/pr-preview/pr-677/about/release-notes.json b/pr-preview/pr-677/about/release-notes.json index 5564295a0..3816c9739 100644 --- a/pr-preview/pr-677/about/release-notes.json +++ b/pr-preview/pr-677/about/release-notes.json @@ -1 +1 @@ -{"id":"about/release-notes","title":"NVIDIA OpenShell Release Notes","url":"about/release-notes.html","last_modified":"2026-03-30T18:03:24.394656+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Track the latest changes and improvements to NVIDIA OpenShell.","tags":["Release Notes","Changelog","AI Agents"],"topics":["Generative AI","Cybersecurity"],"content_type":"reference","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"NVIDIA OpenShell Release Notes NVIDIA OpenShell follows a frequent release cadence. Use the following GitHub resources directly. Resource Description Releases Versioned release notes and downloadable assets. Release comparison Diff between any two tags or branches. Merged pull requests Individual changes with review discussion. Commit history Full commit log on main","format":"text","summary":"NVIDIA OpenShell follows a frequent release cadence. Use the following GitHub resources directly.","headings":[{"text":"NVIDIA OpenShell Release Notes","level":1}]} \ No newline at end of file +{"id":"about/release-notes","title":"NVIDIA OpenShell Release Notes","url":"about/release-notes.html","last_modified":"2026-03-30T18:08:14.786041+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Track the latest changes and improvements to NVIDIA OpenShell.","tags":["Release Notes","Changelog","AI Agents"],"topics":["Generative AI","Cybersecurity"],"content_type":"reference","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"NVIDIA OpenShell Release Notes NVIDIA OpenShell follows a frequent release cadence. Use the following GitHub resources directly. Resource Description Releases Versioned release notes and downloadable assets. Release comparison Diff between any two tags or branches. Merged pull requests Individual changes with review discussion. Commit history Full commit log on main","format":"text","summary":"NVIDIA OpenShell follows a frequent release cadence. Use the following GitHub resources directly.","headings":[{"text":"NVIDIA OpenShell Release Notes","level":1}]} \ No newline at end of file diff --git a/pr-preview/pr-677/about/supported-agents.json b/pr-preview/pr-677/about/supported-agents.json index f8f1bc0cf..1a0c87147 100644 --- a/pr-preview/pr-677/about/supported-agents.json +++ b/pr-preview/pr-677/about/supported-agents.json @@ -1 +1 @@ -{"id":"about/supported-agents","title":"Supported Agents","url":"about/supported-agents.html","last_modified":"2026-03-30T18:03:24.397008+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"content":"Supported Agents The following table summarizes the agents that run in OpenShell sandboxes. All agent sandbox images are maintained in the OpenShell Community repository. Agents in the base image are auto-configured when passed as the trailing command to openshell sandbox create . Agent Source Default Policy Notes Claude Code base Full coverage Works out of the box. Requires ANTHROPIC_API_KEY . OpenCode base Partial coverage Pre-installed. Add opencode.ai endpoint and OpenCode binary paths to the policy for full functionality. Codex base No coverage Pre-installed. Requires a custom policy with OpenAI endpoints and Codex binary paths. Requires OPENAI_API_KEY . GitHub Copilot CLI base Full coverage Pre-installed. Works out of the box. Requires GITHUB_TOKEN or COPILOT_GITHUB_TOKEN . OpenClaw openclaw Bundled Agent orchestration layer. Launch with openshell sandbox create --from openclaw . Ollama ollama Bundled Run cloud and local models. Includes Claude Code, Codex, and OpenCode. Launch with openshell sandbox create --from ollama . More community agent sandboxes are available in the ../sandboxes/community-sandboxes catalog. For a complete support matrix, refer to the ../reference/support-matrix page","format":"text","summary":"The following table summarizes the agents that run in OpenShell sandboxes. All agent sandbox images are maintained in the OpenShell Community repository. Agents in the base image are auto-configured when passed as the trailing command to openshell sandbox create.","headings":[{"text":"Supported Agents","level":1}]} \ No newline at end of file +{"id":"about/supported-agents","title":"Supported Agents","url":"about/supported-agents.html","last_modified":"2026-03-30T18:08:14.791831+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"content":"Supported Agents The following table summarizes the agents that run in OpenShell sandboxes. All agent sandbox images are maintained in the OpenShell Community repository. Agents in the base image are auto-configured when passed as the trailing command to openshell sandbox create . Agent Source Default Policy Notes Claude Code base Full coverage Works out of the box. Requires ANTHROPIC_API_KEY . OpenCode base Partial coverage Pre-installed. Add opencode.ai endpoint and OpenCode binary paths to the policy for full functionality. Codex base No coverage Pre-installed. Requires a custom policy with OpenAI endpoints and Codex binary paths. Requires OPENAI_API_KEY . GitHub Copilot CLI base Full coverage Pre-installed. Works out of the box. Requires GITHUB_TOKEN or COPILOT_GITHUB_TOKEN . OpenClaw openclaw Bundled Agent orchestration layer. Launch with openshell sandbox create --from openclaw . Ollama ollama Bundled Run cloud and local models. Includes Claude Code, Codex, and OpenCode. Launch with openshell sandbox create --from ollama . More community agent sandboxes are available in the ../sandboxes/community-sandboxes catalog. For a complete support matrix, refer to the ../reference/support-matrix page","format":"text","summary":"The following table summarizes the agents that run in OpenShell sandboxes. All agent sandbox images are maintained in the OpenShell Community repository. Agents in the base image are auto-configured when passed as the trailing command to openshell sandbox create.","headings":[{"text":"Supported Agents","level":1}]} \ No newline at end of file diff --git a/pr-preview/pr-677/get-started/quickstart.json b/pr-preview/pr-677/get-started/quickstart.json index cc759f606..2889cd630 100644 --- a/pr-preview/pr-677/get-started/quickstart.json +++ b/pr-preview/pr-677/get-started/quickstart.json @@ -1 +1 @@ -{"id":"get-started/quickstart","title":"Quickstart","url":"get-started/quickstart.html","last_modified":"2026-03-30T18:03:24.400901+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Install the OpenShell CLI and create your first sandboxed AI agent in two commands.","tags":["AI Agents","Sandboxing","Installation","Quickstart"],"topics":["Generative AI","Cybersecurity"],"content_type":"get_started","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Quickstart This page gets you from zero to a running, policy-enforced sandbox in two commands. Prerequisites Before you begin, make sure you have: Docker Desktop running on your machine. For a complete list of requirements, refer to ../reference/support-matrix . Install the OpenShell CLI Run the install script: $ curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | sh\nIf you prefer uv : $ uv tool install -U openshell\nAfter installing the CLI, run openshell --help in your terminal to see the full CLI reference, including all commands and flags. You can also clone the NVIDIA OpenShell GitHub repository and use the /openshell-cli skill to load the CLI reference into your agent. Create Your First OpenShell Sandbox Create a sandbox and launch an agent inside it\nChoose the tab that matches your agent: Claude Code Run the following command to create a sandbox with Claude Code: $ openshell sandbox create -- claude\nThe CLI prompts you to create a provider from local credentials\nType yes to continue\nIf ANTHROPIC_API_KEY is set in your environment, the CLI picks it up automatically\nIf not, you can configure it from inside the sandbox after it launches. OpenCode Run the following command to create a sandbox with OpenCode: $ openshell sandbox create -- opencode\nThe CLI prompts you to create a provider from local credentials\nType yes to continue\nIf OPENAI_API_KEY or OPENROUTER_API_KEY is set in your environment, the CLI picks it up automatically\nIf not, you can configure it from inside the sandbox after it launches. Codex Run the following command to create a sandbox with Codex: $ openshell sandbox create -- codex\nThe CLI prompts you to create a provider from local credentials\nType yes to continue\nIf OPENAI_API_KEY is set in your environment, the CLI picks it up automatically\nIf not, you can configure it from inside the sandbox after it launches. OpenClaw Run the following command to create a sandbox with OpenClaw: $ openshell sandbox create --from openclaw\nThe --from flag pulls a pre-built sandbox definition from the OpenShell Community catalog\nEach definition bundles a container image, a tailored policy, and optional skills into a single package. Community Sandbox Use the --from flag to pull other OpenShell sandbox images from the NVIDIA Container Registry\nFor example, to pull the base image, run the following command: $ openshell sandbox create --from base\nDeploy a Gateway (Optional) Running openshell sandbox create without a gateway auto-bootstraps a local one\nTo start the gateway explicitly or deploy to a remote host, choose the tab that matches your setup. Brev Deploy an OpenShell gateway on Brev by clicking Deploy on the OpenShell Launchable . After the instance starts running, find the gateway URL in the Brev console under Using Secure Links\nCopy the shareable URL for port 8080 , which is the gateway endpoint. $ openshell gateway add https://.brevlab.com\nopenshell status\nDGX Spark Set up your Spark with NVIDIA Sync first, or make sure SSH access is configured (such as SSH keys added to the host). Deploy to a DGX Spark machine over SSH: $ openshell gateway start --remote @.local\nopenshell status\nAfter openshell status shows the gateway as healthy, all subsequent commands route through the SSH tunnel","format":"text","summary":"This page gets you from zero to a running, policy-enforced sandbox in two commands.","headings":[{"text":"Quickstart","level":1},{"text":"Prerequisites","level":2},{"text":"Install the OpenShell CLI","level":2},{"text":"Create Your First OpenShell Sandbox","level":2},{"text":"Deploy a Gateway (Optional)","level":2}]} \ No newline at end of file +{"id":"get-started/quickstart","title":"Quickstart","url":"get-started/quickstart.html","last_modified":"2026-03-30T18:08:14.796455+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Install the OpenShell CLI and create your first sandboxed AI agent in two commands.","tags":["AI Agents","Sandboxing","Installation","Quickstart"],"topics":["Generative AI","Cybersecurity"],"content_type":"get_started","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Quickstart This page gets you from zero to a running, policy-enforced sandbox in two commands. Prerequisites Before you begin, make sure you have: Docker Desktop running on your machine. For a complete list of requirements, refer to ../reference/support-matrix . Install the OpenShell CLI Run the install script: $ curl -LsSf https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | sh\nIf you prefer uv : $ uv tool install -U openshell\nAfter installing the CLI, run openshell --help in your terminal to see the full CLI reference, including all commands and flags. You can also clone the NVIDIA OpenShell GitHub repository and use the /openshell-cli skill to load the CLI reference into your agent. Create Your First OpenShell Sandbox Create a sandbox and launch an agent inside it\nChoose the tab that matches your agent: Claude Code Run the following command to create a sandbox with Claude Code: $ openshell sandbox create -- claude\nThe CLI prompts you to create a provider from local credentials\nType yes to continue\nIf ANTHROPIC_API_KEY is set in your environment, the CLI picks it up automatically\nIf not, you can configure it from inside the sandbox after it launches. OpenCode Run the following command to create a sandbox with OpenCode: $ openshell sandbox create -- opencode\nThe CLI prompts you to create a provider from local credentials\nType yes to continue\nIf OPENAI_API_KEY or OPENROUTER_API_KEY is set in your environment, the CLI picks it up automatically\nIf not, you can configure it from inside the sandbox after it launches. Codex Run the following command to create a sandbox with Codex: $ openshell sandbox create -- codex\nThe CLI prompts you to create a provider from local credentials\nType yes to continue\nIf OPENAI_API_KEY is set in your environment, the CLI picks it up automatically\nIf not, you can configure it from inside the sandbox after it launches. OpenClaw Run the following command to create a sandbox with OpenClaw: $ openshell sandbox create --from openclaw\nThe --from flag pulls a pre-built sandbox definition from the OpenShell Community catalog\nEach definition bundles a container image, a tailored policy, and optional skills into a single package. Community Sandbox Use the --from flag to pull other OpenShell sandbox images from the NVIDIA Container Registry\nFor example, to pull the base image, run the following command: $ openshell sandbox create --from base\nDeploy a Gateway (Optional) Running openshell sandbox create without a gateway auto-bootstraps a local one\nTo start the gateway explicitly or deploy to a remote host, choose the tab that matches your setup. Brev Deploy an OpenShell gateway on Brev by clicking Deploy on the OpenShell Launchable . After the instance starts running, find the gateway URL in the Brev console under Using Secure Links\nCopy the shareable URL for port 8080 , which is the gateway endpoint. $ openshell gateway add https://.brevlab.com\nopenshell status\nDGX Spark Set up your Spark with NVIDIA Sync first, or make sure SSH access is configured (such as SSH keys added to the host). Deploy to a DGX Spark machine over SSH: $ openshell gateway start --remote @.local\nopenshell status\nAfter openshell status shows the gateway as healthy, all subsequent commands route through the SSH tunnel","format":"text","summary":"This page gets you from zero to a running, policy-enforced sandbox in two commands.","headings":[{"text":"Quickstart","level":1},{"text":"Prerequisites","level":2},{"text":"Install the OpenShell CLI","level":2},{"text":"Create Your First OpenShell Sandbox","level":2},{"text":"Deploy a Gateway (Optional)","level":2}]} \ No newline at end of file diff --git a/pr-preview/pr-677/inference/configure.json b/pr-preview/pr-677/inference/configure.json index a8d9ca2f6..775ad8310 100644 --- a/pr-preview/pr-677/inference/configure.json +++ b/pr-preview/pr-677/inference/configure.json @@ -1 +1 @@ -{"id":"inference/configure","title":"Configure Inference Routing","url":"inference/configure.html","last_modified":"2026-03-30T18:03:24.416744+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Set up the managed local inference endpoint with provider credentials and model configuration.","tags":["Inference Routing","Configuration","Privacy","LLM","Provider"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_intermediate","audience":["engineer"],"content":"Configure Inference Routing This page covers the managed local inference endpoint ( https://inference.local ). External inference endpoints go through sandbox network_policies . Refer to Policies for details. The configuration consists of two values: Value Description Provider record The credential backend OpenShell uses to authenticate with the upstream model host. Model ID The model to use for generation requests. For a list of tested providers and their base URLs, refer to Supported Inference Providers . Create a Provider Create a provider that holds the backend credentials you want OpenShell to use. NVIDIA API Catalog $ openshell provider create --name nvidia-prod --type nvidia --from-existing\nThis reads NVIDIA_API_KEY from your environment. OpenAI-compatible Provider Any cloud provider that exposes an OpenAI-compatible API works with the openai provider type. You need three values from the provider: the base URL, an API key, and a model name. $ openshell provider create\nname my-cloud-provider\ntype openai\ncredential OPENAI_API_KEY=\nconfig OPENAI_BASE_URL=https://api.example.com/v1\nReplace the base URL and API key with the values from your provider. For supported providers out of the box, refer to Supported Inference Providers . For other providers, refer to your provider’s documentation for the correct base URL, available models, and API key setup. Local Endpoint $ openshell provider create\nname my-local-model\ntype openai\ncredential OPENAI_API_KEY=empty-if-not-required\nconfig OPENAI_BASE_URL=http://host.openshell.internal:11434/v1\nUse --config OPENAI_BASE_URL to point to any OpenAI-compatible server running where the gateway runs. For host-backed local inference, use host.openshell.internal or the host’s LAN IP. Avoid 127.0.0.1 and localhost . Set OPENAI_API_KEY to a dummy value if the server does not require authentication. For a self-contained setup, the Ollama community sandbox bundles Ollama inside the sandbox itself — no host-level provider needed. See /tutorials/inference-ollama for details. Ollama also supports cloud-hosted models using the :cloud tag suffix (e.g., qwen3.5:cloud ). Anthropic $ openshell provider create --name anthropic-prod --type anthropic --from-existing\nThis reads ANTHROPIC_API_KEY from your environment. Set Inference Routing Point inference.local at that provider and choose the model to use: $ openshell inference set\nprovider nvidia-prod\nmodel nvidia/nemotron-3-nano-30b-a3b\nVerify the Active Config Confirm that the provider and model are set correctly: $ openshell inference get\nGateway inference\nProvider: nvidia-prod\nModel: nvidia/nemotron-3-nano-30b-a3b\nVersion: 1\nUpdate Part of the Config Use update when you want to change only one field: $ openshell inference update --model nvidia/nemotron-3-nano-30b-a3b\nOr switch providers without repeating the current model: $ openshell inference update --provider openai-prod\nUse the Local Endpoint from a Sandbox After inference is configured, code inside any sandbox can call https://inference.local directly: from openai import OpenAI\nclient = OpenAI(base_url=\"https://inference.local/v1\", api_key=\"unused\nresponse = client.chat.completions.create\nmodel=\"anything\nmessages=[{\"role\": \"user\", \"content\": \"Hello\nThe client-supplied model and api_key values are not sent upstream. The privacy router injects the real credentials from the configured provider and rewrites the model before forwarding. Some SDKs require a non-empty API key even though inference.local does not use the sandbox-provided value. In those cases, pass any placeholder such as test or unused . Use this endpoint when inference should stay local to the host for privacy and security reasons. External providers that should be reached directly belong in network_policies instead. When the upstream runs on the same machine as the gateway, bind it to 0.0.0.0 and point the provider at host.openshell.internal or the host’s LAN IP. 127.0.0.1 and localhost usually fail because the request originates from the gateway or sandbox runtime, not from your shell. If the gateway runs on a remote host or behind a cloud deployment, host.openshell.internal points to that remote machine, not to your laptop. A locally running Ollama or vLLM process is not reachable from a remote gateway unless you add your own tunnel or shared network path. Ollama also supports cloud-hosted models that do not require local hardware. Verify the Endpoint from a Sandbox openshell inference set and openshell inference update verify the resolved upstream endpoint by default before saving the configuration. If the endpoint is not live yet, retry with --no-verify to persist the route without the probe. openshell inference get confirms the current saved configuration. To confirm end-to-end connectivity from a sandbox, run: curl https://inference.local/v1/responses\nH \"Content-Type: application/json\"\nd\ninstructions\": \"You are a helpful assistant\ninput\": \"Hello\nA successful response confirms the privacy router can reach the configured backend and the model is serving requests. Gateway-scoped: Every sandbox using the active gateway sees the same inference.local backend. HTTPS only: inference.local is intercepted only for HTTPS traffic. Hot reload: Provider and inference changes are picked up within about 5 seconds by default. Next Steps Explore related topics: To understand the inference routing flow and supported API patterns, refer to index . To follow a complete Ollama-based local setup, refer to /tutorials/inference-ollama . To follow a complete LM Studio-based local setup, refer to /tutorials/local-inference-lmstudio . To control external endpoints, refer to Policies . To manage provider records, refer to ../sandboxes/manage-providers","format":"text","summary":"This page covers the managed local inference endpoint (https://inference.local). External inference endpoints go through sandbox network_policies. Refer to Policies for details.","headings":[{"text":"Configure Inference Routing","level":1},{"text":"Create a Provider","level":2},{"text":"Set Inference Routing","level":2},{"text":"Verify the Active Config","level":2},{"text":"Update Part of the Config","level":2},{"text":"Use the Local Endpoint from a Sandbox","level":2},{"text":"Verify the Endpoint from a Sandbox","level":3},{"text":"Next Steps","level":2}]} \ No newline at end of file +{"id":"inference/configure","title":"Configure Inference Routing","url":"inference/configure.html","last_modified":"2026-03-30T18:08:14.806463+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Set up the managed local inference endpoint with provider credentials and model configuration.","tags":["Inference Routing","Configuration","Privacy","LLM","Provider"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_intermediate","audience":["engineer"],"content":"Configure Inference Routing This page covers the managed local inference endpoint ( https://inference.local ). External inference endpoints go through sandbox network_policies . Refer to Policies for details. The configuration consists of two values: Value Description Provider record The credential backend OpenShell uses to authenticate with the upstream model host. Model ID The model to use for generation requests. For a list of tested providers and their base URLs, refer to Supported Inference Providers . Create a Provider Create a provider that holds the backend credentials you want OpenShell to use. NVIDIA API Catalog $ openshell provider create --name nvidia-prod --type nvidia --from-existing\nThis reads NVIDIA_API_KEY from your environment. OpenAI-compatible Provider Any cloud provider that exposes an OpenAI-compatible API works with the openai provider type. You need three values from the provider: the base URL, an API key, and a model name. $ openshell provider create\nname my-cloud-provider\ntype openai\ncredential OPENAI_API_KEY=\nconfig OPENAI_BASE_URL=https://api.example.com/v1\nReplace the base URL and API key with the values from your provider. For supported providers out of the box, refer to Supported Inference Providers . For other providers, refer to your provider’s documentation for the correct base URL, available models, and API key setup. Local Endpoint $ openshell provider create\nname my-local-model\ntype openai\ncredential OPENAI_API_KEY=empty-if-not-required\nconfig OPENAI_BASE_URL=http://host.openshell.internal:11434/v1\nUse --config OPENAI_BASE_URL to point to any OpenAI-compatible server running where the gateway runs. For host-backed local inference, use host.openshell.internal or the host’s LAN IP. Avoid 127.0.0.1 and localhost . Set OPENAI_API_KEY to a dummy value if the server does not require authentication. For a self-contained setup, the Ollama community sandbox bundles Ollama inside the sandbox itself — no host-level provider needed. See /tutorials/inference-ollama for details. Ollama also supports cloud-hosted models using the :cloud tag suffix (e.g., qwen3.5:cloud ). Anthropic $ openshell provider create --name anthropic-prod --type anthropic --from-existing\nThis reads ANTHROPIC_API_KEY from your environment. Set Inference Routing Point inference.local at that provider and choose the model to use: $ openshell inference set\nprovider nvidia-prod\nmodel nvidia/nemotron-3-nano-30b-a3b\nVerify the Active Config Confirm that the provider and model are set correctly: $ openshell inference get\nGateway inference\nProvider: nvidia-prod\nModel: nvidia/nemotron-3-nano-30b-a3b\nVersion: 1\nUpdate Part of the Config Use update when you want to change only one field: $ openshell inference update --model nvidia/nemotron-3-nano-30b-a3b\nOr switch providers without repeating the current model: $ openshell inference update --provider openai-prod\nUse the Local Endpoint from a Sandbox After inference is configured, code inside any sandbox can call https://inference.local directly: from openai import OpenAI\nclient = OpenAI(base_url=\"https://inference.local/v1\", api_key=\"unused\nresponse = client.chat.completions.create\nmodel=\"anything\nmessages=[{\"role\": \"user\", \"content\": \"Hello\nThe client-supplied model and api_key values are not sent upstream. The privacy router injects the real credentials from the configured provider and rewrites the model before forwarding. Some SDKs require a non-empty API key even though inference.local does not use the sandbox-provided value. In those cases, pass any placeholder such as test or unused . Use this endpoint when inference should stay local to the host for privacy and security reasons. External providers that should be reached directly belong in network_policies instead. When the upstream runs on the same machine as the gateway, bind it to 0.0.0.0 and point the provider at host.openshell.internal or the host’s LAN IP. 127.0.0.1 and localhost usually fail because the request originates from the gateway or sandbox runtime, not from your shell. If the gateway runs on a remote host or behind a cloud deployment, host.openshell.internal points to that remote machine, not to your laptop. A locally running Ollama or vLLM process is not reachable from a remote gateway unless you add your own tunnel or shared network path. Ollama also supports cloud-hosted models that do not require local hardware. Verify the Endpoint from a Sandbox openshell inference set and openshell inference update verify the resolved upstream endpoint by default before saving the configuration. If the endpoint is not live yet, retry with --no-verify to persist the route without the probe. openshell inference get confirms the current saved configuration. To confirm end-to-end connectivity from a sandbox, run: curl https://inference.local/v1/responses\nH \"Content-Type: application/json\"\nd\ninstructions\": \"You are a helpful assistant\ninput\": \"Hello\nA successful response confirms the privacy router can reach the configured backend and the model is serving requests. Gateway-scoped: Every sandbox using the active gateway sees the same inference.local backend. HTTPS only: inference.local is intercepted only for HTTPS traffic. Hot reload: Provider and inference changes are picked up within about 5 seconds by default. Next Steps Explore related topics: To understand the inference routing flow and supported API patterns, refer to index . To follow a complete Ollama-based local setup, refer to /tutorials/inference-ollama . To follow a complete LM Studio-based local setup, refer to /tutorials/local-inference-lmstudio . To control external endpoints, refer to Policies . To manage provider records, refer to ../sandboxes/manage-providers","format":"text","summary":"This page covers the managed local inference endpoint (https://inference.local). External inference endpoints go through sandbox network_policies. Refer to Policies for details.","headings":[{"text":"Configure Inference Routing","level":1},{"text":"Create a Provider","level":2},{"text":"Set Inference Routing","level":2},{"text":"Verify the Active Config","level":2},{"text":"Update Part of the Config","level":2},{"text":"Use the Local Endpoint from a Sandbox","level":2},{"text":"Verify the Endpoint from a Sandbox","level":3},{"text":"Next Steps","level":2}]} \ No newline at end of file diff --git a/pr-preview/pr-677/inference/index.json b/pr-preview/pr-677/inference/index.json index 670e5cadf..5d8ac2bd1 100644 --- a/pr-preview/pr-677/inference/index.json +++ b/pr-preview/pr-677/inference/index.json @@ -1 +1 @@ -{"id":"inference/index","title":"About Inference Routing","url":"inference/index.html","last_modified":"2026-03-30T18:03:24.427688+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Understand how OpenShell routes inference traffic through external endpoints and the local privacy router.","tags":["Inference Routing","Privacy","AI Agents","LLM"],"topics":["Generative AI","Cybersecurity"],"content_type":"concept","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"About Inference Routing NVIDIA OpenShell handles inference traffic through two endpoints: inference.local and external endpoints\nThe following table summarizes how OpenShell handles inference traffic. Path How It Works External endpoints Traffic to hosts like api.openai.com or api.anthropic.com is treated like any other outbound request, allowed or denied by network_policies . Refer to ../sandboxes/policies . inference.local A special endpoint exposed inside every sandbox for routing inference traffic locally, preserving privacy and security. The privacy router strips the original credentials, injects the configured backend credentials, and forwards to the managed model endpoint. How inference.local Works When code inside a sandbox calls https://inference.local , the privacy router routes the request to the configured backend for that gateway. The configured model is applied to generation requests, and provider credentials are supplied by OpenShell rather than by code inside the sandbox. If code calls an external inference host directly, that traffic is evaluated only by network_policies . Property Detail Credentials No sandbox API keys needed. Credentials come from the configured provider record. Configuration One provider and one model define sandbox inference for the active gateway. Every sandbox on that gateway sees the same inference.local backend. Provider support NVIDIA, any OpenAI-compatible provider, and Anthropic all work through the same endpoint. Hot-refresh OpenShell picks up provider credential changes and inference updates without recreating sandboxes. Changes propagate within about 5 seconds by default. Supported API Patterns Supported request patterns depend on the provider configured for inference.local . OpenAI-compatible Pattern Method Path Chat Completions POST /v1/chat/completions Completions POST /v1/completions Responses POST /v1/responses Model Discovery GET /v1/models Model Discovery GET /v1/models/* Anthropic-compatible Pattern Method Path Messages POST /v1/messages Requests to inference.local that do not match the configured provider’s supported patterns are denied. Next Steps Continue with one of the following: To set up the backend behind inference.local , refer to configure . To control external endpoints, refer to Policies","format":"text","summary":"NVIDIA OpenShell handles inference traffic through two endpoints: inference.local and external endpoints. The following table summarizes how OpenShell handles inference traffic.","headings":[{"text":"About Inference Routing","level":1},{"text":"How inference.local Works","level":2},{"text":"Supported API Patterns","level":2},{"text":"Next Steps","level":2}],"children":[{"id":"inference/configure","title":"Configure Inference Routing","url":"inference/configure.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Set up the managed local inference endpoint with provider credentials and model configuration.","tags":["Inference Routing","Configuration","Privacy","LLM","Provider"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_intermediate","audience":["engineer"],"content":"Configure Inference Routing This page covers the managed local inference endpoint ( https://inference.local ). External inference endpoints go through sandbox network_policies . Refer to Policies for details. The configuration consists of two values: Value Description Provider record The credential backend OpenShell uses to authenticate with the upstream model host. Model ID The model to use for generation requests. For a list of tested providers and their base URLs, refer to Supported Inference Providers . Create a Provider Create a provider that holds the backend credentials you want OpenShell to use. NVIDIA API Catalog $ openshell provider create --name nvidia-prod --type nvidia --from-existing\nThis reads NVIDIA_API_KEY from your environment. OpenAI-compatible Provider Any cloud provider that exposes an OpenAI-compatible API works with the openai provider type. You need three values from the provider: the base URL, an API key, and a model name. $ openshell provider create\nname my-cloud-provider\ntype openai\ncredential OPENAI_API_KEY=\nconfig OPENAI_BASE_URL=https://api.example.com/v1\nReplace the base URL and API key with the values from your provider. For supported providers out of the box, refer to Supported Inference Providers . For other providers, refer to your provider’s documentation for the correct base URL, available models, and API key setup. Local Endpoint $ openshell provider create\nname my-local-model\ntype openai\ncredential OPENAI_API_KEY=empty-if-not-required\nconfig OPENAI_BASE_URL=http://host.openshell.internal:11434/v1\nUse --config OPENAI_BASE_URL to point to any OpenAI-compatible server running where the gateway runs. For host-backed local inference, use host.openshell.internal or the host’s LAN IP. Avoid 127.0.0.1 and localhost . Set OPENAI_API_KEY to a dummy value if the server does not require authentication. For a self-contained setup, the Ollama community sandbox bundles Ollama inside the sandbox itself — no host-level provider needed. See /tutorials/inference-ollama for details. Ollama also supports cloud-hosted models using the :cloud tag suffix (e.g., qwen3.5:cloud ). Anthropic $ openshell provider create --name anthropic-prod --type anthropic --from-existing\nThis reads ANTHROPIC_API_KEY from your environment. Set Inference Routing Point inference.local at that provider and choose the model to use: $ openshell inference set\nprovider nvidia-prod\nmodel nvidia/nemotron-3-nano-30b-a3b\nVerify the Active Config Confirm that the provider and model are set correctly: $ openshell inference get\nGateway inference\nProvider: nvidia-prod\nModel: nvidia/nemotron-3-nano-30b-a3b\nVersion: 1\nUpdate Part of the Config Use update when you want to change only one field: $ openshell inference update --model nvidia/nemotron-3-nano-30b-a3b\nOr switch providers without repeating the current model: $ openshell inference update --provider openai-prod\nUse the Local Endpoint from a Sandbox After inference is configured, code inside any sandbox can call https://inference.local directly: from openai import OpenAI\nclient = OpenAI(base_url=\"https://inference.local/v1\", api_key=\"unused\nresponse = client.chat.completions.create\nmodel=\"anything\nmessages=[{\"role\": \"user\", \"content\": \"Hello\nThe client-supplied model and api_key values are not sent upstream. The privacy router injects the real credentials from the configured provider and rewrites the model before forwarding. Some SDKs require a non-empty API key even though inference.local does not use the sandbox-provided value. In those cases, pass any placeholder such as test or unused . Use this endpoint when inference should stay local to the host for privacy and security reasons. External providers that should be reached directly belong in network_policies instead. When the upstream runs on the same machine as the gateway, bind it to 0.0.0.0 and point the provider at host.openshell.internal or the host’s LAN IP. 127.0.0.1 and localhost usually fail because the request originates from the gateway or sandbox runtime, not from your shell. If the gateway runs on a remote host or behind a cloud deployment, host.openshell.internal points to that remote machine, not to your laptop. A locally running Ollama or vLLM process is not reachable from a remote gateway unless you add your own tunnel or shared network path. Ollama also supports cloud-hosted models that do not require local hardware. Verify the Endpoint from a Sandbox openshell inference set and openshell inference update verify the resolved upstream endpoint by default before saving the configuration. If the endpoint is not live yet, retry with --no-verify to persist the route without the probe. openshell inference get confirms the current saved configuration. To confirm end-to-end connectivity from a sandbox, run: curl https://inference.local/v1/responses\nH \"Content-Type: application/json\"\nd\ninstructions\": \"You are a helpful assistant\ninput\": \"Hello\nA successful response confirms the privacy router can reach the configured backend and the model is serving requests. Gateway-scoped: Every sandbox using the active gateway sees the same inference.local backend. HTTPS only: inference.local is intercepted only for HTTPS traffic. Hot reload: Provider and inference changes are picked up within about 5 seconds by default. Next Steps Explore related topics: To understand the inference routing flow and supported API patterns, refer to index . To follow a complete Ollama-based local setup, refer to /tutorials/inference-ollama . To follow a complete LM Studio-based local setup, refer to /tutorials/local-inference-lmstudio . To control external endpoints, refer to Policies . To manage provider records, refer to ../sandboxes/manage-providers","format":"text","content_length":5738,"word_count":791,"summary":"This page covers the managed local inference endpoint (https://inference.local). External inference endpoints go through sandbox network_policies. Refer to Policies for details.","headings":[{"text":"Configure Inference Routing","level":1,"id":"configure-inference-routing"},{"text":"Create a Provider","level":2,"id":"create-a-provider"},{"text":"Set Inference Routing","level":2,"id":"set-inference-routing"},{"text":"Verify the Active Config","level":2,"id":"verify-the-active-config"},{"text":"Update Part of the Config","level":2,"id":"update-part-of-the-config"},{"text":"Use the Local Endpoint from a Sandbox","level":2,"id":"use-the-local-endpoint-from-a-sandbox"},{"text":"Verify the Endpoint from a Sandbox","level":3,"id":"verify-the-endpoint-from-a-sandbox"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Configure Inference Routing Create a Provider Set Inference Routing Verify the Active Config Update Part of the Config Use the Local Endpoint from a Sandbox Verify the Endpoint from a Sandbox Next Steps","keywords":["active","after","anthropic","any","api_key","avoid","base_url","catalog","chat","client","com","config","configure","confirm","content","correctly","create","description","directly","endpoint","every","explore","external","field","from","gateway","hello","hot","http","https","inference","internal","local","messages","model","next","ollama","only","openai","openshell","part","point","policies","provider","providers","refer","reload","replace","response","routing"],"code_blocks":[{"content":"$ openshell provider create --name nvidia-prod --type nvidia --from-existing","language":"text"},{"content":"$ openshell provider create \\\n --name my-cloud-provider \\\n --type openai \\\n --credential OPENAI_API_KEY= \\\n --config OPENAI_BASE_URL=https://api.example.com/v1","language":"text"},{"content":"$ openshell provider create \\\n --name my-local-model \\\n --type openai \\\n --credential OPENAI_API_KEY=empty-if-not-required \\\n --config OPENAI_BASE_URL=http://host.openshell.internal:11434/v1","language":"text"},{"content":"$ openshell provider create --name anthropic-prod --type anthropic --from-existing","language":"text"},{"content":"$ openshell inference set \\\n --provider nvidia-prod \\\n --model nvidia/nemotron-3-nano-30b-a3b","language":"text"},{"content":"$ openshell inference get\nGateway inference:\n\n Provider: nvidia-prod\n Model: nvidia/nemotron-3-nano-30b-a3b\n Version: 1","language":"text"},{"content":"$ openshell inference update --model nvidia/nemotron-3-nano-30b-a3b","language":"text"},{"content":"$ openshell inference update --provider openai-prod","language":"text"},{"content":"from openai import OpenAI\n\nclient = OpenAI(base_url=\"https://inference.local/v1\", api_key=\"unused\")\n\nresponse = client.chat.completions.create(\n model=\"anything\",\n messages=[{\"role\": \"user\", \"content\": \"Hello\"}],\n)","language":"text"},{"content":"curl https://inference.local/v1/responses \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"instructions\": \"You are a helpful assistant.\",\n \"input\": \"Hello!\"\n }'","language":"text"}],"links":[],"images":[],"doc_type":"tutorial","section_path":["Inference","Configure"]}]} \ No newline at end of file +{"id":"inference/index","title":"About Inference Routing","url":"inference/index.html","last_modified":"2026-03-30T18:08:14.815840+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Understand how OpenShell routes inference traffic through external endpoints and the local privacy router.","tags":["Inference Routing","Privacy","AI Agents","LLM"],"topics":["Generative AI","Cybersecurity"],"content_type":"concept","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"About Inference Routing NVIDIA OpenShell handles inference traffic through two endpoints: inference.local and external endpoints\nThe following table summarizes how OpenShell handles inference traffic. Path How It Works External endpoints Traffic to hosts like api.openai.com or api.anthropic.com is treated like any other outbound request, allowed or denied by network_policies . Refer to ../sandboxes/policies . inference.local A special endpoint exposed inside every sandbox for routing inference traffic locally, preserving privacy and security. The privacy router strips the original credentials, injects the configured backend credentials, and forwards to the managed model endpoint. How inference.local Works When code inside a sandbox calls https://inference.local , the privacy router routes the request to the configured backend for that gateway. The configured model is applied to generation requests, and provider credentials are supplied by OpenShell rather than by code inside the sandbox. If code calls an external inference host directly, that traffic is evaluated only by network_policies . Property Detail Credentials No sandbox API keys needed. Credentials come from the configured provider record. Configuration One provider and one model define sandbox inference for the active gateway. Every sandbox on that gateway sees the same inference.local backend. Provider support NVIDIA, any OpenAI-compatible provider, and Anthropic all work through the same endpoint. Hot-refresh OpenShell picks up provider credential changes and inference updates without recreating sandboxes. Changes propagate within about 5 seconds by default. Supported API Patterns Supported request patterns depend on the provider configured for inference.local . OpenAI-compatible Pattern Method Path Chat Completions POST /v1/chat/completions Completions POST /v1/completions Responses POST /v1/responses Model Discovery GET /v1/models Model Discovery GET /v1/models/* Anthropic-compatible Pattern Method Path Messages POST /v1/messages Requests to inference.local that do not match the configured provider’s supported patterns are denied. Next Steps Continue with one of the following: To set up the backend behind inference.local , refer to configure . To control external endpoints, refer to Policies","format":"text","summary":"NVIDIA OpenShell handles inference traffic through two endpoints: inference.local and external endpoints. The following table summarizes how OpenShell handles inference traffic.","headings":[{"text":"About Inference Routing","level":1},{"text":"How inference.local Works","level":2},{"text":"Supported API Patterns","level":2},{"text":"Next Steps","level":2}],"children":[{"id":"inference/configure","title":"Configure Inference Routing","url":"inference/configure.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Set up the managed local inference endpoint with provider credentials and model configuration.","tags":["Inference Routing","Configuration","Privacy","LLM","Provider"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_intermediate","audience":["engineer"],"content":"Configure Inference Routing This page covers the managed local inference endpoint ( https://inference.local ). External inference endpoints go through sandbox network_policies . Refer to Policies for details. The configuration consists of two values: Value Description Provider record The credential backend OpenShell uses to authenticate with the upstream model host. Model ID The model to use for generation requests. For a list of tested providers and their base URLs, refer to Supported Inference Providers . Create a Provider Create a provider that holds the backend credentials you want OpenShell to use. NVIDIA API Catalog $ openshell provider create --name nvidia-prod --type nvidia --from-existing\nThis reads NVIDIA_API_KEY from your environment. OpenAI-compatible Provider Any cloud provider that exposes an OpenAI-compatible API works with the openai provider type. You need three values from the provider: the base URL, an API key, and a model name. $ openshell provider create\nname my-cloud-provider\ntype openai\ncredential OPENAI_API_KEY=\nconfig OPENAI_BASE_URL=https://api.example.com/v1\nReplace the base URL and API key with the values from your provider. For supported providers out of the box, refer to Supported Inference Providers . For other providers, refer to your provider’s documentation for the correct base URL, available models, and API key setup. Local Endpoint $ openshell provider create\nname my-local-model\ntype openai\ncredential OPENAI_API_KEY=empty-if-not-required\nconfig OPENAI_BASE_URL=http://host.openshell.internal:11434/v1\nUse --config OPENAI_BASE_URL to point to any OpenAI-compatible server running where the gateway runs. For host-backed local inference, use host.openshell.internal or the host’s LAN IP. Avoid 127.0.0.1 and localhost . Set OPENAI_API_KEY to a dummy value if the server does not require authentication. For a self-contained setup, the Ollama community sandbox bundles Ollama inside the sandbox itself — no host-level provider needed. See /tutorials/inference-ollama for details. Ollama also supports cloud-hosted models using the :cloud tag suffix (e.g., qwen3.5:cloud ). Anthropic $ openshell provider create --name anthropic-prod --type anthropic --from-existing\nThis reads ANTHROPIC_API_KEY from your environment. Set Inference Routing Point inference.local at that provider and choose the model to use: $ openshell inference set\nprovider nvidia-prod\nmodel nvidia/nemotron-3-nano-30b-a3b\nVerify the Active Config Confirm that the provider and model are set correctly: $ openshell inference get\nGateway inference\nProvider: nvidia-prod\nModel: nvidia/nemotron-3-nano-30b-a3b\nVersion: 1\nUpdate Part of the Config Use update when you want to change only one field: $ openshell inference update --model nvidia/nemotron-3-nano-30b-a3b\nOr switch providers without repeating the current model: $ openshell inference update --provider openai-prod\nUse the Local Endpoint from a Sandbox After inference is configured, code inside any sandbox can call https://inference.local directly: from openai import OpenAI\nclient = OpenAI(base_url=\"https://inference.local/v1\", api_key=\"unused\nresponse = client.chat.completions.create\nmodel=\"anything\nmessages=[{\"role\": \"user\", \"content\": \"Hello\nThe client-supplied model and api_key values are not sent upstream. The privacy router injects the real credentials from the configured provider and rewrites the model before forwarding. Some SDKs require a non-empty API key even though inference.local does not use the sandbox-provided value. In those cases, pass any placeholder such as test or unused . Use this endpoint when inference should stay local to the host for privacy and security reasons. External providers that should be reached directly belong in network_policies instead. When the upstream runs on the same machine as the gateway, bind it to 0.0.0.0 and point the provider at host.openshell.internal or the host’s LAN IP. 127.0.0.1 and localhost usually fail because the request originates from the gateway or sandbox runtime, not from your shell. If the gateway runs on a remote host or behind a cloud deployment, host.openshell.internal points to that remote machine, not to your laptop. A locally running Ollama or vLLM process is not reachable from a remote gateway unless you add your own tunnel or shared network path. Ollama also supports cloud-hosted models that do not require local hardware. Verify the Endpoint from a Sandbox openshell inference set and openshell inference update verify the resolved upstream endpoint by default before saving the configuration. If the endpoint is not live yet, retry with --no-verify to persist the route without the probe. openshell inference get confirms the current saved configuration. To confirm end-to-end connectivity from a sandbox, run: curl https://inference.local/v1/responses\nH \"Content-Type: application/json\"\nd\ninstructions\": \"You are a helpful assistant\ninput\": \"Hello\nA successful response confirms the privacy router can reach the configured backend and the model is serving requests. Gateway-scoped: Every sandbox using the active gateway sees the same inference.local backend. HTTPS only: inference.local is intercepted only for HTTPS traffic. Hot reload: Provider and inference changes are picked up within about 5 seconds by default. Next Steps Explore related topics: To understand the inference routing flow and supported API patterns, refer to index . To follow a complete Ollama-based local setup, refer to /tutorials/inference-ollama . To follow a complete LM Studio-based local setup, refer to /tutorials/local-inference-lmstudio . To control external endpoints, refer to Policies . To manage provider records, refer to ../sandboxes/manage-providers","format":"text","content_length":5738,"word_count":791,"summary":"This page covers the managed local inference endpoint (https://inference.local). External inference endpoints go through sandbox network_policies. Refer to Policies for details.","headings":[{"text":"Configure Inference Routing","level":1,"id":"configure-inference-routing"},{"text":"Create a Provider","level":2,"id":"create-a-provider"},{"text":"Set Inference Routing","level":2,"id":"set-inference-routing"},{"text":"Verify the Active Config","level":2,"id":"verify-the-active-config"},{"text":"Update Part of the Config","level":2,"id":"update-part-of-the-config"},{"text":"Use the Local Endpoint from a Sandbox","level":2,"id":"use-the-local-endpoint-from-a-sandbox"},{"text":"Verify the Endpoint from a Sandbox","level":3,"id":"verify-the-endpoint-from-a-sandbox"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Configure Inference Routing Create a Provider Set Inference Routing Verify the Active Config Update Part of the Config Use the Local Endpoint from a Sandbox Verify the Endpoint from a Sandbox Next Steps","keywords":["active","after","anthropic","any","api_key","avoid","base_url","catalog","chat","client","com","config","configure","confirm","content","correctly","create","description","directly","endpoint","every","explore","external","field","from","gateway","hello","hot","http","https","inference","internal","local","messages","model","next","ollama","only","openai","openshell","part","point","policies","provider","providers","refer","reload","replace","response","routing"],"code_blocks":[{"content":"$ openshell provider create --name nvidia-prod --type nvidia --from-existing","language":"text"},{"content":"$ openshell provider create \\\n --name my-cloud-provider \\\n --type openai \\\n --credential OPENAI_API_KEY= \\\n --config OPENAI_BASE_URL=https://api.example.com/v1","language":"text"},{"content":"$ openshell provider create \\\n --name my-local-model \\\n --type openai \\\n --credential OPENAI_API_KEY=empty-if-not-required \\\n --config OPENAI_BASE_URL=http://host.openshell.internal:11434/v1","language":"text"},{"content":"$ openshell provider create --name anthropic-prod --type anthropic --from-existing","language":"text"},{"content":"$ openshell inference set \\\n --provider nvidia-prod \\\n --model nvidia/nemotron-3-nano-30b-a3b","language":"text"},{"content":"$ openshell inference get\nGateway inference:\n\n Provider: nvidia-prod\n Model: nvidia/nemotron-3-nano-30b-a3b\n Version: 1","language":"text"},{"content":"$ openshell inference update --model nvidia/nemotron-3-nano-30b-a3b","language":"text"},{"content":"$ openshell inference update --provider openai-prod","language":"text"},{"content":"from openai import OpenAI\n\nclient = OpenAI(base_url=\"https://inference.local/v1\", api_key=\"unused\")\n\nresponse = client.chat.completions.create(\n model=\"anything\",\n messages=[{\"role\": \"user\", \"content\": \"Hello\"}],\n)","language":"text"},{"content":"curl https://inference.local/v1/responses \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"instructions\": \"You are a helpful assistant.\",\n \"input\": \"Hello!\"\n }'","language":"text"}],"links":[],"images":[],"doc_type":"tutorial","section_path":["Inference","Configure"]}]} \ No newline at end of file diff --git a/pr-preview/pr-677/reference/default-policy.json b/pr-preview/pr-677/reference/default-policy.json index 2c32a7658..11f4369bd 100644 --- a/pr-preview/pr-677/reference/default-policy.json +++ b/pr-preview/pr-677/reference/default-policy.json @@ -1 +1 @@ -{"id":"reference/default-policy","title":"Default Policy Reference","url":"reference/default-policy.html","last_modified":"2026-03-30T18:03:24.429845+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Breakdown of the built-in default policy applied when you create an OpenShell sandbox without a custom policy.","tags":["ai_agents","sandboxing","security","policy"],"topics":["generative_ai","cybersecurity"],"content_type":"reference","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"keywords":["openshell default policy","sandbox policy","agent compatibility"],"content":"Default Policy Reference The default policy is the policy applied when you create an OpenShell sandbox without --policy . It is baked into the community base image ( ghcr.io/nvidia/openshell-community/sandboxes/base ) and defined in the community repo’s dev-sandbox-policy.yaml . Agent Compatibility The following table shows the coverage of the default policy for common agents. Agent Coverage Action Required Claude Code Full None. Works out of the box. OpenCode Partial Add opencode.ai endpoint and OpenCode binary paths. Codex None Provide a complete custom policy with OpenAI endpoints and Codex binary paths. If you run a non-Claude agent without a custom policy, the agent’s API calls are denied by the proxy. You must provide a policy that declares the agent’s endpoints and binaries. Default Policy Blocks The default policy blocks are defined in the community base image. See the openshell-community repository for the full dev-sandbox-policy.yaml source","format":"text","summary":"The default policy is the policy applied when you create an OpenShell sandbox without --policy. It is baked into the community base image (ghcr.io/nvidia/openshell-community/sandboxes/base) and defined in the community repo’s dev-sandbox-policy.yaml.","headings":[{"text":"Default Policy Reference","level":1},{"text":"Agent Compatibility","level":2},{"text":"Default Policy Blocks","level":2}]} \ No newline at end of file +{"id":"reference/default-policy","title":"Default Policy Reference","url":"reference/default-policy.html","last_modified":"2026-03-30T18:08:14.817328+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Breakdown of the built-in default policy applied when you create an OpenShell sandbox without a custom policy.","tags":["ai_agents","sandboxing","security","policy"],"topics":["generative_ai","cybersecurity"],"content_type":"reference","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"keywords":["openshell default policy","sandbox policy","agent compatibility"],"content":"Default Policy Reference The default policy is the policy applied when you create an OpenShell sandbox without --policy . It is baked into the community base image ( ghcr.io/nvidia/openshell-community/sandboxes/base ) and defined in the community repo’s dev-sandbox-policy.yaml . Agent Compatibility The following table shows the coverage of the default policy for common agents. Agent Coverage Action Required Claude Code Full None. Works out of the box. OpenCode Partial Add opencode.ai endpoint and OpenCode binary paths. Codex None Provide a complete custom policy with OpenAI endpoints and Codex binary paths. If you run a non-Claude agent without a custom policy, the agent’s API calls are denied by the proxy. You must provide a policy that declares the agent’s endpoints and binaries. Default Policy Blocks The default policy blocks are defined in the community base image. See the openshell-community repository for the full dev-sandbox-policy.yaml source","format":"text","summary":"The default policy is the policy applied when you create an OpenShell sandbox without --policy. It is baked into the community base image (ghcr.io/nvidia/openshell-community/sandboxes/base) and defined in the community repo’s dev-sandbox-policy.yaml.","headings":[{"text":"Default Policy Reference","level":1},{"text":"Agent Compatibility","level":2},{"text":"Default Policy Blocks","level":2}]} \ No newline at end of file diff --git a/pr-preview/pr-677/reference/gateway-auth.json b/pr-preview/pr-677/reference/gateway-auth.json index 1c4aeb380..ac8ace5bf 100644 --- a/pr-preview/pr-677/reference/gateway-auth.json +++ b/pr-preview/pr-677/reference/gateway-auth.json @@ -1 +1 @@ -{"id":"reference/gateway-auth","title":"Gateway Authentication","url":"reference/gateway-auth.html","last_modified":"2026-03-30T18:03:24.437232+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Gateway resolution, authentication modes, connection flow, and credential file layout.","tags":["Gateway","Authentication","mTLS","Edge Authentication","Reference"],"topics":["Generative AI","Cybersecurity"],"content_type":"reference","learning_level":"technical_intermediate","audience":["engineer"],"content":"Gateway Authentication This page describes how the CLI resolves a gateway, authenticates with it, and where credentials are stored. For how to deploy or register gateways, refer to /sandboxes/manage-sandboxes . Gateway Resolution When any CLI command needs to talk to the gateway, it resolves the target through a priority chain: --gateway-endpoint flag (direct URL). -g flag. OPENSHELL_GATEWAY environment variable. Active gateway from ~/.config/openshell/active_gateway . The CLI loads gateway metadata from disk to determine the endpoint URL and authentication mode. Authentication Modes The CLI uses one of three connection modes depending on the gateway’s authentication configuration. mTLS (local and remote gateways) The default mode for self-deployed gateways. When you run gateway start or gateway add --local / gateway add --remote , the CLI extracts mTLS certificates from the running container and stores them locally. Every subsequent request presents a client certificate to prove identity. The CLI loads three PEM files from ~/.config/openshell/gateways//mtls/ : File Purpose ca.crt CA certificate. Verifies the gateway’s server certificate. tls.crt Client certificate. Proves the CLI’s identity to the gateway. tls.key Client private key. The connection flow: The CLI loads the three certificate files. Opens a TCP connection to the gateway endpoint. Performs a TLS handshake, presenting the client certificate. The gateway verifies the client certificate against its CA. An HTTP/2 channel is established. All CLI commands use this channel. Edge JWT (cloud gateways) For gateways behind a reverse proxy that handles authentication (e.g. Cloudflare Access), the CLI uses a browser-based login flow and routes traffic through a WebSocket tunnel. Registration flow ( openshell gateway add https://gateway.example.com ): The CLI stores gateway metadata with the edge authentication mode. Opens your browser to the gateway’s authentication endpoint. The reverse proxy handles login (SSO, identity provider, etc.). After authentication, the browser relays the authorization token back to the CLI via a localhost callback. The CLI stores the token and sets the gateway as active. Connection flow (subsequent commands): The CLI starts a local proxy that listens on an ephemeral port. The proxy opens a WebSocket connection ( wss:// ) to the gateway, attaching the stored bearer token in the upgrade headers. The reverse proxy authenticates the WebSocket upgrade request. The gateway bridges the WebSocket into the same service that handles direct mTLS connections. CLI commands send requests through the local proxy as plaintext HTTP/2 over the tunnel. This is transparent to the user. All CLI commands work the same regardless of whether the gateway uses mTLS or edge authentication. Re-authentication : If the token expires, run openshell gateway login to open the browser flow again and update the stored token. Plaintext When a gateway is deployed with --plaintext , TLS is disabled entirely. The CLI connects over plain HTTP/2. This mode is intended for gateways behind a trusted reverse proxy or tunnel that handles TLS termination externally. File Layout All gateway credentials and metadata are stored under ~/.config/openshell/ : openshell\nactive_gateway # Plain text: active gateway name\ngateways\nname\nmetadata.json # Gateway metadata (endpoint, auth mode, type\nmtls/ # mTLS bundle (local and remote gateways\nca.crt # CA certificate\ntls.crt # Client certificate\ntls.key # Client private key\nedge_token # Edge auth JWT (cloud gateways\nlast_sandbox # Last-used sandbox for this gateway","format":"text","summary":"This page describes how the CLI resolves a gateway, authenticates with it, and where credentials are stored. For how to deploy or register gateways, refer to /sandboxes/manage-sandboxes.","headings":[{"text":"Gateway Authentication","level":1},{"text":"Gateway Resolution","level":2},{"text":"Authentication Modes","level":2},{"text":"mTLS (local and remote gateways)","level":3},{"text":"Edge JWT (cloud gateways)","level":3},{"text":"Plaintext","level":3},{"text":"File Layout","level":2}]} \ No newline at end of file +{"id":"reference/gateway-auth","title":"Gateway Authentication","url":"reference/gateway-auth.html","last_modified":"2026-03-30T18:08:14.821434+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Gateway resolution, authentication modes, connection flow, and credential file layout.","tags":["Gateway","Authentication","mTLS","Edge Authentication","Reference"],"topics":["Generative AI","Cybersecurity"],"content_type":"reference","learning_level":"technical_intermediate","audience":["engineer"],"content":"Gateway Authentication This page describes how the CLI resolves a gateway, authenticates with it, and where credentials are stored. For how to deploy or register gateways, refer to /sandboxes/manage-sandboxes . Gateway Resolution When any CLI command needs to talk to the gateway, it resolves the target through a priority chain: --gateway-endpoint flag (direct URL). -g flag. OPENSHELL_GATEWAY environment variable. Active gateway from ~/.config/openshell/active_gateway . The CLI loads gateway metadata from disk to determine the endpoint URL and authentication mode. Authentication Modes The CLI uses one of three connection modes depending on the gateway’s authentication configuration. mTLS (local and remote gateways) The default mode for self-deployed gateways. When you run gateway start or gateway add --local / gateway add --remote , the CLI extracts mTLS certificates from the running container and stores them locally. Every subsequent request presents a client certificate to prove identity. The CLI loads three PEM files from ~/.config/openshell/gateways//mtls/ : File Purpose ca.crt CA certificate. Verifies the gateway’s server certificate. tls.crt Client certificate. Proves the CLI’s identity to the gateway. tls.key Client private key. The connection flow: The CLI loads the three certificate files. Opens a TCP connection to the gateway endpoint. Performs a TLS handshake, presenting the client certificate. The gateway verifies the client certificate against its CA. An HTTP/2 channel is established. All CLI commands use this channel. Edge JWT (cloud gateways) For gateways behind a reverse proxy that handles authentication (e.g. Cloudflare Access), the CLI uses a browser-based login flow and routes traffic through a WebSocket tunnel. Registration flow ( openshell gateway add https://gateway.example.com ): The CLI stores gateway metadata with the edge authentication mode. Opens your browser to the gateway’s authentication endpoint. The reverse proxy handles login (SSO, identity provider, etc.). After authentication, the browser relays the authorization token back to the CLI via a localhost callback. The CLI stores the token and sets the gateway as active. Connection flow (subsequent commands): The CLI starts a local proxy that listens on an ephemeral port. The proxy opens a WebSocket connection ( wss:// ) to the gateway, attaching the stored bearer token in the upgrade headers. The reverse proxy authenticates the WebSocket upgrade request. The gateway bridges the WebSocket into the same service that handles direct mTLS connections. CLI commands send requests through the local proxy as plaintext HTTP/2 over the tunnel. This is transparent to the user. All CLI commands work the same regardless of whether the gateway uses mTLS or edge authentication. Re-authentication : If the token expires, run openshell gateway login to open the browser flow again and update the stored token. Plaintext When a gateway is deployed with --plaintext , TLS is disabled entirely. The CLI connects over plain HTTP/2. This mode is intended for gateways behind a trusted reverse proxy or tunnel that handles TLS termination externally. File Layout All gateway credentials and metadata are stored under ~/.config/openshell/ : openshell\nactive_gateway # Plain text: active gateway name\ngateways\nname\nmetadata.json # Gateway metadata (endpoint, auth mode, type\nmtls/ # mTLS bundle (local and remote gateways\nca.crt # CA certificate\ntls.crt # Client certificate\ntls.key # Client private key\nedge_token # Edge auth JWT (cloud gateways\nlast_sandbox # Last-used sandbox for this gateway","format":"text","summary":"This page describes how the CLI resolves a gateway, authenticates with it, and where credentials are stored. For how to deploy or register gateways, refer to /sandboxes/manage-sandboxes.","headings":[{"text":"Gateway Authentication","level":1},{"text":"Gateway Resolution","level":2},{"text":"Authentication Modes","level":2},{"text":"mTLS (local and remote gateways)","level":3},{"text":"Edge JWT (cloud gateways)","level":3},{"text":"Plaintext","level":3},{"text":"File Layout","level":2}]} \ No newline at end of file diff --git a/pr-preview/pr-677/reference/policy-schema.json b/pr-preview/pr-677/reference/policy-schema.json index 2f5988fc9..8e49bc887 100644 --- a/pr-preview/pr-677/reference/policy-schema.json +++ b/pr-preview/pr-677/reference/policy-schema.json @@ -1 +1 @@ -{"id":"reference/policy-schema","title":"Policy Schema Reference","url":"reference/policy-schema.html","last_modified":"2026-03-30T18:03:24.461093+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Complete field reference for the sandbox policy YAML including static and dynamic sections.","tags":["Policy","Schema","YAML","Reference","Security"],"topics":["Generative AI","Cybersecurity"],"content_type":"reference","learning_level":"technical_advanced","audience":["engineer"],"content":"Policy Schema Reference Complete field reference for the sandbox policy YAML. Each field is documented with its type, whether it is required, and whether it is static (locked at sandbox creation) or dynamic (hot-reloadable on a running sandbox). Top-Level Structure A policy YAML file contains the following top-level fields: version: 1\nfilesystem_policy: { ...\nlandlock: { ...\nprocess: { ...\nnetwork_policies: { ...\nField Type Required Category Description version integer Yes – Policy schema version. Must be 1 . filesystem_policy object No Static Controls which directories the agent can read and write. landlock object No Static Configures Landlock LSM enforcement behavior. process object No Static Sets the user and group the agent process runs as. network_policies map No Dynamic Declares which binaries can reach which network endpoints. Static fields are set at sandbox creation time. Changing them requires destroying and recreating the sandbox. Dynamic fields can be updated on a running sandbox with openshell policy set and take effect without restarting. Version The version field identifies which schema the policy uses: Field Type Required Description version integer Yes Schema version number. Currently must be 1 . Filesystem Policy Category: Static Controls filesystem access inside the sandbox. Paths not listed in either read_only or read_write are inaccessible. Field Type Required Description include_workdir bool No When true , automatically adds the agent’s working directory to read_write . read_only list of strings No Paths the agent can read but not modify. Typically system directories like /usr , /lib , /etc . read_write list of strings No Paths the agent can read and write. Typically /sandbox (working directory) and /tmp . Validation constraints: Every path must be absolute (start with / ). Paths must not contain .. traversal components. The server normalizes paths before storage, but rejects policies where traversal would escape the intended scope. Read-write paths must not be overly broad (for example, / alone is rejected). Each individual path must not exceed 4096 characters. The combined total of read_only and read_write paths must not exceed 256. Policies that violate these constraints are rejected with INVALID_ARGUMENT at creation or update time. Disk-loaded YAML policies that fail validation fall back to a restrictive default. Example: filesystem_policy\ninclude_workdir: true\nread_only\n/usr\n/lib\n/proc\n/dev/urandom\n/etc\nread_write\n/sandbox\n/tmp\n/dev/null\nLandlock Category: Static Configures Landlock LSM enforcement at the kernel level. Landlock provides mandatory filesystem access control below what UNIX permissions allow. Field Type Required Values Description compatibility string No best_effort , hard_requirement How OpenShell handles Landlock failures. See behavior table below. Compatibility modes: Value Kernel ABI unavailable Individual path inaccessible All paths inaccessible best_effort Warns and continues without Landlock. Skips the path, applies remaining rules. Warns and continues without Landlock (refuses to apply an empty ruleset). hard_requirement Aborts sandbox startup. Aborts sandbox startup. Aborts sandbox startup. best_effort (the default) is appropriate for most deployments. It handles missing paths gracefully – for example, /app may not exist in every container image but is included in the baseline path set for containers that do have it. Individual missing paths are skipped while the remaining filesystem rules are still enforced. hard_requirement is for environments where any gap in filesystem isolation is unacceptable. If a listed path cannot be opened for any reason (missing, permission denied, symlink loop), sandbox startup fails immediately rather than running with reduced protection. When a path is skipped under best_effort , the sandbox logs a warning that includes the path, the specific error, and a human-readable reason (for example, “path does not exist” or “permission denied”). Example: landlock\ncompatibility: best_effort\nProcess Category: Static Sets the OS-level identity for the agent process inside the sandbox. Field Type Required Description run_as_user string No The user name or UID the agent process runs as. Default: sandbox . run_as_group string No The group name or GID the agent process runs as. Default: sandbox . Validation constraint: Neither run_as_user nor run_as_group may be set to root or 0 . Policies that request root process identity are rejected at creation or update time. Example: process\nrun_as_user: sandbox\nrun_as_group: sandbox\nNetwork Policies Category: Dynamic A map of named network policy entries. Each entry declares a set of endpoints and a set of binaries. Only the listed binaries are permitted to connect to the listed endpoints. The map key is a logical identifier. The name field inside the entry is the display name used in logs. Network Policy Entry Each entry in the network_policies map has the following fields: Field Type Required Description name string No Display name for the policy entry. Used in log output. Defaults to the map key. endpoints list of endpoint objects Yes Hosts and ports this entry permits. binaries list of binary objects Yes Executables allowed to connect to these endpoints. Endpoint Object Each endpoint defines a reachable destination and optional inspection rules. Field Type Required Description host string Yes Hostname or IP address. Supports wildcards: *.example.com matches any subdomain. port integer Yes TCP port number. protocol string No Set to rest to enable HTTP request inspection. Omit for TCP passthrough. tls string No TLS handling mode. The proxy auto-detects TLS by peeking the first bytes of each connection and terminates it when protocol is rest , so this field is optional in most cases. Set to skip to disable auto-detection for edge cases such as client-certificate mTLS or non-standard protocols. The values terminate and passthrough are deprecated and log a warning; they are still accepted for backward compatibility but have no effect on behavior. enforcement string No enforce actively blocks disallowed requests. audit logs violations but allows traffic through. access string No HTTP access level. One of read-only , read-write , or full . Mutually exclusive with rules . rules list of rule objects No Fine-grained per-method, per-path allow rules. Mutually exclusive with access . Access Levels The access field accepts one of the following values: Value Allowed HTTP Methods full All methods and paths. read-only GET , HEAD , OPTIONS . read-write GET , HEAD , OPTIONS , POST , PUT , PATCH . Rule Object Used when access is not set. Each rule explicitly allows a method and path combination. Field Type Required Description allow.method string Yes HTTP method to allow (for example, GET , POST ). allow.path string Yes URL path pattern. Supports * and ** glob syntax. Example with rules: rules\nallow\nmethod: GET\npath: /**/info/refs\nallow\nmethod: POST\npath: /**/git-upload-pack\nBinary Object Identifies an executable that is permitted to use the associated endpoints. Field Type Required Description path string Yes Filesystem path to the executable. Supports glob patterns with * and ** . For example, /sandbox/.vscode-server/** matches any executable under that directory tree. Full Example The following policy grants read-only GitHub API access and npm registry access: network_policies\ngithub_rest_api\nname: github-rest-api\nendpoints\nhost: api.github.com\nport: 443\nprotocol: rest\nenforcement: enforce\naccess: read-only\nbinaries\npath: /usr/local/bin/claude\npath: /usr/bin/node\npath: /usr/bin/gh\nnpm_registry\nname: npm-registry\nendpoints\nhost: registry.npmjs.org\nport: 443\nbinaries\npath: /usr/bin/npm\npath: /usr/bin/node","format":"text","summary":"Complete field reference for the sandbox policy YAML. Each field is documented with its type, whether it is required, and whether it is static (locked at sandbox creation) or dynamic (hot-reloadable on a running sandbox).","headings":[{"text":"Policy Schema Reference","level":1},{"text":"Top-Level Structure","level":2},{"text":"Version","level":2},{"text":"Filesystem Policy","level":2},{"text":"Landlock","level":2},{"text":"Process","level":2},{"text":"Network Policies","level":2},{"text":"Network Policy Entry","level":3},{"text":"Endpoint Object","level":3},{"text":"Access Levels","level":4},{"text":"Rule Object","level":4},{"text":"Binary Object","level":3},{"text":"Full Example","level":3}]} \ No newline at end of file +{"id":"reference/policy-schema","title":"Policy Schema Reference","url":"reference/policy-schema.html","last_modified":"2026-03-30T18:08:14.832861+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Complete field reference for the sandbox policy YAML including static and dynamic sections.","tags":["Policy","Schema","YAML","Reference","Security"],"topics":["Generative AI","Cybersecurity"],"content_type":"reference","learning_level":"technical_advanced","audience":["engineer"],"content":"Policy Schema Reference Complete field reference for the sandbox policy YAML. Each field is documented with its type, whether it is required, and whether it is static (locked at sandbox creation) or dynamic (hot-reloadable on a running sandbox). Top-Level Structure A policy YAML file contains the following top-level fields: version: 1\nfilesystem_policy: { ...\nlandlock: { ...\nprocess: { ...\nnetwork_policies: { ...\nField Type Required Category Description version integer Yes – Policy schema version. Must be 1 . filesystem_policy object No Static Controls which directories the agent can read and write. landlock object No Static Configures Landlock LSM enforcement behavior. process object No Static Sets the user and group the agent process runs as. network_policies map No Dynamic Declares which binaries can reach which network endpoints. Static fields are set at sandbox creation time. Changing them requires destroying and recreating the sandbox. Dynamic fields can be updated on a running sandbox with openshell policy set and take effect without restarting. Version The version field identifies which schema the policy uses: Field Type Required Description version integer Yes Schema version number. Currently must be 1 . Filesystem Policy Category: Static Controls filesystem access inside the sandbox. Paths not listed in either read_only or read_write are inaccessible. Field Type Required Description include_workdir bool No When true , automatically adds the agent’s working directory to read_write . read_only list of strings No Paths the agent can read but not modify. Typically system directories like /usr , /lib , /etc . read_write list of strings No Paths the agent can read and write. Typically /sandbox (working directory) and /tmp . Validation constraints: Every path must be absolute (start with / ). Paths must not contain .. traversal components. The server normalizes paths before storage, but rejects policies where traversal would escape the intended scope. Read-write paths must not be overly broad (for example, / alone is rejected). Each individual path must not exceed 4096 characters. The combined total of read_only and read_write paths must not exceed 256. Policies that violate these constraints are rejected with INVALID_ARGUMENT at creation or update time. Disk-loaded YAML policies that fail validation fall back to a restrictive default. Example: filesystem_policy\ninclude_workdir: true\nread_only\n/usr\n/lib\n/proc\n/dev/urandom\n/etc\nread_write\n/sandbox\n/tmp\n/dev/null\nLandlock Category: Static Configures Landlock LSM enforcement at the kernel level. Landlock provides mandatory filesystem access control below what UNIX permissions allow. Field Type Required Values Description compatibility string No best_effort , hard_requirement How OpenShell handles Landlock failures. See behavior table below. Compatibility modes: Value Kernel ABI unavailable Individual path inaccessible All paths inaccessible best_effort Warns and continues without Landlock. Skips the path, applies remaining rules. Warns and continues without Landlock (refuses to apply an empty ruleset). hard_requirement Aborts sandbox startup. Aborts sandbox startup. Aborts sandbox startup. best_effort (the default) is appropriate for most deployments. It handles missing paths gracefully – for example, /app may not exist in every container image but is included in the baseline path set for containers that do have it. Individual missing paths are skipped while the remaining filesystem rules are still enforced. hard_requirement is for environments where any gap in filesystem isolation is unacceptable. If a listed path cannot be opened for any reason (missing, permission denied, symlink loop), sandbox startup fails immediately rather than running with reduced protection. When a path is skipped under best_effort , the sandbox logs a warning that includes the path, the specific error, and a human-readable reason (for example, “path does not exist” or “permission denied”). Example: landlock\ncompatibility: best_effort\nProcess Category: Static Sets the OS-level identity for the agent process inside the sandbox. Field Type Required Description run_as_user string No The user name or UID the agent process runs as. Default: sandbox . run_as_group string No The group name or GID the agent process runs as. Default: sandbox . Validation constraint: Neither run_as_user nor run_as_group may be set to root or 0 . Policies that request root process identity are rejected at creation or update time. Example: process\nrun_as_user: sandbox\nrun_as_group: sandbox\nNetwork Policies Category: Dynamic A map of named network policy entries. Each entry declares a set of endpoints and a set of binaries. Only the listed binaries are permitted to connect to the listed endpoints. The map key is a logical identifier. The name field inside the entry is the display name used in logs. Network Policy Entry Each entry in the network_policies map has the following fields: Field Type Required Description name string No Display name for the policy entry. Used in log output. Defaults to the map key. endpoints list of endpoint objects Yes Hosts and ports this entry permits. binaries list of binary objects Yes Executables allowed to connect to these endpoints. Endpoint Object Each endpoint defines a reachable destination and optional inspection rules. Field Type Required Description host string Yes Hostname or IP address. Supports wildcards: *.example.com matches any subdomain. port integer Yes TCP port number. protocol string No Set to rest to enable HTTP request inspection. Omit for TCP passthrough. tls string No TLS handling mode. The proxy auto-detects TLS by peeking the first bytes of each connection and terminates it when protocol is rest , so this field is optional in most cases. Set to skip to disable auto-detection for edge cases such as client-certificate mTLS or non-standard protocols. The values terminate and passthrough are deprecated and log a warning; they are still accepted for backward compatibility but have no effect on behavior. enforcement string No enforce actively blocks disallowed requests. audit logs violations but allows traffic through. access string No HTTP access level. One of read-only , read-write , or full . Mutually exclusive with rules . rules list of rule objects No Fine-grained per-method, per-path allow rules. Mutually exclusive with access . Access Levels The access field accepts one of the following values: Value Allowed HTTP Methods full All methods and paths. read-only GET , HEAD , OPTIONS . read-write GET , HEAD , OPTIONS , POST , PUT , PATCH . Rule Object Used when access is not set. Each rule explicitly allows a method and path combination. Field Type Required Description allow.method string Yes HTTP method to allow (for example, GET , POST ). allow.path string Yes URL path pattern. Supports * and ** glob syntax. Example with rules: rules\nallow\nmethod: GET\npath: /**/info/refs\nallow\nmethod: POST\npath: /**/git-upload-pack\nBinary Object Identifies an executable that is permitted to use the associated endpoints. Field Type Required Description path string Yes Filesystem path to the executable. Supports glob patterns with * and ** . For example, /sandbox/.vscode-server/** matches any executable under that directory tree. Full Example The following policy grants read-only GitHub API access and npm registry access: network_policies\ngithub_rest_api\nname: github-rest-api\nendpoints\nhost: api.github.com\nport: 443\nprotocol: rest\nenforcement: enforce\naccess: read-only\nbinaries\npath: /usr/local/bin/claude\npath: /usr/bin/node\npath: /usr/bin/gh\nnpm_registry\nname: npm-registry\nendpoints\nhost: registry.npmjs.org\nport: 443\nbinaries\npath: /usr/bin/npm\npath: /usr/bin/node","format":"text","summary":"Complete field reference for the sandbox policy YAML. Each field is documented with its type, whether it is required, and whether it is static (locked at sandbox creation) or dynamic (hot-reloadable on a running sandbox).","headings":[{"text":"Policy Schema Reference","level":1},{"text":"Top-Level Structure","level":2},{"text":"Version","level":2},{"text":"Filesystem Policy","level":2},{"text":"Landlock","level":2},{"text":"Process","level":2},{"text":"Network Policies","level":2},{"text":"Network Policy Entry","level":3},{"text":"Endpoint Object","level":3},{"text":"Access Levels","level":4},{"text":"Rule Object","level":4},{"text":"Binary Object","level":3},{"text":"Full Example","level":3}]} \ No newline at end of file diff --git a/pr-preview/pr-677/reference/support-matrix.json b/pr-preview/pr-677/reference/support-matrix.json index 9e893afef..927be9d18 100644 --- a/pr-preview/pr-677/reference/support-matrix.json +++ b/pr-preview/pr-677/reference/support-matrix.json @@ -1 +1 @@ -{"id":"reference/support-matrix","title":"Support Matrix","url":"reference/support-matrix.html","last_modified":"2026-03-30T18:03:24.465579+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"content":"Support Matrix This page lists the platform, software, runtime, and kernel requirements for running OpenShell. Supported Platforms OpenShell publishes multi-architecture container images for linux/amd64 and linux/arm64 . The CLI is supported on the following host platforms: Platform Architecture Status Linux (Debian/Ubuntu) x86_64 (amd64) Supported Linux (Debian/Ubuntu) aarch64 (arm64) Supported macOS (Docker Desktop) Apple Silicon (arm64) Supported Windows (WSL 2 + Docker Desktop) x86_64 Experimental Software Prerequisites The following software must be installed on the host before using the OpenShell CLI: Component Minimum Version Notes Docker Desktop or Docker Engine 28.04 Must be running before any openshell command. Sandbox Runtime Versions Sandbox container images are maintained in the openshell-community repository. Refer to that repository for the current list of installed components and their versions. Container Images OpenShell publishes two container images. Both are published for linux/amd64 and linux/arm64 . Image Reference Pulled When Cluster ghcr.io/nvidia/openshell/cluster:latest openshell gateway start Gateway ghcr.io/nvidia/openshell/gateway:latest Cluster startup (via Helm chart) The cluster image bundles the Helm charts, Kubernetes manifests, and the openshell-sandbox supervisor binary required to bootstrap the control plane. The supervisor binary is side-loaded into sandbox pods at runtime through a read-only host volume mount. The gateway image is pulled at cluster startup and runs the API server. Sandbox images are maintained separately in the openshell-community repository. To override the default image references, set the following environment variables: Variable Purpose OPENSHELL_CLUSTER_IMAGE Override the cluster image reference. OPENSHELL_COMMUNITY_REGISTRY Override the registry for community sandbox images. Kernel Requirements OpenShell enforces sandbox isolation through two Linux kernel security modules: Module Requirement Details Landlock LSM Recommended Enforces filesystem access restrictions at the kernel level. The best_effort compatibility mode uses the highest Landlock ABI the host kernel supports. The hard_requirement mode fails sandbox creation if the required ABI is unavailable. seccomp Required Filters dangerous system calls. Available on all modern Linux kernels (3.17+). On macOS, these kernel modules run inside the Docker Desktop Linux VM, not on the host kernel. Agent Compatibility For the full list of supported agents and their default policy coverage, refer to the ../about/supported-agents page","format":"text","summary":"This page lists the platform, software, runtime, and kernel requirements for running OpenShell.","headings":[{"text":"Support Matrix","level":1},{"text":"Supported Platforms","level":2},{"text":"Software Prerequisites","level":2},{"text":"Sandbox Runtime Versions","level":2},{"text":"Container Images","level":2},{"text":"Kernel Requirements","level":2},{"text":"Agent Compatibility","level":2}]} \ No newline at end of file +{"id":"reference/support-matrix","title":"Support Matrix","url":"reference/support-matrix.html","last_modified":"2026-03-30T18:08:14.837809+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"content":"Support Matrix This page lists the platform, software, runtime, and kernel requirements for running OpenShell. Supported Platforms OpenShell publishes multi-architecture container images for linux/amd64 and linux/arm64 . The CLI is supported on the following host platforms: Platform Architecture Status Linux (Debian/Ubuntu) x86_64 (amd64) Supported Linux (Debian/Ubuntu) aarch64 (arm64) Supported macOS (Docker Desktop) Apple Silicon (arm64) Supported Windows (WSL 2 + Docker Desktop) x86_64 Experimental Software Prerequisites The following software must be installed on the host before using the OpenShell CLI: Component Minimum Version Notes Docker Desktop or Docker Engine 28.04 Must be running before any openshell command. Sandbox Runtime Versions Sandbox container images are maintained in the openshell-community repository. Refer to that repository for the current list of installed components and their versions. Container Images OpenShell publishes two container images. Both are published for linux/amd64 and linux/arm64 . Image Reference Pulled When Cluster ghcr.io/nvidia/openshell/cluster:latest openshell gateway start Gateway ghcr.io/nvidia/openshell/gateway:latest Cluster startup (via Helm chart) The cluster image bundles the Helm charts, Kubernetes manifests, and the openshell-sandbox supervisor binary required to bootstrap the control plane. The supervisor binary is side-loaded into sandbox pods at runtime through a read-only host volume mount. The gateway image is pulled at cluster startup and runs the API server. Sandbox images are maintained separately in the openshell-community repository. To override the default image references, set the following environment variables: Variable Purpose OPENSHELL_CLUSTER_IMAGE Override the cluster image reference. OPENSHELL_COMMUNITY_REGISTRY Override the registry for community sandbox images. Kernel Requirements OpenShell enforces sandbox isolation through two Linux kernel security modules: Module Requirement Details Landlock LSM Recommended Enforces filesystem access restrictions at the kernel level. The best_effort compatibility mode uses the highest Landlock ABI the host kernel supports. The hard_requirement mode fails sandbox creation if the required ABI is unavailable. seccomp Required Filters dangerous system calls. Available on all modern Linux kernels (3.17+). On macOS, these kernel modules run inside the Docker Desktop Linux VM, not on the host kernel. Agent Compatibility For the full list of supported agents and their default policy coverage, refer to the ../about/supported-agents page","format":"text","summary":"This page lists the platform, software, runtime, and kernel requirements for running OpenShell.","headings":[{"text":"Support Matrix","level":1},{"text":"Supported Platforms","level":2},{"text":"Software Prerequisites","level":2},{"text":"Sandbox Runtime Versions","level":2},{"text":"Container Images","level":2},{"text":"Kernel Requirements","level":2},{"text":"Agent Compatibility","level":2}]} \ No newline at end of file diff --git a/pr-preview/pr-677/resources/license.json b/pr-preview/pr-677/resources/license.json index cb7d556fe..49319db00 100644 --- a/pr-preview/pr-677/resources/license.json +++ b/pr-preview/pr-677/resources/license.json @@ -1 +1 @@ -{"id":"resources/license","title":"License","url":"resources/license.html","last_modified":"2026-03-30T18:03:24.475513+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"NVIDIA OpenShell is licensed under the Apache License, Version 2.0.","tags":["License","Apache 2.0"],"topics":["Legal"],"content_type":"reference","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"License NVIDIA OpenShell is licensed under the Apache License, Version 2.0 . Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION Definitions. “License” shall mean the terms and conditions for use, reproduction\nand distribution as defined by Sections 1 through 9 of this document. “Licensor” shall mean the copyright owner or entity authorized by\nthe copyright owner that is granting the License. “Legal Entity” shall mean the union of the acting entity and all\nother entities that control, are controlled by, or are under common\ncontrol with that entity. For the purposes of this definition\ncontrol” means (i) the power, direct or indirect, to cause the\ndirection or management of such entity, whether by contract or\notherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity. “You” (or “Your”) shall mean an individual or Legal Entity\nexercising permissions granted by this License. “Source” form shall mean the preferred form for making modifications\nincluding but not limited to software source code, documentation\nsource, and configuration files. “Object” form shall mean any form resulting from mechanical\ntransformation or translation of a Source form, including but\nnot limited to compiled object code, generated documentation\nand conversions to other media types. “Work” shall mean the work of authorship, whether in Source or\nObject form, made available under the License, as indicated by a\ncopyright notice that is included in or attached to the work\nan example is provided in the Appendix below). “Derivative Works” shall mean any work, whether in Source or Object\nform, that is based on (or derived from) the Work and for which the\neditorial revisions, annotations, elaborations, or other modifications\nrepresent, as a whole, an original work of authorship. For the purposes\nof this License, Derivative Works shall not include works that remain\nseparable from, or merely link (or bind by name) to the interfaces of\nthe Work and Derivative Works thereof. “Contribution” shall mean any work of authorship, including\nthe original version of the Work and any modifications or additions\nto that Work or Derivative Works thereof, that is intentionally\nsubmitted to the Licensor for inclusion in the Work by the copyright owner\nor by an individual or Legal Entity authorized to submit on behalf of\nthe copyright owner. For the purposes of this definition, “submitted\nmeans any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems\nand issue tracking systems that are managed by, or on behalf of, the\nLicensor for the purpose of discussing and improving the Work, but\nexcluding communication that is conspicuously marked or otherwise\ndesignated in writing by the copyright owner as “Not a Contribution.” “Contributor” shall mean Licensor and any individual or Legal Entity\non behalf of whom a Contribution has been received by the Licensor and\nsubsequently incorporated within the Work. Grant of Copyright License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\ncopyright license to reproduce, prepare Derivative Works of\npublicly display, publicly perform, sublicense, and distribute the\nWork and such Derivative Works in Source or Object form. Grant of Patent License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\nexcept as stated in this section) patent license to make, have made\nuse, offer to sell, sell, import, and otherwise transfer the Work\nwhere such license applies only to those patent claims licensable\nby such Contributor that are necessarily infringed by their\nContribution(s) alone or by combination of their Contribution(s\nwith the Work to which such Contribution(s) was submitted. If You\ninstitute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work\nor a Contribution incorporated within the Work constitutes direct\nor contributory patent infringement, then any patent licenses\ngranted to You under this License for that Work shall terminate\nas of the date such litigation is filed. Redistribution. You may reproduce and distribute copies of the\nWork or Derivative Works thereof in any medium, with or without\nmodifications, and in Source or Object form, provided that You\nmeet the following conditions: (a) You must give any other recipients of the Work or\nDerivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices\nstating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works\nthat You distribute, all copyright, patent, trademark, and\nattribution notices from the Source form of the Work\nexcluding those notices that do not pertain to any part of\nthe Derivative Works; and (d) If the Work includes a “NOTICE” text file as part of its\ndistribution, then any Derivative Works that You distribute must\ninclude a readable copy of the attribution notices contained\nwithin such NOTICE file, excluding any notices that do not\npertain to any part of the Derivative Works, in at least one\nof the following places: within a NOTICE text file distributed\nas part of the Derivative Works; within the Source form or\ndocumentation, if provided along with the Derivative Works; or\nwithin a display generated by the Derivative Works, if and\nwherever such third-party notices normally appear. The contents\nof the NOTICE file are for informational purposes only and\ndo not modify the License. You may add Your own attribution\nnotices within Derivative Works that You distribute, alongside\nor as an addendum to the NOTICE text from the Work, provided\nthat such additional attribution notices cannot be construed\nas modifying the License. You may add Your own copyright statement to Your modifications and\nmay provide additional or different license terms and conditions\nfor use, reproduction, or distribution of Your modifications, or\nfor any such Derivative Works as a whole, provided Your use\nreproduction, and distribution of the Work otherwise complies with\nthe conditions stated in this License. Submission of Contributions. Unless You explicitly state otherwise\nany Contribution intentionally submitted for inclusion in the Work\nby You to the Licensor shall be under the terms and conditions of\nthis License, without any additional terms or conditions\nNotwithstanding the above, nothing herein shall supersede or modify\nthe terms of any separate license agreement you may have executed\nwith Licensor regarding such Contributions. Trademarks. This License does not grant permission to use the trade\nnames, trademarks, service marks, or product names of the Licensor\nexcept as required for reasonable and customary use in describing the\norigin of the Work and reproducing the content of the NOTICE file. Disclaimer of Warranty. Unless required by applicable law or\nagreed to in writing, Licensor provides the Work (and each\nContributor provides its Contributions) on an “AS IS” BASIS\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\nimplied, including, without limitation, any warranties or conditions\nof TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\nPARTICULAR PURPOSE. You are solely responsible for determining the\nappropriateness of using or redistributing the Work and assume any\nrisks associated with Your exercise of permissions under this License. Limitation of Liability. In no event and under no legal theory\nwhether in tort (including negligence), contract, or otherwise\nunless required by applicable law (such as deliberate and grossly\nnegligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special\nincidental, or consequential damages of any character arising as a\nresult of this License or out of the use or inability to use the\nWork (including but not limited to damages for loss of goodwill\nwork stoppage, computer failure or malfunction, or any and all\nother commercial damages or losses), even if such Contributor\nhas been advised of the possibility of such damages. Accepting Warranty or Additional Liability. While redistributing\nthe Work or Derivative Works thereof, You may choose to offer\nand charge a fee for, acceptance of support, warranty, indemnity\nor other liability obligations and/or rights consistent with this\nLicense. However, in accepting such obligations, You may act only\non Your own behalf and on Your sole responsibility, not on behalf\nof any other Contributor, and only if You agree to indemnify\ndefend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason\nof your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS Copyright 2025-2026 NVIDIA CORPORATION & AFFILIATES Licensed under the Apache License, Version 2.0 (the “License\nyou may not use this file except in compliance with the License\nYou may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an “AS IS” BASIS\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\nSee the License for the specific language governing permissions and\nlimitations under the License","format":"text","summary":"NVIDIA OpenShell is licensed under the Apache License, Version 2.0.","headings":[{"text":"License","level":1}]} \ No newline at end of file +{"id":"resources/license","title":"License","url":"resources/license.html","last_modified":"2026-03-30T18:08:14.846338+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"NVIDIA OpenShell is licensed under the Apache License, Version 2.0.","tags":["License","Apache 2.0"],"topics":["Legal"],"content_type":"reference","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"License NVIDIA OpenShell is licensed under the Apache License, Version 2.0 . Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION Definitions. “License” shall mean the terms and conditions for use, reproduction\nand distribution as defined by Sections 1 through 9 of this document. “Licensor” shall mean the copyright owner or entity authorized by\nthe copyright owner that is granting the License. “Legal Entity” shall mean the union of the acting entity and all\nother entities that control, are controlled by, or are under common\ncontrol with that entity. For the purposes of this definition\ncontrol” means (i) the power, direct or indirect, to cause the\ndirection or management of such entity, whether by contract or\notherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity. “You” (or “Your”) shall mean an individual or Legal Entity\nexercising permissions granted by this License. “Source” form shall mean the preferred form for making modifications\nincluding but not limited to software source code, documentation\nsource, and configuration files. “Object” form shall mean any form resulting from mechanical\ntransformation or translation of a Source form, including but\nnot limited to compiled object code, generated documentation\nand conversions to other media types. “Work” shall mean the work of authorship, whether in Source or\nObject form, made available under the License, as indicated by a\ncopyright notice that is included in or attached to the work\nan example is provided in the Appendix below). “Derivative Works” shall mean any work, whether in Source or Object\nform, that is based on (or derived from) the Work and for which the\neditorial revisions, annotations, elaborations, or other modifications\nrepresent, as a whole, an original work of authorship. For the purposes\nof this License, Derivative Works shall not include works that remain\nseparable from, or merely link (or bind by name) to the interfaces of\nthe Work and Derivative Works thereof. “Contribution” shall mean any work of authorship, including\nthe original version of the Work and any modifications or additions\nto that Work or Derivative Works thereof, that is intentionally\nsubmitted to the Licensor for inclusion in the Work by the copyright owner\nor by an individual or Legal Entity authorized to submit on behalf of\nthe copyright owner. For the purposes of this definition, “submitted\nmeans any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems\nand issue tracking systems that are managed by, or on behalf of, the\nLicensor for the purpose of discussing and improving the Work, but\nexcluding communication that is conspicuously marked or otherwise\ndesignated in writing by the copyright owner as “Not a Contribution.” “Contributor” shall mean Licensor and any individual or Legal Entity\non behalf of whom a Contribution has been received by the Licensor and\nsubsequently incorporated within the Work. Grant of Copyright License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\ncopyright license to reproduce, prepare Derivative Works of\npublicly display, publicly perform, sublicense, and distribute the\nWork and such Derivative Works in Source or Object form. Grant of Patent License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\nexcept as stated in this section) patent license to make, have made\nuse, offer to sell, sell, import, and otherwise transfer the Work\nwhere such license applies only to those patent claims licensable\nby such Contributor that are necessarily infringed by their\nContribution(s) alone or by combination of their Contribution(s\nwith the Work to which such Contribution(s) was submitted. If You\ninstitute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work\nor a Contribution incorporated within the Work constitutes direct\nor contributory patent infringement, then any patent licenses\ngranted to You under this License for that Work shall terminate\nas of the date such litigation is filed. Redistribution. You may reproduce and distribute copies of the\nWork or Derivative Works thereof in any medium, with or without\nmodifications, and in Source or Object form, provided that You\nmeet the following conditions: (a) You must give any other recipients of the Work or\nDerivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices\nstating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works\nthat You distribute, all copyright, patent, trademark, and\nattribution notices from the Source form of the Work\nexcluding those notices that do not pertain to any part of\nthe Derivative Works; and (d) If the Work includes a “NOTICE” text file as part of its\ndistribution, then any Derivative Works that You distribute must\ninclude a readable copy of the attribution notices contained\nwithin such NOTICE file, excluding any notices that do not\npertain to any part of the Derivative Works, in at least one\nof the following places: within a NOTICE text file distributed\nas part of the Derivative Works; within the Source form or\ndocumentation, if provided along with the Derivative Works; or\nwithin a display generated by the Derivative Works, if and\nwherever such third-party notices normally appear. The contents\nof the NOTICE file are for informational purposes only and\ndo not modify the License. You may add Your own attribution\nnotices within Derivative Works that You distribute, alongside\nor as an addendum to the NOTICE text from the Work, provided\nthat such additional attribution notices cannot be construed\nas modifying the License. You may add Your own copyright statement to Your modifications and\nmay provide additional or different license terms and conditions\nfor use, reproduction, or distribution of Your modifications, or\nfor any such Derivative Works as a whole, provided Your use\nreproduction, and distribution of the Work otherwise complies with\nthe conditions stated in this License. Submission of Contributions. Unless You explicitly state otherwise\nany Contribution intentionally submitted for inclusion in the Work\nby You to the Licensor shall be under the terms and conditions of\nthis License, without any additional terms or conditions\nNotwithstanding the above, nothing herein shall supersede or modify\nthe terms of any separate license agreement you may have executed\nwith Licensor regarding such Contributions. Trademarks. This License does not grant permission to use the trade\nnames, trademarks, service marks, or product names of the Licensor\nexcept as required for reasonable and customary use in describing the\norigin of the Work and reproducing the content of the NOTICE file. Disclaimer of Warranty. Unless required by applicable law or\nagreed to in writing, Licensor provides the Work (and each\nContributor provides its Contributions) on an “AS IS” BASIS\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\nimplied, including, without limitation, any warranties or conditions\nof TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\nPARTICULAR PURPOSE. You are solely responsible for determining the\nappropriateness of using or redistributing the Work and assume any\nrisks associated with Your exercise of permissions under this License. Limitation of Liability. In no event and under no legal theory\nwhether in tort (including negligence), contract, or otherwise\nunless required by applicable law (such as deliberate and grossly\nnegligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special\nincidental, or consequential damages of any character arising as a\nresult of this License or out of the use or inability to use the\nWork (including but not limited to damages for loss of goodwill\nwork stoppage, computer failure or malfunction, or any and all\nother commercial damages or losses), even if such Contributor\nhas been advised of the possibility of such damages. Accepting Warranty or Additional Liability. While redistributing\nthe Work or Derivative Works thereof, You may choose to offer\nand charge a fee for, acceptance of support, warranty, indemnity\nor other liability obligations and/or rights consistent with this\nLicense. However, in accepting such obligations, You may act only\non Your own behalf and on Your sole responsibility, not on behalf\nof any other Contributor, and only if You agree to indemnify\ndefend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason\nof your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS Copyright 2025-2026 NVIDIA CORPORATION & AFFILIATES Licensed under the Apache License, Version 2.0 (the “License\nyou may not use this file except in compliance with the License\nYou may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an “AS IS” BASIS\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied\nSee the License for the specific language governing permissions and\nlimitations under the License","format":"text","summary":"NVIDIA OpenShell is licensed under the Apache License, Version 2.0.","headings":[{"text":"License","level":1}]} \ No newline at end of file diff --git a/pr-preview/pr-677/sandboxes/community-sandboxes.json b/pr-preview/pr-677/sandboxes/community-sandboxes.json index 1729a04d4..27897d412 100644 --- a/pr-preview/pr-677/sandboxes/community-sandboxes.json +++ b/pr-preview/pr-677/sandboxes/community-sandboxes.json @@ -1 +1 @@ -{"id":"sandboxes/community-sandboxes","title":"Community Sandboxes","url":"sandboxes/community-sandboxes.html","last_modified":"2026-03-30T18:03:24.480968+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Use pre-built sandboxes from the OpenShell Community catalog or contribute your own.","tags":["Community","Sandbox","Container Image","Open Source"],"topics":["Generative AI","Cybersecurity"],"content_type":"concept","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Community Sandboxes Use pre-built sandboxes from the OpenShell Community catalog, or contribute your\nown. What Are Community Sandboxes Community sandboxes are ready-to-use environments published in the\nOpenShell Community repository\nEach sandbox bundles a Dockerfile, policy, optional skills, and startup scripts\ninto a single package that you can launch with one command. Current Catalog The following community sandboxes are available in the catalog. Sandbox Description base Foundational image with system tools and dev environment ollama Ollama with cloud and local model support, Claude Code, OpenCode, and Codex pre-installed. Use ollama launch inside the sandbox to start coding agents with zero config. openclaw Open agent manipulation and control sdg Synthetic data generation workflows Use a Community Sandbox Launch a community sandbox by name with the --from flag: $ openshell sandbox create --from openclaw\nWhen you pass --from with a community sandbox name, the CLI: Resolves the name against the\nOpenShell Community repository. Pulls the Dockerfile, policy, skills, and any startup scripts. Builds the container image locally. Creates the sandbox with the bundled configuration applied. You end up with a running sandbox whose image, policy, and tooling are all\npreconfigured by the community package. Other Sources The --from flag also accepts: Local directory paths: Point to a directory on disk that contains a\nDockerfile and optional policy/skills: $ openshell sandbox create --from ./my-sandbox-dir\nContainer image references: Use an existing container image directly: $ openshell sandbox create --from my-registry.example.com/my-image:latest\nContribute a Community Sandbox Each community sandbox is a directory under sandboxes/ in the\nOpenShell Community repository\nAt minimum, a sandbox directory must contain the following files: Dockerfile that defines the container image. README.md that describes the sandbox and how to use it. You can also include the following optional files: policy.yaml that defines the default policy applied when the sandbox launches. skills/ that contains agent skill definitions bundled with the sandbox. Startup scripts that are any scripts the Dockerfile or entrypoint invokes. To contribute, fork the repository, add your sandbox directory, and open a pull\nrequest. Refer to the repository’s\nCONTRIBUTING.md\nfor submission guidelines. The community catalog is designed to grow. If you have built a sandbox that\nsupports a particular workflow (data processing, simulation, code review\nor anything else), consider contributing it back so others can use it. Next Steps Explore related topics: Need to supply API keys or tokens? Set up manage-providers for credential management. Want to customize the sandbox policy? Write custom rules in policies","format":"text","summary":"Use pre-built sandboxes from the OpenShell Community catalog, or contribute your own.","headings":[{"text":"Community Sandboxes","level":1},{"text":"What Are Community Sandboxes","level":2},{"text":"Current Catalog","level":2},{"text":"Use a Community Sandbox","level":2},{"text":"Other Sources","level":3},{"text":"Contribute a Community Sandbox","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file +{"id":"sandboxes/community-sandboxes","title":"Community Sandboxes","url":"sandboxes/community-sandboxes.html","last_modified":"2026-03-30T18:08:14.851079+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Use pre-built sandboxes from the OpenShell Community catalog or contribute your own.","tags":["Community","Sandbox","Container Image","Open Source"],"topics":["Generative AI","Cybersecurity"],"content_type":"concept","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Community Sandboxes Use pre-built sandboxes from the OpenShell Community catalog, or contribute your\nown. What Are Community Sandboxes Community sandboxes are ready-to-use environments published in the\nOpenShell Community repository\nEach sandbox bundles a Dockerfile, policy, optional skills, and startup scripts\ninto a single package that you can launch with one command. Current Catalog The following community sandboxes are available in the catalog. Sandbox Description base Foundational image with system tools and dev environment ollama Ollama with cloud and local model support, Claude Code, OpenCode, and Codex pre-installed. Use ollama launch inside the sandbox to start coding agents with zero config. openclaw Open agent manipulation and control sdg Synthetic data generation workflows Use a Community Sandbox Launch a community sandbox by name with the --from flag: $ openshell sandbox create --from openclaw\nWhen you pass --from with a community sandbox name, the CLI: Resolves the name against the\nOpenShell Community repository. Pulls the Dockerfile, policy, skills, and any startup scripts. Builds the container image locally. Creates the sandbox with the bundled configuration applied. You end up with a running sandbox whose image, policy, and tooling are all\npreconfigured by the community package. Other Sources The --from flag also accepts: Local directory paths: Point to a directory on disk that contains a\nDockerfile and optional policy/skills: $ openshell sandbox create --from ./my-sandbox-dir\nContainer image references: Use an existing container image directly: $ openshell sandbox create --from my-registry.example.com/my-image:latest\nContribute a Community Sandbox Each community sandbox is a directory under sandboxes/ in the\nOpenShell Community repository\nAt minimum, a sandbox directory must contain the following files: Dockerfile that defines the container image. README.md that describes the sandbox and how to use it. You can also include the following optional files: policy.yaml that defines the default policy applied when the sandbox launches. skills/ that contains agent skill definitions bundled with the sandbox. Startup scripts that are any scripts the Dockerfile or entrypoint invokes. To contribute, fork the repository, add your sandbox directory, and open a pull\nrequest. Refer to the repository’s\nCONTRIBUTING.md\nfor submission guidelines. The community catalog is designed to grow. If you have built a sandbox that\nsupports a particular workflow (data processing, simulation, code review\nor anything else), consider contributing it back so others can use it. Next Steps Explore related topics: Need to supply API keys or tokens? Set up manage-providers for credential management. Want to customize the sandbox policy? Write custom rules in policies","format":"text","summary":"Use pre-built sandboxes from the OpenShell Community catalog, or contribute your own.","headings":[{"text":"Community Sandboxes","level":1},{"text":"What Are Community Sandboxes","level":2},{"text":"Current Catalog","level":2},{"text":"Use a Community Sandbox","level":2},{"text":"Other Sources","level":3},{"text":"Contribute a Community Sandbox","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file diff --git a/pr-preview/pr-677/sandboxes/index.json b/pr-preview/pr-677/sandboxes/index.json index 21eff3218..d11507d8e 100644 --- a/pr-preview/pr-677/sandboxes/index.json +++ b/pr-preview/pr-677/sandboxes/index.json @@ -1 +1 @@ -{"id":"sandboxes/index","title":"About Gateways and Sandboxes","url":"sandboxes/index.html","last_modified":"2026-03-30T18:03:24.486949+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Understand gateways, gateway types, sandbox lifecycle, supported agents, built-in default policy, and network access rules in OpenShell.","tags":["Gateway","Sandboxing","AI Agents","Security","Policy","Isolation"],"topics":["Generative AI","Cybersecurity"],"content_type":"concept","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"About Gateways and Sandboxes Every OpenShell deployment starts with a gateway and one or more sandboxes . The gateway is the control plane that manages sandbox lifecycle, providers, and policies. A sandbox is the data plane, a safe, private execution environment where an AI agent runs. Each sandbox runs with multiple layers of protection that prevent unauthorized data access, credential exposure, and network exfiltration. Protection layers include filesystem restrictions (Landlock), system call filtering (seccomp), network namespace isolation, and a privacy-enforcing HTTP CONNECT proxy. Gateway Types A gateway provisions sandboxes, brokers CLI requests, enforces policies, and manages provider credentials. OpenShell supports three deployment models, so the gateway can run wherever your workload requires. Type Where It Runs Best For Local Docker on your workstation Solo development and quick iteration. The CLI auto-bootstraps a local gateway if none exists. Remote Docker on a remote host via SSH Running sandboxes on a more powerful machine (for example, a DGX Spark) while keeping the CLI on your laptop. Cloud Behind a reverse proxy (for example, Cloudflare Access) Individual users accessing OpenShell behind a cloud VM. Cloud gateways are not yet intended for shared team access. All three types expose the same API surface. Sandboxes, policies, and providers work identically regardless of where the gateway runs. The only difference is how the CLI reaches the gateway, whether through a direct Docker socket, SSH tunnel, or HTTPS through a proxy. You do not need to deploy a gateway manually. Running openshell sandbox create without a gateway auto-bootstraps a local one for you. Sandbox Lifecycle Every sandbox moves through a defined set of phases: Phase Description Provisioning The runtime is setting up the sandbox environment, injecting credentials, and applying your policy. Ready The sandbox is running. The agent process is active and all isolation layers are enforced. You can connect, sync files, and view logs. Error Something went wrong during provisioning or execution. Check logs with openshell logs for details. Deleting The sandbox is being torn down. The system releases resources and purges credentials. Sandbox Policies OpenShell ships a built-in policy that covers common agent workflows out of the box\nWhen you create a sandbox without --policy , the default policy is applied. It controls three areas. Layer What It Controls How It Works Filesystem What the agent can access on disk Paths are split into read-only and read-write sets. Landlock LSM enforces these restrictions at the kernel level. Network What the agent can reach on the network Each policy block pairs allowed destinations (host and port) with allowed binaries (executable paths). The proxy matches every outbound connection to the binary that opened it. Both must match or the connection is denied. Process What privileges the agent has The agent runs as an unprivileged user with seccomp filters that block dangerous system calls. No sudo , no setuid , no path to elevated privileges. For the full breakdown of each default policy block and agent compatibility details, refer to ../reference/default-policy . For the full policy structure with annotated YAML examples, refer to policies . Next Steps Continue with one of the following: To create your first sandbox, refer to manage-sandboxes . To supply API keys or tokens, refer to manage-providers . To control what the agent can access, refer to policies . To use a pre-built environment, refer to the community-sandboxes catalog","format":"text","summary":"Every OpenShell deployment starts with a gateway and one or more sandboxes. The gateway is the control plane that manages sandbox lifecycle, providers, and policies. A sandbox is the data plane, a safe, private execution environment where an AI agent runs. Each sandbox runs with multiple layers o...","headings":[{"text":"About Gateways and Sandboxes","level":1},{"text":"Gateway Types","level":2},{"text":"Sandbox Lifecycle","level":2},{"text":"Sandbox Policies","level":2},{"text":"Next Steps","level":2}],"children":[{"id":"sandboxes/community-sandboxes","title":"Community Sandboxes","url":"sandboxes/community-sandboxes.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Use pre-built sandboxes from the OpenShell Community catalog or contribute your own.","tags":["Community","Sandbox","Container Image","Open Source"],"topics":["Generative AI","Cybersecurity"],"content_type":"concept","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Community Sandboxes Use pre-built sandboxes from the OpenShell Community catalog, or contribute your\nown. What Are Community Sandboxes Community sandboxes are ready-to-use environments published in the\nOpenShell Community repository\nEach sandbox bundles a Dockerfile, policy, optional skills, and startup scripts\ninto a single package that you can launch with one command. Current Catalog The following community sandboxes are available in the catalog. Sandbox Description base Foundational image with system tools and dev environment ollama Ollama with cloud and local model support, Claude Code, OpenCode, and Codex pre-installed. Use ollama launch inside the sandbox to start coding agents with zero config. openclaw Open agent manipulation and control sdg Synthetic data generation workflows Use a Community Sandbox Launch a community sandbox by name with the --from flag: $ openshell sandbox create --from openclaw\nWhen you pass --from with a community sandbox name, the CLI: Resolves the name against the\nOpenShell Community repository. Pulls the Dockerfile, policy, skills, and any startup scripts. Builds the container image locally. Creates the sandbox with the bundled configuration applied. You end up with a running sandbox whose image, policy, and tooling are all\npreconfigured by the community package. Other Sources The --from flag also accepts: Local directory paths: Point to a directory on disk that contains a\nDockerfile and optional policy/skills: $ openshell sandbox create --from ./my-sandbox-dir\nContainer image references: Use an existing container image directly: $ openshell sandbox create --from my-registry.example.com/my-image:latest\nContribute a Community Sandbox Each community sandbox is a directory under sandboxes/ in the\nOpenShell Community repository\nAt minimum, a sandbox directory must contain the following files: Dockerfile that defines the container image. README.md that describes the sandbox and how to use it. You can also include the following optional files: policy.yaml that defines the default policy applied when the sandbox launches. skills/ that contains agent skill definitions bundled with the sandbox. Startup scripts that are any scripts the Dockerfile or entrypoint invokes. To contribute, fork the repository, add your sandbox directory, and open a pull\nrequest. Refer to the repository’s\nCONTRIBUTING.md\nfor submission guidelines. The community catalog is designed to grow. If you have built a sandbox that\nsupports a particular workflow (data processing, simulation, code review\nor anything else), consider contributing it back so others can use it. Next Steps Explore related topics: Need to supply API keys or tokens? Set up manage-providers for credential management. Want to customize the sandbox policy? Write custom rules in policies","format":"text","content_length":2798,"word_count":404,"summary":"Use pre-built sandboxes from the OpenShell Community catalog, or contribute your own.","headings":[{"text":"Community Sandboxes","level":1,"id":"community-sandboxes"},{"text":"What Are Community Sandboxes","level":2,"id":"what-are-community-sandboxes"},{"text":"Current Catalog","level":2,"id":"current-catalog"},{"text":"Use a Community Sandbox","level":2,"id":"use-a-community-sandbox"},{"text":"Other Sources","level":3,"id":"other-sources"},{"text":"Contribute a Community Sandbox","level":2,"id":"contribute-a-community-sandbox"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Community Sandboxes What Are Community Sandboxes Current Catalog Use a Community Sandbox Other Sources Contribute a Community Sandbox Next Steps","keywords":["accepts","builds","catalog","claude","code","codex","com","community","container","contribute","creates","current","description","directly","dockerfile","each","explore","files","flag","foundational","image","launch","local","need","next","ollama","open","opencode","openshell","other","paths","point","pulls","refer","references","resolves","sandbox","sandboxes","set","skills","sources","startup","steps","synthetic","topics","want","write","yaml"],"code_blocks":[{"content":"$ openshell sandbox create --from openclaw","language":"text"},{"content":"$ openshell sandbox create --from ./my-sandbox-dir","language":"text"},{"content":"$ openshell sandbox create --from my-registry.example.com/my-image:latest","language":"text"}],"links":[{"text":"OpenShell Community","type":"external","url":"https://github.com/NVIDIA/OpenShell-Community"},{"text":"OpenShell Community","type":"external","url":"https://github.com/NVIDIA/OpenShell-Community"},{"text":"OpenShell Community","type":"external","url":"https://github.com/NVIDIA/OpenShell-Community"},{"text":"Contributing","type":"external","url":"https://github.com/NVIDIA/OpenShell-Community/blob/main/CONTRIBUTING.md","original_text":"CONTRIBUTING.md"}],"images":[],"doc_type":"tutorial","section_path":["Sandboxes","Community Sandboxes"]},{"id":"sandboxes/manage-gateways","title":"Deploy and Manage Gateways","url":"sandboxes/manage-gateways.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Deploy local and remote gateways, register cloud gateways, and manage multiple gateway environments.","tags":["Gateway","Deployment","Remote Gateway","CLI"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Deploy and Manage Gateways The gateway is the control plane for OpenShell. All control-plane traffic between the CLI and running sandboxes flows through the gateway. The gateway is responsible for: Provisioning and managing sandboxes, including creation, deletion, and status monitoring. Storing provider credentials (API keys, tokens) and delivering them to sandboxes at startup. Delivering network and filesystem policies to sandboxes. Policy enforcement itself happens inside each sandbox through the proxy, OPA, Landlock, and seccomp. Managing inference configuration and serving inference bundles so sandboxes can route requests to the correct backend. Providing the SSH tunnel endpoint so you can connect to sandboxes without exposing them directly. The gateway runs inside a Docker container and exposes a single port (gRPC and HTTP multiplexed), secured by mTLS by default. No separate Kubernetes installation is required. It can be deployed locally, on a remote host via SSH, or behind a cloud reverse proxy. Deploy a Local Gateway Deploy a gateway on your workstation. The only prerequisite is a running Docker daemon. $ openshell gateway start\nThe gateway becomes reachable at https://127.0.0.1:8080 . Verify it is healthy: $ openshell status\nYou do not need to deploy a gateway manually. If you run openshell sandbox create without a gateway, the CLI auto-bootstraps a local gateway for you. To use a different port or name: $ openshell gateway start --port 9090\nopenshell gateway start --name dev-local\nDeploy a Remote Gateway Deploy a gateway on a remote machine accessible via SSH. The only dependency on the remote host is Docker. $ openshell gateway start --remote user@hostname\nThe gateway is reachable at https://:8080 . To specify an SSH key: $ openshell gateway start --remote user@hostname --ssh-key ~/.ssh/my_key\nFor DGX Spark, use your Spark’s mDNS hostname: $ openshell gateway start --remote @.local\nRegister an Existing Gateway Use openshell gateway add to register a gateway that is already running. Cloud Gateway Register a gateway behind a reverse proxy such as Cloudflare Access: $ openshell gateway add https://gateway.example.com\nThis opens your browser for the proxy’s login flow. After authentication, the CLI stores a bearer token and sets the gateway as active. To give the gateway a specific name instead of deriving it from the hostname, use --name : $ openshell gateway add https://gateway.example.com --name production\nIf the token expires later, re-authenticate with: $ openshell gateway login\nRemote Gateway Register a gateway on a remote host you have SSH access to: $ openshell gateway add https://remote-host:8080 --remote user@remote-host\nOr use the ssh:// scheme to combine the SSH destination and gateway port: $ openshell gateway add ssh://user@remote-host:8080\nLocal Gateway Register a gateway running locally that was started outside the CLI: $ openshell gateway add https://127.0.0.1:8080 --local\nManage Multiple Gateways One gateway is always the active gateway. All CLI commands target it by default. Both gateway start and gateway add automatically set the new gateway as active. List all registered gateways: $ openshell gateway select\nSwitch the active gateway: $ openshell gateway select my-remote-cluster\nOverride the active gateway for a single command with -g : $ openshell status -g my-other-cluster\nShow deployment details for a gateway, including endpoint, auth mode, and port: $ openshell gateway info\nopenshell gateway info --name my-remote-cluster\nAdvanced Start Options Flag Purpose --gpu Enable NVIDIA GPU passthrough. Requires NVIDIA drivers and the Container Toolkit on the host. --plaintext Listen on HTTP instead of mTLS. Use behind a TLS-terminating reverse proxy. --disable-gateway-auth Skip mTLS client certificate checks. Use when a reverse proxy cannot forward client certs. --registry-username Username for registry authentication. Defaults to __token__ when --registry-token is set. Only needed for private registries. Also configurable with OPENSHELL_REGISTRY_USERNAME . --registry-token Authentication token for pulling container images. For GHCR, a GitHub PAT with read:packages scope. Only needed for private registries. Also configurable with OPENSHELL_REGISTRY_TOKEN . Stop and Destroy Stop a gateway while preserving its state for later restart: $ openshell gateway stop\nPermanently destroy a gateway and all its state: $ openshell gateway destroy\nFor cloud gateways, gateway destroy removes only the local registration. It does not affect the remote deployment. Target a specific gateway with --name : $ openshell gateway stop --name my-gateway\nopenshell gateway destroy --name my-gateway\nTroubleshoot Check gateway health: $ openshell status\nView gateway logs: $ openshell doctor logs\nopenshell doctor logs --tail # stream live\nopenshell doctor logs --lines 50 # last 50 lines\nRun a command inside the gateway container for deeper inspection: $ openshell doctor exec -- kubectl get pods -A\nopenshell doctor exec -- sh\nIf the gateway is in a bad state, recreate it: $ openshell gateway start --recreate\nNext Steps To create a sandbox using the gateway, refer to manage-sandboxes . To install the CLI and get started quickly, refer to the /get-started/quickstart","format":"text","content_length":5282,"word_count":779,"summary":"The gateway is the control plane for OpenShell. All control-plane traffic between the CLI and running sandboxes flows through the gateway.","headings":[{"text":"Deploy and Manage Gateways","level":1,"id":"deploy-and-manage-gateways"},{"text":"Deploy a Local Gateway","level":2,"id":"deploy-a-local-gateway"},{"text":"Deploy a Remote Gateway","level":2,"id":"deploy-a-remote-gateway"},{"text":"Register an Existing Gateway","level":2,"id":"register-an-existing-gateway"},{"text":"Cloud Gateway","level":3,"id":"cloud-gateway"},{"text":"Remote Gateway","level":3,"id":"remote-gateway"},{"text":"Local Gateway","level":3,"id":"local-gateway"},{"text":"Manage Multiple Gateways","level":2,"id":"manage-multiple-gateways"},{"text":"Advanced Start Options","level":2,"id":"advanced-start-options"},{"text":"Stop and Destroy","level":2,"id":"stop-and-destroy"},{"text":"Troubleshoot","level":2,"id":"troubleshoot"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Deploy and Manage Gateways Deploy a Local Gateway Deploy a Remote Gateway Register an Existing Gateway Cloud Gateway Remote Gateway Local Gateway Manage Multiple Gateways Advanced Start Options Stop and Destroy Troubleshoot Next Steps","keywords":["access","advanced","after","also","authentication","both","check","cloud","cloudflare","com","container","defaults","delivering","deploy","destroy","docker","enable","existing","flag","gateway","gateways","github","health","healthy","host","hostname","https","inspection","key","kubernetes","landlock","list","listen","local","logs","manage","managing","multiple","name","next","only","openshell","options","override","permanently","policy","port","providing","provisioning","purpose"],"code_blocks":[{"content":"$ openshell gateway start","language":"text"},{"content":"$ openshell status","language":"text"},{"content":"$ openshell gateway start --port 9090\n$ openshell gateway start --name dev-local","language":"text"},{"content":"$ openshell gateway start --remote user@hostname","language":"text"},{"content":"$ openshell gateway start --remote user@hostname --ssh-key ~/.ssh/my_key","language":"text"},{"content":"$ openshell gateway start --remote @.local","language":"text"},{"content":"$ openshell gateway add https://gateway.example.com","language":"text"},{"content":"$ openshell gateway add https://gateway.example.com --name production","language":"text"},{"content":"$ openshell gateway login","language":"text"},{"content":"$ openshell gateway add https://remote-host:8080 --remote user@remote-host","language":"text"},{"content":"$ openshell gateway add ssh://user@remote-host:8080","language":"text"},{"content":"$ openshell gateway add https://127.0.0.1:8080 --local","language":"text"},{"content":"$ openshell gateway select","language":"text"},{"content":"$ openshell gateway select my-remote-cluster","language":"text"},{"content":"$ openshell status -g my-other-cluster","language":"text"},{"content":"$ openshell gateway info\n$ openshell gateway info --name my-remote-cluster","language":"text"},{"content":"$ openshell gateway stop","language":"text"},{"content":"$ openshell gateway destroy","language":"text"},{"content":"$ openshell gateway stop --name my-gateway\n$ openshell gateway destroy --name my-gateway","language":"text"},{"content":"$ openshell status","language":"text"},{"content":"$ openshell doctor logs\n$ openshell doctor logs --tail # stream live\n$ openshell doctor logs --lines 50 # last 50 lines","language":"text"},{"content":"$ openshell doctor exec -- kubectl get pods -A\n$ openshell doctor exec -- sh","language":"text"},{"content":"$ openshell gateway start --recreate","language":"text"}],"links":[],"images":[],"doc_type":"documentation","section_path":["Sandboxes","Manage Gateways"]},{"id":"sandboxes/manage-providers","title":"Manage Providers and Credentials","url":"sandboxes/manage-providers.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Create and manage credential providers that inject API keys and tokens into OpenShell sandboxes.","tags":["Providers","Credentials","API Keys","Sandbox","Security"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Manage Providers and Credentials AI agents typically need credentials to access external services: an API key for the AI model provider, a token for GitHub or GitLab, and so on. OpenShell manages these credentials as first-class entities called providers . Create and manage providers that supply credentials to sandboxes. Create a Provider Providers can be created from local environment variables or with explicit credential values. From Local Credentials The fastest way to create a provider is to let the CLI discover credentials from\nyour shell environment: $ openshell provider create --name my-claude --type claude --from-existing\nThis reads ANTHROPIC_API_KEY or CLAUDE_API_KEY from your current environment\nand stores them in the provider. With Explicit Credentials Supply a credential value directly: $ openshell provider create --name my-api --type generic --credential API_KEY=sk-abc123\nBare Key Form Pass a key name without a value to read the value from the environment variable\nof that name: $ openshell provider create --name my-api --type generic --credential API_KEY\nThis looks up the current value of $API_KEY in your shell and stores it. Manage Providers List, inspect, update, and delete providers from the active cluster. List all providers: $ openshell provider list\nInspect a provider: $ openshell provider get my-claude\nUpdate a provider’s credentials: $ openshell provider update my-claude --type claude --from-existing\nDelete a provider: $ openshell provider delete my-claude\nAttach Providers to Sandboxes Pass one or more --provider flags when creating a sandbox: $ openshell sandbox create --provider my-claude --provider my-github -- claude\nEach --provider flag attaches one provider. The sandbox receives all\ncredentials from every attached provider at runtime. Providers cannot be added to a running sandbox. If you need to attach an\nadditional provider, delete the sandbox and recreate it with all required\nproviders specified. Auto-Discovery Shortcut When the trailing command in openshell sandbox create is a recognized tool name ( claude , codex , or opencode ), the CLI auto-creates the required\nprovider from your local credentials if one does not already exist. You do not\nneed to create the provider separately: $ openshell sandbox create -- claude\nThis detects claude as a known tool, finds your ANTHROPIC_API_KEY , creates\na provider, attaches it to the sandbox, and launches Claude Code. Supported Provider Types The following provider types are supported. Type Environment Variables Injected Typical Use claude ANTHROPIC_API_KEY , CLAUDE_API_KEY Claude Code, Anthropic API codex OPENAI_API_KEY OpenAI Codex generic User-defined Any service with custom credentials github GITHUB_TOKEN , GH_TOKEN GitHub API, gh CLI — refer to /tutorials/github-sandbox gitlab GITLAB_TOKEN , GLAB_TOKEN , CI_JOB_TOKEN GitLab API, glab CLI nvidia NVIDIA_API_KEY NVIDIA API Catalog openai OPENAI_API_KEY Any OpenAI-compatible endpoint. Set --config OPENAI_BASE_URL to point to the provider. Refer to /inference/configure . opencode OPENCODE_API_KEY , OPENROUTER_API_KEY , OPENAI_API_KEY opencode tool Use the generic type for any service not listed above. You define the\nenvironment variable names and values yourself with --credential . Supported Inference Providers The following providers have been tested with inference.local . Any provider that exposes an OpenAI-compatible API works with the openai type. Set --config OPENAI_BASE_URL to the provider’s base URL and --credential OPENAI_API_KEY to your API key. Provider Name Type Base URL API Key Variable NVIDIA API Catalog nvidia-prod nvidia https://integrate.api.nvidia.com/v1 NVIDIA_API_KEY Anthropic anthropic-prod anthropic https://api.anthropic.com ANTHROPIC_API_KEY Baseten baseten openai https://inference.baseten.co/v1 OPENAI_API_KEY Bitdeer AI bitdeer openai https://api-inference.bitdeer.ai/v1 OPENAI_API_KEY Deepinfra deepinfra openai https://api.deepinfra.com/v1/openai OPENAI_API_KEY Groq groq openai https://api.groq.com/openai/v1 OPENAI_API_KEY Ollama (local) ollama openai http://host.openshell.internal:11434/v1 OPENAI_API_KEY LM Studio (local) lmstudio openai http://host.openshell.internal:1234/v1 OPENAI_API_KEY Refer to your provider’s documentation for the correct base URL, available models, and API key setup. To configure inference routing, refer to /inference/configure . Next Steps Explore related topics: To control what the agent can access, refer to policies . To use a pre-built environment, refer to the community-sandboxes catalog. To view the complete field reference for the policy YAML, refer to the Policy Schema Reference","format":"text","content_length":4638,"word_count":632,"summary":"AI agents typically need credentials to access external services: an API key for the AI model provider, a token for GitHub or GitLab, and so on. OpenShell manages these credentials as first-class entities called providers.","headings":[{"text":"Manage Providers and Credentials","level":1,"id":"manage-providers-and-credentials"},{"text":"Create a Provider","level":2,"id":"create-a-provider"},{"text":"From Local Credentials","level":3,"id":"from-local-credentials"},{"text":"With Explicit Credentials","level":3,"id":"with-explicit-credentials"},{"text":"Bare Key Form","level":3,"id":"bare-key-form"},{"text":"Manage Providers","level":2,"id":"manage-providers"},{"text":"Attach Providers to Sandboxes","level":2,"id":"attach-providers-to-sandboxes"},{"text":"Auto-Discovery Shortcut","level":3,"id":"auto-discovery-shortcut"},{"text":"Supported Provider Types","level":2,"id":"supported-provider-types"},{"text":"Supported Inference Providers","level":2,"id":"supported-inference-providers"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Manage Providers and Credentials Create a Provider From Local Credentials With Explicit Credentials Bare Key Form Manage Providers Attach Providers to Sandboxes Auto-Discovery Shortcut Supported Provider Types Supported Inference Providers Next Steps","keywords":["anthropic","any","api","attach","auto","bare","base","baseten","bitdeer","catalog","claude","code","codex","com","create","credentials","deepinfra","delete","directly","discovery","each","environment","explicit","explore","form","from","github","gitlab","groq","http","https","inference","injected","inspect","internal","key","list","local","manage","name","next","ollama","openai","openshell","pass","policy","provider","providers","refer","reference"],"code_blocks":[{"content":"$ openshell provider create --name my-claude --type claude --from-existing","language":"text"},{"content":"$ openshell provider create --name my-api --type generic --credential API_KEY=sk-abc123","language":"text"},{"content":"$ openshell provider create --name my-api --type generic --credential API_KEY","language":"text"},{"content":"$ openshell provider list","language":"text"},{"content":"$ openshell provider get my-claude","language":"text"},{"content":"$ openshell provider update my-claude --type claude --from-existing","language":"text"},{"content":"$ openshell provider delete my-claude","language":"text"},{"content":"$ openshell sandbox create --provider my-claude --provider my-github -- claude","language":"text"},{"content":"$ openshell sandbox create -- claude","language":"text"}],"links":[],"images":[],"doc_type":"tutorial","section_path":["Sandboxes","Manage Providers"]},{"id":"sandboxes/manage-sandboxes","title":"Manage Sandboxes","url":"sandboxes/manage-sandboxes.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Set up gateways, create sandboxes, and manage the full sandbox lifecycle.","tags":["Gateway","Sandboxing","AI Agents","Sandbox Management","CLI"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Manage Sandboxes This page covers creating sandboxes and managing them. For background on what sandboxes are and how isolation works, refer to About Sandboxes . Docker must be running before you create a gateway or sandbox. If it is not, the CLI\nreturns a connection-refused error ( os error 61 ) without explaining\nthe cause. Start Docker and try again. Create a Sandbox Create a sandbox with a single command. For example, to create a sandbox with Claude, run: $ openshell sandbox create -- claude\nEvery sandbox requires a gateway. If you run openshell sandbox create without a gateway, the CLI auto-bootstraps a local gateway. Remote Gateways If you plan to run sandboxes on a remote host or a cloud-hosted gateway, set up the gateway first. Refer to manage-gateways for deployment options and multi-gateway management. GPU Resources To request GPU resources, add --gpu : $ openshell sandbox create --gpu -- claude\nCustom Containers Use --from to create a sandbox from a pre-built community package, a local directory, or a container image: $ openshell sandbox create --from openclaw\nopenshell sandbox create --from ./my-sandbox-dir\nopenshell sandbox create --from my-registry.example.com/my-image:latest\nThe CLI resolves community names against the OpenShell Community catalog, pulls the bundled Dockerfile and policy, builds the image locally, and creates the sandbox. For the full catalog and how to contribute your own, refer to community-sandboxes . Connect to a Sandbox Open an SSH session into a running sandbox: $ openshell sandbox connect my-sandbox\nLaunch VS Code or Cursor directly into the sandbox workspace: $ openshell sandbox create --editor vscode --name my-sandbox\nopenshell sandbox connect my-sandbox --editor cursor\nWhen --editor is used, OpenShell keeps the sandbox alive and installs an\nOpenShell-managed SSH include file instead of cluttering your main\nssh/config with generated host blocks. Monitor and Debug List all sandboxes: $ openshell sandbox list\nGet detailed information about a specific sandbox: $ openshell sandbox get my-sandbox\nStream sandbox logs to monitor agent activity and diagnose policy decisions: $ openshell logs my-sandbox\nFlag Purpose Example --tail Stream logs in real time openshell logs my-sandbox --tail --source Filter by log source --source sandbox --level Filter by severity --level warn --since Show logs from a time window --since 5m OpenShell Terminal combines sandbox status and live logs in a single real-time dashboard: $ openshell term\nUse the terminal to spot blocked connections marked action=deny and inference-related proxy activity. If a connection is blocked unexpectedly, add the host to your network policy. Refer to policies for the workflow. Port Forwarding Forward a local port to a running sandbox to access services inside it, such as a web server or database: $ openshell forward start 8000 my-sandbox\nopenshell forward start 8000 my-sandbox -d # run in background\nList and stop active forwards: $ openshell forward list\nopenshell forward stop 8000 my-sandbox\nYou can also forward a port at creation time with --forward : $ openshell sandbox create --forward 8000 -- claude\nSSH Config Generate an SSH config entry for a sandbox so tools like VS Code Remote-SSH can connect directly: $ openshell sandbox ssh-config my-sandbox\nAppend the output to ~/.ssh/config or use --editor on sandbox create / sandbox connect for automatic setup. Transfer Files Upload files from your host into the sandbox: $ openshell sandbox upload my-sandbox ./src /sandbox/src\nDownload files from the sandbox to your host: $ openshell sandbox download my-sandbox /sandbox/output ./local\nYou can also upload files at creation time with the --upload flag on\nopenshell sandbox create . Delete Sandboxes Deleting a sandbox stops all processes, releases resources, and purges injected credentials. $ openshell sandbox delete my-sandbox\nNext Steps To follow a complete end-to-end example, refer to the /tutorials/github-sandbox tutorial. To supply API keys or tokens, refer to manage-providers . To control what the agent can access, refer to policies . To use a pre-built environment, refer to the community-sandboxes catalog","format":"text","content_length":4171,"word_count":637,"summary":"This page covers creating sandboxes and managing them. For background on what sandboxes are and how isolation works, refer to About Sandboxes.","headings":[{"text":"Manage Sandboxes","level":1,"id":"manage-sandboxes"},{"text":"Create a Sandbox","level":2,"id":"create-a-sandbox"},{"text":"Remote Gateways","level":3,"id":"remote-gateways"},{"text":"GPU Resources","level":3,"id":"gpu-resources"},{"text":"Custom Containers","level":3,"id":"custom-containers"},{"text":"Connect to a Sandbox","level":2,"id":"connect-to-a-sandbox"},{"text":"Monitor and Debug","level":2,"id":"monitor-and-debug"},{"text":"Port Forwarding","level":2,"id":"port-forwarding"},{"text":"SSH Config","level":2,"id":"ssh-config"},{"text":"Transfer Files","level":2,"id":"transfer-files"},{"text":"Delete Sandboxes","level":2,"id":"delete-sandboxes"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Manage Sandboxes Create a Sandbox Remote Gateways GPU Resources Custom Containers Connect to a Sandbox Monitor and Debug Port Forwarding SSH Config Transfer Files Delete Sandboxes Next Steps","keywords":["about","action","append","claude","code","com","community","config","connect","containers","create","cursor","custom","dashboard","database","debug","decisions","delete","deleting","directly","docker","dockerfile","download","every","example","files","filter","flag","forward","forwarding","forwards","gateways","generate","gpu","host","image","launch","list","manage","monitor","next","open","openshell","port","purpose","refer","remote","resources","run","sandbox"],"code_blocks":[{"content":"$ openshell sandbox create -- claude","language":"text"},{"content":"$ openshell sandbox create --gpu -- claude","language":"text"},{"content":"$ openshell sandbox create --from openclaw\n$ openshell sandbox create --from ./my-sandbox-dir\n$ openshell sandbox create --from my-registry.example.com/my-image:latest","language":"text"},{"content":"$ openshell sandbox connect my-sandbox","language":"text"},{"content":"$ openshell sandbox create --editor vscode --name my-sandbox\n$ openshell sandbox connect my-sandbox --editor cursor","language":"text"},{"content":"$ openshell sandbox list","language":"text"},{"content":"$ openshell sandbox get my-sandbox","language":"text"},{"content":"$ openshell logs my-sandbox","language":"text"},{"content":"$ openshell term","language":"text"},{"content":"$ openshell forward start 8000 my-sandbox\n$ openshell forward start 8000 my-sandbox -d # run in background","language":"text"},{"content":"$ openshell forward list\n$ openshell forward stop 8000 my-sandbox","language":"text"},{"content":"$ openshell sandbox create --forward 8000 -- claude","language":"text"},{"content":"$ openshell sandbox ssh-config my-sandbox","language":"text"},{"content":"$ openshell sandbox upload my-sandbox ./src /sandbox/src","language":"text"},{"content":"$ openshell sandbox download my-sandbox /sandbox/output ./local","language":"text"},{"content":"$ openshell sandbox delete my-sandbox","language":"text"}],"links":[{"text":"OpenShell Community","type":"external","url":"https://github.com/NVIDIA/OpenShell-Community"}],"images":[],"doc_type":"tutorial","section_path":["Sandboxes","Manage Sandboxes"]},{"id":"sandboxes/policies","title":"Customize Sandbox Policies","url":"sandboxes/policies.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Apply, iterate, and debug sandbox network policies with hot-reload on running OpenShell sandboxes.","tags":["Policy","Network Policy","Sandbox","Security","Hot Reload"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_intermediate","audience":["engineer"],"content":"Customize Sandbox Policies Use this page to apply and iterate policy changes on running sandboxes. For a full field-by-field YAML definition, use the Policy Schema Reference . Policy Structure A policy has static sections filesystem_policy , landlock , and process that are locked at sandbox creation, and a dynamic section network_policies that is hot-reloadable on a running sandbox. version: 1\nStatic: locked at sandbox creation. Paths the agent can read vs read/write\nfilesystem_policy\nread_only: [/usr, /lib, /etc\nread_write: [/sandbox, /tmp\nStatic: Landlock LSM kernel enforcement. best_effort uses highest ABI the host supports\nlandlock\ncompatibility: best_effort\nStatic: Unprivileged user/group the agent process runs as\nprocess\nrun_as_user: sandbox\nrun_as_group: sandbox\nDynamic: hot-reloadable. Named blocks of endpoints + binaries allowed to reach them\nnetwork_policies\nmy_api\nname: my-api\nendpoints\nhost: api.example.com\nport: 443\nprotocol: rest\nenforcement: enforce\naccess: full\nbinaries\npath: /usr/bin/curl\nStatic sections are locked at sandbox creation. Changing them requires destroying and recreating the sandbox\nDynamic sections can be updated on a running sandbox with openshell policy set and take effect without restarting. Section Type Description filesystem_policy Static Controls which directories the agent can access on disk. Paths are split into read_only and read_write lists. Any path not listed in either list is inaccessible. Set include_workdir: true to automatically add the agent’s working directory to read_write . Landlock LSM enforces these restrictions at the kernel level. landlock Static Configures Landlock LSM enforcement behavior. Set compatibility to best_effort (skip individual inaccessible paths while applying remaining rules) or hard_requirement (fail if any path is inaccessible or the required kernel ABI is unavailable). See the Policy Schema Reference for the full behavior table. process Static Sets the OS-level identity for the agent process. run_as_user and run_as_group default to sandbox . Root ( root or 0 ) is rejected. The agent also runs with seccomp filters that block dangerous system calls. network_policies Dynamic Controls network access for ordinary outbound traffic from the sandbox. Each block has a name, a list of endpoints (host, port, protocol, and optional rules), and a list of binaries allowed to use those endpoints.
Every outbound connection except https://inference.local goes through the proxy, which queries the policy engine with the destination and calling binary. A connection is allowed only when both match an entry in the same policy block.
For endpoints with protocol: rest , the proxy auto-detects TLS and terminates it so each HTTP request is checked against that endpoint’s rules (method and path).
Endpoints without protocol allow the TCP stream through without inspecting payloads.
If no endpoint matches, the connection is denied. Configure managed inference separately through ../inference/configure . Baseline Filesystem Paths When a sandbox runs in proxy mode (the default), OpenShell automatically adds baseline filesystem paths required for the sandbox child process to function: /usr , /lib , /etc , /var/log (read-only) and /sandbox , /tmp (read-write). Paths like /app are included in the baseline set but are only added if they exist in the container image. This filtering prevents a missing baseline path from degrading Landlock enforcement. Without it, a single missing path could cause the entire Landlock ruleset to fail, leaving the sandbox with no filesystem restrictions at all. User-specified paths in your policy YAML are not pre-filtered. If you list a path that does not exist: In best_effort mode, the path is skipped with a warning and remaining rules are still applied. In hard_requirement mode, sandbox startup fails immediately. This distinction means baseline system paths degrade gracefully while user-specified paths surface configuration errors. Apply a Custom Policy Pass a policy YAML file when creating the sandbox: $ openshell sandbox create --policy ./my-policy.yaml -- claude\nopenshell sandbox create keeps the sandbox running after the initial command exits, which is useful when you plan to iterate on the policy. Add --no-keep if you want the sandbox deleted automatically instead. To avoid passing --policy every time, set a default policy with an environment variable: $ export OPENSHELL_SANDBOX_POLICY=./my-policy.yaml\nopenshell sandbox create -- claude\nThe CLI uses the policy from OPENSHELL_SANDBOX_POLICY whenever --policy is not explicitly provided. Iterate on a Running Sandbox To change what the sandbox can access, pull the current policy, edit the YAML, and push the update. The workflow is iterative: create the sandbox, monitor logs for denied actions, pull the policy, modify it, push, and verify. The following steps outline the hot-reload policy update workflow. Create the sandbox with your initial policy by following Apply a Custom Policy above (or set OPENSHELL_SANDBOX_POLICY ). Monitor denials. Each log entry shows host, port, binary, and reason. Alternatively, use openshell term for a live dashboard. $ openshell logs --tail --source sandbox\nPull the current policy. Strip the metadata header (Version, Hash, Status) before reusing the file. $ openshell policy get --full > current-policy.yaml\nEdit the YAML: add or adjust network_policies entries, binaries, access , or rules . Push the updated policy. Exit codes: 0 = loaded, 1 = validation failed, 124 = timeout. $ openshell policy set --policy current-policy.yaml --wait\nVerify the new revision. If status is loaded , repeat from step 2 as needed; if failed , fix the policy and repeat from step 4. $ openshell policy list --tail --source sandbox for the denied host, path, and binary. When triaging denied requests, check: Destination host and port to confirm which endpoint is missing. Calling binary path to confirm which binaries entry needs to be added or adjusted. HTTP method and path (for REST endpoints) to confirm which rules entry needs to be added or adjusted. Then push the updated policy as described above. Examples Add these blocks to the network_policies section of your sandbox policy. Apply with openshell policy set --policy --wait\nUse Simple endpoint for host-level allowlists and Granular rules for method/path control. Simple endpoint Allow pip install and uv pip install to reach PyPI: pypi\nname: pypi\nendpoints\nhost: pypi.org\nport: 443\nhost: files.pythonhosted.org\nport: 443\nbinaries\n{ path: /usr/bin/pip\n{ path: /usr/local/bin/uv\nEndpoints without protocol use TCP passthrough, where the proxy allows the stream without inspecting payloads. Granular rules Allow Claude and the GitHub CLI to reach api.github.com with per-path rules: read-only (GET, HEAD, OPTIONS) and GraphQL (POST) for all paths; full write access for alpha-repo ; and create/edit issues only for bravo-repo . Replace with your GitHub org or username. For an end-to-end walkthrough that combines this policy with a GitHub credential provider and sandbox creation, refer to /tutorials/github-sandbox . github_repos\nname: github_repos\nendpoints\nhost: api.github.com\nport: 443\nprotocol: rest\nenforcement: enforce\nrules\nallow\nmethod: GET\npath:\nallow\nmethod: HEAD\npath:\nallow\nmethod: OPTIONS\npath:\nallow\nmethod: POST\npath: \"/graphql\nallow\nmethod:\npath: \"/repos//alpha-repo\nallow\nmethod: POST\npath: \"/repos//bravo-repo/issues\nallow\nmethod: PATCH\npath: \"/repos//bravo-repo/issues\nbinaries\n{ path: /usr/local/bin/claude\n{ path: /usr/bin/gh\nEndpoints with protocol: rest enable HTTP request inspection. The proxy auto-detects TLS on HTTPS endpoints, terminates it, and checks each HTTP request against the rules list. Next Steps Explore related topics: To learn about network access rules and sandbox isolation layers, refer to index . To view the full field-by-field YAML definition, refer to the Policy Schema Reference . To review the default policy breakdown, refer to ../reference/default-policy","format":"text","content_length":8698,"word_count":1276,"summary":"Use this page to apply and iterate policy changes on running sandboxes. For a full field-by-field YAML definition, use the Policy Schema Reference.","headings":[{"text":"Customize Sandbox Policies","level":1,"id":"customize-sandbox-policies"},{"text":"Policy Structure","level":2,"id":"policy-structure"},{"text":"Baseline Filesystem Paths","level":2,"id":"baseline-filesystem-paths"},{"text":"Apply a Custom Policy","level":2,"id":"apply-a-custom-policy"},{"text":"Iterate on a Running Sandbox","level":2,"id":"iterate-on-a-running-sandbox"},{"text":"Global Policy Override","level":2,"id":"global-policy-override"},{"text":"Debug Denied Requests","level":2,"id":"debug-denied-requests"},{"text":"Examples","level":2,"id":"examples"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Customize Sandbox Policies Policy Structure Baseline Filesystem Paths Apply a Custom Policy Iterate on a Running Sandbox Global Policy Override Debug Denied Requests Examples Next Steps","keywords":["access","add","allow","alternatively","any","apply","baseline","calling","changing","check","claude","codes","com","compatibility","configure","configured","configures","controls","create","custom","customize","debug","denied","description","destination","dynamic","each","edit","endpoints","enforcement","every","examples","exist","exit","explore","filesystem","function","github","global","granular","graphql","hash","host","https","include_workdir","iterate","iterative","landlock","method","monitor"],"code_blocks":[{"content":"version: 1\n\n# Static: locked at sandbox creation. Paths the agent can read vs read/write.\nfilesystem_policy:\n read_only: [/usr, /lib, /etc]\n read_write: [/sandbox, /tmp]\n\n# Static: Landlock LSM kernel enforcement. best_effort uses highest ABI the host supports.\nlandlock:\n compatibility: best_effort\n\n# Static: Unprivileged user/group the agent process runs as.\nprocess:\n run_as_user: sandbox\n run_as_group: sandbox\n\n# Dynamic: hot-reloadable. Named blocks of endpoints + binaries allowed to reach them.\nnetwork_policies:\n my_api:\n name: my-api\n endpoints:\n - host: api.example.com\n port: 443\n protocol: rest\n enforcement: enforce\n access: full\n binaries:\n - path: /usr/bin/curl","language":"text"},{"content":"$ openshell sandbox create --policy ./my-policy.yaml -- claude","language":"text"},{"content":"$ export OPENSHELL_SANDBOX_POLICY=./my-policy.yaml\n$ openshell sandbox create -- claude","language":"text"},{"content":"$ openshell logs --tail --source sandbox","language":"text"},{"content":"$ openshell policy get --full > current-policy.yaml","language":"text"},{"content":"$ openshell policy set --policy current-policy.yaml --wait","language":"text"},{"content":"$ openshell policy list ","language":"text"},{"content":"$ openshell policy set --global --policy ./global-policy.yaml","language":"text"},{"content":"$ openshell policy delete --global","language":"text"},{"content":"$ openshell settings get ","language":"text"},{"content":"pypi:\n name: pypi\n endpoints:\n - host: pypi.org\n port: 443\n - host: files.pythonhosted.org\n port: 443\n binaries:\n - { path: /usr/bin/pip }\n - { path: /usr/local/bin/uv }","language":"text"},{"content":"github_repos:\n name: github_repos\n endpoints:\n - host: api.github.com\n port: 443\n protocol: rest\n enforcement: enforce\n rules:\n - allow:\n method: GET\n path: \"/**\"\n - allow:\n method: HEAD\n path: \"/**\"\n - allow:\n method: OPTIONS\n path: \"/**\"\n - allow:\n method: POST\n path: \"/graphql\"\n - allow:\n method: \"*\"\n path: \"/repos//alpha-repo/**\"\n - allow:\n method: POST\n path: \"/repos//bravo-repo/issues\"\n - allow:\n method: PATCH\n path: \"/repos//bravo-repo/issues/*\"\n binaries:\n - { path: /usr/local/bin/claude }\n - { path: /usr/bin/gh }","language":"text"}],"links":[{"text":"Landlock LSM","type":"external","url":"https://docs.kernel.org/security/landlock.html"},{"text":"Apply a Custom Policy","type":"anchor","url":"#apply-a-custom-policy"}],"images":[],"doc_type":"documentation","section_path":["Sandboxes","Policies"]}]} \ No newline at end of file +{"id":"sandboxes/index","title":"About Gateways and Sandboxes","url":"sandboxes/index.html","last_modified":"2026-03-30T18:08:14.856154+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Understand gateways, gateway types, sandbox lifecycle, supported agents, built-in default policy, and network access rules in OpenShell.","tags":["Gateway","Sandboxing","AI Agents","Security","Policy","Isolation"],"topics":["Generative AI","Cybersecurity"],"content_type":"concept","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"About Gateways and Sandboxes Every OpenShell deployment starts with a gateway and one or more sandboxes . The gateway is the control plane that manages sandbox lifecycle, providers, and policies. A sandbox is the data plane, a safe, private execution environment where an AI agent runs. Each sandbox runs with multiple layers of protection that prevent unauthorized data access, credential exposure, and network exfiltration. Protection layers include filesystem restrictions (Landlock), system call filtering (seccomp), network namespace isolation, and a privacy-enforcing HTTP CONNECT proxy. Gateway Types A gateway provisions sandboxes, brokers CLI requests, enforces policies, and manages provider credentials. OpenShell supports three deployment models, so the gateway can run wherever your workload requires. Type Where It Runs Best For Local Docker on your workstation Solo development and quick iteration. The CLI auto-bootstraps a local gateway if none exists. Remote Docker on a remote host via SSH Running sandboxes on a more powerful machine (for example, a DGX Spark) while keeping the CLI on your laptop. Cloud Behind a reverse proxy (for example, Cloudflare Access) Individual users accessing OpenShell behind a cloud VM. Cloud gateways are not yet intended for shared team access. All three types expose the same API surface. Sandboxes, policies, and providers work identically regardless of where the gateway runs. The only difference is how the CLI reaches the gateway, whether through a direct Docker socket, SSH tunnel, or HTTPS through a proxy. You do not need to deploy a gateway manually. Running openshell sandbox create without a gateway auto-bootstraps a local one for you. Sandbox Lifecycle Every sandbox moves through a defined set of phases: Phase Description Provisioning The runtime is setting up the sandbox environment, injecting credentials, and applying your policy. Ready The sandbox is running. The agent process is active and all isolation layers are enforced. You can connect, sync files, and view logs. Error Something went wrong during provisioning or execution. Check logs with openshell logs for details. Deleting The sandbox is being torn down. The system releases resources and purges credentials. Sandbox Policies OpenShell ships a built-in policy that covers common agent workflows out of the box\nWhen you create a sandbox without --policy , the default policy is applied. It controls three areas. Layer What It Controls How It Works Filesystem What the agent can access on disk Paths are split into read-only and read-write sets. Landlock LSM enforces these restrictions at the kernel level. Network What the agent can reach on the network Each policy block pairs allowed destinations (host and port) with allowed binaries (executable paths). The proxy matches every outbound connection to the binary that opened it. Both must match or the connection is denied. Process What privileges the agent has The agent runs as an unprivileged user with seccomp filters that block dangerous system calls. No sudo , no setuid , no path to elevated privileges. For the full breakdown of each default policy block and agent compatibility details, refer to ../reference/default-policy . For the full policy structure with annotated YAML examples, refer to policies . Next Steps Continue with one of the following: To create your first sandbox, refer to manage-sandboxes . To supply API keys or tokens, refer to manage-providers . To control what the agent can access, refer to policies . To use a pre-built environment, refer to the community-sandboxes catalog","format":"text","summary":"Every OpenShell deployment starts with a gateway and one or more sandboxes. The gateway is the control plane that manages sandbox lifecycle, providers, and policies. A sandbox is the data plane, a safe, private execution environment where an AI agent runs. Each sandbox runs with multiple layers o...","headings":[{"text":"About Gateways and Sandboxes","level":1},{"text":"Gateway Types","level":2},{"text":"Sandbox Lifecycle","level":2},{"text":"Sandbox Policies","level":2},{"text":"Next Steps","level":2}],"children":[{"id":"sandboxes/community-sandboxes","title":"Community Sandboxes","url":"sandboxes/community-sandboxes.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Use pre-built sandboxes from the OpenShell Community catalog or contribute your own.","tags":["Community","Sandbox","Container Image","Open Source"],"topics":["Generative AI","Cybersecurity"],"content_type":"concept","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Community Sandboxes Use pre-built sandboxes from the OpenShell Community catalog, or contribute your\nown. What Are Community Sandboxes Community sandboxes are ready-to-use environments published in the\nOpenShell Community repository\nEach sandbox bundles a Dockerfile, policy, optional skills, and startup scripts\ninto a single package that you can launch with one command. Current Catalog The following community sandboxes are available in the catalog. Sandbox Description base Foundational image with system tools and dev environment ollama Ollama with cloud and local model support, Claude Code, OpenCode, and Codex pre-installed. Use ollama launch inside the sandbox to start coding agents with zero config. openclaw Open agent manipulation and control sdg Synthetic data generation workflows Use a Community Sandbox Launch a community sandbox by name with the --from flag: $ openshell sandbox create --from openclaw\nWhen you pass --from with a community sandbox name, the CLI: Resolves the name against the\nOpenShell Community repository. Pulls the Dockerfile, policy, skills, and any startup scripts. Builds the container image locally. Creates the sandbox with the bundled configuration applied. You end up with a running sandbox whose image, policy, and tooling are all\npreconfigured by the community package. Other Sources The --from flag also accepts: Local directory paths: Point to a directory on disk that contains a\nDockerfile and optional policy/skills: $ openshell sandbox create --from ./my-sandbox-dir\nContainer image references: Use an existing container image directly: $ openshell sandbox create --from my-registry.example.com/my-image:latest\nContribute a Community Sandbox Each community sandbox is a directory under sandboxes/ in the\nOpenShell Community repository\nAt minimum, a sandbox directory must contain the following files: Dockerfile that defines the container image. README.md that describes the sandbox and how to use it. You can also include the following optional files: policy.yaml that defines the default policy applied when the sandbox launches. skills/ that contains agent skill definitions bundled with the sandbox. Startup scripts that are any scripts the Dockerfile or entrypoint invokes. To contribute, fork the repository, add your sandbox directory, and open a pull\nrequest. Refer to the repository’s\nCONTRIBUTING.md\nfor submission guidelines. The community catalog is designed to grow. If you have built a sandbox that\nsupports a particular workflow (data processing, simulation, code review\nor anything else), consider contributing it back so others can use it. Next Steps Explore related topics: Need to supply API keys or tokens? Set up manage-providers for credential management. Want to customize the sandbox policy? Write custom rules in policies","format":"text","content_length":2798,"word_count":404,"summary":"Use pre-built sandboxes from the OpenShell Community catalog, or contribute your own.","headings":[{"text":"Community Sandboxes","level":1,"id":"community-sandboxes"},{"text":"What Are Community Sandboxes","level":2,"id":"what-are-community-sandboxes"},{"text":"Current Catalog","level":2,"id":"current-catalog"},{"text":"Use a Community Sandbox","level":2,"id":"use-a-community-sandbox"},{"text":"Other Sources","level":3,"id":"other-sources"},{"text":"Contribute a Community Sandbox","level":2,"id":"contribute-a-community-sandbox"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Community Sandboxes What Are Community Sandboxes Current Catalog Use a Community Sandbox Other Sources Contribute a Community Sandbox Next Steps","keywords":["accepts","builds","catalog","claude","code","codex","com","community","container","contribute","creates","current","description","directly","dockerfile","each","explore","files","flag","foundational","image","launch","local","need","next","ollama","open","opencode","openshell","other","paths","point","pulls","refer","references","resolves","sandbox","sandboxes","set","skills","sources","startup","steps","synthetic","topics","want","write","yaml"],"code_blocks":[{"content":"$ openshell sandbox create --from openclaw","language":"text"},{"content":"$ openshell sandbox create --from ./my-sandbox-dir","language":"text"},{"content":"$ openshell sandbox create --from my-registry.example.com/my-image:latest","language":"text"}],"links":[{"text":"OpenShell Community","type":"external","url":"https://github.com/NVIDIA/OpenShell-Community"},{"text":"OpenShell Community","type":"external","url":"https://github.com/NVIDIA/OpenShell-Community"},{"text":"OpenShell Community","type":"external","url":"https://github.com/NVIDIA/OpenShell-Community"},{"text":"Contributing","type":"external","url":"https://github.com/NVIDIA/OpenShell-Community/blob/main/CONTRIBUTING.md","original_text":"CONTRIBUTING.md"}],"images":[],"doc_type":"tutorial","section_path":["Sandboxes","Community Sandboxes"]},{"id":"sandboxes/manage-gateways","title":"Deploy and Manage Gateways","url":"sandboxes/manage-gateways.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Deploy local and remote gateways, register cloud gateways, and manage multiple gateway environments.","tags":["Gateway","Deployment","Remote Gateway","CLI"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Deploy and Manage Gateways The gateway is the control plane for OpenShell. All control-plane traffic between the CLI and running sandboxes flows through the gateway. The gateway is responsible for: Provisioning and managing sandboxes, including creation, deletion, and status monitoring. Storing provider credentials (API keys, tokens) and delivering them to sandboxes at startup. Delivering network and filesystem policies to sandboxes. Policy enforcement itself happens inside each sandbox through the proxy, OPA, Landlock, and seccomp. Managing inference configuration and serving inference bundles so sandboxes can route requests to the correct backend. Providing the SSH tunnel endpoint so you can connect to sandboxes without exposing them directly. The gateway runs inside a Docker container and exposes a single port (gRPC and HTTP multiplexed), secured by mTLS by default. No separate Kubernetes installation is required. It can be deployed locally, on a remote host via SSH, or behind a cloud reverse proxy. Deploy a Local Gateway Deploy a gateway on your workstation. The only prerequisite is a running Docker daemon. $ openshell gateway start\nThe gateway becomes reachable at https://127.0.0.1:8080 . Verify it is healthy: $ openshell status\nYou do not need to deploy a gateway manually. If you run openshell sandbox create without a gateway, the CLI auto-bootstraps a local gateway for you. To use a different port or name: $ openshell gateway start --port 9090\nopenshell gateway start --name dev-local\nDeploy a Remote Gateway Deploy a gateway on a remote machine accessible via SSH. The only dependency on the remote host is Docker. $ openshell gateway start --remote user@hostname\nThe gateway is reachable at https://:8080 . To specify an SSH key: $ openshell gateway start --remote user@hostname --ssh-key ~/.ssh/my_key\nFor DGX Spark, use your Spark’s mDNS hostname: $ openshell gateway start --remote @.local\nRegister an Existing Gateway Use openshell gateway add to register a gateway that is already running. Cloud Gateway Register a gateway behind a reverse proxy such as Cloudflare Access: $ openshell gateway add https://gateway.example.com\nThis opens your browser for the proxy’s login flow. After authentication, the CLI stores a bearer token and sets the gateway as active. To give the gateway a specific name instead of deriving it from the hostname, use --name : $ openshell gateway add https://gateway.example.com --name production\nIf the token expires later, re-authenticate with: $ openshell gateway login\nRemote Gateway Register a gateway on a remote host you have SSH access to: $ openshell gateway add https://remote-host:8080 --remote user@remote-host\nOr use the ssh:// scheme to combine the SSH destination and gateway port: $ openshell gateway add ssh://user@remote-host:8080\nLocal Gateway Register a gateway running locally that was started outside the CLI: $ openshell gateway add https://127.0.0.1:8080 --local\nManage Multiple Gateways One gateway is always the active gateway. All CLI commands target it by default. Both gateway start and gateway add automatically set the new gateway as active. List all registered gateways: $ openshell gateway select\nSwitch the active gateway: $ openshell gateway select my-remote-cluster\nOverride the active gateway for a single command with -g : $ openshell status -g my-other-cluster\nShow deployment details for a gateway, including endpoint, auth mode, and port: $ openshell gateway info\nopenshell gateway info --name my-remote-cluster\nAdvanced Start Options Flag Purpose --gpu Enable NVIDIA GPU passthrough. Requires NVIDIA drivers and the Container Toolkit on the host. --plaintext Listen on HTTP instead of mTLS. Use behind a TLS-terminating reverse proxy. --disable-gateway-auth Skip mTLS client certificate checks. Use when a reverse proxy cannot forward client certs. --registry-username Username for registry authentication. Defaults to __token__ when --registry-token is set. Only needed for private registries. Also configurable with OPENSHELL_REGISTRY_USERNAME . --registry-token Authentication token for pulling container images. For GHCR, a GitHub PAT with read:packages scope. Only needed for private registries. Also configurable with OPENSHELL_REGISTRY_TOKEN . Stop and Destroy Stop a gateway while preserving its state for later restart: $ openshell gateway stop\nPermanently destroy a gateway and all its state: $ openshell gateway destroy\nFor cloud gateways, gateway destroy removes only the local registration. It does not affect the remote deployment. Target a specific gateway with --name : $ openshell gateway stop --name my-gateway\nopenshell gateway destroy --name my-gateway\nTroubleshoot Check gateway health: $ openshell status\nView gateway logs: $ openshell doctor logs\nopenshell doctor logs --tail # stream live\nopenshell doctor logs --lines 50 # last 50 lines\nRun a command inside the gateway container for deeper inspection: $ openshell doctor exec -- kubectl get pods -A\nopenshell doctor exec -- sh\nIf the gateway is in a bad state, recreate it: $ openshell gateway start --recreate\nNext Steps To create a sandbox using the gateway, refer to manage-sandboxes . To install the CLI and get started quickly, refer to the /get-started/quickstart","format":"text","content_length":5282,"word_count":779,"summary":"The gateway is the control plane for OpenShell. All control-plane traffic between the CLI and running sandboxes flows through the gateway.","headings":[{"text":"Deploy and Manage Gateways","level":1,"id":"deploy-and-manage-gateways"},{"text":"Deploy a Local Gateway","level":2,"id":"deploy-a-local-gateway"},{"text":"Deploy a Remote Gateway","level":2,"id":"deploy-a-remote-gateway"},{"text":"Register an Existing Gateway","level":2,"id":"register-an-existing-gateway"},{"text":"Cloud Gateway","level":3,"id":"cloud-gateway"},{"text":"Remote Gateway","level":3,"id":"remote-gateway"},{"text":"Local Gateway","level":3,"id":"local-gateway"},{"text":"Manage Multiple Gateways","level":2,"id":"manage-multiple-gateways"},{"text":"Advanced Start Options","level":2,"id":"advanced-start-options"},{"text":"Stop and Destroy","level":2,"id":"stop-and-destroy"},{"text":"Troubleshoot","level":2,"id":"troubleshoot"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Deploy and Manage Gateways Deploy a Local Gateway Deploy a Remote Gateway Register an Existing Gateway Cloud Gateway Remote Gateway Local Gateway Manage Multiple Gateways Advanced Start Options Stop and Destroy Troubleshoot Next Steps","keywords":["access","advanced","after","also","authentication","both","check","cloud","cloudflare","com","container","defaults","delivering","deploy","destroy","docker","enable","existing","flag","gateway","gateways","github","health","healthy","host","hostname","https","inspection","key","kubernetes","landlock","list","listen","local","logs","manage","managing","multiple","name","next","only","openshell","options","override","permanently","policy","port","providing","provisioning","purpose"],"code_blocks":[{"content":"$ openshell gateway start","language":"text"},{"content":"$ openshell status","language":"text"},{"content":"$ openshell gateway start --port 9090\n$ openshell gateway start --name dev-local","language":"text"},{"content":"$ openshell gateway start --remote user@hostname","language":"text"},{"content":"$ openshell gateway start --remote user@hostname --ssh-key ~/.ssh/my_key","language":"text"},{"content":"$ openshell gateway start --remote @.local","language":"text"},{"content":"$ openshell gateway add https://gateway.example.com","language":"text"},{"content":"$ openshell gateway add https://gateway.example.com --name production","language":"text"},{"content":"$ openshell gateway login","language":"text"},{"content":"$ openshell gateway add https://remote-host:8080 --remote user@remote-host","language":"text"},{"content":"$ openshell gateway add ssh://user@remote-host:8080","language":"text"},{"content":"$ openshell gateway add https://127.0.0.1:8080 --local","language":"text"},{"content":"$ openshell gateway select","language":"text"},{"content":"$ openshell gateway select my-remote-cluster","language":"text"},{"content":"$ openshell status -g my-other-cluster","language":"text"},{"content":"$ openshell gateway info\n$ openshell gateway info --name my-remote-cluster","language":"text"},{"content":"$ openshell gateway stop","language":"text"},{"content":"$ openshell gateway destroy","language":"text"},{"content":"$ openshell gateway stop --name my-gateway\n$ openshell gateway destroy --name my-gateway","language":"text"},{"content":"$ openshell status","language":"text"},{"content":"$ openshell doctor logs\n$ openshell doctor logs --tail # stream live\n$ openshell doctor logs --lines 50 # last 50 lines","language":"text"},{"content":"$ openshell doctor exec -- kubectl get pods -A\n$ openshell doctor exec -- sh","language":"text"},{"content":"$ openshell gateway start --recreate","language":"text"}],"links":[],"images":[],"doc_type":"documentation","section_path":["Sandboxes","Manage Gateways"]},{"id":"sandboxes/manage-providers","title":"Manage Providers and Credentials","url":"sandboxes/manage-providers.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Create and manage credential providers that inject API keys and tokens into OpenShell sandboxes.","tags":["Providers","Credentials","API Keys","Sandbox","Security"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Manage Providers and Credentials AI agents typically need credentials to access external services: an API key for the AI model provider, a token for GitHub or GitLab, and so on. OpenShell manages these credentials as first-class entities called providers . Create and manage providers that supply credentials to sandboxes. Create a Provider Providers can be created from local environment variables or with explicit credential values. From Local Credentials The fastest way to create a provider is to let the CLI discover credentials from\nyour shell environment: $ openshell provider create --name my-claude --type claude --from-existing\nThis reads ANTHROPIC_API_KEY or CLAUDE_API_KEY from your current environment\nand stores them in the provider. With Explicit Credentials Supply a credential value directly: $ openshell provider create --name my-api --type generic --credential API_KEY=sk-abc123\nBare Key Form Pass a key name without a value to read the value from the environment variable\nof that name: $ openshell provider create --name my-api --type generic --credential API_KEY\nThis looks up the current value of $API_KEY in your shell and stores it. Manage Providers List, inspect, update, and delete providers from the active cluster. List all providers: $ openshell provider list\nInspect a provider: $ openshell provider get my-claude\nUpdate a provider’s credentials: $ openshell provider update my-claude --type claude --from-existing\nDelete a provider: $ openshell provider delete my-claude\nAttach Providers to Sandboxes Pass one or more --provider flags when creating a sandbox: $ openshell sandbox create --provider my-claude --provider my-github -- claude\nEach --provider flag attaches one provider. The sandbox receives all\ncredentials from every attached provider at runtime. Providers cannot be added to a running sandbox. If you need to attach an\nadditional provider, delete the sandbox and recreate it with all required\nproviders specified. Auto-Discovery Shortcut When the trailing command in openshell sandbox create is a recognized tool name ( claude , codex , or opencode ), the CLI auto-creates the required\nprovider from your local credentials if one does not already exist. You do not\nneed to create the provider separately: $ openshell sandbox create -- claude\nThis detects claude as a known tool, finds your ANTHROPIC_API_KEY , creates\na provider, attaches it to the sandbox, and launches Claude Code. Supported Provider Types The following provider types are supported. Type Environment Variables Injected Typical Use claude ANTHROPIC_API_KEY , CLAUDE_API_KEY Claude Code, Anthropic API codex OPENAI_API_KEY OpenAI Codex generic User-defined Any service with custom credentials github GITHUB_TOKEN , GH_TOKEN GitHub API, gh CLI — refer to /tutorials/github-sandbox gitlab GITLAB_TOKEN , GLAB_TOKEN , CI_JOB_TOKEN GitLab API, glab CLI nvidia NVIDIA_API_KEY NVIDIA API Catalog openai OPENAI_API_KEY Any OpenAI-compatible endpoint. Set --config OPENAI_BASE_URL to point to the provider. Refer to /inference/configure . opencode OPENCODE_API_KEY , OPENROUTER_API_KEY , OPENAI_API_KEY opencode tool Use the generic type for any service not listed above. You define the\nenvironment variable names and values yourself with --credential . Supported Inference Providers The following providers have been tested with inference.local . Any provider that exposes an OpenAI-compatible API works with the openai type. Set --config OPENAI_BASE_URL to the provider’s base URL and --credential OPENAI_API_KEY to your API key. Provider Name Type Base URL API Key Variable NVIDIA API Catalog nvidia-prod nvidia https://integrate.api.nvidia.com/v1 NVIDIA_API_KEY Anthropic anthropic-prod anthropic https://api.anthropic.com ANTHROPIC_API_KEY Baseten baseten openai https://inference.baseten.co/v1 OPENAI_API_KEY Bitdeer AI bitdeer openai https://api-inference.bitdeer.ai/v1 OPENAI_API_KEY Deepinfra deepinfra openai https://api.deepinfra.com/v1/openai OPENAI_API_KEY Groq groq openai https://api.groq.com/openai/v1 OPENAI_API_KEY Ollama (local) ollama openai http://host.openshell.internal:11434/v1 OPENAI_API_KEY LM Studio (local) lmstudio openai http://host.openshell.internal:1234/v1 OPENAI_API_KEY Refer to your provider’s documentation for the correct base URL, available models, and API key setup. To configure inference routing, refer to /inference/configure . Next Steps Explore related topics: To control what the agent can access, refer to policies . To use a pre-built environment, refer to the community-sandboxes catalog. To view the complete field reference for the policy YAML, refer to the Policy Schema Reference","format":"text","content_length":4638,"word_count":632,"summary":"AI agents typically need credentials to access external services: an API key for the AI model provider, a token for GitHub or GitLab, and so on. OpenShell manages these credentials as first-class entities called providers.","headings":[{"text":"Manage Providers and Credentials","level":1,"id":"manage-providers-and-credentials"},{"text":"Create a Provider","level":2,"id":"create-a-provider"},{"text":"From Local Credentials","level":3,"id":"from-local-credentials"},{"text":"With Explicit Credentials","level":3,"id":"with-explicit-credentials"},{"text":"Bare Key Form","level":3,"id":"bare-key-form"},{"text":"Manage Providers","level":2,"id":"manage-providers"},{"text":"Attach Providers to Sandboxes","level":2,"id":"attach-providers-to-sandboxes"},{"text":"Auto-Discovery Shortcut","level":3,"id":"auto-discovery-shortcut"},{"text":"Supported Provider Types","level":2,"id":"supported-provider-types"},{"text":"Supported Inference Providers","level":2,"id":"supported-inference-providers"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Manage Providers and Credentials Create a Provider From Local Credentials With Explicit Credentials Bare Key Form Manage Providers Attach Providers to Sandboxes Auto-Discovery Shortcut Supported Provider Types Supported Inference Providers Next Steps","keywords":["anthropic","any","api","attach","auto","bare","base","baseten","bitdeer","catalog","claude","code","codex","com","create","credentials","deepinfra","delete","directly","discovery","each","environment","explicit","explore","form","from","github","gitlab","groq","http","https","inference","injected","inspect","internal","key","list","local","manage","name","next","ollama","openai","openshell","pass","policy","provider","providers","refer","reference"],"code_blocks":[{"content":"$ openshell provider create --name my-claude --type claude --from-existing","language":"text"},{"content":"$ openshell provider create --name my-api --type generic --credential API_KEY=sk-abc123","language":"text"},{"content":"$ openshell provider create --name my-api --type generic --credential API_KEY","language":"text"},{"content":"$ openshell provider list","language":"text"},{"content":"$ openshell provider get my-claude","language":"text"},{"content":"$ openshell provider update my-claude --type claude --from-existing","language":"text"},{"content":"$ openshell provider delete my-claude","language":"text"},{"content":"$ openshell sandbox create --provider my-claude --provider my-github -- claude","language":"text"},{"content":"$ openshell sandbox create -- claude","language":"text"}],"links":[],"images":[],"doc_type":"tutorial","section_path":["Sandboxes","Manage Providers"]},{"id":"sandboxes/manage-sandboxes","title":"Manage Sandboxes","url":"sandboxes/manage-sandboxes.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Set up gateways, create sandboxes, and manage the full sandbox lifecycle.","tags":["Gateway","Sandboxing","AI Agents","Sandbox Management","CLI"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Manage Sandboxes This page covers creating sandboxes and managing them. For background on what sandboxes are and how isolation works, refer to About Sandboxes . Docker must be running before you create a gateway or sandbox. If it is not, the CLI\nreturns a connection-refused error ( os error 61 ) without explaining\nthe cause. Start Docker and try again. Create a Sandbox Create a sandbox with a single command. For example, to create a sandbox with Claude, run: $ openshell sandbox create -- claude\nEvery sandbox requires a gateway. If you run openshell sandbox create without a gateway, the CLI auto-bootstraps a local gateway. Remote Gateways If you plan to run sandboxes on a remote host or a cloud-hosted gateway, set up the gateway first. Refer to manage-gateways for deployment options and multi-gateway management. GPU Resources To request GPU resources, add --gpu : $ openshell sandbox create --gpu -- claude\nCustom Containers Use --from to create a sandbox from a pre-built community package, a local directory, or a container image: $ openshell sandbox create --from openclaw\nopenshell sandbox create --from ./my-sandbox-dir\nopenshell sandbox create --from my-registry.example.com/my-image:latest\nThe CLI resolves community names against the OpenShell Community catalog, pulls the bundled Dockerfile and policy, builds the image locally, and creates the sandbox. For the full catalog and how to contribute your own, refer to community-sandboxes . Connect to a Sandbox Open an SSH session into a running sandbox: $ openshell sandbox connect my-sandbox\nLaunch VS Code or Cursor directly into the sandbox workspace: $ openshell sandbox create --editor vscode --name my-sandbox\nopenshell sandbox connect my-sandbox --editor cursor\nWhen --editor is used, OpenShell keeps the sandbox alive and installs an\nOpenShell-managed SSH include file instead of cluttering your main\nssh/config with generated host blocks. Monitor and Debug List all sandboxes: $ openshell sandbox list\nGet detailed information about a specific sandbox: $ openshell sandbox get my-sandbox\nStream sandbox logs to monitor agent activity and diagnose policy decisions: $ openshell logs my-sandbox\nFlag Purpose Example --tail Stream logs in real time openshell logs my-sandbox --tail --source Filter by log source --source sandbox --level Filter by severity --level warn --since Show logs from a time window --since 5m OpenShell Terminal combines sandbox status and live logs in a single real-time dashboard: $ openshell term\nUse the terminal to spot blocked connections marked action=deny and inference-related proxy activity. If a connection is blocked unexpectedly, add the host to your network policy. Refer to policies for the workflow. Port Forwarding Forward a local port to a running sandbox to access services inside it, such as a web server or database: $ openshell forward start 8000 my-sandbox\nopenshell forward start 8000 my-sandbox -d # run in background\nList and stop active forwards: $ openshell forward list\nopenshell forward stop 8000 my-sandbox\nYou can also forward a port at creation time with --forward : $ openshell sandbox create --forward 8000 -- claude\nSSH Config Generate an SSH config entry for a sandbox so tools like VS Code Remote-SSH can connect directly: $ openshell sandbox ssh-config my-sandbox\nAppend the output to ~/.ssh/config or use --editor on sandbox create / sandbox connect for automatic setup. Transfer Files Upload files from your host into the sandbox: $ openshell sandbox upload my-sandbox ./src /sandbox/src\nDownload files from the sandbox to your host: $ openshell sandbox download my-sandbox /sandbox/output ./local\nYou can also upload files at creation time with the --upload flag on\nopenshell sandbox create . Delete Sandboxes Deleting a sandbox stops all processes, releases resources, and purges injected credentials. $ openshell sandbox delete my-sandbox\nNext Steps To follow a complete end-to-end example, refer to the /tutorials/github-sandbox tutorial. To supply API keys or tokens, refer to manage-providers . To control what the agent can access, refer to policies . To use a pre-built environment, refer to the community-sandboxes catalog","format":"text","content_length":4171,"word_count":637,"summary":"This page covers creating sandboxes and managing them. For background on what sandboxes are and how isolation works, refer to About Sandboxes.","headings":[{"text":"Manage Sandboxes","level":1,"id":"manage-sandboxes"},{"text":"Create a Sandbox","level":2,"id":"create-a-sandbox"},{"text":"Remote Gateways","level":3,"id":"remote-gateways"},{"text":"GPU Resources","level":3,"id":"gpu-resources"},{"text":"Custom Containers","level":3,"id":"custom-containers"},{"text":"Connect to a Sandbox","level":2,"id":"connect-to-a-sandbox"},{"text":"Monitor and Debug","level":2,"id":"monitor-and-debug"},{"text":"Port Forwarding","level":2,"id":"port-forwarding"},{"text":"SSH Config","level":2,"id":"ssh-config"},{"text":"Transfer Files","level":2,"id":"transfer-files"},{"text":"Delete Sandboxes","level":2,"id":"delete-sandboxes"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Manage Sandboxes Create a Sandbox Remote Gateways GPU Resources Custom Containers Connect to a Sandbox Monitor and Debug Port Forwarding SSH Config Transfer Files Delete Sandboxes Next Steps","keywords":["about","action","append","claude","code","com","community","config","connect","containers","create","cursor","custom","dashboard","database","debug","decisions","delete","deleting","directly","docker","dockerfile","download","every","example","files","filter","flag","forward","forwarding","forwards","gateways","generate","gpu","host","image","launch","list","manage","monitor","next","open","openshell","port","purpose","refer","remote","resources","run","sandbox"],"code_blocks":[{"content":"$ openshell sandbox create -- claude","language":"text"},{"content":"$ openshell sandbox create --gpu -- claude","language":"text"},{"content":"$ openshell sandbox create --from openclaw\n$ openshell sandbox create --from ./my-sandbox-dir\n$ openshell sandbox create --from my-registry.example.com/my-image:latest","language":"text"},{"content":"$ openshell sandbox connect my-sandbox","language":"text"},{"content":"$ openshell sandbox create --editor vscode --name my-sandbox\n$ openshell sandbox connect my-sandbox --editor cursor","language":"text"},{"content":"$ openshell sandbox list","language":"text"},{"content":"$ openshell sandbox get my-sandbox","language":"text"},{"content":"$ openshell logs my-sandbox","language":"text"},{"content":"$ openshell term","language":"text"},{"content":"$ openshell forward start 8000 my-sandbox\n$ openshell forward start 8000 my-sandbox -d # run in background","language":"text"},{"content":"$ openshell forward list\n$ openshell forward stop 8000 my-sandbox","language":"text"},{"content":"$ openshell sandbox create --forward 8000 -- claude","language":"text"},{"content":"$ openshell sandbox ssh-config my-sandbox","language":"text"},{"content":"$ openshell sandbox upload my-sandbox ./src /sandbox/src","language":"text"},{"content":"$ openshell sandbox download my-sandbox /sandbox/output ./local","language":"text"},{"content":"$ openshell sandbox delete my-sandbox","language":"text"}],"links":[{"text":"OpenShell Community","type":"external","url":"https://github.com/NVIDIA/OpenShell-Community"}],"images":[],"doc_type":"tutorial","section_path":["Sandboxes","Manage Sandboxes"]},{"id":"sandboxes/policies","title":"Customize Sandbox Policies","url":"sandboxes/policies.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Apply, iterate, and debug sandbox network policies with hot-reload on running OpenShell sandboxes.","tags":["Policy","Network Policy","Sandbox","Security","Hot Reload"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_intermediate","audience":["engineer"],"content":"Customize Sandbox Policies Use this page to apply and iterate policy changes on running sandboxes. For a full field-by-field YAML definition, use the Policy Schema Reference . Policy Structure A policy has static sections filesystem_policy , landlock , and process that are locked at sandbox creation, and a dynamic section network_policies that is hot-reloadable on a running sandbox. version: 1\nStatic: locked at sandbox creation. Paths the agent can read vs read/write\nfilesystem_policy\nread_only: [/usr, /lib, /etc\nread_write: [/sandbox, /tmp\nStatic: Landlock LSM kernel enforcement. best_effort uses highest ABI the host supports\nlandlock\ncompatibility: best_effort\nStatic: Unprivileged user/group the agent process runs as\nprocess\nrun_as_user: sandbox\nrun_as_group: sandbox\nDynamic: hot-reloadable. Named blocks of endpoints + binaries allowed to reach them\nnetwork_policies\nmy_api\nname: my-api\nendpoints\nhost: api.example.com\nport: 443\nprotocol: rest\nenforcement: enforce\naccess: full\nbinaries\npath: /usr/bin/curl\nStatic sections are locked at sandbox creation. Changing them requires destroying and recreating the sandbox\nDynamic sections can be updated on a running sandbox with openshell policy set and take effect without restarting. Section Type Description filesystem_policy Static Controls which directories the agent can access on disk. Paths are split into read_only and read_write lists. Any path not listed in either list is inaccessible. Set include_workdir: true to automatically add the agent’s working directory to read_write . Landlock LSM enforces these restrictions at the kernel level. landlock Static Configures Landlock LSM enforcement behavior. Set compatibility to best_effort (skip individual inaccessible paths while applying remaining rules) or hard_requirement (fail if any path is inaccessible or the required kernel ABI is unavailable). See the Policy Schema Reference for the full behavior table. process Static Sets the OS-level identity for the agent process. run_as_user and run_as_group default to sandbox . Root ( root or 0 ) is rejected. The agent also runs with seccomp filters that block dangerous system calls. network_policies Dynamic Controls network access for ordinary outbound traffic from the sandbox. Each block has a name, a list of endpoints (host, port, protocol, and optional rules), and a list of binaries allowed to use those endpoints.
Every outbound connection except https://inference.local goes through the proxy, which queries the policy engine with the destination and calling binary. A connection is allowed only when both match an entry in the same policy block.
For endpoints with protocol: rest , the proxy auto-detects TLS and terminates it so each HTTP request is checked against that endpoint’s rules (method and path).
Endpoints without protocol allow the TCP stream through without inspecting payloads.
If no endpoint matches, the connection is denied. Configure managed inference separately through ../inference/configure . Baseline Filesystem Paths When a sandbox runs in proxy mode (the default), OpenShell automatically adds baseline filesystem paths required for the sandbox child process to function: /usr , /lib , /etc , /var/log (read-only) and /sandbox , /tmp (read-write). Paths like /app are included in the baseline set but are only added if they exist in the container image. This filtering prevents a missing baseline path from degrading Landlock enforcement. Without it, a single missing path could cause the entire Landlock ruleset to fail, leaving the sandbox with no filesystem restrictions at all. User-specified paths in your policy YAML are not pre-filtered. If you list a path that does not exist: In best_effort mode, the path is skipped with a warning and remaining rules are still applied. In hard_requirement mode, sandbox startup fails immediately. This distinction means baseline system paths degrade gracefully while user-specified paths surface configuration errors. Apply a Custom Policy Pass a policy YAML file when creating the sandbox: $ openshell sandbox create --policy ./my-policy.yaml -- claude\nopenshell sandbox create keeps the sandbox running after the initial command exits, which is useful when you plan to iterate on the policy. Add --no-keep if you want the sandbox deleted automatically instead. To avoid passing --policy every time, set a default policy with an environment variable: $ export OPENSHELL_SANDBOX_POLICY=./my-policy.yaml\nopenshell sandbox create -- claude\nThe CLI uses the policy from OPENSHELL_SANDBOX_POLICY whenever --policy is not explicitly provided. Iterate on a Running Sandbox To change what the sandbox can access, pull the current policy, edit the YAML, and push the update. The workflow is iterative: create the sandbox, monitor logs for denied actions, pull the policy, modify it, push, and verify. The following steps outline the hot-reload policy update workflow. Create the sandbox with your initial policy by following Apply a Custom Policy above (or set OPENSHELL_SANDBOX_POLICY ). Monitor denials. Each log entry shows host, port, binary, and reason. Alternatively, use openshell term for a live dashboard. $ openshell logs --tail --source sandbox\nPull the current policy. Strip the metadata header (Version, Hash, Status) before reusing the file. $ openshell policy get --full > current-policy.yaml\nEdit the YAML: add or adjust network_policies entries, binaries, access , or rules . Push the updated policy. Exit codes: 0 = loaded, 1 = validation failed, 124 = timeout. $ openshell policy set --policy current-policy.yaml --wait\nVerify the new revision. If status is loaded , repeat from step 2 as needed; if failed , fix the policy and repeat from step 4. $ openshell policy list --tail --source sandbox for the denied host, path, and binary. When triaging denied requests, check: Destination host and port to confirm which endpoint is missing. Calling binary path to confirm which binaries entry needs to be added or adjusted. HTTP method and path (for REST endpoints) to confirm which rules entry needs to be added or adjusted. Then push the updated policy as described above. Examples Add these blocks to the network_policies section of your sandbox policy. Apply with openshell policy set --policy --wait\nUse Simple endpoint for host-level allowlists and Granular rules for method/path control. Simple endpoint Allow pip install and uv pip install to reach PyPI: pypi\nname: pypi\nendpoints\nhost: pypi.org\nport: 443\nhost: files.pythonhosted.org\nport: 443\nbinaries\n{ path: /usr/bin/pip\n{ path: /usr/local/bin/uv\nEndpoints without protocol use TCP passthrough, where the proxy allows the stream without inspecting payloads. Granular rules Allow Claude and the GitHub CLI to reach api.github.com with per-path rules: read-only (GET, HEAD, OPTIONS) and GraphQL (POST) for all paths; full write access for alpha-repo ; and create/edit issues only for bravo-repo . Replace with your GitHub org or username. For an end-to-end walkthrough that combines this policy with a GitHub credential provider and sandbox creation, refer to /tutorials/github-sandbox . github_repos\nname: github_repos\nendpoints\nhost: api.github.com\nport: 443\nprotocol: rest\nenforcement: enforce\nrules\nallow\nmethod: GET\npath:\nallow\nmethod: HEAD\npath:\nallow\nmethod: OPTIONS\npath:\nallow\nmethod: POST\npath: \"/graphql\nallow\nmethod:\npath: \"/repos//alpha-repo\nallow\nmethod: POST\npath: \"/repos//bravo-repo/issues\nallow\nmethod: PATCH\npath: \"/repos//bravo-repo/issues\nbinaries\n{ path: /usr/local/bin/claude\n{ path: /usr/bin/gh\nEndpoints with protocol: rest enable HTTP request inspection. The proxy auto-detects TLS on HTTPS endpoints, terminates it, and checks each HTTP request against the rules list. Next Steps Explore related topics: To learn about network access rules and sandbox isolation layers, refer to index . To view the full field-by-field YAML definition, refer to the Policy Schema Reference . To review the default policy breakdown, refer to ../reference/default-policy","format":"text","content_length":8698,"word_count":1276,"summary":"Use this page to apply and iterate policy changes on running sandboxes. For a full field-by-field YAML definition, use the Policy Schema Reference.","headings":[{"text":"Customize Sandbox Policies","level":1,"id":"customize-sandbox-policies"},{"text":"Policy Structure","level":2,"id":"policy-structure"},{"text":"Baseline Filesystem Paths","level":2,"id":"baseline-filesystem-paths"},{"text":"Apply a Custom Policy","level":2,"id":"apply-a-custom-policy"},{"text":"Iterate on a Running Sandbox","level":2,"id":"iterate-on-a-running-sandbox"},{"text":"Global Policy Override","level":2,"id":"global-policy-override"},{"text":"Debug Denied Requests","level":2,"id":"debug-denied-requests"},{"text":"Examples","level":2,"id":"examples"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Customize Sandbox Policies Policy Structure Baseline Filesystem Paths Apply a Custom Policy Iterate on a Running Sandbox Global Policy Override Debug Denied Requests Examples Next Steps","keywords":["access","add","allow","alternatively","any","apply","baseline","calling","changing","check","claude","codes","com","compatibility","configure","configured","configures","controls","create","custom","customize","debug","denied","description","destination","dynamic","each","edit","endpoints","enforcement","every","examples","exist","exit","explore","filesystem","function","github","global","granular","graphql","hash","host","https","include_workdir","iterate","iterative","landlock","method","monitor"],"code_blocks":[{"content":"version: 1\n\n# Static: locked at sandbox creation. Paths the agent can read vs read/write.\nfilesystem_policy:\n read_only: [/usr, /lib, /etc]\n read_write: [/sandbox, /tmp]\n\n# Static: Landlock LSM kernel enforcement. best_effort uses highest ABI the host supports.\nlandlock:\n compatibility: best_effort\n\n# Static: Unprivileged user/group the agent process runs as.\nprocess:\n run_as_user: sandbox\n run_as_group: sandbox\n\n# Dynamic: hot-reloadable. Named blocks of endpoints + binaries allowed to reach them.\nnetwork_policies:\n my_api:\n name: my-api\n endpoints:\n - host: api.example.com\n port: 443\n protocol: rest\n enforcement: enforce\n access: full\n binaries:\n - path: /usr/bin/curl","language":"text"},{"content":"$ openshell sandbox create --policy ./my-policy.yaml -- claude","language":"text"},{"content":"$ export OPENSHELL_SANDBOX_POLICY=./my-policy.yaml\n$ openshell sandbox create -- claude","language":"text"},{"content":"$ openshell logs --tail --source sandbox","language":"text"},{"content":"$ openshell policy get --full > current-policy.yaml","language":"text"},{"content":"$ openshell policy set --policy current-policy.yaml --wait","language":"text"},{"content":"$ openshell policy list ","language":"text"},{"content":"$ openshell policy set --global --policy ./global-policy.yaml","language":"text"},{"content":"$ openshell policy delete --global","language":"text"},{"content":"$ openshell settings get ","language":"text"},{"content":"pypi:\n name: pypi\n endpoints:\n - host: pypi.org\n port: 443\n - host: files.pythonhosted.org\n port: 443\n binaries:\n - { path: /usr/bin/pip }\n - { path: /usr/local/bin/uv }","language":"text"},{"content":"github_repos:\n name: github_repos\n endpoints:\n - host: api.github.com\n port: 443\n protocol: rest\n enforcement: enforce\n rules:\n - allow:\n method: GET\n path: \"/**\"\n - allow:\n method: HEAD\n path: \"/**\"\n - allow:\n method: OPTIONS\n path: \"/**\"\n - allow:\n method: POST\n path: \"/graphql\"\n - allow:\n method: \"*\"\n path: \"/repos//alpha-repo/**\"\n - allow:\n method: POST\n path: \"/repos//bravo-repo/issues\"\n - allow:\n method: PATCH\n path: \"/repos//bravo-repo/issues/*\"\n binaries:\n - { path: /usr/local/bin/claude }\n - { path: /usr/bin/gh }","language":"text"}],"links":[{"text":"Landlock LSM","type":"external","url":"https://docs.kernel.org/security/landlock.html"},{"text":"Apply a Custom Policy","type":"anchor","url":"#apply-a-custom-policy"}],"images":[],"doc_type":"documentation","section_path":["Sandboxes","Policies"]}]} \ No newline at end of file diff --git a/pr-preview/pr-677/sandboxes/manage-gateways.json b/pr-preview/pr-677/sandboxes/manage-gateways.json index 34d5f9ed6..f7ba8312c 100644 --- a/pr-preview/pr-677/sandboxes/manage-gateways.json +++ b/pr-preview/pr-677/sandboxes/manage-gateways.json @@ -1 +1 @@ -{"id":"sandboxes/manage-gateways","title":"Deploy and Manage Gateways","url":"sandboxes/manage-gateways.html","last_modified":"2026-03-30T18:03:24.493883+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Deploy local and remote gateways, register cloud gateways, and manage multiple gateway environments.","tags":["Gateway","Deployment","Remote Gateway","CLI"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Deploy and Manage Gateways The gateway is the control plane for OpenShell. All control-plane traffic between the CLI and running sandboxes flows through the gateway. The gateway is responsible for: Provisioning and managing sandboxes, including creation, deletion, and status monitoring. Storing provider credentials (API keys, tokens) and delivering them to sandboxes at startup. Delivering network and filesystem policies to sandboxes. Policy enforcement itself happens inside each sandbox through the proxy, OPA, Landlock, and seccomp. Managing inference configuration and serving inference bundles so sandboxes can route requests to the correct backend. Providing the SSH tunnel endpoint so you can connect to sandboxes without exposing them directly. The gateway runs inside a Docker container and exposes a single port (gRPC and HTTP multiplexed), secured by mTLS by default. No separate Kubernetes installation is required. It can be deployed locally, on a remote host via SSH, or behind a cloud reverse proxy. Deploy a Local Gateway Deploy a gateway on your workstation. The only prerequisite is a running Docker daemon. $ openshell gateway start\nThe gateway becomes reachable at https://127.0.0.1:8080 . Verify it is healthy: $ openshell status\nYou do not need to deploy a gateway manually. If you run openshell sandbox create without a gateway, the CLI auto-bootstraps a local gateway for you. To use a different port or name: $ openshell gateway start --port 9090\nopenshell gateway start --name dev-local\nDeploy a Remote Gateway Deploy a gateway on a remote machine accessible via SSH. The only dependency on the remote host is Docker. $ openshell gateway start --remote user@hostname\nThe gateway is reachable at https://:8080 . To specify an SSH key: $ openshell gateway start --remote user@hostname --ssh-key ~/.ssh/my_key\nFor DGX Spark, use your Spark’s mDNS hostname: $ openshell gateway start --remote @.local\nRegister an Existing Gateway Use openshell gateway add to register a gateway that is already running. Cloud Gateway Register a gateway behind a reverse proxy such as Cloudflare Access: $ openshell gateway add https://gateway.example.com\nThis opens your browser for the proxy’s login flow. After authentication, the CLI stores a bearer token and sets the gateway as active. To give the gateway a specific name instead of deriving it from the hostname, use --name : $ openshell gateway add https://gateway.example.com --name production\nIf the token expires later, re-authenticate with: $ openshell gateway login\nRemote Gateway Register a gateway on a remote host you have SSH access to: $ openshell gateway add https://remote-host:8080 --remote user@remote-host\nOr use the ssh:// scheme to combine the SSH destination and gateway port: $ openshell gateway add ssh://user@remote-host:8080\nLocal Gateway Register a gateway running locally that was started outside the CLI: $ openshell gateway add https://127.0.0.1:8080 --local\nManage Multiple Gateways One gateway is always the active gateway. All CLI commands target it by default. Both gateway start and gateway add automatically set the new gateway as active. List all registered gateways: $ openshell gateway select\nSwitch the active gateway: $ openshell gateway select my-remote-cluster\nOverride the active gateway for a single command with -g : $ openshell status -g my-other-cluster\nShow deployment details for a gateway, including endpoint, auth mode, and port: $ openshell gateway info\nopenshell gateway info --name my-remote-cluster\nAdvanced Start Options Flag Purpose --gpu Enable NVIDIA GPU passthrough. Requires NVIDIA drivers and the Container Toolkit on the host. --plaintext Listen on HTTP instead of mTLS. Use behind a TLS-terminating reverse proxy. --disable-gateway-auth Skip mTLS client certificate checks. Use when a reverse proxy cannot forward client certs. --registry-username Username for registry authentication. Defaults to __token__ when --registry-token is set. Only needed for private registries. Also configurable with OPENSHELL_REGISTRY_USERNAME . --registry-token Authentication token for pulling container images. For GHCR, a GitHub PAT with read:packages scope. Only needed for private registries. Also configurable with OPENSHELL_REGISTRY_TOKEN . Stop and Destroy Stop a gateway while preserving its state for later restart: $ openshell gateway stop\nPermanently destroy a gateway and all its state: $ openshell gateway destroy\nFor cloud gateways, gateway destroy removes only the local registration. It does not affect the remote deployment. Target a specific gateway with --name : $ openshell gateway stop --name my-gateway\nopenshell gateway destroy --name my-gateway\nTroubleshoot Check gateway health: $ openshell status\nView gateway logs: $ openshell doctor logs\nopenshell doctor logs --tail # stream live\nopenshell doctor logs --lines 50 # last 50 lines\nRun a command inside the gateway container for deeper inspection: $ openshell doctor exec -- kubectl get pods -A\nopenshell doctor exec -- sh\nIf the gateway is in a bad state, recreate it: $ openshell gateway start --recreate\nNext Steps To create a sandbox using the gateway, refer to manage-sandboxes . To install the CLI and get started quickly, refer to the /get-started/quickstart","format":"text","summary":"The gateway is the control plane for OpenShell. All control-plane traffic between the CLI and running sandboxes flows through the gateway.","headings":[{"text":"Deploy and Manage Gateways","level":1},{"text":"Deploy a Local Gateway","level":2},{"text":"Deploy a Remote Gateway","level":2},{"text":"Register an Existing Gateway","level":2},{"text":"Cloud Gateway","level":3},{"text":"Remote Gateway","level":3},{"text":"Local Gateway","level":3},{"text":"Manage Multiple Gateways","level":2},{"text":"Advanced Start Options","level":2},{"text":"Stop and Destroy","level":2},{"text":"Troubleshoot","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file +{"id":"sandboxes/manage-gateways","title":"Deploy and Manage Gateways","url":"sandboxes/manage-gateways.html","last_modified":"2026-03-30T18:08:14.861967+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Deploy local and remote gateways, register cloud gateways, and manage multiple gateway environments.","tags":["Gateway","Deployment","Remote Gateway","CLI"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Deploy and Manage Gateways The gateway is the control plane for OpenShell. All control-plane traffic between the CLI and running sandboxes flows through the gateway. The gateway is responsible for: Provisioning and managing sandboxes, including creation, deletion, and status monitoring. Storing provider credentials (API keys, tokens) and delivering them to sandboxes at startup. Delivering network and filesystem policies to sandboxes. Policy enforcement itself happens inside each sandbox through the proxy, OPA, Landlock, and seccomp. Managing inference configuration and serving inference bundles so sandboxes can route requests to the correct backend. Providing the SSH tunnel endpoint so you can connect to sandboxes without exposing them directly. The gateway runs inside a Docker container and exposes a single port (gRPC and HTTP multiplexed), secured by mTLS by default. No separate Kubernetes installation is required. It can be deployed locally, on a remote host via SSH, or behind a cloud reverse proxy. Deploy a Local Gateway Deploy a gateway on your workstation. The only prerequisite is a running Docker daemon. $ openshell gateway start\nThe gateway becomes reachable at https://127.0.0.1:8080 . Verify it is healthy: $ openshell status\nYou do not need to deploy a gateway manually. If you run openshell sandbox create without a gateway, the CLI auto-bootstraps a local gateway for you. To use a different port or name: $ openshell gateway start --port 9090\nopenshell gateway start --name dev-local\nDeploy a Remote Gateway Deploy a gateway on a remote machine accessible via SSH. The only dependency on the remote host is Docker. $ openshell gateway start --remote user@hostname\nThe gateway is reachable at https://:8080 . To specify an SSH key: $ openshell gateway start --remote user@hostname --ssh-key ~/.ssh/my_key\nFor DGX Spark, use your Spark’s mDNS hostname: $ openshell gateway start --remote @.local\nRegister an Existing Gateway Use openshell gateway add to register a gateway that is already running. Cloud Gateway Register a gateway behind a reverse proxy such as Cloudflare Access: $ openshell gateway add https://gateway.example.com\nThis opens your browser for the proxy’s login flow. After authentication, the CLI stores a bearer token and sets the gateway as active. To give the gateway a specific name instead of deriving it from the hostname, use --name : $ openshell gateway add https://gateway.example.com --name production\nIf the token expires later, re-authenticate with: $ openshell gateway login\nRemote Gateway Register a gateway on a remote host you have SSH access to: $ openshell gateway add https://remote-host:8080 --remote user@remote-host\nOr use the ssh:// scheme to combine the SSH destination and gateway port: $ openshell gateway add ssh://user@remote-host:8080\nLocal Gateway Register a gateway running locally that was started outside the CLI: $ openshell gateway add https://127.0.0.1:8080 --local\nManage Multiple Gateways One gateway is always the active gateway. All CLI commands target it by default. Both gateway start and gateway add automatically set the new gateway as active. List all registered gateways: $ openshell gateway select\nSwitch the active gateway: $ openshell gateway select my-remote-cluster\nOverride the active gateway for a single command with -g : $ openshell status -g my-other-cluster\nShow deployment details for a gateway, including endpoint, auth mode, and port: $ openshell gateway info\nopenshell gateway info --name my-remote-cluster\nAdvanced Start Options Flag Purpose --gpu Enable NVIDIA GPU passthrough. Requires NVIDIA drivers and the Container Toolkit on the host. --plaintext Listen on HTTP instead of mTLS. Use behind a TLS-terminating reverse proxy. --disable-gateway-auth Skip mTLS client certificate checks. Use when a reverse proxy cannot forward client certs. --registry-username Username for registry authentication. Defaults to __token__ when --registry-token is set. Only needed for private registries. Also configurable with OPENSHELL_REGISTRY_USERNAME . --registry-token Authentication token for pulling container images. For GHCR, a GitHub PAT with read:packages scope. Only needed for private registries. Also configurable with OPENSHELL_REGISTRY_TOKEN . Stop and Destroy Stop a gateway while preserving its state for later restart: $ openshell gateway stop\nPermanently destroy a gateway and all its state: $ openshell gateway destroy\nFor cloud gateways, gateway destroy removes only the local registration. It does not affect the remote deployment. Target a specific gateway with --name : $ openshell gateway stop --name my-gateway\nopenshell gateway destroy --name my-gateway\nTroubleshoot Check gateway health: $ openshell status\nView gateway logs: $ openshell doctor logs\nopenshell doctor logs --tail # stream live\nopenshell doctor logs --lines 50 # last 50 lines\nRun a command inside the gateway container for deeper inspection: $ openshell doctor exec -- kubectl get pods -A\nopenshell doctor exec -- sh\nIf the gateway is in a bad state, recreate it: $ openshell gateway start --recreate\nNext Steps To create a sandbox using the gateway, refer to manage-sandboxes . To install the CLI and get started quickly, refer to the /get-started/quickstart","format":"text","summary":"The gateway is the control plane for OpenShell. All control-plane traffic between the CLI and running sandboxes flows through the gateway.","headings":[{"text":"Deploy and Manage Gateways","level":1},{"text":"Deploy a Local Gateway","level":2},{"text":"Deploy a Remote Gateway","level":2},{"text":"Register an Existing Gateway","level":2},{"text":"Cloud Gateway","level":3},{"text":"Remote Gateway","level":3},{"text":"Local Gateway","level":3},{"text":"Manage Multiple Gateways","level":2},{"text":"Advanced Start Options","level":2},{"text":"Stop and Destroy","level":2},{"text":"Troubleshoot","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file diff --git a/pr-preview/pr-677/sandboxes/manage-providers.json b/pr-preview/pr-677/sandboxes/manage-providers.json index c02a37b50..06f42e225 100644 --- a/pr-preview/pr-677/sandboxes/manage-providers.json +++ b/pr-preview/pr-677/sandboxes/manage-providers.json @@ -1 +1 @@ -{"id":"sandboxes/manage-providers","title":"Manage Providers and Credentials","url":"sandboxes/manage-providers.html","last_modified":"2026-03-30T18:03:24.509491+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Create and manage credential providers that inject API keys and tokens into OpenShell sandboxes.","tags":["Providers","Credentials","API Keys","Sandbox","Security"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Manage Providers and Credentials AI agents typically need credentials to access external services: an API key for the AI model provider, a token for GitHub or GitLab, and so on. OpenShell manages these credentials as first-class entities called providers . Create and manage providers that supply credentials to sandboxes. Create a Provider Providers can be created from local environment variables or with explicit credential values. From Local Credentials The fastest way to create a provider is to let the CLI discover credentials from\nyour shell environment: $ openshell provider create --name my-claude --type claude --from-existing\nThis reads ANTHROPIC_API_KEY or CLAUDE_API_KEY from your current environment\nand stores them in the provider. With Explicit Credentials Supply a credential value directly: $ openshell provider create --name my-api --type generic --credential API_KEY=sk-abc123\nBare Key Form Pass a key name without a value to read the value from the environment variable\nof that name: $ openshell provider create --name my-api --type generic --credential API_KEY\nThis looks up the current value of $API_KEY in your shell and stores it. Manage Providers List, inspect, update, and delete providers from the active cluster. List all providers: $ openshell provider list\nInspect a provider: $ openshell provider get my-claude\nUpdate a provider’s credentials: $ openshell provider update my-claude --type claude --from-existing\nDelete a provider: $ openshell provider delete my-claude\nAttach Providers to Sandboxes Pass one or more --provider flags when creating a sandbox: $ openshell sandbox create --provider my-claude --provider my-github -- claude\nEach --provider flag attaches one provider. The sandbox receives all\ncredentials from every attached provider at runtime. Providers cannot be added to a running sandbox. If you need to attach an\nadditional provider, delete the sandbox and recreate it with all required\nproviders specified. Auto-Discovery Shortcut When the trailing command in openshell sandbox create is a recognized tool name ( claude , codex , or opencode ), the CLI auto-creates the required\nprovider from your local credentials if one does not already exist. You do not\nneed to create the provider separately: $ openshell sandbox create -- claude\nThis detects claude as a known tool, finds your ANTHROPIC_API_KEY , creates\na provider, attaches it to the sandbox, and launches Claude Code. Supported Provider Types The following provider types are supported. Type Environment Variables Injected Typical Use claude ANTHROPIC_API_KEY , CLAUDE_API_KEY Claude Code, Anthropic API codex OPENAI_API_KEY OpenAI Codex generic User-defined Any service with custom credentials github GITHUB_TOKEN , GH_TOKEN GitHub API, gh CLI — refer to /tutorials/github-sandbox gitlab GITLAB_TOKEN , GLAB_TOKEN , CI_JOB_TOKEN GitLab API, glab CLI nvidia NVIDIA_API_KEY NVIDIA API Catalog openai OPENAI_API_KEY Any OpenAI-compatible endpoint. Set --config OPENAI_BASE_URL to point to the provider. Refer to /inference/configure . opencode OPENCODE_API_KEY , OPENROUTER_API_KEY , OPENAI_API_KEY opencode tool Use the generic type for any service not listed above. You define the\nenvironment variable names and values yourself with --credential . Supported Inference Providers The following providers have been tested with inference.local . Any provider that exposes an OpenAI-compatible API works with the openai type. Set --config OPENAI_BASE_URL to the provider’s base URL and --credential OPENAI_API_KEY to your API key. Provider Name Type Base URL API Key Variable NVIDIA API Catalog nvidia-prod nvidia https://integrate.api.nvidia.com/v1 NVIDIA_API_KEY Anthropic anthropic-prod anthropic https://api.anthropic.com ANTHROPIC_API_KEY Baseten baseten openai https://inference.baseten.co/v1 OPENAI_API_KEY Bitdeer AI bitdeer openai https://api-inference.bitdeer.ai/v1 OPENAI_API_KEY Deepinfra deepinfra openai https://api.deepinfra.com/v1/openai OPENAI_API_KEY Groq groq openai https://api.groq.com/openai/v1 OPENAI_API_KEY Ollama (local) ollama openai http://host.openshell.internal:11434/v1 OPENAI_API_KEY LM Studio (local) lmstudio openai http://host.openshell.internal:1234/v1 OPENAI_API_KEY Refer to your provider’s documentation for the correct base URL, available models, and API key setup. To configure inference routing, refer to /inference/configure . Next Steps Explore related topics: To control what the agent can access, refer to policies . To use a pre-built environment, refer to the community-sandboxes catalog. To view the complete field reference for the policy YAML, refer to the Policy Schema Reference","format":"text","summary":"AI agents typically need credentials to access external services: an API key for the AI model provider, a token for GitHub or GitLab, and so on. OpenShell manages these credentials as first-class entities called providers.","headings":[{"text":"Manage Providers and Credentials","level":1},{"text":"Create a Provider","level":2},{"text":"From Local Credentials","level":3},{"text":"With Explicit Credentials","level":3},{"text":"Bare Key Form","level":3},{"text":"Manage Providers","level":2},{"text":"Attach Providers to Sandboxes","level":2},{"text":"Auto-Discovery Shortcut","level":3},{"text":"Supported Provider Types","level":2},{"text":"Supported Inference Providers","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file +{"id":"sandboxes/manage-providers","title":"Manage Providers and Credentials","url":"sandboxes/manage-providers.html","last_modified":"2026-03-30T18:08:14.869091+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Create and manage credential providers that inject API keys and tokens into OpenShell sandboxes.","tags":["Providers","Credentials","API Keys","Sandbox","Security"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Manage Providers and Credentials AI agents typically need credentials to access external services: an API key for the AI model provider, a token for GitHub or GitLab, and so on. OpenShell manages these credentials as first-class entities called providers . Create and manage providers that supply credentials to sandboxes. Create a Provider Providers can be created from local environment variables or with explicit credential values. From Local Credentials The fastest way to create a provider is to let the CLI discover credentials from\nyour shell environment: $ openshell provider create --name my-claude --type claude --from-existing\nThis reads ANTHROPIC_API_KEY or CLAUDE_API_KEY from your current environment\nand stores them in the provider. With Explicit Credentials Supply a credential value directly: $ openshell provider create --name my-api --type generic --credential API_KEY=sk-abc123\nBare Key Form Pass a key name without a value to read the value from the environment variable\nof that name: $ openshell provider create --name my-api --type generic --credential API_KEY\nThis looks up the current value of $API_KEY in your shell and stores it. Manage Providers List, inspect, update, and delete providers from the active cluster. List all providers: $ openshell provider list\nInspect a provider: $ openshell provider get my-claude\nUpdate a provider’s credentials: $ openshell provider update my-claude --type claude --from-existing\nDelete a provider: $ openshell provider delete my-claude\nAttach Providers to Sandboxes Pass one or more --provider flags when creating a sandbox: $ openshell sandbox create --provider my-claude --provider my-github -- claude\nEach --provider flag attaches one provider. The sandbox receives all\ncredentials from every attached provider at runtime. Providers cannot be added to a running sandbox. If you need to attach an\nadditional provider, delete the sandbox and recreate it with all required\nproviders specified. Auto-Discovery Shortcut When the trailing command in openshell sandbox create is a recognized tool name ( claude , codex , or opencode ), the CLI auto-creates the required\nprovider from your local credentials if one does not already exist. You do not\nneed to create the provider separately: $ openshell sandbox create -- claude\nThis detects claude as a known tool, finds your ANTHROPIC_API_KEY , creates\na provider, attaches it to the sandbox, and launches Claude Code. Supported Provider Types The following provider types are supported. Type Environment Variables Injected Typical Use claude ANTHROPIC_API_KEY , CLAUDE_API_KEY Claude Code, Anthropic API codex OPENAI_API_KEY OpenAI Codex generic User-defined Any service with custom credentials github GITHUB_TOKEN , GH_TOKEN GitHub API, gh CLI — refer to /tutorials/github-sandbox gitlab GITLAB_TOKEN , GLAB_TOKEN , CI_JOB_TOKEN GitLab API, glab CLI nvidia NVIDIA_API_KEY NVIDIA API Catalog openai OPENAI_API_KEY Any OpenAI-compatible endpoint. Set --config OPENAI_BASE_URL to point to the provider. Refer to /inference/configure . opencode OPENCODE_API_KEY , OPENROUTER_API_KEY , OPENAI_API_KEY opencode tool Use the generic type for any service not listed above. You define the\nenvironment variable names and values yourself with --credential . Supported Inference Providers The following providers have been tested with inference.local . Any provider that exposes an OpenAI-compatible API works with the openai type. Set --config OPENAI_BASE_URL to the provider’s base URL and --credential OPENAI_API_KEY to your API key. Provider Name Type Base URL API Key Variable NVIDIA API Catalog nvidia-prod nvidia https://integrate.api.nvidia.com/v1 NVIDIA_API_KEY Anthropic anthropic-prod anthropic https://api.anthropic.com ANTHROPIC_API_KEY Baseten baseten openai https://inference.baseten.co/v1 OPENAI_API_KEY Bitdeer AI bitdeer openai https://api-inference.bitdeer.ai/v1 OPENAI_API_KEY Deepinfra deepinfra openai https://api.deepinfra.com/v1/openai OPENAI_API_KEY Groq groq openai https://api.groq.com/openai/v1 OPENAI_API_KEY Ollama (local) ollama openai http://host.openshell.internal:11434/v1 OPENAI_API_KEY LM Studio (local) lmstudio openai http://host.openshell.internal:1234/v1 OPENAI_API_KEY Refer to your provider’s documentation for the correct base URL, available models, and API key setup. To configure inference routing, refer to /inference/configure . Next Steps Explore related topics: To control what the agent can access, refer to policies . To use a pre-built environment, refer to the community-sandboxes catalog. To view the complete field reference for the policy YAML, refer to the Policy Schema Reference","format":"text","summary":"AI agents typically need credentials to access external services: an API key for the AI model provider, a token for GitHub or GitLab, and so on. OpenShell manages these credentials as first-class entities called providers.","headings":[{"text":"Manage Providers and Credentials","level":1},{"text":"Create a Provider","level":2},{"text":"From Local Credentials","level":3},{"text":"With Explicit Credentials","level":3},{"text":"Bare Key Form","level":3},{"text":"Manage Providers","level":2},{"text":"Attach Providers to Sandboxes","level":2},{"text":"Auto-Discovery Shortcut","level":3},{"text":"Supported Provider Types","level":2},{"text":"Supported Inference Providers","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file diff --git a/pr-preview/pr-677/sandboxes/manage-sandboxes.json b/pr-preview/pr-677/sandboxes/manage-sandboxes.json index f2d9f0a67..be681af3f 100644 --- a/pr-preview/pr-677/sandboxes/manage-sandboxes.json +++ b/pr-preview/pr-677/sandboxes/manage-sandboxes.json @@ -1 +1 @@ -{"id":"sandboxes/manage-sandboxes","title":"Manage Sandboxes","url":"sandboxes/manage-sandboxes.html","last_modified":"2026-03-30T18:03:24.514549+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Set up gateways, create sandboxes, and manage the full sandbox lifecycle.","tags":["Gateway","Sandboxing","AI Agents","Sandbox Management","CLI"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Manage Sandboxes This page covers creating sandboxes and managing them. For background on what sandboxes are and how isolation works, refer to About Sandboxes . Docker must be running before you create a gateway or sandbox. If it is not, the CLI\nreturns a connection-refused error ( os error 61 ) without explaining\nthe cause. Start Docker and try again. Create a Sandbox Create a sandbox with a single command. For example, to create a sandbox with Claude, run: $ openshell sandbox create -- claude\nEvery sandbox requires a gateway. If you run openshell sandbox create without a gateway, the CLI auto-bootstraps a local gateway. Remote Gateways If you plan to run sandboxes on a remote host or a cloud-hosted gateway, set up the gateway first. Refer to manage-gateways for deployment options and multi-gateway management. GPU Resources To request GPU resources, add --gpu : $ openshell sandbox create --gpu -- claude\nCustom Containers Use --from to create a sandbox from a pre-built community package, a local directory, or a container image: $ openshell sandbox create --from openclaw\nopenshell sandbox create --from ./my-sandbox-dir\nopenshell sandbox create --from my-registry.example.com/my-image:latest\nThe CLI resolves community names against the OpenShell Community catalog, pulls the bundled Dockerfile and policy, builds the image locally, and creates the sandbox. For the full catalog and how to contribute your own, refer to community-sandboxes . Connect to a Sandbox Open an SSH session into a running sandbox: $ openshell sandbox connect my-sandbox\nLaunch VS Code or Cursor directly into the sandbox workspace: $ openshell sandbox create --editor vscode --name my-sandbox\nopenshell sandbox connect my-sandbox --editor cursor\nWhen --editor is used, OpenShell keeps the sandbox alive and installs an\nOpenShell-managed SSH include file instead of cluttering your main\nssh/config with generated host blocks. Monitor and Debug List all sandboxes: $ openshell sandbox list\nGet detailed information about a specific sandbox: $ openshell sandbox get my-sandbox\nStream sandbox logs to monitor agent activity and diagnose policy decisions: $ openshell logs my-sandbox\nFlag Purpose Example --tail Stream logs in real time openshell logs my-sandbox --tail --source Filter by log source --source sandbox --level Filter by severity --level warn --since Show logs from a time window --since 5m OpenShell Terminal combines sandbox status and live logs in a single real-time dashboard: $ openshell term\nUse the terminal to spot blocked connections marked action=deny and inference-related proxy activity. If a connection is blocked unexpectedly, add the host to your network policy. Refer to policies for the workflow. Port Forwarding Forward a local port to a running sandbox to access services inside it, such as a web server or database: $ openshell forward start 8000 my-sandbox\nopenshell forward start 8000 my-sandbox -d # run in background\nList and stop active forwards: $ openshell forward list\nopenshell forward stop 8000 my-sandbox\nYou can also forward a port at creation time with --forward : $ openshell sandbox create --forward 8000 -- claude\nSSH Config Generate an SSH config entry for a sandbox so tools like VS Code Remote-SSH can connect directly: $ openshell sandbox ssh-config my-sandbox\nAppend the output to ~/.ssh/config or use --editor on sandbox create / sandbox connect for automatic setup. Transfer Files Upload files from your host into the sandbox: $ openshell sandbox upload my-sandbox ./src /sandbox/src\nDownload files from the sandbox to your host: $ openshell sandbox download my-sandbox /sandbox/output ./local\nYou can also upload files at creation time with the --upload flag on\nopenshell sandbox create . Delete Sandboxes Deleting a sandbox stops all processes, releases resources, and purges injected credentials. $ openshell sandbox delete my-sandbox\nNext Steps To follow a complete end-to-end example, refer to the /tutorials/github-sandbox tutorial. To supply API keys or tokens, refer to manage-providers . To control what the agent can access, refer to policies . To use a pre-built environment, refer to the community-sandboxes catalog","format":"text","summary":"This page covers creating sandboxes and managing them. For background on what sandboxes are and how isolation works, refer to About Sandboxes.","headings":[{"text":"Manage Sandboxes","level":1},{"text":"Create a Sandbox","level":2},{"text":"Remote Gateways","level":3},{"text":"GPU Resources","level":3},{"text":"Custom Containers","level":3},{"text":"Connect to a Sandbox","level":2},{"text":"Monitor and Debug","level":2},{"text":"Port Forwarding","level":2},{"text":"SSH Config","level":2},{"text":"Transfer Files","level":2},{"text":"Delete Sandboxes","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file +{"id":"sandboxes/manage-sandboxes","title":"Manage Sandboxes","url":"sandboxes/manage-sandboxes.html","last_modified":"2026-03-30T18:08:14.874816+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Set up gateways, create sandboxes, and manage the full sandbox lifecycle.","tags":["Gateway","Sandboxing","AI Agents","Sandbox Management","CLI"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_beginner","audience":["engineer","data_scientist"],"content":"Manage Sandboxes This page covers creating sandboxes and managing them. For background on what sandboxes are and how isolation works, refer to About Sandboxes . Docker must be running before you create a gateway or sandbox. If it is not, the CLI\nreturns a connection-refused error ( os error 61 ) without explaining\nthe cause. Start Docker and try again. Create a Sandbox Create a sandbox with a single command. For example, to create a sandbox with Claude, run: $ openshell sandbox create -- claude\nEvery sandbox requires a gateway. If you run openshell sandbox create without a gateway, the CLI auto-bootstraps a local gateway. Remote Gateways If you plan to run sandboxes on a remote host or a cloud-hosted gateway, set up the gateway first. Refer to manage-gateways for deployment options and multi-gateway management. GPU Resources To request GPU resources, add --gpu : $ openshell sandbox create --gpu -- claude\nCustom Containers Use --from to create a sandbox from a pre-built community package, a local directory, or a container image: $ openshell sandbox create --from openclaw\nopenshell sandbox create --from ./my-sandbox-dir\nopenshell sandbox create --from my-registry.example.com/my-image:latest\nThe CLI resolves community names against the OpenShell Community catalog, pulls the bundled Dockerfile and policy, builds the image locally, and creates the sandbox. For the full catalog and how to contribute your own, refer to community-sandboxes . Connect to a Sandbox Open an SSH session into a running sandbox: $ openshell sandbox connect my-sandbox\nLaunch VS Code or Cursor directly into the sandbox workspace: $ openshell sandbox create --editor vscode --name my-sandbox\nopenshell sandbox connect my-sandbox --editor cursor\nWhen --editor is used, OpenShell keeps the sandbox alive and installs an\nOpenShell-managed SSH include file instead of cluttering your main\nssh/config with generated host blocks. Monitor and Debug List all sandboxes: $ openshell sandbox list\nGet detailed information about a specific sandbox: $ openshell sandbox get my-sandbox\nStream sandbox logs to monitor agent activity and diagnose policy decisions: $ openshell logs my-sandbox\nFlag Purpose Example --tail Stream logs in real time openshell logs my-sandbox --tail --source Filter by log source --source sandbox --level Filter by severity --level warn --since Show logs from a time window --since 5m OpenShell Terminal combines sandbox status and live logs in a single real-time dashboard: $ openshell term\nUse the terminal to spot blocked connections marked action=deny and inference-related proxy activity. If a connection is blocked unexpectedly, add the host to your network policy. Refer to policies for the workflow. Port Forwarding Forward a local port to a running sandbox to access services inside it, such as a web server or database: $ openshell forward start 8000 my-sandbox\nopenshell forward start 8000 my-sandbox -d # run in background\nList and stop active forwards: $ openshell forward list\nopenshell forward stop 8000 my-sandbox\nYou can also forward a port at creation time with --forward : $ openshell sandbox create --forward 8000 -- claude\nSSH Config Generate an SSH config entry for a sandbox so tools like VS Code Remote-SSH can connect directly: $ openshell sandbox ssh-config my-sandbox\nAppend the output to ~/.ssh/config or use --editor on sandbox create / sandbox connect for automatic setup. Transfer Files Upload files from your host into the sandbox: $ openshell sandbox upload my-sandbox ./src /sandbox/src\nDownload files from the sandbox to your host: $ openshell sandbox download my-sandbox /sandbox/output ./local\nYou can also upload files at creation time with the --upload flag on\nopenshell sandbox create . Delete Sandboxes Deleting a sandbox stops all processes, releases resources, and purges injected credentials. $ openshell sandbox delete my-sandbox\nNext Steps To follow a complete end-to-end example, refer to the /tutorials/github-sandbox tutorial. To supply API keys or tokens, refer to manage-providers . To control what the agent can access, refer to policies . To use a pre-built environment, refer to the community-sandboxes catalog","format":"text","summary":"This page covers creating sandboxes and managing them. For background on what sandboxes are and how isolation works, refer to About Sandboxes.","headings":[{"text":"Manage Sandboxes","level":1},{"text":"Create a Sandbox","level":2},{"text":"Remote Gateways","level":3},{"text":"GPU Resources","level":3},{"text":"Custom Containers","level":3},{"text":"Connect to a Sandbox","level":2},{"text":"Monitor and Debug","level":2},{"text":"Port Forwarding","level":2},{"text":"SSH Config","level":2},{"text":"Transfer Files","level":2},{"text":"Delete Sandboxes","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file diff --git a/pr-preview/pr-677/sandboxes/policies.json b/pr-preview/pr-677/sandboxes/policies.json index 0a9e84189..1c183371d 100644 --- a/pr-preview/pr-677/sandboxes/policies.json +++ b/pr-preview/pr-677/sandboxes/policies.json @@ -1 +1 @@ -{"id":"sandboxes/policies","title":"Customize Sandbox Policies","url":"sandboxes/policies.html","last_modified":"2026-03-30T18:03:24.530643+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Apply, iterate, and debug sandbox network policies with hot-reload on running OpenShell sandboxes.","tags":["Policy","Network Policy","Sandbox","Security","Hot Reload"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_intermediate","audience":["engineer"],"content":"Customize Sandbox Policies Use this page to apply and iterate policy changes on running sandboxes. For a full field-by-field YAML definition, use the Policy Schema Reference . Policy Structure A policy has static sections filesystem_policy , landlock , and process that are locked at sandbox creation, and a dynamic section network_policies that is hot-reloadable on a running sandbox. version: 1\nStatic: locked at sandbox creation. Paths the agent can read vs read/write\nfilesystem_policy\nread_only: [/usr, /lib, /etc\nread_write: [/sandbox, /tmp\nStatic: Landlock LSM kernel enforcement. best_effort uses highest ABI the host supports\nlandlock\ncompatibility: best_effort\nStatic: Unprivileged user/group the agent process runs as\nprocess\nrun_as_user: sandbox\nrun_as_group: sandbox\nDynamic: hot-reloadable. Named blocks of endpoints + binaries allowed to reach them\nnetwork_policies\nmy_api\nname: my-api\nendpoints\nhost: api.example.com\nport: 443\nprotocol: rest\nenforcement: enforce\naccess: full\nbinaries\npath: /usr/bin/curl\nStatic sections are locked at sandbox creation. Changing them requires destroying and recreating the sandbox\nDynamic sections can be updated on a running sandbox with openshell policy set and take effect without restarting. Section Type Description filesystem_policy Static Controls which directories the agent can access on disk. Paths are split into read_only and read_write lists. Any path not listed in either list is inaccessible. Set include_workdir: true to automatically add the agent’s working directory to read_write . Landlock LSM enforces these restrictions at the kernel level. landlock Static Configures Landlock LSM enforcement behavior. Set compatibility to best_effort (skip individual inaccessible paths while applying remaining rules) or hard_requirement (fail if any path is inaccessible or the required kernel ABI is unavailable). See the Policy Schema Reference for the full behavior table. process Static Sets the OS-level identity for the agent process. run_as_user and run_as_group default to sandbox . Root ( root or 0 ) is rejected. The agent also runs with seccomp filters that block dangerous system calls. network_policies Dynamic Controls network access for ordinary outbound traffic from the sandbox. Each block has a name, a list of endpoints (host, port, protocol, and optional rules), and a list of binaries allowed to use those endpoints.
Every outbound connection except https://inference.local goes through the proxy, which queries the policy engine with the destination and calling binary. A connection is allowed only when both match an entry in the same policy block.
For endpoints with protocol: rest , the proxy auto-detects TLS and terminates it so each HTTP request is checked against that endpoint’s rules (method and path).
Endpoints without protocol allow the TCP stream through without inspecting payloads.
If no endpoint matches, the connection is denied. Configure managed inference separately through ../inference/configure . Baseline Filesystem Paths When a sandbox runs in proxy mode (the default), OpenShell automatically adds baseline filesystem paths required for the sandbox child process to function: /usr , /lib , /etc , /var/log (read-only) and /sandbox , /tmp (read-write). Paths like /app are included in the baseline set but are only added if they exist in the container image. This filtering prevents a missing baseline path from degrading Landlock enforcement. Without it, a single missing path could cause the entire Landlock ruleset to fail, leaving the sandbox with no filesystem restrictions at all. User-specified paths in your policy YAML are not pre-filtered. If you list a path that does not exist: In best_effort mode, the path is skipped with a warning and remaining rules are still applied. In hard_requirement mode, sandbox startup fails immediately. This distinction means baseline system paths degrade gracefully while user-specified paths surface configuration errors. Apply a Custom Policy Pass a policy YAML file when creating the sandbox: $ openshell sandbox create --policy ./my-policy.yaml -- claude\nopenshell sandbox create keeps the sandbox running after the initial command exits, which is useful when you plan to iterate on the policy. Add --no-keep if you want the sandbox deleted automatically instead. To avoid passing --policy every time, set a default policy with an environment variable: $ export OPENSHELL_SANDBOX_POLICY=./my-policy.yaml\nopenshell sandbox create -- claude\nThe CLI uses the policy from OPENSHELL_SANDBOX_POLICY whenever --policy is not explicitly provided. Iterate on a Running Sandbox To change what the sandbox can access, pull the current policy, edit the YAML, and push the update. The workflow is iterative: create the sandbox, monitor logs for denied actions, pull the policy, modify it, push, and verify. The following steps outline the hot-reload policy update workflow. Create the sandbox with your initial policy by following Apply a Custom Policy above (or set OPENSHELL_SANDBOX_POLICY ). Monitor denials. Each log entry shows host, port, binary, and reason. Alternatively, use openshell term for a live dashboard. $ openshell logs --tail --source sandbox\nPull the current policy. Strip the metadata header (Version, Hash, Status) before reusing the file. $ openshell policy get --full > current-policy.yaml\nEdit the YAML: add or adjust network_policies entries, binaries, access , or rules . Push the updated policy. Exit codes: 0 = loaded, 1 = validation failed, 124 = timeout. $ openshell policy set --policy current-policy.yaml --wait\nVerify the new revision. If status is loaded , repeat from step 2 as needed; if failed , fix the policy and repeat from step 4. $ openshell policy list --tail --source sandbox for the denied host, path, and binary. When triaging denied requests, check: Destination host and port to confirm which endpoint is missing. Calling binary path to confirm which binaries entry needs to be added or adjusted. HTTP method and path (for REST endpoints) to confirm which rules entry needs to be added or adjusted. Then push the updated policy as described above. Examples Add these blocks to the network_policies section of your sandbox policy. Apply with openshell policy set --policy --wait\nUse Simple endpoint for host-level allowlists and Granular rules for method/path control. Simple endpoint Allow pip install and uv pip install to reach PyPI: pypi\nname: pypi\nendpoints\nhost: pypi.org\nport: 443\nhost: files.pythonhosted.org\nport: 443\nbinaries\n{ path: /usr/bin/pip\n{ path: /usr/local/bin/uv\nEndpoints without protocol use TCP passthrough, where the proxy allows the stream without inspecting payloads. Granular rules Allow Claude and the GitHub CLI to reach api.github.com with per-path rules: read-only (GET, HEAD, OPTIONS) and GraphQL (POST) for all paths; full write access for alpha-repo ; and create/edit issues only for bravo-repo . Replace with your GitHub org or username. For an end-to-end walkthrough that combines this policy with a GitHub credential provider and sandbox creation, refer to /tutorials/github-sandbox . github_repos\nname: github_repos\nendpoints\nhost: api.github.com\nport: 443\nprotocol: rest\nenforcement: enforce\nrules\nallow\nmethod: GET\npath:\nallow\nmethod: HEAD\npath:\nallow\nmethod: OPTIONS\npath:\nallow\nmethod: POST\npath: \"/graphql\nallow\nmethod:\npath: \"/repos//alpha-repo\nallow\nmethod: POST\npath: \"/repos//bravo-repo/issues\nallow\nmethod: PATCH\npath: \"/repos//bravo-repo/issues\nbinaries\n{ path: /usr/local/bin/claude\n{ path: /usr/bin/gh\nEndpoints with protocol: rest enable HTTP request inspection. The proxy auto-detects TLS on HTTPS endpoints, terminates it, and checks each HTTP request against the rules list. Next Steps Explore related topics: To learn about network access rules and sandbox isolation layers, refer to index . To view the full field-by-field YAML definition, refer to the Policy Schema Reference . To review the default policy breakdown, refer to ../reference/default-policy","format":"text","summary":"Use this page to apply and iterate policy changes on running sandboxes. For a full field-by-field YAML definition, use the Policy Schema Reference.","headings":[{"text":"Customize Sandbox Policies","level":1},{"text":"Policy Structure","level":2},{"text":"Baseline Filesystem Paths","level":2},{"text":"Apply a Custom Policy","level":2},{"text":"Iterate on a Running Sandbox","level":2},{"text":"Global Policy Override","level":2},{"text":"Debug Denied Requests","level":2},{"text":"Examples","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file +{"id":"sandboxes/policies","title":"Customize Sandbox Policies","url":"sandboxes/policies.html","last_modified":"2026-03-30T18:08:14.888081+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Apply, iterate, and debug sandbox network policies with hot-reload on running OpenShell sandboxes.","tags":["Policy","Network Policy","Sandbox","Security","Hot Reload"],"topics":["Generative AI","Cybersecurity"],"content_type":"how_to","learning_level":"technical_intermediate","audience":["engineer"],"content":"Customize Sandbox Policies Use this page to apply and iterate policy changes on running sandboxes. For a full field-by-field YAML definition, use the Policy Schema Reference . Policy Structure A policy has static sections filesystem_policy , landlock , and process that are locked at sandbox creation, and a dynamic section network_policies that is hot-reloadable on a running sandbox. version: 1\nStatic: locked at sandbox creation. Paths the agent can read vs read/write\nfilesystem_policy\nread_only: [/usr, /lib, /etc\nread_write: [/sandbox, /tmp\nStatic: Landlock LSM kernel enforcement. best_effort uses highest ABI the host supports\nlandlock\ncompatibility: best_effort\nStatic: Unprivileged user/group the agent process runs as\nprocess\nrun_as_user: sandbox\nrun_as_group: sandbox\nDynamic: hot-reloadable. Named blocks of endpoints + binaries allowed to reach them\nnetwork_policies\nmy_api\nname: my-api\nendpoints\nhost: api.example.com\nport: 443\nprotocol: rest\nenforcement: enforce\naccess: full\nbinaries\npath: /usr/bin/curl\nStatic sections are locked at sandbox creation. Changing them requires destroying and recreating the sandbox\nDynamic sections can be updated on a running sandbox with openshell policy set and take effect without restarting. Section Type Description filesystem_policy Static Controls which directories the agent can access on disk. Paths are split into read_only and read_write lists. Any path not listed in either list is inaccessible. Set include_workdir: true to automatically add the agent’s working directory to read_write . Landlock LSM enforces these restrictions at the kernel level. landlock Static Configures Landlock LSM enforcement behavior. Set compatibility to best_effort (skip individual inaccessible paths while applying remaining rules) or hard_requirement (fail if any path is inaccessible or the required kernel ABI is unavailable). See the Policy Schema Reference for the full behavior table. process Static Sets the OS-level identity for the agent process. run_as_user and run_as_group default to sandbox . Root ( root or 0 ) is rejected. The agent also runs with seccomp filters that block dangerous system calls. network_policies Dynamic Controls network access for ordinary outbound traffic from the sandbox. Each block has a name, a list of endpoints (host, port, protocol, and optional rules), and a list of binaries allowed to use those endpoints.
Every outbound connection except https://inference.local goes through the proxy, which queries the policy engine with the destination and calling binary. A connection is allowed only when both match an entry in the same policy block.
For endpoints with protocol: rest , the proxy auto-detects TLS and terminates it so each HTTP request is checked against that endpoint’s rules (method and path).
Endpoints without protocol allow the TCP stream through without inspecting payloads.
If no endpoint matches, the connection is denied. Configure managed inference separately through ../inference/configure . Baseline Filesystem Paths When a sandbox runs in proxy mode (the default), OpenShell automatically adds baseline filesystem paths required for the sandbox child process to function: /usr , /lib , /etc , /var/log (read-only) and /sandbox , /tmp (read-write). Paths like /app are included in the baseline set but are only added if they exist in the container image. This filtering prevents a missing baseline path from degrading Landlock enforcement. Without it, a single missing path could cause the entire Landlock ruleset to fail, leaving the sandbox with no filesystem restrictions at all. User-specified paths in your policy YAML are not pre-filtered. If you list a path that does not exist: In best_effort mode, the path is skipped with a warning and remaining rules are still applied. In hard_requirement mode, sandbox startup fails immediately. This distinction means baseline system paths degrade gracefully while user-specified paths surface configuration errors. Apply a Custom Policy Pass a policy YAML file when creating the sandbox: $ openshell sandbox create --policy ./my-policy.yaml -- claude\nopenshell sandbox create keeps the sandbox running after the initial command exits, which is useful when you plan to iterate on the policy. Add --no-keep if you want the sandbox deleted automatically instead. To avoid passing --policy every time, set a default policy with an environment variable: $ export OPENSHELL_SANDBOX_POLICY=./my-policy.yaml\nopenshell sandbox create -- claude\nThe CLI uses the policy from OPENSHELL_SANDBOX_POLICY whenever --policy is not explicitly provided. Iterate on a Running Sandbox To change what the sandbox can access, pull the current policy, edit the YAML, and push the update. The workflow is iterative: create the sandbox, monitor logs for denied actions, pull the policy, modify it, push, and verify. The following steps outline the hot-reload policy update workflow. Create the sandbox with your initial policy by following Apply a Custom Policy above (or set OPENSHELL_SANDBOX_POLICY ). Monitor denials. Each log entry shows host, port, binary, and reason. Alternatively, use openshell term for a live dashboard. $ openshell logs --tail --source sandbox\nPull the current policy. Strip the metadata header (Version, Hash, Status) before reusing the file. $ openshell policy get --full > current-policy.yaml\nEdit the YAML: add or adjust network_policies entries, binaries, access , or rules . Push the updated policy. Exit codes: 0 = loaded, 1 = validation failed, 124 = timeout. $ openshell policy set --policy current-policy.yaml --wait\nVerify the new revision. If status is loaded , repeat from step 2 as needed; if failed , fix the policy and repeat from step 4. $ openshell policy list --tail --source sandbox for the denied host, path, and binary. When triaging denied requests, check: Destination host and port to confirm which endpoint is missing. Calling binary path to confirm which binaries entry needs to be added or adjusted. HTTP method and path (for REST endpoints) to confirm which rules entry needs to be added or adjusted. Then push the updated policy as described above. Examples Add these blocks to the network_policies section of your sandbox policy. Apply with openshell policy set --policy --wait\nUse Simple endpoint for host-level allowlists and Granular rules for method/path control. Simple endpoint Allow pip install and uv pip install to reach PyPI: pypi\nname: pypi\nendpoints\nhost: pypi.org\nport: 443\nhost: files.pythonhosted.org\nport: 443\nbinaries\n{ path: /usr/bin/pip\n{ path: /usr/local/bin/uv\nEndpoints without protocol use TCP passthrough, where the proxy allows the stream without inspecting payloads. Granular rules Allow Claude and the GitHub CLI to reach api.github.com with per-path rules: read-only (GET, HEAD, OPTIONS) and GraphQL (POST) for all paths; full write access for alpha-repo ; and create/edit issues only for bravo-repo . Replace with your GitHub org or username. For an end-to-end walkthrough that combines this policy with a GitHub credential provider and sandbox creation, refer to /tutorials/github-sandbox . github_repos\nname: github_repos\nendpoints\nhost: api.github.com\nport: 443\nprotocol: rest\nenforcement: enforce\nrules\nallow\nmethod: GET\npath:\nallow\nmethod: HEAD\npath:\nallow\nmethod: OPTIONS\npath:\nallow\nmethod: POST\npath: \"/graphql\nallow\nmethod:\npath: \"/repos//alpha-repo\nallow\nmethod: POST\npath: \"/repos//bravo-repo/issues\nallow\nmethod: PATCH\npath: \"/repos//bravo-repo/issues\nbinaries\n{ path: /usr/local/bin/claude\n{ path: /usr/bin/gh\nEndpoints with protocol: rest enable HTTP request inspection. The proxy auto-detects TLS on HTTPS endpoints, terminates it, and checks each HTTP request against the rules list. Next Steps Explore related topics: To learn about network access rules and sandbox isolation layers, refer to index . To view the full field-by-field YAML definition, refer to the Policy Schema Reference . To review the default policy breakdown, refer to ../reference/default-policy","format":"text","summary":"Use this page to apply and iterate policy changes on running sandboxes. For a full field-by-field YAML definition, use the Policy Schema Reference.","headings":[{"text":"Customize Sandbox Policies","level":1},{"text":"Policy Structure","level":2},{"text":"Baseline Filesystem Paths","level":2},{"text":"Apply a Custom Policy","level":2},{"text":"Iterate on a Running Sandbox","level":2},{"text":"Global Policy Override","level":2},{"text":"Debug Denied Requests","level":2},{"text":"Examples","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file diff --git a/pr-preview/pr-677/tutorials/first-network-policy.json b/pr-preview/pr-677/tutorials/first-network-policy.json index 589e6922e..8997a10dd 100644 --- a/pr-preview/pr-677/tutorials/first-network-policy.json +++ b/pr-preview/pr-677/tutorials/first-network-policy.json @@ -1 +1 @@ -{"id":"tutorials/first-network-policy","title":"Write Your First Sandbox Network Policy","url":"tutorials/first-network-policy.html","last_modified":"2026-03-30T18:03:24.537212+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"See how OpenShell network policies work by creating a sandbox, observing default-deny in action, and applying a fine-grained L7 read-only rule.","tags":["Tutorial","Policy","Network Policy","Sandbox","Security"],"topics":["Generative AI","Cybersecurity"],"content_type":"tutorial","learning_level":"technical_beginner","audience":["engineer"],"content":"Write Your First Sandbox Network Policy This tutorial shows how OpenShell’s network policy system works in under five minutes. You create a sandbox, watch a request get blocked by the default-deny policy, apply a fine-grained L7 rule, and verify that reads are allowed while writes are blocked, all without restarting anything. After completing this tutorial, you understand: How default-deny networking blocks all outbound traffic from a sandbox. How to apply a network policy that grants read-only access to a specific API. How L7 enforcement distinguishes between HTTP methods such as GET and POST on the same endpoint. How to inspect deny logs for a complete audit trail. Prerequisites A working OpenShell installation. Complete the /get-started/quickstart before proceeding. Docker Desktop running on your machine. To run every step of this tutorial, you can also use the automated demo script at the examples/sandbox-policy-quickstart directory in the NVIDIA OpenShell repository. It runs the full walkthrough in under a minute but without any user interaction. $ bash examples/sandbox-policy-quickstart/demo.sh\nCreate a Sandbox Start by creating a sandbox with no network policies. This gives you a clean environment to observe default-deny behavior. $ openshell sandbox create --name demo --keep --no-auto-providers\nkeep keeps the sandbox running after you exit so you can reconnect later. --no-auto-providers skips the provider setup prompt since this tutorial uses curl instead of an AI agent. You land in an interactive shell inside the sandbox: sandbox@demo\nTry to Reach the GitHub API With no network policy in place, every outbound connection is blocked. Test this by making a simple API call from inside the sandbox: $ curl -s https://api.github.com/zen\nhttps://api.github.com/zen is a lightweight, unauthenticated GitHub REST endpoint that returns a random aphorism on each call. It requires no tokens or parameters, which makes it a convenient smoke-test target for verifying outbound HTTPS connectivity. The request fails. By default, all outbound network traffic is denied. The sandbox proxy intercepted the HTTPS CONNECT request to api.github.com:443 and rejected it because no network policy authorizes curl to reach that host. curl: (56) Received HTTP code 403 from proxy after CONNECT\nExit the sandbox. The --keep flag keeps it running: $ exit\nCheck the Deny Log Every denied connection produces a structured log entry. Query the sandbox logs from your host to confirm the denial and inspect the reason. $ openshell logs demo --since 5m\nYou see a line like: action=deny dst_host=api.github.com dst_port=443 binary=/usr/bin/curl deny_reason=\"no matching network policy\nEvery denied connection is logged with the destination, the binary that attempted it, and the reason. Nothing gets out silently. Apply a Read-Only GitHub API Policy To allow the sandbox to reach the GitHub API, define a network policy that grants read-only access. The policy specifies which host, port, binary, and HTTP methods are permitted. Create a file called github-readonly.yaml with the following content: version: 1\nfilesystem_policy\ninclude_workdir: true\nread_only: [/usr, /lib, /proc, /dev/urandom, /app, /etc, /var/log\nread_write: [/sandbox, /tmp, /dev/null\nlandlock\ncompatibility: best_effort\nprocess\nrun_as_user: sandbox\nrun_as_group: sandbox\nnetwork_policies\ngithub_api\nname: github-api-readonly\nendpoints\nhost: api.github.com\nport: 443\nprotocol: rest\nenforcement: enforce\naccess: read-only\nbinaries\n{ path: /usr/bin/curl\nThe filesystem_policy , landlock , and process sections preserve the default sandbox settings. This is required because policy set replaces the entire policy. The network_policies section is the key part: curl may make GET, HEAD, and OPTIONS requests to api.github.com over HTTPS. Everything else is denied. The proxy auto-detects TLS on HTTPS endpoints and terminates it to inspect each HTTP request and enforce the read-only access preset at the method level. Apply it: $ openshell policy set demo --policy github-readonly.yaml --wait\nwait blocks until the sandbox confirms the new policy is loaded. No restart required. Policies are hot-reloaded. This tutorial uses curl and read-only access to keep things simple. When building policies for real workloads: To scope the policy to an agent, replace the binaries section with your agent’s binary, such as /usr/local/bin/claude , instead of curl . To grant write access, change access: read-only to read-write or add explicit rules for specific paths. Refer to the /reference/policy-schema . To allow additional endpoints, stack multiple policies in the same file for PyPI, npm, or your internal APIs. Refer to /sandboxes/policies for examples. Verify If GET Requests Are Allowed The policy is now active. Reconnect to the sandbox and retry the same request to confirm that read access works. $ openshell sandbox connect demo\nRetry the same request: $ curl -s https://api.github.com/zen\nAnything added dilutes everything else\nIt works. The read-only preset allows GET requests through. Try a Write The read-only preset allows GET but blocks mutating methods like POST, PUT, and DELETE. Test this by sending a POST request to the GitHub API while still inside the sandbox: $ curl -s -X POST https://api.github.com/repos/octocat/hello-world/issues\nH \"Content-Type: application/json\"\nd '{\"title\":\"oops\nerror\":\"policy_denied\",\"policy\":\"github-api-readonly\",\"detail\":\"POST /repos/octocat/hello-world/issues not permitted by policy\nThe CONNECT request succeeded because api.github.com is allowed, but the L7 proxy inspected the HTTP method and returned 403 . POST is not in the read-only preset. An agent with this policy can read code from GitHub but cannot create issues, push commits, or modify anything. Exit the sandbox: $ exit\nCheck the L7 Deny Log L7 denials are logged separately from connection-level denials. The log entry includes the exact HTTP method and path that the proxy rejected. $ openshell logs demo --level warn --since 5m\nl7_decision=deny dst_host=api.github.com l7_action=POST l7_target=/repos/octocat/hello-world/issues l7_deny_reason=\"POST /repos/octocat/hello-world/issues not permitted by policy\nThe log captures the exact HTTP method, path, and deny reason. In production, pipe these logs to your SIEM for a complete audit trail of every request your agent makes. To log violations without blocking requests, set enforcement: audit instead of enforcement: enforce in the policy. This is useful for building a policy iteratively: deploy in audit mode, review the logs, and switch to enforce when the rules are correct. Clean Up Delete the sandbox to free resources. This stops all processes and purges any injected credentials. $ openshell sandbox delete demo\nTo run this entire walkthrough non-interactively, use the automated demo script: $ bash examples/sandbox-policy-quickstart/demo.sh\nNext Steps To walk through a full policy iteration with Claude Code, including diagnosing denials and applying fixes from outside the sandbox, refer to /tutorials/github-sandbox","format":"text","summary":"This tutorial shows how OpenShell’s network policy system works in under five minutes. You create a sandbox, watch a request get blocked by the default-deny policy, apply a fine-grained L7 rule, and verify that reads are allowed while writes are blocked, all without restarting anything.","headings":[{"text":"Write Your First Sandbox Network Policy","level":1},{"text":"Prerequisites","level":2},{"text":"Create a Sandbox","level":2},{"text":"Try to Reach the GitHub API","level":2},{"text":"Check the Deny Log","level":2},{"text":"Apply a Read-Only GitHub API Policy","level":2},{"text":"Verify If GET Requests Are Allowed","level":2},{"text":"Try a Write","level":2},{"text":"Check the L7 Deny Log","level":2},{"text":"Clean Up","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file +{"id":"tutorials/first-network-policy","title":"Write Your First Sandbox Network Policy","url":"tutorials/first-network-policy.html","last_modified":"2026-03-30T18:08:14.895870+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"See how OpenShell network policies work by creating a sandbox, observing default-deny in action, and applying a fine-grained L7 read-only rule.","tags":["Tutorial","Policy","Network Policy","Sandbox","Security"],"topics":["Generative AI","Cybersecurity"],"content_type":"tutorial","learning_level":"technical_beginner","audience":["engineer"],"content":"Write Your First Sandbox Network Policy This tutorial shows how OpenShell’s network policy system works in under five minutes. You create a sandbox, watch a request get blocked by the default-deny policy, apply a fine-grained L7 rule, and verify that reads are allowed while writes are blocked, all without restarting anything. After completing this tutorial, you understand: How default-deny networking blocks all outbound traffic from a sandbox. How to apply a network policy that grants read-only access to a specific API. How L7 enforcement distinguishes between HTTP methods such as GET and POST on the same endpoint. How to inspect deny logs for a complete audit trail. Prerequisites A working OpenShell installation. Complete the /get-started/quickstart before proceeding. Docker Desktop running on your machine. To run every step of this tutorial, you can also use the automated demo script at the examples/sandbox-policy-quickstart directory in the NVIDIA OpenShell repository. It runs the full walkthrough in under a minute but without any user interaction. $ bash examples/sandbox-policy-quickstart/demo.sh\nCreate a Sandbox Start by creating a sandbox with no network policies. This gives you a clean environment to observe default-deny behavior. $ openshell sandbox create --name demo --keep --no-auto-providers\nkeep keeps the sandbox running after you exit so you can reconnect later. --no-auto-providers skips the provider setup prompt since this tutorial uses curl instead of an AI agent. You land in an interactive shell inside the sandbox: sandbox@demo\nTry to Reach the GitHub API With no network policy in place, every outbound connection is blocked. Test this by making a simple API call from inside the sandbox: $ curl -s https://api.github.com/zen\nhttps://api.github.com/zen is a lightweight, unauthenticated GitHub REST endpoint that returns a random aphorism on each call. It requires no tokens or parameters, which makes it a convenient smoke-test target for verifying outbound HTTPS connectivity. The request fails. By default, all outbound network traffic is denied. The sandbox proxy intercepted the HTTPS CONNECT request to api.github.com:443 and rejected it because no network policy authorizes curl to reach that host. curl: (56) Received HTTP code 403 from proxy after CONNECT\nExit the sandbox. The --keep flag keeps it running: $ exit\nCheck the Deny Log Every denied connection produces a structured log entry. Query the sandbox logs from your host to confirm the denial and inspect the reason. $ openshell logs demo --since 5m\nYou see a line like: action=deny dst_host=api.github.com dst_port=443 binary=/usr/bin/curl deny_reason=\"no matching network policy\nEvery denied connection is logged with the destination, the binary that attempted it, and the reason. Nothing gets out silently. Apply a Read-Only GitHub API Policy To allow the sandbox to reach the GitHub API, define a network policy that grants read-only access. The policy specifies which host, port, binary, and HTTP methods are permitted. Create a file called github-readonly.yaml with the following content: version: 1\nfilesystem_policy\ninclude_workdir: true\nread_only: [/usr, /lib, /proc, /dev/urandom, /app, /etc, /var/log\nread_write: [/sandbox, /tmp, /dev/null\nlandlock\ncompatibility: best_effort\nprocess\nrun_as_user: sandbox\nrun_as_group: sandbox\nnetwork_policies\ngithub_api\nname: github-api-readonly\nendpoints\nhost: api.github.com\nport: 443\nprotocol: rest\nenforcement: enforce\naccess: read-only\nbinaries\n{ path: /usr/bin/curl\nThe filesystem_policy , landlock , and process sections preserve the default sandbox settings. This is required because policy set replaces the entire policy. The network_policies section is the key part: curl may make GET, HEAD, and OPTIONS requests to api.github.com over HTTPS. Everything else is denied. The proxy auto-detects TLS on HTTPS endpoints and terminates it to inspect each HTTP request and enforce the read-only access preset at the method level. Apply it: $ openshell policy set demo --policy github-readonly.yaml --wait\nwait blocks until the sandbox confirms the new policy is loaded. No restart required. Policies are hot-reloaded. This tutorial uses curl and read-only access to keep things simple. When building policies for real workloads: To scope the policy to an agent, replace the binaries section with your agent’s binary, such as /usr/local/bin/claude , instead of curl . To grant write access, change access: read-only to read-write or add explicit rules for specific paths. Refer to the /reference/policy-schema . To allow additional endpoints, stack multiple policies in the same file for PyPI, npm, or your internal APIs. Refer to /sandboxes/policies for examples. Verify If GET Requests Are Allowed The policy is now active. Reconnect to the sandbox and retry the same request to confirm that read access works. $ openshell sandbox connect demo\nRetry the same request: $ curl -s https://api.github.com/zen\nAnything added dilutes everything else\nIt works. The read-only preset allows GET requests through. Try a Write The read-only preset allows GET but blocks mutating methods like POST, PUT, and DELETE. Test this by sending a POST request to the GitHub API while still inside the sandbox: $ curl -s -X POST https://api.github.com/repos/octocat/hello-world/issues\nH \"Content-Type: application/json\"\nd '{\"title\":\"oops\nerror\":\"policy_denied\",\"policy\":\"github-api-readonly\",\"detail\":\"POST /repos/octocat/hello-world/issues not permitted by policy\nThe CONNECT request succeeded because api.github.com is allowed, but the L7 proxy inspected the HTTP method and returned 403 . POST is not in the read-only preset. An agent with this policy can read code from GitHub but cannot create issues, push commits, or modify anything. Exit the sandbox: $ exit\nCheck the L7 Deny Log L7 denials are logged separately from connection-level denials. The log entry includes the exact HTTP method and path that the proxy rejected. $ openshell logs demo --level warn --since 5m\nl7_decision=deny dst_host=api.github.com l7_action=POST l7_target=/repos/octocat/hello-world/issues l7_deny_reason=\"POST /repos/octocat/hello-world/issues not permitted by policy\nThe log captures the exact HTTP method, path, and deny reason. In production, pipe these logs to your SIEM for a complete audit trail of every request your agent makes. To log violations without blocking requests, set enforcement: audit instead of enforcement: enforce in the policy. This is useful for building a policy iteratively: deploy in audit mode, review the logs, and switch to enforce when the rules are correct. Clean Up Delete the sandbox to free resources. This stops all processes and purges any injected credentials. $ openshell sandbox delete demo\nTo run this entire walkthrough non-interactively, use the automated demo script: $ bash examples/sandbox-policy-quickstart/demo.sh\nNext Steps To walk through a full policy iteration with Claude Code, including diagnosing denials and applying fixes from outside the sandbox, refer to /tutorials/github-sandbox","format":"text","summary":"This tutorial shows how OpenShell’s network policy system works in under five minutes. You create a sandbox, watch a request get blocked by the default-deny policy, apply a fine-grained L7 rule, and verify that reads are allowed while writes are blocked, all without restarting anything.","headings":[{"text":"Write Your First Sandbox Network Policy","level":1},{"text":"Prerequisites","level":2},{"text":"Create a Sandbox","level":2},{"text":"Try to Reach the GitHub API","level":2},{"text":"Check the Deny Log","level":2},{"text":"Apply a Read-Only GitHub API Policy","level":2},{"text":"Verify If GET Requests Are Allowed","level":2},{"text":"Try a Write","level":2},{"text":"Check the L7 Deny Log","level":2},{"text":"Clean Up","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file diff --git a/pr-preview/pr-677/tutorials/github-sandbox.json b/pr-preview/pr-677/tutorials/github-sandbox.json index eb0bb483c..c9e533a07 100644 --- a/pr-preview/pr-677/tutorials/github-sandbox.json +++ b/pr-preview/pr-677/tutorials/github-sandbox.json @@ -1 +1 @@ -{"id":"tutorials/github-sandbox","title":"Grant GitHub Push Access to a Sandboxed Agent","url":"tutorials/github-sandbox.html","last_modified":"2026-03-30T18:03:24.567664+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Learn the iterative policy workflow by launching a sandbox, diagnosing a GitHub access denial, and applying a custom policy to fix it.","tags":["Tutorial","GitHub","Sandbox","Policy","Claude Code"],"topics":["Generative AI","Cybersecurity"],"content_type":"tutorial","learning_level":"technical_intermediate","audience":["engineer"],"content":"Grant GitHub Push Access to a Sandboxed Agent This tutorial walks through an iterative sandbox policy workflow. You launch a sandbox, ask Claude Code to push code to GitHub, and observe the default network policy denying the request\nYou then diagnose the denial from your machine and from inside the sandbox, apply a policy update, and verify that the policy update to the sandbox takes effect. After completing this tutorial, you will have: A running sandbox with Claude Code that can push to a GitHub repository. A custom network policy that grants GitHub access for a specific repository. Experience with the policy iteration workflow: fail, diagnose, update, verify. This tutorial shows example prompts and responses from Claude Code. The exact wording you see might vary between sessions. Use the examples as a guide for the type of interaction, not as expected output. Prerequisites This tutorial requires the following: A working OpenShell installation. Complete the Quickstart before proceeding. A GitHub personal access token (PAT) with repo scope. Generate one from the GitHub personal access token settings page by selecting Generate new token (classic) and enabling the repo scope. An Anthropic account with access to Claude Code. OpenShell provides the sandbox runtime, not the agent. You must authenticate with your own account. A GitHub repository you own to use as the push target. A scratch repository is sufficient. You can create one with a README if needed. This tutorial uses two terminals to demonstrate the iterative policy workflow: Terminal 1 : The sandbox terminal. You create the sandbox in this terminal by running openshell sandbox create and interact with Claude Code inside it. Terminal 2 : A terminal outside the sandbox on your machine. You use this terminal for viewing the sandbox logs with openshell term and applying an updated policy with openshell policy set . Each section below indicates which terminal to use. Set Up a Sandbox with Your GitHub Token Depending on whether you start a new sandbox or use an existing sandbox, choose the appropriate tab and follow the instructions. Starting a new sandbox In terminal 2, create a new sandbox with Claude Code. The default policy is applied automatically, which allows read-only access to GitHub. Create a credential provider that injects your GitHub token into the sandbox automatically. The provider reads GITHUB_TOKEN from your host environment and sets it as an environment variable inside the sandbox: $ GITHUB_TOKEN= with your GitHub organization or username and with your repository name. Prompt Write a hello_world.py script and push it to https://github.com// . Claude recognizes that it needs GitHub credentials. It asks how you want to authenticate. Provide your GitHub personal access token by pasting it into the conversation. Claude configures authentication and attempts the push. The push fails. Claude reports an error, but the failure is not an authentication problem. The default sandbox policy permits read-only access to GitHub and blocks write operations, so the proxy denies the push before the request reaches the GitHub server. Diagnose the Denial In this section, you diagnose the denial from your machine and from inside the sandbox. View the Logs from Your Machine In terminal 2, launch the OpenShell terminal: $ openshell term\nThe dashboard shows sandbox status and a live stream of policy decisions. Look for entries with l7_decision=deny . Select a deny entry to see the full detail: l7_action: PUT\nl7_target: /repos///contents/hello_world.py\nl7_decision: deny\ndst_host: api.github.com\ndst_port: 443\nl7_protocol: rest\npolicy: github_rest_api\nl7_deny_reason: PUT /repos///contents/hello_world.py not permitted by policy\nThe log shows that the sandbox proxy intercepted an outbound PUT request to api.github.com and denied it. The github_rest_api policy allows read operations (GET) but blocks write operations (PUT, POST, DELETE) to the GitHub API. A similar denial appears for github.com if Claude attempted a git push over HTTPS. Ask Claude Code to Check the Sandbox Logs In terminal 1, ask Claude Code to check the sandbox logs for denied requests: Prompt Check the sandbox logs for any denied network requests. What is blocking the push? Claude reads the deny entries and identifies the root cause. It explains that the failure is a sandbox network policy restriction, not a token permissions issue. For example, the following is a possible response: Response The sandbox runs a proxy that enforces policies on outbound traffic\nThe github_rest_api policy allows GET requests (used to read the file\nbut blocks PUT/write requests to GitHub. This is a sandbox-level restriction\nnot a token issue. No matter what token you provide, pushes through the API\nwill be blocked until the policy is updated. Both perspectives confirm the same thing: the proxy is doing its job. The default policy is designed to be restrictive. To allow GitHub pushes, you need to update the network policy. Copy the deny reason from Claude’s response. You paste it into an agent running on your machine in the next step. Update the Policy from Your Machine In terminal 2, paste the deny reason from the previous step into your coding agent on your machine, such as Claude Code or Cursor, and ask it to recommend a policy update. The deny reason gives the agent the context it needs to generate the correct policy rules. After pasting the following prompt sample, properly provide the GitHub organization and repository names of the repository you are pushing to. Prompt Based on the following deny reasons, recommend a sandbox policy update that allows GitHub pushes to https://github.com// , and save to /tmp/sandbox-policy-update.yaml : The filesystem_policy , landlock , and process sections are static. They are read once at sandbox creation and cannot be changed by a hot-reload. They are included here for completeness so the file is self-contained, but only the network_policies section takes effect when you apply this to a running sandbox. The following steps outline the expected process done by the agent: Inspects the deny reasons. Writes an updated policy that adds github_git and github_api blocks that grant write access to your repository. Saves the policy to /tmp/sandbox-policy-update.yaml . Review the Generated Policy Refer to the following policy example to compare with the generated policy before applying it. Confirm that the policy grants only the access you expect. In this case, git push operations and GitHub REST API access scoped to a single repository. Full reference policy The following YAML shows a complete policy that extends the default policy with GitHub access for a single repository. Replace with your GitHub organization or username and with your repository name. The filesystem_policy , landlock , and process sections are static. They are read once at sandbox creation and cannot be changed by a hot-reload. They are included here for completeness so the file is self-contained, but only the network_policies section takes effect when you apply this to a running sandbox. version: 1\n── Static (locked at sandbox creation)\nfilesystem_policy\ninclude_workdir: true\nread_only\n/usr\n/lib\n/proc\n/dev/urandom\n/app\n/etc\n/var/log\nread_write\n/sandbox\n/tmp\n/dev/null\nlandlock\ncompatibility: best_effort\nprocess\nrun_as_user: sandbox\nrun_as_group: sandbox\n── Dynamic (hot-reloadable)\nnetwork_policies\nClaude Code ↔ Anthropic API\nclaude_code\nname: claude-code\nendpoints\n{ host: api.anthropic.com, port: 443, protocol: rest, enforcement: enforce, access: full\n{ host: statsig.anthropic.com, port: 443\n{ host: sentry.io, port: 443\n{ host: raw.githubusercontent.com, port: 443\n{ host: platform.claude.com, port: 443\nbinaries\n{ path: /usr/local/bin/claude\n{ path: /usr/bin/node\nNVIDIA inference endpoint\nnvidia_inference\nname: nvidia-inference\nendpoints\n{ host: integrate.api.nvidia.com, port: 443\nbinaries\n{ path: /usr/bin/curl\n{ path: /bin/bash\n{ path: /usr/local/bin/opencode\n── GitHub: git operations (clone, fetch, push)\ngithub_git\nname: github-git\nendpoints\nhost: github.com\nport: 443\nprotocol: rest\nenforcement: enforce\nrules\nallow\nmethod: GET\npath: \"//.git/info/refs\nallow\nmethod: POST\npath: \"//.git/git-upload-pack\nallow\nmethod: POST\npath: \"//.git/git-receive-pack\nbinaries\n{ path: /usr/bin/git\n── GitHub: REST API\ngithub_api\nname: github-api\nendpoints\nhost: api.github.com\nport: 443\nprotocol: rest\nenforcement: enforce\nrules\nGraphQL API (used by gh CLI\nallow\nmethod: POST\npath: \"/graphql\nFull read-write access to the repository\nallow\nmethod:\npath: \"/repos// --policy /tmp/sandbox-policy-update.yaml --wait\nNetwork policies are hot-reloadable. The --wait flag blocks until the policy engine confirms the new revision loaded, and the update takes effect immediately without restarting the sandbox or reconnecting Claude Code. Retry the Push In terminal 1, ask Claude Code to retry the push: The sandbox policy has been updated. Try pushing to the repository again\nThe push completes successfully. The openshell term dashboard now shows l7_decision=allow entries for api.github.com and github.com where it previously showed denials. Clean Up When you are finished, delete the sandbox to free cluster resources: $ openshell sandbox delete with your GitHub organization or username and with your repository name. Prompt Write a hello_world.py script and push it to https://github.com// . Claude recognizes that it needs GitHub credentials. It asks how you want to authenticate. Provide your GitHub personal access token by pasting it into the conversation. Claude configures authentication and attempts the push. The push fails. Claude reports an error, but the failure is not an authentication problem. The default sandbox policy permits read-only access to GitHub and blocks write operations, so the proxy denies the push before the request reaches the GitHub server. Diagnose the Denial In this section, you diagnose the denial from your machine and from inside the sandbox. View the Logs from Your Machine In terminal 2, launch the OpenShell terminal: $ openshell term\nThe dashboard shows sandbox status and a live stream of policy decisions. Look for entries with l7_decision=deny . Select a deny entry to see the full detail: l7_action: PUT\nl7_target: /repos///contents/hello_world.py\nl7_decision: deny\ndst_host: api.github.com\ndst_port: 443\nl7_protocol: rest\npolicy: github_rest_api\nl7_deny_reason: PUT /repos///contents/hello_world.py not permitted by policy\nThe log shows that the sandbox proxy intercepted an outbound PUT request to api.github.com and denied it. The github_rest_api policy allows read operations (GET) but blocks write operations (PUT, POST, DELETE) to the GitHub API. A similar denial appears for github.com if Claude attempted a git push over HTTPS. Ask Claude Code to Check the Sandbox Logs In terminal 1, ask Claude Code to check the sandbox logs for denied requests: Prompt Check the sandbox logs for any denied network requests. What is blocking the push? Claude reads the deny entries and identifies the root cause. It explains that the failure is a sandbox network policy restriction, not a token permissions issue. For example, the following is a possible response: Response The sandbox runs a proxy that enforces policies on outbound traffic\nThe github_rest_api policy allows GET requests (used to read the file\nbut blocks PUT/write requests to GitHub. This is a sandbox-level restriction\nnot a token issue. No matter what token you provide, pushes through the API\nwill be blocked until the policy is updated. Both perspectives confirm the same thing: the proxy is doing its job. The default policy is designed to be restrictive. To allow GitHub pushes, you need to update the network policy. Copy the deny reason from Claude’s response. You paste it into an agent running on your machine in the next step. Update the Policy from Your Machine In terminal 2, paste the deny reason from the previous step into your coding agent on your machine, such as Claude Code or Cursor, and ask it to recommend a policy update. The deny reason gives the agent the context it needs to generate the correct policy rules. After pasting the following prompt sample, properly provide the GitHub organization and repository names of the repository you are pushing to. Prompt Based on the following deny reasons, recommend a sandbox policy update that allows GitHub pushes to https://github.com// , and save to /tmp/sandbox-policy-update.yaml : The filesystem_policy , landlock , and process sections are static. They are read once at sandbox creation and cannot be changed by a hot-reload. They are included here for completeness so the file is self-contained, but only the network_policies section takes effect when you apply this to a running sandbox. The following steps outline the expected process done by the agent: Inspects the deny reasons. Writes an updated policy that adds github_git and github_api blocks that grant write access to your repository. Saves the policy to /tmp/sandbox-policy-update.yaml . Review the Generated Policy Refer to the following policy example to compare with the generated policy before applying it. Confirm that the policy grants only the access you expect. In this case, git push operations and GitHub REST API access scoped to a single repository. Full reference policy The following YAML shows a complete policy that extends the default policy with GitHub access for a single repository. Replace with your GitHub organization or username and with your repository name. The filesystem_policy , landlock , and process sections are static. They are read once at sandbox creation and cannot be changed by a hot-reload. They are included here for completeness so the file is self-contained, but only the network_policies section takes effect when you apply this to a running sandbox. version: 1\n── Static (locked at sandbox creation)\nfilesystem_policy\ninclude_workdir: true\nread_only\n/usr\n/lib\n/proc\n/dev/urandom\n/app\n/etc\n/var/log\nread_write\n/sandbox\n/tmp\n/dev/null\nlandlock\ncompatibility: best_effort\nprocess\nrun_as_user: sandbox\nrun_as_group: sandbox\n── Dynamic (hot-reloadable)\nnetwork_policies\nClaude Code ↔ Anthropic API\nclaude_code\nname: claude-code\nendpoints\n{ host: api.anthropic.com, port: 443, protocol: rest, enforcement: enforce, access: full\n{ host: statsig.anthropic.com, port: 443\n{ host: sentry.io, port: 443\n{ host: raw.githubusercontent.com, port: 443\n{ host: platform.claude.com, port: 443\nbinaries\n{ path: /usr/local/bin/claude\n{ path: /usr/bin/node\nNVIDIA inference endpoint\nnvidia_inference\nname: nvidia-inference\nendpoints\n{ host: integrate.api.nvidia.com, port: 443\nbinaries\n{ path: /usr/bin/curl\n{ path: /bin/bash\n{ path: /usr/local/bin/opencode\n── GitHub: git operations (clone, fetch, push)\ngithub_git\nname: github-git\nendpoints\nhost: github.com\nport: 443\nprotocol: rest\nenforcement: enforce\nrules\nallow\nmethod: GET\npath: \"//.git/info/refs\nallow\nmethod: POST\npath: \"//.git/git-upload-pack\nallow\nmethod: POST\npath: \"//.git/git-receive-pack\nbinaries\n{ path: /usr/bin/git\n── GitHub: REST API\ngithub_api\nname: github-api\nendpoints\nhost: api.github.com\nport: 443\nprotocol: rest\nenforcement: enforce\nrules\nGraphQL API (used by gh CLI\nallow\nmethod: POST\npath: \"/graphql\nFull read-write access to the repository\nallow\nmethod:\npath: \"/repos// --policy /tmp/sandbox-policy-update.yaml --wait\nNetwork policies are hot-reloadable. The --wait flag blocks until the policy engine confirms the new revision loaded, and the update takes effect immediately without restarting the sandbox or reconnecting Claude Code. Retry the Push In terminal 1, ask Claude Code to retry the push: The sandbox policy has been updated. Try pushing to the repository again\nThe push completes successfully. The openshell term dashboard now shows l7_decision=allow entries for api.github.com and github.com where it previously showed denials. Clean Up When you are finished, delete the sandbox to free cluster resources: $ openshell sandbox delete with your GitHub organization or username and with your repository name. Prompt Write a hello_world.py script and push it to https://github.com// . Claude recognizes that it needs GitHub credentials. It asks how you want to authenticate. Provide your GitHub personal access token by pasting it into the conversation. Claude configures authentication and attempts the push. The push fails. Claude reports an error, but the failure is not an authentication problem. The default sandbox policy permits read-only access to GitHub and blocks write operations, so the proxy denies the push before the request reaches the GitHub server. Diagnose the Denial In this section, you diagnose the denial from your machine and from inside the sandbox. View the Logs from Your Machine In terminal 2, launch the OpenShell terminal: $ openshell term\nThe dashboard shows sandbox status and a live stream of policy decisions. Look for entries with l7_decision=deny . Select a deny entry to see the full detail: l7_action: PUT\nl7_target: /repos///contents/hello_world.py\nl7_decision: deny\ndst_host: api.github.com\ndst_port: 443\nl7_protocol: rest\npolicy: github_rest_api\nl7_deny_reason: PUT /repos///contents/hello_world.py not permitted by policy\nThe log shows that the sandbox proxy intercepted an outbound PUT request to api.github.com and denied it. The github_rest_api policy allows read operations (GET) but blocks write operations (PUT, POST, DELETE) to the GitHub API. A similar denial appears for github.com if Claude attempted a git push over HTTPS. Ask Claude Code to Check the Sandbox Logs In terminal 1, ask Claude Code to check the sandbox logs for denied requests: Prompt Check the sandbox logs for any denied network requests. What is blocking the push? Claude reads the deny entries and identifies the root cause. It explains that the failure is a sandbox network policy restriction, not a token permissions issue. For example, the following is a possible response: Response The sandbox runs a proxy that enforces policies on outbound traffic\nThe github_rest_api policy allows GET requests (used to read the file\nbut blocks PUT/write requests to GitHub. This is a sandbox-level restriction\nnot a token issue. No matter what token you provide, pushes through the API\nwill be blocked until the policy is updated. Both perspectives confirm the same thing: the proxy is doing its job. The default policy is designed to be restrictive. To allow GitHub pushes, you need to update the network policy. Copy the deny reason from Claude’s response. You paste it into an agent running on your machine in the next step. Update the Policy from Your Machine In terminal 2, paste the deny reason from the previous step into your coding agent on your machine, such as Claude Code or Cursor, and ask it to recommend a policy update. The deny reason gives the agent the context it needs to generate the correct policy rules. After pasting the following prompt sample, properly provide the GitHub organization and repository names of the repository you are pushing to. Prompt Based on the following deny reasons, recommend a sandbox policy update that allows GitHub pushes to https://github.com// , and save to /tmp/sandbox-policy-update.yaml : The filesystem_policy , landlock , and process sections are static. They are read once at sandbox creation and cannot be changed by a hot-reload. They are included here for completeness so the file is self-contained, but only the network_policies section takes effect when you apply this to a running sandbox. The following steps outline the expected process done by the agent: Inspects the deny reasons. Writes an updated policy that adds github_git and github_api blocks that grant write access to your repository. Saves the policy to /tmp/sandbox-policy-update.yaml . Review the Generated Policy Refer to the following policy example to compare with the generated policy before applying it. Confirm that the policy grants only the access you expect. In this case, git push operations and GitHub REST API access scoped to a single repository. Full reference policy The following YAML shows a complete policy that extends the default policy with GitHub access for a single repository. Replace with your GitHub organization or username and with your repository name. The filesystem_policy , landlock , and process sections are static. They are read once at sandbox creation and cannot be changed by a hot-reload. They are included here for completeness so the file is self-contained, but only the network_policies section takes effect when you apply this to a running sandbox. version: 1\n── Static (locked at sandbox creation)\nfilesystem_policy\ninclude_workdir: true\nread_only\n/usr\n/lib\n/proc\n/dev/urandom\n/app\n/etc\n/var/log\nread_write\n/sandbox\n/tmp\n/dev/null\nlandlock\ncompatibility: best_effort\nprocess\nrun_as_user: sandbox\nrun_as_group: sandbox\n── Dynamic (hot-reloadable)\nnetwork_policies\nClaude Code ↔ Anthropic API\nclaude_code\nname: claude-code\nendpoints\n{ host: api.anthropic.com, port: 443, protocol: rest, enforcement: enforce, access: full\n{ host: statsig.anthropic.com, port: 443\n{ host: sentry.io, port: 443\n{ host: raw.githubusercontent.com, port: 443\n{ host: platform.claude.com, port: 443\nbinaries\n{ path: /usr/local/bin/claude\n{ path: /usr/bin/node\nNVIDIA inference endpoint\nnvidia_inference\nname: nvidia-inference\nendpoints\n{ host: integrate.api.nvidia.com, port: 443\nbinaries\n{ path: /usr/bin/curl\n{ path: /bin/bash\n{ path: /usr/local/bin/opencode\n── GitHub: git operations (clone, fetch, push)\ngithub_git\nname: github-git\nendpoints\nhost: github.com\nport: 443\nprotocol: rest\nenforcement: enforce\nrules\nallow\nmethod: GET\npath: \"//.git/info/refs\nallow\nmethod: POST\npath: \"//.git/git-upload-pack\nallow\nmethod: POST\npath: \"//.git/git-receive-pack\nbinaries\n{ path: /usr/bin/git\n── GitHub: REST API\ngithub_api\nname: github-api\nendpoints\nhost: api.github.com\nport: 443\nprotocol: rest\nenforcement: enforce\nrules\nGraphQL API (used by gh CLI\nallow\nmethod: POST\npath: \"/graphql\nFull read-write access to the repository\nallow\nmethod:\npath: \"/repos// --policy /tmp/sandbox-policy-update.yaml --wait\nNetwork policies are hot-reloadable. The --wait flag blocks until the policy engine confirms the new revision loaded, and the update takes effect immediately without restarting the sandbox or reconnecting Claude Code. Retry the Push In terminal 1, ask Claude Code to retry the push: The sandbox policy has been updated. Try pushing to the repository again\nThe push completes successfully. The openshell term dashboard now shows l7_decision=allow entries for api.github.com and github.com where it previously showed denials. Clean Up When you are finished, delete the sandbox to free cluster resources: $ openshell sandbox delete \n$ openshell provider create --name my-github --type github --from-existing\n$ openshell sandbox create --provider my-github -- claude","language":"text"},{"content":"$ openshell sandbox connect \n$ export GITHUB_TOKEN=","language":"text"},{"content":"$ openshell term","language":"text"},{"content":"l7_action: PUT\nl7_target: /repos///contents/hello_world.py\nl7_decision: deny\ndst_host: api.github.com\ndst_port: 443\nl7_protocol: rest\npolicy: github_rest_api\nl7_deny_reason: PUT /repos///contents/hello_world.py not permitted by policy","language":"text"},{"content":"version: 1\n\n# ── Static (locked at sandbox creation) ──────────────────────────\n\nfilesystem_policy:\n include_workdir: true\n read_only:\n - /usr\n - /lib\n - /proc\n - /dev/urandom\n - /app\n - /etc\n - /var/log\n read_write:\n - /sandbox\n - /tmp\n - /dev/null\n\nlandlock:\n compatibility: best_effort\n\nprocess:\n run_as_user: sandbox\n run_as_group: sandbox\n\n# ── Dynamic (hot-reloadable) ─────────────────────────────────────\n\nnetwork_policies:\n\n # Claude Code ↔ Anthropic API\n claude_code:\n name: claude-code\n endpoints:\n - { host: api.anthropic.com, port: 443, protocol: rest, enforcement: enforce, access: full }\n - { host: statsig.anthropic.com, port: 443 }\n - { host: sentry.io, port: 443 }\n - { host: raw.githubusercontent.com, port: 443 }\n - { host: platform.claude.com, port: 443 }\n binaries:\n - { path: /usr/local/bin/claude }\n - { path: /usr/bin/node }\n\n # NVIDIA inference endpoint\n nvidia_inference:\n name: nvidia-inference\n endpoints:\n - { host: integrate.api.nvidia.com, port: 443 }\n binaries:\n - { path: /usr/bin/curl }\n - { path: /bin/bash }\n - { path: /usr/local/bin/opencode }\n\n # ── GitHub: git operations (clone, fetch, push) ──────────────\n\n github_git:\n name: github-git\n endpoints:\n - host: github.com\n port: 443\n protocol: rest\n enforcement: enforce\n rules:\n - allow:\n method: GET\n path: \"//.git/info/refs*\"\n - allow:\n method: POST\n path: \"//.git/git-upload-pack\"\n - allow:\n method: POST\n path: \"//.git/git-receive-pack\"\n binaries:\n - { path: /usr/bin/git }\n\n # ── GitHub: REST API ─────────────────────────────────────────\n\n github_api:\n name: github-api\n endpoints:\n - host: api.github.com\n port: 443\n protocol: rest\n enforcement: enforce\n rules:\n # GraphQL API (used by gh CLI)\n - allow:\n method: POST\n path: \"/graphql\"\n # Full read-write access to the repository\n - allow:\n method: \"*\"\n path: \"/repos///**\"\n binaries:\n - { path: /usr/local/bin/claude }\n - { path: /usr/local/bin/opencode }\n - { path: /usr/bin/gh }\n - { path: /usr/bin/curl }\n\n # ── Package managers ─────────────────────────────────────────\n\n pypi:\n name: pypi\n endpoints:\n - { host: pypi.org, port: 443 }\n - { host: files.pythonhosted.org, port: 443 }\n - { host: github.com, port: 443 }\n - { host: objects.githubusercontent.com, port: 443 }\n - { host: api.github.com, port: 443 }\n - { host: downloads.python.org, port: 443 }\n binaries:\n - { path: /sandbox/.venv/bin/python }\n - { path: /sandbox/.venv/bin/python3 }\n - { path: /sandbox/.venv/bin/pip }\n - { path: \"/sandbox/.uv/python/**/python*\" }\n - { path: /usr/local/bin/uv }\n - { path: \"/sandbox/.uv/python/**\" }\n\n # ── VS Code Remote ──────────────────────────────────────────\n\n vscode:\n name: vscode\n endpoints:\n - { host: update.code.visualstudio.com, port: 443 }\n - { host: \"*.vo.msecnd.net\", port: 443 }\n - { host: vscode.download.prss.microsoft.com, port: 443 }\n - { host: marketplace.visualstudio.com, port: 443 }\n - { host: \"*.gallerycdn.vsassets.io\", port: 443 }\n binaries:\n - { path: /usr/bin/curl }\n - { path: /usr/bin/wget }\n - { path: \"/sandbox/.vscode-server/**\" }\n - { path: \"/sandbox/.vscode-remote-containers/**\" }","language":"text"},{"content":"$ openshell policy set --policy /tmp/sandbox-policy-update.yaml --wait","language":"text"},{"content":"The sandbox policy has been updated. Try pushing to the repository again.","language":"text"},{"content":"$ openshell sandbox delete ","language":"text"}],"links":[{"text":"GitHub personal access token settings page","type":"external","url":"https://github.com/settings/tokens"},{"text":"Anthropic account","type":"external","url":"https://console.anthropic.com/"},{"text":"create one","type":"external","url":"https://github.com/new"}],"images":[],"doc_type":"tutorial","section_path":["Tutorials","Github Sandbox"]},{"id":"tutorials/inference-ollama","title":"Run Local Inference with Ollama","url":"tutorials/inference-ollama.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Run local and cloud models inside an OpenShell sandbox using the Ollama community sandbox, or route sandbox requests to a host-level Ollama server.","tags":["Tutorial","Inference Routing","Ollama","Local Inference","Sandbox"],"topics":["Generative AI","Cybersecurity"],"content_type":"tutorial","learning_level":"technical_intermediate","audience":["engineer"],"content":"Run Local Inference with Ollama This tutorial covers two ways to use Ollama with OpenShell: Ollama sandbox (recommended) — a self-contained sandbox with Ollama, Claude Code, and Codex pre-installed. One command to start. Host-level Ollama — run Ollama on the gateway host and route sandbox inference to it. Useful when you want a single Ollama instance shared across multiple sandboxes. After completing this tutorial, you will know how to: Launch the Ollama community sandbox for a batteries-included experience. Use ollama launch to start coding agents inside a sandbox. Expose a host-level Ollama server to sandboxes through inference.local . Prerequisites A working OpenShell installation. Complete the /get-started/quickstart before proceeding. Option A: Ollama Community Sandbox (Recommended) The Ollama community sandbox bundles Ollama, Claude Code, OpenCode, and Codex into a single image. Ollama starts automatically when the sandbox launches. Step 1: Create the Sandbox $ openshell sandbox create --from ollama\nThis pulls the community sandbox image, applies the bundled policy, and drops you into a shell with Ollama running. Step 2: Chat with a Model Chat with a local model $ ollama run qwen3.5\nOr a cloud model $ ollama run kimi-k2.5:cloud\nOr use ollama launch to start a coding agent with Ollama as the model backend: $ ollama launch claude\nollama launch codex\nollama launch opencode\nFor CI/CD and automated workflows, ollama launch supports a headless mode: $ ollama launch claude --yes --model qwen3.5\nModel Recommendations Use case Model Notes Smoke test qwen3.5:0.8b Fast, lightweight, good for verifying setup Coding and reasoning qwen3.5 Strong tool calling support for agentic workflows Complex tasks nemotron-3-super 122B parameter model, needs 48GB+ VRAM No local GPU qwen3.5:cloud Runs on Ollama’s cloud infrastructure, no ollama pull required Cloud models use the :cloud tag suffix and do not require local hardware. $ openshell sandbox create --from ollama\nTool Calling Agentic workflows (Claude Code, Codex, OpenCode) rely on tool calling. The following models have reliable tool calling support: Qwen 3.5, Nemotron-3-Super, GLM-5, and Kimi-K2.5. Check the Ollama model library for the latest models. Updating Ollama To update Ollama inside a running sandbox: $ update-ollama\nOr auto-update on every sandbox start: $ openshell sandbox create --from ollama -e OLLAMA_UPDATE=1\nOption B: Host-Level Ollama Use this approach when you want a single Ollama instance on the gateway host, shared across multiple sandboxes through inference.local . This approach uses Ollama because it is easy to install and run locally, but you can substitute other inference engines such as vLLM, SGLang, TRT-LLM, and NVIDIA NIM by changing the startup command, base URL, and model name. Step 1: Install and Start Ollama Install Ollama on the gateway host: $ curl -fsSL https://ollama.com/install.sh | sh\nStart Ollama on all interfaces so it is reachable from sandboxes: $ OLLAMA_HOST=0.0.0.0:11434 ollama serve\nIf you see Error: listen tcp 0.0.0.0:11434: bind: address already in use , Ollama is already running as a system service. Stop it first: $ systemctl stop ollama\nOLLAMA_HOST=0.0.0.0:11434 ollama serve\nStep 2: Pull a Model In a second terminal, pull a model: $ ollama run qwen3.5:0.8b\nType /bye to exit the interactive session. The model stays loaded. Step 3: Create a Provider Create an OpenAI-compatible provider pointing at the host Ollama: $ openshell provider create\nname ollama\ntype openai\ncredential OPENAI_API_KEY=empty\nconfig OPENAI_BASE_URL=http://host.openshell.internal:11434/v1\nOpenShell injects host.openshell.internal so sandboxes and the gateway can reach the host machine. You can also use the host’s LAN IP. Step 4: Set Inference Routing $ openshell inference set --provider ollama --model qwen3.5:0.8b\nConfirm: $ openshell inference get\nStep 5: Verify from a Sandbox $ openshell sandbox create --\ncurl https://inference.local/v1/chat/completions\njson '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10\nThe response should be JSON from the model. Troubleshooting Common issues and fixes: Ollama not reachable from sandbox — Ollama must be bound to 0.0.0.0 , not 127.0.0.1 . This applies to host-level Ollama only; the community sandbox handles this automatically. OPENAI_BASE_URL wrong — Use http://host.openshell.internal:11434/v1 , not localhost or 127.0.0.1 . Model not found — Run ollama ps to confirm the model is loaded. Run ollama pull if needed. HTTPS vs HTTP — Code inside sandboxes must call https://inference.local , not http:// . AMD GPU driver issues — Ollama v0.18+ requires ROCm 7 drivers for AMD GPUs. Update your drivers if you see GPU detection failures. Useful commands: $ openshell status\nopenshell inference get\nopenshell provider get ollama\nNext Steps To learn more about managed inference, refer to /inference/index . To configure a different self-hosted backend, refer to /inference/configure . To explore more community sandboxes, refer to /sandboxes/community-sandboxes","format":"text","content_length":5050,"word_count":743,"summary":"This tutorial covers two ways to use Ollama with OpenShell:","headings":[{"text":"Run Local Inference with Ollama","level":1,"id":"run-local-inference-with-ollama"},{"text":"Prerequisites","level":2,"id":"prerequisites"},{"text":"Option A: Ollama Community Sandbox (Recommended)","level":2,"id":"option-a-ollama-community-sandbox-recommended"},{"text":"Step 1: Create the Sandbox","level":3,"id":"step-1-create-the-sandbox"},{"text":"Tool Calling","level":3,"id":"tool-calling"},{"text":"Updating Ollama","level":3,"id":"updating-ollama"},{"text":"Option B: Host-Level Ollama","level":2,"id":"option-b-host-level-ollama"},{"text":"Step 1: Install and Start Ollama","level":3,"id":"step-1-install-and-start-ollama"},{"text":"Step 2: Pull a Model","level":3,"id":"step-2-pull-a-model"},{"text":"Step 3: Create a Provider","level":3,"id":"step-3-create-a-provider"},{"text":"Step 4: Set Inference Routing","level":3,"id":"step-4-set-inference-routing"},{"text":"Step 5: Verify from a Sandbox","level":3,"id":"step-5-verify-from-a-sandbox"},{"text":"Troubleshooting","level":2,"id":"troubleshooting"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Run Local Inference with Ollama Prerequisites Option A: Ollama Community Sandbox (Recommended) Step 1: Create the Sandbox Tool Calling Updating Ollama Option B: Host-Level Ollama Step 1: Install and Start Ollama Step 2: Pull a Model Step 3: Create a Provider Step 4: Set Inference Routing Step 5: Verify from a Sandbox Troubleshooting Next Steps","keywords":["after","agentic","backend","bind","calling","chat","check","claude","cloud","code","codex","coding","com","commands","common","community","complete","complex","confirm","content","create","error","expose","fast","first","fixes","from","gpus","hello","host","http","https","inference","install","internal","kimi","launch","level","local","max_tokens","messages","mode","model","nemotron","next","notes","ollama","openai","opencode","openshell"],"code_blocks":[{"content":"$ openshell sandbox create --from ollama","language":"text"},{"content":"$ ollama run qwen3.5","language":"text"},{"content":"$ ollama run kimi-k2.5:cloud","language":"text"},{"content":"$ ollama launch claude\n$ ollama launch codex\n$ ollama launch opencode","language":"text"},{"content":"$ ollama launch claude --yes --model qwen3.5","language":"text"},{"content":"$ openshell sandbox create --from ollama","language":"text"},{"content":"$ update-ollama","language":"text"},{"content":"$ openshell sandbox create --from ollama -e OLLAMA_UPDATE=1","language":"text"},{"content":"$ curl -fsSL https://ollama.com/install.sh | sh","language":"text"},{"content":"$ OLLAMA_HOST=0.0.0.0:11434 ollama serve","language":"text"},{"content":"$ systemctl stop ollama\n$ OLLAMA_HOST=0.0.0.0:11434 ollama serve","language":"text"},{"content":"$ ollama run qwen3.5:0.8b","language":"text"},{"content":"$ openshell provider create \\\n --name ollama \\\n --type openai \\\n --credential OPENAI_API_KEY=empty \\\n --config OPENAI_BASE_URL=http://host.openshell.internal:11434/v1","language":"text"},{"content":"$ openshell inference set --provider ollama --model qwen3.5:0.8b","language":"text"},{"content":"$ openshell inference get","language":"text"},{"content":"$ openshell sandbox create -- \\\n curl https://inference.local/v1/chat/completions \\\n --json '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10}'","language":"text"},{"content":"$ openshell status\n$ openshell inference get\n$ openshell provider get ollama","language":"text"}],"links":[{"text":"Ollama model library","type":"external","url":"https://ollama.com/library"},{"text":"Ollama","type":"external","url":"https://ollama.com/"}],"images":[],"doc_type":"tutorial","section_path":["Tutorials","Inference Ollama"]},{"id":"tutorials/local-inference-lmstudio","title":"Route Local Inference Requests to LM Studio","url":"tutorials/local-inference-lmstudio.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Configure inference.local to route sandbox requests to a local LM Studio server running on the gateway host.","tags":["Tutorial","Inference Routing","LM Studio","Local Inference","Sandbox"],"topics":["Generative AI","Cybersecurity"],"content_type":"tutorial","learning_level":"technical_intermediate","audience":["engineer"],"content":"Route Local Inference Requests to LM Studio This tutorial describes how to configure OpenShell to route inference requests to a local LM Studio server. The LM Studio server provides easy setup with both OpenAI and Anthropic compatible endpoints. This tutorial will cover: Expose a local inference server to OpenShell sandboxes. Verify end-to-end inference from inside a sandbox. Prerequisites First, complete OpenShell installation and follow the /get-started/quickstart . Install the LM Studio app . Make sure that your LM Studio is running in the same environment as your gateway. If you prefer to work without having to keep the LM Studio app open, download llmster (headless LM Studio) with the following command: Linux/Mac $ curl -fsSL https://lmstudio.ai/install.sh | bash\nWindows $ irm https://lmstudio.ai/install.ps1 | iex\nAnd start llmster: $ lms daemon up\nStep 1: Start LM Studio Local Server Start the LM Studio local server from the Developer tab, and verify the OpenAI-compatible endpoint is enabled. LM Studio will listen to 127.0.0.1:1234 by default. For use with OpenShell, you’ll need to configure LM Studio to listen on all interfaces ( 0.0.0.0 ). If you’re using the GUI, go to the Developer Tab, select Server Settings, then enable Serve on Local Network. If you’re using llmster in headless mode, run lms server start --bind 0.0.0.0 . Step 2: Test with a small model In the LM Studio app, head to the Model Search tab to download a small model like Qwen3.5 2B. In the terminal, use the following command to download and load the model: $ lms get qwen/qwen3.5-2b\nlms load qwen/qwen3.5-2b\nStep 3: Add LM Studio as a provider Choose the provider type that matches the client protocol you want to route through inference.local . OpenAI-compatible Add LM Studio as an OpenAI-compatible provider through host.openshell.internal : $ openshell provider create\nname lmstudio\ntype openai\ncredential OPENAI_API_KEY=lmstudio\nconfig OPENAI_BASE_URL=http://host.openshell.internal:1234/v1\nUse this provider for clients that send OpenAI-compatible requests such as POST /v1/chat/completions or POST /v1/responses . Anthropic-compatible Add a provider that points to LM Studio’s Anthropic-compatible POST /v1/messages endpoint: $ openshell provider create\nname lmstudio-anthropic\ntype anthropic\ncredential ANTHROPIC_API_KEY=lmstudio\nconfig ANTHROPIC_BASE_URL=http://host.openshell.internal:1234\nUse this provider for Anthropic-compatible POST /v1/messages requests. Step 4: Configure LM Studio as the local inference provider Set the managed inference route for the active gateway: OpenAI-compatible $ openshell inference set --provider lmstudio --model qwen/qwen3.5-2b\nIf the command succeeds, OpenShell has verified that the upstream is reachable and accepts the expected OpenAI-compatible request shape. Anthropic-compatible $ openshell inference set --provider lmstudio-anthropic --model qwen/qwen3.5-2b\nIf the command succeeds, OpenShell has verified that the upstream is reachable and accepts the expected Anthropic-compatible request shape. The active inference.local route is gateway-scoped, so only one provider and model pair is active at a time. Re-run openshell inference set whenever you want to switch between OpenAI-compatible and Anthropic-compatible clients. Confirm the saved config: $ openshell inference get\nYou should see either Provider: lmstudio or Provider: lmstudio-anthropic , along with Model: qwen/qwen3.5-2b . Step 5: Verify from Inside a Sandbox Run a simple request through https://inference.local : OpenAI-compatible openshell sandbox create --\ncurl https://inference.local/v1/chat/completions\njson '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10\nopenshell sandbox create --\ncurl https://inference.local/v1/responses\njson\ninstructions\": \"You are a helpful assistant\ninput\": \"hello\nmax_output_tokens\": 10\nAnthropic-compatible openshell sandbox create --\ncurl https://inference.local/v1/messages\njson '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10\nTroubleshooting If setup fails, check these first: LM Studio local server is running and reachable from the gateway host OPENAI_BASE_URL uses http://host.openshell.internal:1234/v1 when you use an openai provider ANTHROPIC_BASE_URL uses http://host.openshell.internal:1234 when you use an anthropic provider The gateway and LM Studio run on the same machine or a reachable network path The configured model name matches the model exposed by LM Studio Useful commands: $ openshell status\nopenshell inference get\nopenshell provider get lmstudio\nopenshell provider get lmstudio-anthropic\nNext Steps To learn more about using the LM Studio CLI, refer to LM Studio docs To learn more about managed inference, refer to /inference/index . To configure a different self-hosted backend, refer to /inference/configure","format":"text","content_length":4825,"word_count":650,"summary":"This tutorial describes how to configure OpenShell to route inference requests to a local LM Studio server.","headings":[{"text":"Route Local Inference Requests to LM Studio","level":1,"id":"route-local-inference-requests-to-lm-studio"},{"text":"Prerequisites","level":2,"id":"prerequisites"},{"text":"Linux/Mac","level":3,"id":"linuxmac"},{"text":"Windows","level":3,"id":"windows"},{"text":"Step 1: Start LM Studio Local Server","level":2,"id":"step-1-start-lm-studio-local-server"},{"text":"Step 2: Test with a small model","level":2,"id":"step-2-test-with-a-small-model"},{"text":"Step 3: Add LM Studio as a provider","level":2,"id":"step-3-add-lm-studio-as-a-provider"},{"text":"Step 4: Configure LM Studio as the local inference provider","level":2,"id":"step-4-configure-lm-studio-as-the-local-inference-provider"},{"text":"Step 5: Verify from Inside a Sandbox","level":2,"id":"step-5-verify-from-inside-a-sandbox"},{"text":"Troubleshooting","level":2,"id":"troubleshooting"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Route Local Inference Requests to LM Studio Prerequisites Linux/Mac Windows Step 1: Start LM Studio Local Server Step 2: Test with a small model Step 3: Add LM Studio as a provider Step 4: Configure LM Studio as the local inference provider Step 5: Verify from Inside a Sandbox Troubleshooting Next Steps","keywords":["add","anthropic","choose","command","commands","config","configure","confirm","content","cover","developer","endpoint","expose","first","from","gateway","hello","http","https","inference","inside","install","internal","linux","llmster","local","mac","make","max_tokens","messages","model","network","next","openai","openshell","prerequisites","provider","qwen3","requests","role","route","run","sandbox","search","serve","server","set","settings","small","start"],"code_blocks":[{"content":"$ curl -fsSL https://lmstudio.ai/install.sh | bash","language":"text"},{"content":"$ irm https://lmstudio.ai/install.ps1 | iex","language":"text"},{"content":"$ lms daemon up","language":"text"},{"content":"$ lms get qwen/qwen3.5-2b\n$ lms load qwen/qwen3.5-2b","language":"text"},{"content":"$ openshell provider create \\\n --name lmstudio \\\n --type openai \\\n --credential OPENAI_API_KEY=lmstudio \\\n --config OPENAI_BASE_URL=http://host.openshell.internal:1234/v1","language":"text"},{"content":"$ openshell provider create \\\n --name lmstudio-anthropic \\\n --type anthropic \\\n --credential ANTHROPIC_API_KEY=lmstudio \\\n --config ANTHROPIC_BASE_URL=http://host.openshell.internal:1234","language":"text"},{"content":"$ openshell inference set --provider lmstudio --model qwen/qwen3.5-2b","language":"text"},{"content":"$ openshell inference set --provider lmstudio-anthropic --model qwen/qwen3.5-2b","language":"text"},{"content":"$ openshell inference get","language":"text"},{"content":"openshell sandbox create -- \\\n curl https://inference.local/v1/chat/completions \\\n --json '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10}'\n\nopenshell sandbox create -- \\\n curl https://inference.local/v1/responses \\\n --json '{\n \"instructions\": \"You are a helpful assistant.\",\n \"input\": \"hello\",\n \"max_output_tokens\": 10\n }'","language":"text"},{"content":"openshell sandbox create -- \\\n curl https://inference.local/v1/messages \\\n --json '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10}'","language":"text"},{"content":"$ openshell status\n$ openshell inference get\n$ openshell provider get lmstudio\n$ openshell provider get lmstudio-anthropic","language":"text"}],"links":[{"text":"Install the LM Studio app","type":"external","url":"https://lmstudio.ai/download"},{"text":"LM Studio docs","type":"external","url":"https://lmstudio.ai/docs/cli"}],"images":[],"doc_type":"tutorial","section_path":["Tutorials","Local Inference Lmstudio"]}]} \ No newline at end of file +{"id":"tutorials/index","title":"Tutorials","url":"tutorials/index.html","last_modified":"2026-03-30T18:08:14.911286+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Step-by-step walkthroughs for OpenShell, from first sandbox to production-ready policies.","tags":["Tutorial","Sandbox","Policy"],"topics":["Generative AI","Cybersecurity"],"content_type":"index","content":"Tutorials Hands-on walkthroughs that teach OpenShell concepts by building real configurations. Each tutorial builds on the previous one, starting with core sandbox mechanics and progressing to production workflows. First Network Policy Create a sandbox, observe default-deny networking, apply a read-only L7 policy, and inspect audit logs. No AI agent required. Tutorial first-network-policy GitHub Push Access Launch Claude Code in a sandbox, diagnose a policy denial, and iterate on a custom GitHub policy from outside the sandbox. Tutorial github-sandbox Inference with Ollama Route inference through Ollama using cloud-hosted or local models, and verify it from a sandbox. Tutorial inference-ollama Local Inference with LM Studio Route inference to a local LM Studio server via the OpenAI or Anthropic compatible APIs. Tutorial local-inference-lmstudio","format":"text","summary":"Hands-on walkthroughs that teach OpenShell concepts by building real configurations. Each tutorial builds on the previous one, starting with core sandbox mechanics and progressing to production workflows.","headings":[{"text":"Tutorials","level":1}],"children":[{"id":"tutorials/first-network-policy","title":"Write Your First Sandbox Network Policy","url":"tutorials/first-network-policy.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"See how OpenShell network policies work by creating a sandbox, observing default-deny in action, and applying a fine-grained L7 read-only rule.","tags":["Tutorial","Policy","Network Policy","Sandbox","Security"],"topics":["Generative AI","Cybersecurity"],"content_type":"tutorial","learning_level":"technical_beginner","audience":["engineer"],"content":"Write Your First Sandbox Network Policy This tutorial shows how OpenShell’s network policy system works in under five minutes. You create a sandbox, watch a request get blocked by the default-deny policy, apply a fine-grained L7 rule, and verify that reads are allowed while writes are blocked, all without restarting anything. After completing this tutorial, you understand: How default-deny networking blocks all outbound traffic from a sandbox. How to apply a network policy that grants read-only access to a specific API. How L7 enforcement distinguishes between HTTP methods such as GET and POST on the same endpoint. How to inspect deny logs for a complete audit trail. Prerequisites A working OpenShell installation. Complete the /get-started/quickstart before proceeding. Docker Desktop running on your machine. To run every step of this tutorial, you can also use the automated demo script at the examples/sandbox-policy-quickstart directory in the NVIDIA OpenShell repository. It runs the full walkthrough in under a minute but without any user interaction. $ bash examples/sandbox-policy-quickstart/demo.sh\nCreate a Sandbox Start by creating a sandbox with no network policies. This gives you a clean environment to observe default-deny behavior. $ openshell sandbox create --name demo --keep --no-auto-providers\nkeep keeps the sandbox running after you exit so you can reconnect later. --no-auto-providers skips the provider setup prompt since this tutorial uses curl instead of an AI agent. You land in an interactive shell inside the sandbox: sandbox@demo\nTry to Reach the GitHub API With no network policy in place, every outbound connection is blocked. Test this by making a simple API call from inside the sandbox: $ curl -s https://api.github.com/zen\nhttps://api.github.com/zen is a lightweight, unauthenticated GitHub REST endpoint that returns a random aphorism on each call. It requires no tokens or parameters, which makes it a convenient smoke-test target for verifying outbound HTTPS connectivity. The request fails. By default, all outbound network traffic is denied. The sandbox proxy intercepted the HTTPS CONNECT request to api.github.com:443 and rejected it because no network policy authorizes curl to reach that host. curl: (56) Received HTTP code 403 from proxy after CONNECT\nExit the sandbox. The --keep flag keeps it running: $ exit\nCheck the Deny Log Every denied connection produces a structured log entry. Query the sandbox logs from your host to confirm the denial and inspect the reason. $ openshell logs demo --since 5m\nYou see a line like: action=deny dst_host=api.github.com dst_port=443 binary=/usr/bin/curl deny_reason=\"no matching network policy\nEvery denied connection is logged with the destination, the binary that attempted it, and the reason. Nothing gets out silently. Apply a Read-Only GitHub API Policy To allow the sandbox to reach the GitHub API, define a network policy that grants read-only access. The policy specifies which host, port, binary, and HTTP methods are permitted. Create a file called github-readonly.yaml with the following content: version: 1\nfilesystem_policy\ninclude_workdir: true\nread_only: [/usr, /lib, /proc, /dev/urandom, /app, /etc, /var/log\nread_write: [/sandbox, /tmp, /dev/null\nlandlock\ncompatibility: best_effort\nprocess\nrun_as_user: sandbox\nrun_as_group: sandbox\nnetwork_policies\ngithub_api\nname: github-api-readonly\nendpoints\nhost: api.github.com\nport: 443\nprotocol: rest\nenforcement: enforce\naccess: read-only\nbinaries\n{ path: /usr/bin/curl\nThe filesystem_policy , landlock , and process sections preserve the default sandbox settings. This is required because policy set replaces the entire policy. The network_policies section is the key part: curl may make GET, HEAD, and OPTIONS requests to api.github.com over HTTPS. Everything else is denied. The proxy auto-detects TLS on HTTPS endpoints and terminates it to inspect each HTTP request and enforce the read-only access preset at the method level. Apply it: $ openshell policy set demo --policy github-readonly.yaml --wait\nwait blocks until the sandbox confirms the new policy is loaded. No restart required. Policies are hot-reloaded. This tutorial uses curl and read-only access to keep things simple. When building policies for real workloads: To scope the policy to an agent, replace the binaries section with your agent’s binary, such as /usr/local/bin/claude , instead of curl . To grant write access, change access: read-only to read-write or add explicit rules for specific paths. Refer to the /reference/policy-schema . To allow additional endpoints, stack multiple policies in the same file for PyPI, npm, or your internal APIs. Refer to /sandboxes/policies for examples. Verify If GET Requests Are Allowed The policy is now active. Reconnect to the sandbox and retry the same request to confirm that read access works. $ openshell sandbox connect demo\nRetry the same request: $ curl -s https://api.github.com/zen\nAnything added dilutes everything else\nIt works. The read-only preset allows GET requests through. Try a Write The read-only preset allows GET but blocks mutating methods like POST, PUT, and DELETE. Test this by sending a POST request to the GitHub API while still inside the sandbox: $ curl -s -X POST https://api.github.com/repos/octocat/hello-world/issues\nH \"Content-Type: application/json\"\nd '{\"title\":\"oops\nerror\":\"policy_denied\",\"policy\":\"github-api-readonly\",\"detail\":\"POST /repos/octocat/hello-world/issues not permitted by policy\nThe CONNECT request succeeded because api.github.com is allowed, but the L7 proxy inspected the HTTP method and returned 403 . POST is not in the read-only preset. An agent with this policy can read code from GitHub but cannot create issues, push commits, or modify anything. Exit the sandbox: $ exit\nCheck the L7 Deny Log L7 denials are logged separately from connection-level denials. The log entry includes the exact HTTP method and path that the proxy rejected. $ openshell logs demo --level warn --since 5m\nl7_decision=deny dst_host=api.github.com l7_action=POST l7_target=/repos/octocat/hello-world/issues l7_deny_reason=\"POST /repos/octocat/hello-world/issues not permitted by policy\nThe log captures the exact HTTP method, path, and deny reason. In production, pipe these logs to your SIEM for a complete audit trail of every request your agent makes. To log violations without blocking requests, set enforcement: audit instead of enforcement: enforce in the policy. This is useful for building a policy iteratively: deploy in audit mode, review the logs, and switch to enforce when the rules are correct. Clean Up Delete the sandbox to free resources. This stops all processes and purges any injected credentials. $ openshell sandbox delete demo\nTo run this entire walkthrough non-interactively, use the automated demo script: $ bash examples/sandbox-policy-quickstart/demo.sh\nNext Steps To walk through a full policy iteration with Claude Code, including diagnosing denials and applying fixes from outside the sandbox, refer to /tutorials/github-sandbox","format":"text","content_length":7068,"word_count":1021,"summary":"This tutorial shows how OpenShell’s network policy system works in under five minutes. You create a sandbox, watch a request get blocked by the default-deny policy, apply a fine-grained L7 rule, and verify that reads are allowed while writes are blocked, all without restarting anything.","headings":[{"text":"Write Your First Sandbox Network Policy","level":1,"id":"write-your-first-sandbox-network-policy"},{"text":"Prerequisites","level":2,"id":"prerequisites"},{"text":"Create a Sandbox","level":2,"id":"create-a-sandbox"},{"text":"Try to Reach the GitHub API","level":2,"id":"try-to-reach-the-github-api"},{"text":"Check the Deny Log","level":2,"id":"check-the-deny-log"},{"text":"Apply a Read-Only GitHub API Policy","level":2,"id":"apply-a-read-only-github-api-policy"},{"text":"Verify If GET Requests Are Allowed","level":2,"id":"verify-if-get-requests-are-allowed"},{"text":"Try a Write","level":2,"id":"try-a-write"},{"text":"Check the L7 Deny Log","level":2,"id":"check-the-l7-deny-log"},{"text":"Clean Up","level":2,"id":"clean-up"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Write Your First Sandbox Network Policy Prerequisites Create a Sandbox Try to Reach the GitHub API Check the Deny Log Apply a Read-Only GitHub API Policy Verify If GET Requests Are Allowed Try a Write Check the L7 Deny Log Clean Up Next Steps","keywords":["access","action","after","allowed","anything","api","apis","apply","binary","check","claude","clean","code","com","compatibility","complete","content","create","curl","delete","deny","deny_reason","desktop","detail","docker","dst_host","dst_port","enforcement","every","everything","exit","first","github","github-api-readonly","host","https","include_workdir","iteratively","l7_action","l7_decision","l7_deny_reason","l7_target","like","log","name","network","next","nothing","only","oops\nerror"],"code_blocks":[{"content":"$ bash examples/sandbox-policy-quickstart/demo.sh","language":"text"},{"content":"$ openshell sandbox create --name demo --keep --no-auto-providers","language":"text"},{"content":"sandbox@demo:~$","language":"text"},{"content":"$ curl -s https://api.github.com/zen","language":"text"},{"content":"curl: (56) Received HTTP code 403 from proxy after CONNECT","language":"text"},{"content":"$ exit","language":"text"},{"content":"$ openshell logs demo --since 5m","language":"text"},{"content":"action=deny dst_host=api.github.com dst_port=443 binary=/usr/bin/curl deny_reason=\"no matching network policy\"","language":"text"},{"content":"version: 1\n\nfilesystem_policy:\n include_workdir: true\n read_only: [/usr, /lib, /proc, /dev/urandom, /app, /etc, /var/log]\n read_write: [/sandbox, /tmp, /dev/null]\nlandlock:\n compatibility: best_effort\nprocess:\n run_as_user: sandbox\n run_as_group: sandbox\n\nnetwork_policies:\n github_api:\n name: github-api-readonly\n endpoints:\n - host: api.github.com\n port: 443\n protocol: rest\n enforcement: enforce\n access: read-only\n binaries:\n - { path: /usr/bin/curl }","language":"text"},{"content":"$ openshell policy set demo --policy github-readonly.yaml --wait","language":"text"},{"content":"$ openshell sandbox connect demo","language":"text"},{"content":"$ curl -s https://api.github.com/zen","language":"text"},{"content":"Anything added dilutes everything else.","language":"text"},{"content":"$ curl -s -X POST https://api.github.com/repos/octocat/hello-world/issues \\\n -H \"Content-Type: application/json\" \\\n -d '{\"title\":\"oops\"}'","language":"text"},{"content":"{\"error\":\"policy_denied\",\"policy\":\"github-api-readonly\",\"detail\":\"POST /repos/octocat/hello-world/issues not permitted by policy\"}","language":"text"},{"content":"$ exit","language":"text"},{"content":"$ openshell logs demo --level warn --since 5m","language":"text"},{"content":"l7_decision=deny dst_host=api.github.com l7_action=POST l7_target=/repos/octocat/hello-world/issues l7_deny_reason=\"POST /repos/octocat/hello-world/issues not permitted by policy\"","language":"text"},{"content":"$ openshell sandbox delete demo","language":"text"},{"content":"$ bash examples/sandbox-policy-quickstart/demo.sh","language":"text"}],"links":[{"text":"Sandbox Policy Quickstart","type":"external","url":"https://github.com/NVIDIA/OpenShell/blob/main/examples/sandbox-policy-quickstart","original_text":"examples/sandbox-policy-quickstart"}],"images":[],"doc_type":"tutorial","section_path":["Tutorials","First Network Policy"]},{"id":"tutorials/github-sandbox","title":"Grant GitHub Push Access to a Sandboxed Agent","url":"tutorials/github-sandbox.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Learn the iterative policy workflow by launching a sandbox, diagnosing a GitHub access denial, and applying a custom policy to fix it.","tags":["Tutorial","GitHub","Sandbox","Policy","Claude Code"],"topics":["Generative AI","Cybersecurity"],"content_type":"tutorial","learning_level":"technical_intermediate","audience":["engineer"],"content":"Grant GitHub Push Access to a Sandboxed Agent This tutorial walks through an iterative sandbox policy workflow. You launch a sandbox, ask Claude Code to push code to GitHub, and observe the default network policy denying the request\nYou then diagnose the denial from your machine and from inside the sandbox, apply a policy update, and verify that the policy update to the sandbox takes effect. After completing this tutorial, you will have: A running sandbox with Claude Code that can push to a GitHub repository. A custom network policy that grants GitHub access for a specific repository. Experience with the policy iteration workflow: fail, diagnose, update, verify. This tutorial shows example prompts and responses from Claude Code. The exact wording you see might vary between sessions. Use the examples as a guide for the type of interaction, not as expected output. Prerequisites This tutorial requires the following: A working OpenShell installation. Complete the Quickstart before proceeding. A GitHub personal access token (PAT) with repo scope. Generate one from the GitHub personal access token settings page by selecting Generate new token (classic) and enabling the repo scope. An Anthropic account with access to Claude Code. OpenShell provides the sandbox runtime, not the agent. You must authenticate with your own account. A GitHub repository you own to use as the push target. A scratch repository is sufficient. You can create one with a README if needed. This tutorial uses two terminals to demonstrate the iterative policy workflow: Terminal 1 : The sandbox terminal. You create the sandbox in this terminal by running openshell sandbox create and interact with Claude Code inside it. Terminal 2 : A terminal outside the sandbox on your machine. You use this terminal for viewing the sandbox logs with openshell term and applying an updated policy with openshell policy set . Each section below indicates which terminal to use. Set Up a Sandbox with Your GitHub Token Depending on whether you start a new sandbox or use an existing sandbox, choose the appropriate tab and follow the instructions. Starting a new sandbox In terminal 2, create a new sandbox with Claude Code. The default policy is applied automatically, which allows read-only access to GitHub. Create a credential provider that injects your GitHub token into the sandbox automatically. The provider reads GITHUB_TOKEN from your host environment and sets it as an environment variable inside the sandbox: $ GITHUB_TOKEN= with your GitHub organization or username and with your repository name. Prompt Write a hello_world.py script and push it to https://github.com// . Claude recognizes that it needs GitHub credentials. It asks how you want to authenticate. Provide your GitHub personal access token by pasting it into the conversation. Claude configures authentication and attempts the push. The push fails. Claude reports an error, but the failure is not an authentication problem. The default sandbox policy permits read-only access to GitHub and blocks write operations, so the proxy denies the push before the request reaches the GitHub server. Diagnose the Denial In this section, you diagnose the denial from your machine and from inside the sandbox. View the Logs from Your Machine In terminal 2, launch the OpenShell terminal: $ openshell term\nThe dashboard shows sandbox status and a live stream of policy decisions. Look for entries with l7_decision=deny . Select a deny entry to see the full detail: l7_action: PUT\nl7_target: /repos///contents/hello_world.py\nl7_decision: deny\ndst_host: api.github.com\ndst_port: 443\nl7_protocol: rest\npolicy: github_rest_api\nl7_deny_reason: PUT /repos///contents/hello_world.py not permitted by policy\nThe log shows that the sandbox proxy intercepted an outbound PUT request to api.github.com and denied it. The github_rest_api policy allows read operations (GET) but blocks write operations (PUT, POST, DELETE) to the GitHub API. A similar denial appears for github.com if Claude attempted a git push over HTTPS. Ask Claude Code to Check the Sandbox Logs In terminal 1, ask Claude Code to check the sandbox logs for denied requests: Prompt Check the sandbox logs for any denied network requests. What is blocking the push? Claude reads the deny entries and identifies the root cause. It explains that the failure is a sandbox network policy restriction, not a token permissions issue. For example, the following is a possible response: Response The sandbox runs a proxy that enforces policies on outbound traffic\nThe github_rest_api policy allows GET requests (used to read the file\nbut blocks PUT/write requests to GitHub. This is a sandbox-level restriction\nnot a token issue. No matter what token you provide, pushes through the API\nwill be blocked until the policy is updated. Both perspectives confirm the same thing: the proxy is doing its job. The default policy is designed to be restrictive. To allow GitHub pushes, you need to update the network policy. Copy the deny reason from Claude’s response. You paste it into an agent running on your machine in the next step. Update the Policy from Your Machine In terminal 2, paste the deny reason from the previous step into your coding agent on your machine, such as Claude Code or Cursor, and ask it to recommend a policy update. The deny reason gives the agent the context it needs to generate the correct policy rules. After pasting the following prompt sample, properly provide the GitHub organization and repository names of the repository you are pushing to. Prompt Based on the following deny reasons, recommend a sandbox policy update that allows GitHub pushes to https://github.com// , and save to /tmp/sandbox-policy-update.yaml : The filesystem_policy , landlock , and process sections are static. They are read once at sandbox creation and cannot be changed by a hot-reload. They are included here for completeness so the file is self-contained, but only the network_policies section takes effect when you apply this to a running sandbox. The following steps outline the expected process done by the agent: Inspects the deny reasons. Writes an updated policy that adds github_git and github_api blocks that grant write access to your repository. Saves the policy to /tmp/sandbox-policy-update.yaml . Review the Generated Policy Refer to the following policy example to compare with the generated policy before applying it. Confirm that the policy grants only the access you expect. In this case, git push operations and GitHub REST API access scoped to a single repository. Full reference policy The following YAML shows a complete policy that extends the default policy with GitHub access for a single repository. Replace with your GitHub organization or username and with your repository name. The filesystem_policy , landlock , and process sections are static. They are read once at sandbox creation and cannot be changed by a hot-reload. They are included here for completeness so the file is self-contained, but only the network_policies section takes effect when you apply this to a running sandbox. version: 1\n── Static (locked at sandbox creation)\nfilesystem_policy\ninclude_workdir: true\nread_only\n/usr\n/lib\n/proc\n/dev/urandom\n/app\n/etc\n/var/log\nread_write\n/sandbox\n/tmp\n/dev/null\nlandlock\ncompatibility: best_effort\nprocess\nrun_as_user: sandbox\nrun_as_group: sandbox\n── Dynamic (hot-reloadable)\nnetwork_policies\nClaude Code ↔ Anthropic API\nclaude_code\nname: claude-code\nendpoints\n{ host: api.anthropic.com, port: 443, protocol: rest, enforcement: enforce, access: full\n{ host: statsig.anthropic.com, port: 443\n{ host: sentry.io, port: 443\n{ host: raw.githubusercontent.com, port: 443\n{ host: platform.claude.com, port: 443\nbinaries\n{ path: /usr/local/bin/claude\n{ path: /usr/bin/node\nNVIDIA inference endpoint\nnvidia_inference\nname: nvidia-inference\nendpoints\n{ host: integrate.api.nvidia.com, port: 443\nbinaries\n{ path: /usr/bin/curl\n{ path: /bin/bash\n{ path: /usr/local/bin/opencode\n── GitHub: git operations (clone, fetch, push)\ngithub_git\nname: github-git\nendpoints\nhost: github.com\nport: 443\nprotocol: rest\nenforcement: enforce\nrules\nallow\nmethod: GET\npath: \"//.git/info/refs\nallow\nmethod: POST\npath: \"//.git/git-upload-pack\nallow\nmethod: POST\npath: \"//.git/git-receive-pack\nbinaries\n{ path: /usr/bin/git\n── GitHub: REST API\ngithub_api\nname: github-api\nendpoints\nhost: api.github.com\nport: 443\nprotocol: rest\nenforcement: enforce\nrules\nGraphQL API (used by gh CLI\nallow\nmethod: POST\npath: \"/graphql\nFull read-write access to the repository\nallow\nmethod:\npath: \"/repos// --policy /tmp/sandbox-policy-update.yaml --wait\nNetwork policies are hot-reloadable. The --wait flag blocks until the policy engine confirms the new revision loaded, and the update takes effect immediately without restarting the sandbox or reconnecting Claude Code. Retry the Push In terminal 1, ask Claude Code to retry the push: The sandbox policy has been updated. Try pushing to the repository again\nThe push completes successfully. The openshell term dashboard now shows l7_decision=allow entries for api.github.com and github.com where it previously showed denials. Clean Up When you are finished, delete the sandbox to free cluster resources: $ openshell sandbox delete \n$ openshell provider create --name my-github --type github --from-existing\n$ openshell sandbox create --provider my-github -- claude","language":"text"},{"content":"$ openshell sandbox connect \n$ export GITHUB_TOKEN=","language":"text"},{"content":"$ openshell term","language":"text"},{"content":"l7_action: PUT\nl7_target: /repos///contents/hello_world.py\nl7_decision: deny\ndst_host: api.github.com\ndst_port: 443\nl7_protocol: rest\npolicy: github_rest_api\nl7_deny_reason: PUT /repos///contents/hello_world.py not permitted by policy","language":"text"},{"content":"version: 1\n\n# ── Static (locked at sandbox creation) ──────────────────────────\n\nfilesystem_policy:\n include_workdir: true\n read_only:\n - /usr\n - /lib\n - /proc\n - /dev/urandom\n - /app\n - /etc\n - /var/log\n read_write:\n - /sandbox\n - /tmp\n - /dev/null\n\nlandlock:\n compatibility: best_effort\n\nprocess:\n run_as_user: sandbox\n run_as_group: sandbox\n\n# ── Dynamic (hot-reloadable) ─────────────────────────────────────\n\nnetwork_policies:\n\n # Claude Code ↔ Anthropic API\n claude_code:\n name: claude-code\n endpoints:\n - { host: api.anthropic.com, port: 443, protocol: rest, enforcement: enforce, access: full }\n - { host: statsig.anthropic.com, port: 443 }\n - { host: sentry.io, port: 443 }\n - { host: raw.githubusercontent.com, port: 443 }\n - { host: platform.claude.com, port: 443 }\n binaries:\n - { path: /usr/local/bin/claude }\n - { path: /usr/bin/node }\n\n # NVIDIA inference endpoint\n nvidia_inference:\n name: nvidia-inference\n endpoints:\n - { host: integrate.api.nvidia.com, port: 443 }\n binaries:\n - { path: /usr/bin/curl }\n - { path: /bin/bash }\n - { path: /usr/local/bin/opencode }\n\n # ── GitHub: git operations (clone, fetch, push) ──────────────\n\n github_git:\n name: github-git\n endpoints:\n - host: github.com\n port: 443\n protocol: rest\n enforcement: enforce\n rules:\n - allow:\n method: GET\n path: \"//.git/info/refs*\"\n - allow:\n method: POST\n path: \"//.git/git-upload-pack\"\n - allow:\n method: POST\n path: \"//.git/git-receive-pack\"\n binaries:\n - { path: /usr/bin/git }\n\n # ── GitHub: REST API ─────────────────────────────────────────\n\n github_api:\n name: github-api\n endpoints:\n - host: api.github.com\n port: 443\n protocol: rest\n enforcement: enforce\n rules:\n # GraphQL API (used by gh CLI)\n - allow:\n method: POST\n path: \"/graphql\"\n # Full read-write access to the repository\n - allow:\n method: \"*\"\n path: \"/repos///**\"\n binaries:\n - { path: /usr/local/bin/claude }\n - { path: /usr/local/bin/opencode }\n - { path: /usr/bin/gh }\n - { path: /usr/bin/curl }\n\n # ── Package managers ─────────────────────────────────────────\n\n pypi:\n name: pypi\n endpoints:\n - { host: pypi.org, port: 443 }\n - { host: files.pythonhosted.org, port: 443 }\n - { host: github.com, port: 443 }\n - { host: objects.githubusercontent.com, port: 443 }\n - { host: api.github.com, port: 443 }\n - { host: downloads.python.org, port: 443 }\n binaries:\n - { path: /sandbox/.venv/bin/python }\n - { path: /sandbox/.venv/bin/python3 }\n - { path: /sandbox/.venv/bin/pip }\n - { path: \"/sandbox/.uv/python/**/python*\" }\n - { path: /usr/local/bin/uv }\n - { path: \"/sandbox/.uv/python/**\" }\n\n # ── VS Code Remote ──────────────────────────────────────────\n\n vscode:\n name: vscode\n endpoints:\n - { host: update.code.visualstudio.com, port: 443 }\n - { host: \"*.vo.msecnd.net\", port: 443 }\n - { host: vscode.download.prss.microsoft.com, port: 443 }\n - { host: marketplace.visualstudio.com, port: 443 }\n - { host: \"*.gallerycdn.vsassets.io\", port: 443 }\n binaries:\n - { path: /usr/bin/curl }\n - { path: /usr/bin/wget }\n - { path: \"/sandbox/.vscode-server/**\" }\n - { path: \"/sandbox/.vscode-remote-containers/**\" }","language":"text"},{"content":"$ openshell policy set --policy /tmp/sandbox-policy-update.yaml --wait","language":"text"},{"content":"The sandbox policy has been updated. Try pushing to the repository again.","language":"text"},{"content":"$ openshell sandbox delete ","language":"text"}],"links":[{"text":"GitHub personal access token settings page","type":"external","url":"https://github.com/settings/tokens"},{"text":"Anthropic account","type":"external","url":"https://console.anthropic.com/"},{"text":"create one","type":"external","url":"https://github.com/new"}],"images":[],"doc_type":"tutorial","section_path":["Tutorials","Github Sandbox"]},{"id":"tutorials/inference-ollama","title":"Run Local Inference with Ollama","url":"tutorials/inference-ollama.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Run local and cloud models inside an OpenShell sandbox using the Ollama community sandbox, or route sandbox requests to a host-level Ollama server.","tags":["Tutorial","Inference Routing","Ollama","Local Inference","Sandbox"],"topics":["Generative AI","Cybersecurity"],"content_type":"tutorial","learning_level":"technical_intermediate","audience":["engineer"],"content":"Run Local Inference with Ollama This tutorial covers two ways to use Ollama with OpenShell: Ollama sandbox (recommended) — a self-contained sandbox with Ollama, Claude Code, and Codex pre-installed. One command to start. Host-level Ollama — run Ollama on the gateway host and route sandbox inference to it. Useful when you want a single Ollama instance shared across multiple sandboxes. After completing this tutorial, you will know how to: Launch the Ollama community sandbox for a batteries-included experience. Use ollama launch to start coding agents inside a sandbox. Expose a host-level Ollama server to sandboxes through inference.local . Prerequisites A working OpenShell installation. Complete the /get-started/quickstart before proceeding. Option A: Ollama Community Sandbox (Recommended) The Ollama community sandbox bundles Ollama, Claude Code, OpenCode, and Codex into a single image. Ollama starts automatically when the sandbox launches. Step 1: Create the Sandbox $ openshell sandbox create --from ollama\nThis pulls the community sandbox image, applies the bundled policy, and drops you into a shell with Ollama running. Step 2: Chat with a Model Chat with a local model $ ollama run qwen3.5\nOr a cloud model $ ollama run kimi-k2.5:cloud\nOr use ollama launch to start a coding agent with Ollama as the model backend: $ ollama launch claude\nollama launch codex\nollama launch opencode\nFor CI/CD and automated workflows, ollama launch supports a headless mode: $ ollama launch claude --yes --model qwen3.5\nModel Recommendations Use case Model Notes Smoke test qwen3.5:0.8b Fast, lightweight, good for verifying setup Coding and reasoning qwen3.5 Strong tool calling support for agentic workflows Complex tasks nemotron-3-super 122B parameter model, needs 48GB+ VRAM No local GPU qwen3.5:cloud Runs on Ollama’s cloud infrastructure, no ollama pull required Cloud models use the :cloud tag suffix and do not require local hardware. $ openshell sandbox create --from ollama\nTool Calling Agentic workflows (Claude Code, Codex, OpenCode) rely on tool calling. The following models have reliable tool calling support: Qwen 3.5, Nemotron-3-Super, GLM-5, and Kimi-K2.5. Check the Ollama model library for the latest models. Updating Ollama To update Ollama inside a running sandbox: $ update-ollama\nOr auto-update on every sandbox start: $ openshell sandbox create --from ollama -e OLLAMA_UPDATE=1\nOption B: Host-Level Ollama Use this approach when you want a single Ollama instance on the gateway host, shared across multiple sandboxes through inference.local . This approach uses Ollama because it is easy to install and run locally, but you can substitute other inference engines such as vLLM, SGLang, TRT-LLM, and NVIDIA NIM by changing the startup command, base URL, and model name. Step 1: Install and Start Ollama Install Ollama on the gateway host: $ curl -fsSL https://ollama.com/install.sh | sh\nStart Ollama on all interfaces so it is reachable from sandboxes: $ OLLAMA_HOST=0.0.0.0:11434 ollama serve\nIf you see Error: listen tcp 0.0.0.0:11434: bind: address already in use , Ollama is already running as a system service. Stop it first: $ systemctl stop ollama\nOLLAMA_HOST=0.0.0.0:11434 ollama serve\nStep 2: Pull a Model In a second terminal, pull a model: $ ollama run qwen3.5:0.8b\nType /bye to exit the interactive session. The model stays loaded. Step 3: Create a Provider Create an OpenAI-compatible provider pointing at the host Ollama: $ openshell provider create\nname ollama\ntype openai\ncredential OPENAI_API_KEY=empty\nconfig OPENAI_BASE_URL=http://host.openshell.internal:11434/v1\nOpenShell injects host.openshell.internal so sandboxes and the gateway can reach the host machine. You can also use the host’s LAN IP. Step 4: Set Inference Routing $ openshell inference set --provider ollama --model qwen3.5:0.8b\nConfirm: $ openshell inference get\nStep 5: Verify from a Sandbox $ openshell sandbox create --\ncurl https://inference.local/v1/chat/completions\njson '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10\nThe response should be JSON from the model. Troubleshooting Common issues and fixes: Ollama not reachable from sandbox — Ollama must be bound to 0.0.0.0 , not 127.0.0.1 . This applies to host-level Ollama only; the community sandbox handles this automatically. OPENAI_BASE_URL wrong — Use http://host.openshell.internal:11434/v1 , not localhost or 127.0.0.1 . Model not found — Run ollama ps to confirm the model is loaded. Run ollama pull if needed. HTTPS vs HTTP — Code inside sandboxes must call https://inference.local , not http:// . AMD GPU driver issues — Ollama v0.18+ requires ROCm 7 drivers for AMD GPUs. Update your drivers if you see GPU detection failures. Useful commands: $ openshell status\nopenshell inference get\nopenshell provider get ollama\nNext Steps To learn more about managed inference, refer to /inference/index . To configure a different self-hosted backend, refer to /inference/configure . To explore more community sandboxes, refer to /sandboxes/community-sandboxes","format":"text","content_length":5050,"word_count":743,"summary":"This tutorial covers two ways to use Ollama with OpenShell:","headings":[{"text":"Run Local Inference with Ollama","level":1,"id":"run-local-inference-with-ollama"},{"text":"Prerequisites","level":2,"id":"prerequisites"},{"text":"Option A: Ollama Community Sandbox (Recommended)","level":2,"id":"option-a-ollama-community-sandbox-recommended"},{"text":"Step 1: Create the Sandbox","level":3,"id":"step-1-create-the-sandbox"},{"text":"Tool Calling","level":3,"id":"tool-calling"},{"text":"Updating Ollama","level":3,"id":"updating-ollama"},{"text":"Option B: Host-Level Ollama","level":2,"id":"option-b-host-level-ollama"},{"text":"Step 1: Install and Start Ollama","level":3,"id":"step-1-install-and-start-ollama"},{"text":"Step 2: Pull a Model","level":3,"id":"step-2-pull-a-model"},{"text":"Step 3: Create a Provider","level":3,"id":"step-3-create-a-provider"},{"text":"Step 4: Set Inference Routing","level":3,"id":"step-4-set-inference-routing"},{"text":"Step 5: Verify from a Sandbox","level":3,"id":"step-5-verify-from-a-sandbox"},{"text":"Troubleshooting","level":2,"id":"troubleshooting"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Run Local Inference with Ollama Prerequisites Option A: Ollama Community Sandbox (Recommended) Step 1: Create the Sandbox Tool Calling Updating Ollama Option B: Host-Level Ollama Step 1: Install and Start Ollama Step 2: Pull a Model Step 3: Create a Provider Step 4: Set Inference Routing Step 5: Verify from a Sandbox Troubleshooting Next Steps","keywords":["after","agentic","backend","bind","calling","chat","check","claude","cloud","code","codex","coding","com","commands","common","community","complete","complex","confirm","content","create","error","expose","fast","first","fixes","from","gpus","hello","host","http","https","inference","install","internal","kimi","launch","level","local","max_tokens","messages","mode","model","nemotron","next","notes","ollama","openai","opencode","openshell"],"code_blocks":[{"content":"$ openshell sandbox create --from ollama","language":"text"},{"content":"$ ollama run qwen3.5","language":"text"},{"content":"$ ollama run kimi-k2.5:cloud","language":"text"},{"content":"$ ollama launch claude\n$ ollama launch codex\n$ ollama launch opencode","language":"text"},{"content":"$ ollama launch claude --yes --model qwen3.5","language":"text"},{"content":"$ openshell sandbox create --from ollama","language":"text"},{"content":"$ update-ollama","language":"text"},{"content":"$ openshell sandbox create --from ollama -e OLLAMA_UPDATE=1","language":"text"},{"content":"$ curl -fsSL https://ollama.com/install.sh | sh","language":"text"},{"content":"$ OLLAMA_HOST=0.0.0.0:11434 ollama serve","language":"text"},{"content":"$ systemctl stop ollama\n$ OLLAMA_HOST=0.0.0.0:11434 ollama serve","language":"text"},{"content":"$ ollama run qwen3.5:0.8b","language":"text"},{"content":"$ openshell provider create \\\n --name ollama \\\n --type openai \\\n --credential OPENAI_API_KEY=empty \\\n --config OPENAI_BASE_URL=http://host.openshell.internal:11434/v1","language":"text"},{"content":"$ openshell inference set --provider ollama --model qwen3.5:0.8b","language":"text"},{"content":"$ openshell inference get","language":"text"},{"content":"$ openshell sandbox create -- \\\n curl https://inference.local/v1/chat/completions \\\n --json '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10}'","language":"text"},{"content":"$ openshell status\n$ openshell inference get\n$ openshell provider get ollama","language":"text"}],"links":[{"text":"Ollama model library","type":"external","url":"https://ollama.com/library"},{"text":"Ollama","type":"external","url":"https://ollama.com/"}],"images":[],"doc_type":"tutorial","section_path":["Tutorials","Inference Ollama"]},{"id":"tutorials/local-inference-lmstudio","title":"Route Local Inference Requests to LM Studio","url":"tutorials/local-inference-lmstudio.html","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Configure inference.local to route sandbox requests to a local LM Studio server running on the gateway host.","tags":["Tutorial","Inference Routing","LM Studio","Local Inference","Sandbox"],"topics":["Generative AI","Cybersecurity"],"content_type":"tutorial","learning_level":"technical_intermediate","audience":["engineer"],"content":"Route Local Inference Requests to LM Studio This tutorial describes how to configure OpenShell to route inference requests to a local LM Studio server. The LM Studio server provides easy setup with both OpenAI and Anthropic compatible endpoints. This tutorial will cover: Expose a local inference server to OpenShell sandboxes. Verify end-to-end inference from inside a sandbox. Prerequisites First, complete OpenShell installation and follow the /get-started/quickstart . Install the LM Studio app . Make sure that your LM Studio is running in the same environment as your gateway. If you prefer to work without having to keep the LM Studio app open, download llmster (headless LM Studio) with the following command: Linux/Mac $ curl -fsSL https://lmstudio.ai/install.sh | bash\nWindows $ irm https://lmstudio.ai/install.ps1 | iex\nAnd start llmster: $ lms daemon up\nStep 1: Start LM Studio Local Server Start the LM Studio local server from the Developer tab, and verify the OpenAI-compatible endpoint is enabled. LM Studio will listen to 127.0.0.1:1234 by default. For use with OpenShell, you’ll need to configure LM Studio to listen on all interfaces ( 0.0.0.0 ). If you’re using the GUI, go to the Developer Tab, select Server Settings, then enable Serve on Local Network. If you’re using llmster in headless mode, run lms server start --bind 0.0.0.0 . Step 2: Test with a small model In the LM Studio app, head to the Model Search tab to download a small model like Qwen3.5 2B. In the terminal, use the following command to download and load the model: $ lms get qwen/qwen3.5-2b\nlms load qwen/qwen3.5-2b\nStep 3: Add LM Studio as a provider Choose the provider type that matches the client protocol you want to route through inference.local . OpenAI-compatible Add LM Studio as an OpenAI-compatible provider through host.openshell.internal : $ openshell provider create\nname lmstudio\ntype openai\ncredential OPENAI_API_KEY=lmstudio\nconfig OPENAI_BASE_URL=http://host.openshell.internal:1234/v1\nUse this provider for clients that send OpenAI-compatible requests such as POST /v1/chat/completions or POST /v1/responses . Anthropic-compatible Add a provider that points to LM Studio’s Anthropic-compatible POST /v1/messages endpoint: $ openshell provider create\nname lmstudio-anthropic\ntype anthropic\ncredential ANTHROPIC_API_KEY=lmstudio\nconfig ANTHROPIC_BASE_URL=http://host.openshell.internal:1234\nUse this provider for Anthropic-compatible POST /v1/messages requests. Step 4: Configure LM Studio as the local inference provider Set the managed inference route for the active gateway: OpenAI-compatible $ openshell inference set --provider lmstudio --model qwen/qwen3.5-2b\nIf the command succeeds, OpenShell has verified that the upstream is reachable and accepts the expected OpenAI-compatible request shape. Anthropic-compatible $ openshell inference set --provider lmstudio-anthropic --model qwen/qwen3.5-2b\nIf the command succeeds, OpenShell has verified that the upstream is reachable and accepts the expected Anthropic-compatible request shape. The active inference.local route is gateway-scoped, so only one provider and model pair is active at a time. Re-run openshell inference set whenever you want to switch between OpenAI-compatible and Anthropic-compatible clients. Confirm the saved config: $ openshell inference get\nYou should see either Provider: lmstudio or Provider: lmstudio-anthropic , along with Model: qwen/qwen3.5-2b . Step 5: Verify from Inside a Sandbox Run a simple request through https://inference.local : OpenAI-compatible openshell sandbox create --\ncurl https://inference.local/v1/chat/completions\njson '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10\nopenshell sandbox create --\ncurl https://inference.local/v1/responses\njson\ninstructions\": \"You are a helpful assistant\ninput\": \"hello\nmax_output_tokens\": 10\nAnthropic-compatible openshell sandbox create --\ncurl https://inference.local/v1/messages\njson '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10\nTroubleshooting If setup fails, check these first: LM Studio local server is running and reachable from the gateway host OPENAI_BASE_URL uses http://host.openshell.internal:1234/v1 when you use an openai provider ANTHROPIC_BASE_URL uses http://host.openshell.internal:1234 when you use an anthropic provider The gateway and LM Studio run on the same machine or a reachable network path The configured model name matches the model exposed by LM Studio Useful commands: $ openshell status\nopenshell inference get\nopenshell provider get lmstudio\nopenshell provider get lmstudio-anthropic\nNext Steps To learn more about using the LM Studio CLI, refer to LM Studio docs To learn more about managed inference, refer to /inference/index . To configure a different self-hosted backend, refer to /inference/configure","format":"text","content_length":4825,"word_count":650,"summary":"This tutorial describes how to configure OpenShell to route inference requests to a local LM Studio server.","headings":[{"text":"Route Local Inference Requests to LM Studio","level":1,"id":"route-local-inference-requests-to-lm-studio"},{"text":"Prerequisites","level":2,"id":"prerequisites"},{"text":"Linux/Mac","level":3,"id":"linuxmac"},{"text":"Windows","level":3,"id":"windows"},{"text":"Step 1: Start LM Studio Local Server","level":2,"id":"step-1-start-lm-studio-local-server"},{"text":"Step 2: Test with a small model","level":2,"id":"step-2-test-with-a-small-model"},{"text":"Step 3: Add LM Studio as a provider","level":2,"id":"step-3-add-lm-studio-as-a-provider"},{"text":"Step 4: Configure LM Studio as the local inference provider","level":2,"id":"step-4-configure-lm-studio-as-the-local-inference-provider"},{"text":"Step 5: Verify from Inside a Sandbox","level":2,"id":"step-5-verify-from-inside-a-sandbox"},{"text":"Troubleshooting","level":2,"id":"troubleshooting"},{"text":"Next Steps","level":2,"id":"next-steps"}],"headings_text":"Route Local Inference Requests to LM Studio Prerequisites Linux/Mac Windows Step 1: Start LM Studio Local Server Step 2: Test with a small model Step 3: Add LM Studio as a provider Step 4: Configure LM Studio as the local inference provider Step 5: Verify from Inside a Sandbox Troubleshooting Next Steps","keywords":["add","anthropic","choose","command","commands","config","configure","confirm","content","cover","developer","endpoint","expose","first","from","gateway","hello","http","https","inference","inside","install","internal","linux","llmster","local","mac","make","max_tokens","messages","model","network","next","openai","openshell","prerequisites","provider","qwen3","requests","role","route","run","sandbox","search","serve","server","set","settings","small","start"],"code_blocks":[{"content":"$ curl -fsSL https://lmstudio.ai/install.sh | bash","language":"text"},{"content":"$ irm https://lmstudio.ai/install.ps1 | iex","language":"text"},{"content":"$ lms daemon up","language":"text"},{"content":"$ lms get qwen/qwen3.5-2b\n$ lms load qwen/qwen3.5-2b","language":"text"},{"content":"$ openshell provider create \\\n --name lmstudio \\\n --type openai \\\n --credential OPENAI_API_KEY=lmstudio \\\n --config OPENAI_BASE_URL=http://host.openshell.internal:1234/v1","language":"text"},{"content":"$ openshell provider create \\\n --name lmstudio-anthropic \\\n --type anthropic \\\n --credential ANTHROPIC_API_KEY=lmstudio \\\n --config ANTHROPIC_BASE_URL=http://host.openshell.internal:1234","language":"text"},{"content":"$ openshell inference set --provider lmstudio --model qwen/qwen3.5-2b","language":"text"},{"content":"$ openshell inference set --provider lmstudio-anthropic --model qwen/qwen3.5-2b","language":"text"},{"content":"$ openshell inference get","language":"text"},{"content":"openshell sandbox create -- \\\n curl https://inference.local/v1/chat/completions \\\n --json '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10}'\n\nopenshell sandbox create -- \\\n curl https://inference.local/v1/responses \\\n --json '{\n \"instructions\": \"You are a helpful assistant.\",\n \"input\": \"hello\",\n \"max_output_tokens\": 10\n }'","language":"text"},{"content":"openshell sandbox create -- \\\n curl https://inference.local/v1/messages \\\n --json '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10}'","language":"text"},{"content":"$ openshell status\n$ openshell inference get\n$ openshell provider get lmstudio\n$ openshell provider get lmstudio-anthropic","language":"text"}],"links":[{"text":"Install the LM Studio app","type":"external","url":"https://lmstudio.ai/download"},{"text":"LM Studio docs","type":"external","url":"https://lmstudio.ai/docs/cli"}],"images":[],"doc_type":"tutorial","section_path":["Tutorials","Local Inference Lmstudio"]}]} \ No newline at end of file diff --git a/pr-preview/pr-677/tutorials/inference-ollama.json b/pr-preview/pr-677/tutorials/inference-ollama.json index 978d33ef0..e3186fc34 100644 --- a/pr-preview/pr-677/tutorials/inference-ollama.json +++ b/pr-preview/pr-677/tutorials/inference-ollama.json @@ -1 +1 @@ -{"id":"tutorials/inference-ollama","title":"Run Local Inference with Ollama","url":"tutorials/inference-ollama.html","last_modified":"2026-03-30T18:03:24.575620+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Run local and cloud models inside an OpenShell sandbox using the Ollama community sandbox, or route sandbox requests to a host-level Ollama server.","tags":["Tutorial","Inference Routing","Ollama","Local Inference","Sandbox"],"topics":["Generative AI","Cybersecurity"],"content_type":"tutorial","learning_level":"technical_intermediate","audience":["engineer"],"content":"Run Local Inference with Ollama This tutorial covers two ways to use Ollama with OpenShell: Ollama sandbox (recommended) — a self-contained sandbox with Ollama, Claude Code, and Codex pre-installed. One command to start. Host-level Ollama — run Ollama on the gateway host and route sandbox inference to it. Useful when you want a single Ollama instance shared across multiple sandboxes. After completing this tutorial, you will know how to: Launch the Ollama community sandbox for a batteries-included experience. Use ollama launch to start coding agents inside a sandbox. Expose a host-level Ollama server to sandboxes through inference.local . Prerequisites A working OpenShell installation. Complete the /get-started/quickstart before proceeding. Option A: Ollama Community Sandbox (Recommended) The Ollama community sandbox bundles Ollama, Claude Code, OpenCode, and Codex into a single image. Ollama starts automatically when the sandbox launches. Step 1: Create the Sandbox $ openshell sandbox create --from ollama\nThis pulls the community sandbox image, applies the bundled policy, and drops you into a shell with Ollama running. Step 2: Chat with a Model Chat with a local model $ ollama run qwen3.5\nOr a cloud model $ ollama run kimi-k2.5:cloud\nOr use ollama launch to start a coding agent with Ollama as the model backend: $ ollama launch claude\nollama launch codex\nollama launch opencode\nFor CI/CD and automated workflows, ollama launch supports a headless mode: $ ollama launch claude --yes --model qwen3.5\nModel Recommendations Use case Model Notes Smoke test qwen3.5:0.8b Fast, lightweight, good for verifying setup Coding and reasoning qwen3.5 Strong tool calling support for agentic workflows Complex tasks nemotron-3-super 122B parameter model, needs 48GB+ VRAM No local GPU qwen3.5:cloud Runs on Ollama’s cloud infrastructure, no ollama pull required Cloud models use the :cloud tag suffix and do not require local hardware. $ openshell sandbox create --from ollama\nTool Calling Agentic workflows (Claude Code, Codex, OpenCode) rely on tool calling. The following models have reliable tool calling support: Qwen 3.5, Nemotron-3-Super, GLM-5, and Kimi-K2.5. Check the Ollama model library for the latest models. Updating Ollama To update Ollama inside a running sandbox: $ update-ollama\nOr auto-update on every sandbox start: $ openshell sandbox create --from ollama -e OLLAMA_UPDATE=1\nOption B: Host-Level Ollama Use this approach when you want a single Ollama instance on the gateway host, shared across multiple sandboxes through inference.local . This approach uses Ollama because it is easy to install and run locally, but you can substitute other inference engines such as vLLM, SGLang, TRT-LLM, and NVIDIA NIM by changing the startup command, base URL, and model name. Step 1: Install and Start Ollama Install Ollama on the gateway host: $ curl -fsSL https://ollama.com/install.sh | sh\nStart Ollama on all interfaces so it is reachable from sandboxes: $ OLLAMA_HOST=0.0.0.0:11434 ollama serve\nIf you see Error: listen tcp 0.0.0.0:11434: bind: address already in use , Ollama is already running as a system service. Stop it first: $ systemctl stop ollama\nOLLAMA_HOST=0.0.0.0:11434 ollama serve\nStep 2: Pull a Model In a second terminal, pull a model: $ ollama run qwen3.5:0.8b\nType /bye to exit the interactive session. The model stays loaded. Step 3: Create a Provider Create an OpenAI-compatible provider pointing at the host Ollama: $ openshell provider create\nname ollama\ntype openai\ncredential OPENAI_API_KEY=empty\nconfig OPENAI_BASE_URL=http://host.openshell.internal:11434/v1\nOpenShell injects host.openshell.internal so sandboxes and the gateway can reach the host machine. You can also use the host’s LAN IP. Step 4: Set Inference Routing $ openshell inference set --provider ollama --model qwen3.5:0.8b\nConfirm: $ openshell inference get\nStep 5: Verify from a Sandbox $ openshell sandbox create --\ncurl https://inference.local/v1/chat/completions\njson '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10\nThe response should be JSON from the model. Troubleshooting Common issues and fixes: Ollama not reachable from sandbox — Ollama must be bound to 0.0.0.0 , not 127.0.0.1 . This applies to host-level Ollama only; the community sandbox handles this automatically. OPENAI_BASE_URL wrong — Use http://host.openshell.internal:11434/v1 , not localhost or 127.0.0.1 . Model not found — Run ollama ps to confirm the model is loaded. Run ollama pull if needed. HTTPS vs HTTP — Code inside sandboxes must call https://inference.local , not http:// . AMD GPU driver issues — Ollama v0.18+ requires ROCm 7 drivers for AMD GPUs. Update your drivers if you see GPU detection failures. Useful commands: $ openshell status\nopenshell inference get\nopenshell provider get ollama\nNext Steps To learn more about managed inference, refer to /inference/index . To configure a different self-hosted backend, refer to /inference/configure . To explore more community sandboxes, refer to /sandboxes/community-sandboxes","format":"text","summary":"This tutorial covers two ways to use Ollama with OpenShell:","headings":[{"text":"Run Local Inference with Ollama","level":1},{"text":"Prerequisites","level":2},{"text":"Option A: Ollama Community Sandbox (Recommended)","level":2},{"text":"Step 1: Create the Sandbox","level":3},{"text":"Tool Calling","level":3},{"text":"Updating Ollama","level":3},{"text":"Option B: Host-Level Ollama","level":2},{"text":"Step 1: Install and Start Ollama","level":3},{"text":"Step 2: Pull a Model","level":3},{"text":"Step 3: Create a Provider","level":3},{"text":"Step 4: Set Inference Routing","level":3},{"text":"Step 5: Verify from a Sandbox","level":3},{"text":"Troubleshooting","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file +{"id":"tutorials/inference-ollama","title":"Run Local Inference with Ollama","url":"tutorials/inference-ollama.html","last_modified":"2026-03-30T18:08:14.916391+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Run local and cloud models inside an OpenShell sandbox using the Ollama community sandbox, or route sandbox requests to a host-level Ollama server.","tags":["Tutorial","Inference Routing","Ollama","Local Inference","Sandbox"],"topics":["Generative AI","Cybersecurity"],"content_type":"tutorial","learning_level":"technical_intermediate","audience":["engineer"],"content":"Run Local Inference with Ollama This tutorial covers two ways to use Ollama with OpenShell: Ollama sandbox (recommended) — a self-contained sandbox with Ollama, Claude Code, and Codex pre-installed. One command to start. Host-level Ollama — run Ollama on the gateway host and route sandbox inference to it. Useful when you want a single Ollama instance shared across multiple sandboxes. After completing this tutorial, you will know how to: Launch the Ollama community sandbox for a batteries-included experience. Use ollama launch to start coding agents inside a sandbox. Expose a host-level Ollama server to sandboxes through inference.local . Prerequisites A working OpenShell installation. Complete the /get-started/quickstart before proceeding. Option A: Ollama Community Sandbox (Recommended) The Ollama community sandbox bundles Ollama, Claude Code, OpenCode, and Codex into a single image. Ollama starts automatically when the sandbox launches. Step 1: Create the Sandbox $ openshell sandbox create --from ollama\nThis pulls the community sandbox image, applies the bundled policy, and drops you into a shell with Ollama running. Step 2: Chat with a Model Chat with a local model $ ollama run qwen3.5\nOr a cloud model $ ollama run kimi-k2.5:cloud\nOr use ollama launch to start a coding agent with Ollama as the model backend: $ ollama launch claude\nollama launch codex\nollama launch opencode\nFor CI/CD and automated workflows, ollama launch supports a headless mode: $ ollama launch claude --yes --model qwen3.5\nModel Recommendations Use case Model Notes Smoke test qwen3.5:0.8b Fast, lightweight, good for verifying setup Coding and reasoning qwen3.5 Strong tool calling support for agentic workflows Complex tasks nemotron-3-super 122B parameter model, needs 48GB+ VRAM No local GPU qwen3.5:cloud Runs on Ollama’s cloud infrastructure, no ollama pull required Cloud models use the :cloud tag suffix and do not require local hardware. $ openshell sandbox create --from ollama\nTool Calling Agentic workflows (Claude Code, Codex, OpenCode) rely on tool calling. The following models have reliable tool calling support: Qwen 3.5, Nemotron-3-Super, GLM-5, and Kimi-K2.5. Check the Ollama model library for the latest models. Updating Ollama To update Ollama inside a running sandbox: $ update-ollama\nOr auto-update on every sandbox start: $ openshell sandbox create --from ollama -e OLLAMA_UPDATE=1\nOption B: Host-Level Ollama Use this approach when you want a single Ollama instance on the gateway host, shared across multiple sandboxes through inference.local . This approach uses Ollama because it is easy to install and run locally, but you can substitute other inference engines such as vLLM, SGLang, TRT-LLM, and NVIDIA NIM by changing the startup command, base URL, and model name. Step 1: Install and Start Ollama Install Ollama on the gateway host: $ curl -fsSL https://ollama.com/install.sh | sh\nStart Ollama on all interfaces so it is reachable from sandboxes: $ OLLAMA_HOST=0.0.0.0:11434 ollama serve\nIf you see Error: listen tcp 0.0.0.0:11434: bind: address already in use , Ollama is already running as a system service. Stop it first: $ systemctl stop ollama\nOLLAMA_HOST=0.0.0.0:11434 ollama serve\nStep 2: Pull a Model In a second terminal, pull a model: $ ollama run qwen3.5:0.8b\nType /bye to exit the interactive session. The model stays loaded. Step 3: Create a Provider Create an OpenAI-compatible provider pointing at the host Ollama: $ openshell provider create\nname ollama\ntype openai\ncredential OPENAI_API_KEY=empty\nconfig OPENAI_BASE_URL=http://host.openshell.internal:11434/v1\nOpenShell injects host.openshell.internal so sandboxes and the gateway can reach the host machine. You can also use the host’s LAN IP. Step 4: Set Inference Routing $ openshell inference set --provider ollama --model qwen3.5:0.8b\nConfirm: $ openshell inference get\nStep 5: Verify from a Sandbox $ openshell sandbox create --\ncurl https://inference.local/v1/chat/completions\njson '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10\nThe response should be JSON from the model. Troubleshooting Common issues and fixes: Ollama not reachable from sandbox — Ollama must be bound to 0.0.0.0 , not 127.0.0.1 . This applies to host-level Ollama only; the community sandbox handles this automatically. OPENAI_BASE_URL wrong — Use http://host.openshell.internal:11434/v1 , not localhost or 127.0.0.1 . Model not found — Run ollama ps to confirm the model is loaded. Run ollama pull if needed. HTTPS vs HTTP — Code inside sandboxes must call https://inference.local , not http:// . AMD GPU driver issues — Ollama v0.18+ requires ROCm 7 drivers for AMD GPUs. Update your drivers if you see GPU detection failures. Useful commands: $ openshell status\nopenshell inference get\nopenshell provider get ollama\nNext Steps To learn more about managed inference, refer to /inference/index . To configure a different self-hosted backend, refer to /inference/configure . To explore more community sandboxes, refer to /sandboxes/community-sandboxes","format":"text","summary":"This tutorial covers two ways to use Ollama with OpenShell:","headings":[{"text":"Run Local Inference with Ollama","level":1},{"text":"Prerequisites","level":2},{"text":"Option A: Ollama Community Sandbox (Recommended)","level":2},{"text":"Step 1: Create the Sandbox","level":3},{"text":"Tool Calling","level":3},{"text":"Updating Ollama","level":3},{"text":"Option B: Host-Level Ollama","level":2},{"text":"Step 1: Install and Start Ollama","level":3},{"text":"Step 2: Pull a Model","level":3},{"text":"Step 3: Create a Provider","level":3},{"text":"Step 4: Set Inference Routing","level":3},{"text":"Step 5: Verify from a Sandbox","level":3},{"text":"Troubleshooting","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file diff --git a/pr-preview/pr-677/tutorials/local-inference-lmstudio.json b/pr-preview/pr-677/tutorials/local-inference-lmstudio.json index 4b5ed7e28..49956a8ea 100644 --- a/pr-preview/pr-677/tutorials/local-inference-lmstudio.json +++ b/pr-preview/pr-677/tutorials/local-inference-lmstudio.json @@ -1 +1 @@ -{"id":"tutorials/local-inference-lmstudio","title":"Route Local Inference Requests to LM Studio","url":"tutorials/local-inference-lmstudio.html","last_modified":"2026-03-30T18:03:24.580882+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Configure inference.local to route sandbox requests to a local LM Studio server running on the gateway host.","tags":["Tutorial","Inference Routing","LM Studio","Local Inference","Sandbox"],"topics":["Generative AI","Cybersecurity"],"content_type":"tutorial","learning_level":"technical_intermediate","audience":["engineer"],"content":"Route Local Inference Requests to LM Studio This tutorial describes how to configure OpenShell to route inference requests to a local LM Studio server. The LM Studio server provides easy setup with both OpenAI and Anthropic compatible endpoints. This tutorial will cover: Expose a local inference server to OpenShell sandboxes. Verify end-to-end inference from inside a sandbox. Prerequisites First, complete OpenShell installation and follow the /get-started/quickstart . Install the LM Studio app . Make sure that your LM Studio is running in the same environment as your gateway. If you prefer to work without having to keep the LM Studio app open, download llmster (headless LM Studio) with the following command: Linux/Mac $ curl -fsSL https://lmstudio.ai/install.sh | bash\nWindows $ irm https://lmstudio.ai/install.ps1 | iex\nAnd start llmster: $ lms daemon up\nStep 1: Start LM Studio Local Server Start the LM Studio local server from the Developer tab, and verify the OpenAI-compatible endpoint is enabled. LM Studio will listen to 127.0.0.1:1234 by default. For use with OpenShell, you’ll need to configure LM Studio to listen on all interfaces ( 0.0.0.0 ). If you’re using the GUI, go to the Developer Tab, select Server Settings, then enable Serve on Local Network. If you’re using llmster in headless mode, run lms server start --bind 0.0.0.0 . Step 2: Test with a small model In the LM Studio app, head to the Model Search tab to download a small model like Qwen3.5 2B. In the terminal, use the following command to download and load the model: $ lms get qwen/qwen3.5-2b\nlms load qwen/qwen3.5-2b\nStep 3: Add LM Studio as a provider Choose the provider type that matches the client protocol you want to route through inference.local . OpenAI-compatible Add LM Studio as an OpenAI-compatible provider through host.openshell.internal : $ openshell provider create\nname lmstudio\ntype openai\ncredential OPENAI_API_KEY=lmstudio\nconfig OPENAI_BASE_URL=http://host.openshell.internal:1234/v1\nUse this provider for clients that send OpenAI-compatible requests such as POST /v1/chat/completions or POST /v1/responses . Anthropic-compatible Add a provider that points to LM Studio’s Anthropic-compatible POST /v1/messages endpoint: $ openshell provider create\nname lmstudio-anthropic\ntype anthropic\ncredential ANTHROPIC_API_KEY=lmstudio\nconfig ANTHROPIC_BASE_URL=http://host.openshell.internal:1234\nUse this provider for Anthropic-compatible POST /v1/messages requests. Step 4: Configure LM Studio as the local inference provider Set the managed inference route for the active gateway: OpenAI-compatible $ openshell inference set --provider lmstudio --model qwen/qwen3.5-2b\nIf the command succeeds, OpenShell has verified that the upstream is reachable and accepts the expected OpenAI-compatible request shape. Anthropic-compatible $ openshell inference set --provider lmstudio-anthropic --model qwen/qwen3.5-2b\nIf the command succeeds, OpenShell has verified that the upstream is reachable and accepts the expected Anthropic-compatible request shape. The active inference.local route is gateway-scoped, so only one provider and model pair is active at a time. Re-run openshell inference set whenever you want to switch between OpenAI-compatible and Anthropic-compatible clients. Confirm the saved config: $ openshell inference get\nYou should see either Provider: lmstudio or Provider: lmstudio-anthropic , along with Model: qwen/qwen3.5-2b . Step 5: Verify from Inside a Sandbox Run a simple request through https://inference.local : OpenAI-compatible openshell sandbox create --\ncurl https://inference.local/v1/chat/completions\njson '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10\nopenshell sandbox create --\ncurl https://inference.local/v1/responses\njson\ninstructions\": \"You are a helpful assistant\ninput\": \"hello\nmax_output_tokens\": 10\nAnthropic-compatible openshell sandbox create --\ncurl https://inference.local/v1/messages\njson '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10\nTroubleshooting If setup fails, check these first: LM Studio local server is running and reachable from the gateway host OPENAI_BASE_URL uses http://host.openshell.internal:1234/v1 when you use an openai provider ANTHROPIC_BASE_URL uses http://host.openshell.internal:1234 when you use an anthropic provider The gateway and LM Studio run on the same machine or a reachable network path The configured model name matches the model exposed by LM Studio Useful commands: $ openshell status\nopenshell inference get\nopenshell provider get lmstudio\nopenshell provider get lmstudio-anthropic\nNext Steps To learn more about using the LM Studio CLI, refer to LM Studio docs To learn more about managed inference, refer to /inference/index . To configure a different self-hosted backend, refer to /inference/configure","format":"text","summary":"This tutorial describes how to configure OpenShell to route inference requests to a local LM Studio server.","headings":[{"text":"Route Local Inference Requests to LM Studio","level":1},{"text":"Prerequisites","level":2},{"text":"Linux/Mac","level":3},{"text":"Windows","level":3},{"text":"Step 1: Start LM Studio Local Server","level":2},{"text":"Step 2: Test with a small model","level":2},{"text":"Step 3: Add LM Studio as a provider","level":2},{"text":"Step 4: Configure LM Studio as the local inference provider","level":2},{"text":"Step 5: Verify from Inside a Sandbox","level":2},{"text":"Troubleshooting","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file +{"id":"tutorials/local-inference-lmstudio","title":"Route Local Inference Requests to LM Studio","url":"tutorials/local-inference-lmstudio.html","last_modified":"2026-03-30T18:08:14.920922+00:00","book":{"title":"NVIDIA OpenShell Developer Guide","version":"latest"},"product":{"name":"OpenShell","version":"latest"},"description":"Configure inference.local to route sandbox requests to a local LM Studio server running on the gateway host.","tags":["Tutorial","Inference Routing","LM Studio","Local Inference","Sandbox"],"topics":["Generative AI","Cybersecurity"],"content_type":"tutorial","learning_level":"technical_intermediate","audience":["engineer"],"content":"Route Local Inference Requests to LM Studio This tutorial describes how to configure OpenShell to route inference requests to a local LM Studio server. The LM Studio server provides easy setup with both OpenAI and Anthropic compatible endpoints. This tutorial will cover: Expose a local inference server to OpenShell sandboxes. Verify end-to-end inference from inside a sandbox. Prerequisites First, complete OpenShell installation and follow the /get-started/quickstart . Install the LM Studio app . Make sure that your LM Studio is running in the same environment as your gateway. If you prefer to work without having to keep the LM Studio app open, download llmster (headless LM Studio) with the following command: Linux/Mac $ curl -fsSL https://lmstudio.ai/install.sh | bash\nWindows $ irm https://lmstudio.ai/install.ps1 | iex\nAnd start llmster: $ lms daemon up\nStep 1: Start LM Studio Local Server Start the LM Studio local server from the Developer tab, and verify the OpenAI-compatible endpoint is enabled. LM Studio will listen to 127.0.0.1:1234 by default. For use with OpenShell, you’ll need to configure LM Studio to listen on all interfaces ( 0.0.0.0 ). If you’re using the GUI, go to the Developer Tab, select Server Settings, then enable Serve on Local Network. If you’re using llmster in headless mode, run lms server start --bind 0.0.0.0 . Step 2: Test with a small model In the LM Studio app, head to the Model Search tab to download a small model like Qwen3.5 2B. In the terminal, use the following command to download and load the model: $ lms get qwen/qwen3.5-2b\nlms load qwen/qwen3.5-2b\nStep 3: Add LM Studio as a provider Choose the provider type that matches the client protocol you want to route through inference.local . OpenAI-compatible Add LM Studio as an OpenAI-compatible provider through host.openshell.internal : $ openshell provider create\nname lmstudio\ntype openai\ncredential OPENAI_API_KEY=lmstudio\nconfig OPENAI_BASE_URL=http://host.openshell.internal:1234/v1\nUse this provider for clients that send OpenAI-compatible requests such as POST /v1/chat/completions or POST /v1/responses . Anthropic-compatible Add a provider that points to LM Studio’s Anthropic-compatible POST /v1/messages endpoint: $ openshell provider create\nname lmstudio-anthropic\ntype anthropic\ncredential ANTHROPIC_API_KEY=lmstudio\nconfig ANTHROPIC_BASE_URL=http://host.openshell.internal:1234\nUse this provider for Anthropic-compatible POST /v1/messages requests. Step 4: Configure LM Studio as the local inference provider Set the managed inference route for the active gateway: OpenAI-compatible $ openshell inference set --provider lmstudio --model qwen/qwen3.5-2b\nIf the command succeeds, OpenShell has verified that the upstream is reachable and accepts the expected OpenAI-compatible request shape. Anthropic-compatible $ openshell inference set --provider lmstudio-anthropic --model qwen/qwen3.5-2b\nIf the command succeeds, OpenShell has verified that the upstream is reachable and accepts the expected Anthropic-compatible request shape. The active inference.local route is gateway-scoped, so only one provider and model pair is active at a time. Re-run openshell inference set whenever you want to switch between OpenAI-compatible and Anthropic-compatible clients. Confirm the saved config: $ openshell inference get\nYou should see either Provider: lmstudio or Provider: lmstudio-anthropic , along with Model: qwen/qwen3.5-2b . Step 5: Verify from Inside a Sandbox Run a simple request through https://inference.local : OpenAI-compatible openshell sandbox create --\ncurl https://inference.local/v1/chat/completions\njson '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10\nopenshell sandbox create --\ncurl https://inference.local/v1/responses\njson\ninstructions\": \"You are a helpful assistant\ninput\": \"hello\nmax_output_tokens\": 10\nAnthropic-compatible openshell sandbox create --\ncurl https://inference.local/v1/messages\njson '{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}],\"max_tokens\":10\nTroubleshooting If setup fails, check these first: LM Studio local server is running and reachable from the gateway host OPENAI_BASE_URL uses http://host.openshell.internal:1234/v1 when you use an openai provider ANTHROPIC_BASE_URL uses http://host.openshell.internal:1234 when you use an anthropic provider The gateway and LM Studio run on the same machine or a reachable network path The configured model name matches the model exposed by LM Studio Useful commands: $ openshell status\nopenshell inference get\nopenshell provider get lmstudio\nopenshell provider get lmstudio-anthropic\nNext Steps To learn more about using the LM Studio CLI, refer to LM Studio docs To learn more about managed inference, refer to /inference/index . To configure a different self-hosted backend, refer to /inference/configure","format":"text","summary":"This tutorial describes how to configure OpenShell to route inference requests to a local LM Studio server.","headings":[{"text":"Route Local Inference Requests to LM Studio","level":1},{"text":"Prerequisites","level":2},{"text":"Linux/Mac","level":3},{"text":"Windows","level":3},{"text":"Step 1: Start LM Studio Local Server","level":2},{"text":"Step 2: Test with a small model","level":2},{"text":"Step 3: Add LM Studio as a provider","level":2},{"text":"Step 4: Configure LM Studio as the local inference provider","level":2},{"text":"Step 5: Verify from Inside a Sandbox","level":2},{"text":"Troubleshooting","level":2},{"text":"Next Steps","level":2}]} \ No newline at end of file