|
| 1 | +--- |
| 2 | +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. |
| 3 | +# SPDX-License-Identifier: Apache-2.0 |
| 4 | +title: "Gateway Configuration File" |
| 5 | +sidebar-title: "Gateway Config" |
| 6 | +description: "Reference for the OpenShell gateway TOML configuration file (RFC 0003)." |
| 7 | +keywords: "Generative AI, Cybersecurity, AI Agents, Sandboxing, Gateway, Configuration, TOML, Reference" |
| 8 | +position: 5 |
| 9 | +--- |
| 10 | + |
| 11 | +The OpenShell gateway reads its configuration from a TOML file when `--config` or `OPENSHELL_GATEWAY_CONFIG` is set. CLI flags and `OPENSHELL_*` environment variables always override the file. See [RFC 0003](https://github.com/NVIDIA/OpenShell/blob/main/rfc/0003-gateway-configuration/README.md) for the full schema. |
| 12 | + |
| 13 | +## Source Precedence |
| 14 | + |
| 15 | +```text |
| 16 | +CLI flag > OPENSHELL_* env var > TOML file > built-in default |
| 17 | +``` |
| 18 | + |
| 19 | +`database_url` and `ssh_handshake_secret` are env-only. The loader rejects them when they appear in the file. |
| 20 | + |
| 21 | +## Layout |
| 22 | + |
| 23 | +The file is rooted at `[openshell]`. Gateway-wide settings live under `[openshell.gateway]`. Each compute driver owns its own `[openshell.drivers.<name>]` table. Shared keys set at gateway scope are inherited into driver tables when not overridden. |
| 24 | + |
| 25 | +```toml |
| 26 | +[openshell] |
| 27 | +version = 1 |
| 28 | + |
| 29 | +[openshell.gateway] |
| 30 | +# ... gateway-wide settings ... |
| 31 | + |
| 32 | +[openshell.gateway.tls] |
| 33 | +# ... gateway listener TLS ... |
| 34 | + |
| 35 | +[openshell.gateway.oidc] |
| 36 | +# ... JWT bearer auth ... |
| 37 | + |
| 38 | +[openshell.drivers.kubernetes] |
| 39 | +# ... driver-specific settings ... |
| 40 | +``` |
| 41 | + |
| 42 | +## Full Example |
| 43 | + |
| 44 | +A complete gateway configuration covering every section. Trim to the fields you need. |
| 45 | + |
| 46 | +```toml |
| 47 | +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. |
| 48 | +# SPDX-License-Identifier: Apache-2.0 |
| 49 | + |
| 50 | +[openshell] |
| 51 | +version = 1 |
| 52 | + |
| 53 | +[openshell.gateway] |
| 54 | +bind_address = "0.0.0.0:8080" |
| 55 | +health_bind_address = "0.0.0.0:8081" |
| 56 | +metrics_bind_address = "0.0.0.0:9090" |
| 57 | + |
| 58 | +log_level = "info" |
| 59 | + |
| 60 | +# When empty the gateway auto-detects (Kubernetes -> Podman -> Docker). VM is |
| 61 | +# never auto-detected and requires an explicit entry here. |
| 62 | +compute_drivers = ["kubernetes"] |
| 63 | + |
| 64 | +sandbox_namespace = "openshell" |
| 65 | +sandbox_ssh_port = 2222 |
| 66 | +ssh_gateway_host = "127.0.0.1" |
| 67 | +ssh_gateway_port = 8080 |
| 68 | + |
| 69 | +# Subject Alternative Names baked into the gateway server certificate. |
| 70 | +# Wildcard DNS SANs (e.g. "*.dev.openshell.localhost") also enable sandbox |
| 71 | +# service URLs under that domain. |
| 72 | +server_sans = ["openshell", "*.dev.openshell.localhost"] |
| 73 | +# Allow plaintext HTTP routing for loopback sandbox service URLs. |
| 74 | +enable_loopback_service_http = true |
| 75 | + |
| 76 | +# Shared driver defaults — inherited into [openshell.drivers.<name>] tables |
| 77 | +# when the driver-specific table does not override them. |
| 78 | +default_image = "ghcr.io/nvidia/openshell/sandbox:latest" |
| 79 | +supervisor_image = "ghcr.io/nvidia/openshell/supervisor:latest" |
| 80 | +client_tls_secret_name = "openshell-client-tls" |
| 81 | + |
| 82 | +# Gateway listener TLS (distinct from the per-driver guest_tls_*). |
| 83 | +[openshell.gateway.tls] |
| 84 | +cert_path = "/etc/openshell/certs/gateway.pem" |
| 85 | +key_path = "/etc/openshell/certs/gateway-key.pem" |
| 86 | +client_ca_path = "/etc/openshell/certs/client-ca.pem" |
| 87 | +allow_unauthenticated = false |
| 88 | + |
| 89 | +[openshell.gateway.oidc] |
| 90 | +issuer = "https://idp.example.com/realms/openshell" |
| 91 | +audience = "openshell-cli" |
| 92 | +jwks_ttl_secs = 3600 |
| 93 | +roles_claim = "realm_access.roles" |
| 94 | +admin_role = "openshell-admin" |
| 95 | +user_role = "openshell-user" |
| 96 | +``` |
| 97 | + |
| 98 | +`image_pull_policy` is intentionally not a shared gateway key. Kubernetes uses `Always | IfNotPresent | Never` while Podman uses `always | missing | never | newer`. Set it inside the relevant driver table. |
| 99 | + |
| 100 | +## Per-Driver Examples |
| 101 | + |
| 102 | +### Kubernetes |
| 103 | + |
| 104 | +The gateway runs as a Pod and creates sandbox Pods in another namespace. mTLS material for sandboxes is delivered via a Kubernetes Secret rather than host-side file paths. |
| 105 | + |
| 106 | +```toml |
| 107 | +[openshell] |
| 108 | +version = 1 |
| 109 | + |
| 110 | +[openshell.gateway] |
| 111 | +bind_address = "0.0.0.0:8080" |
| 112 | +health_bind_address = "0.0.0.0:8081" |
| 113 | +metrics_bind_address = "0.0.0.0:9090" |
| 114 | +log_level = "info" |
| 115 | +compute_drivers = ["kubernetes"] |
| 116 | + |
| 117 | +default_image = "ghcr.io/nvidia/openshell/sandbox:latest" |
| 118 | +supervisor_image = "ghcr.io/nvidia/openshell/supervisor:latest" |
| 119 | +client_tls_secret_name = "openshell-client-tls" |
| 120 | + |
| 121 | +[openshell.gateway.tls] |
| 122 | +cert_path = "/etc/openshell-tls/server/tls.crt" |
| 123 | +key_path = "/etc/openshell-tls/server/tls.key" |
| 124 | +client_ca_path = "/etc/openshell-tls/client-ca/ca.crt" |
| 125 | + |
| 126 | +[openshell.drivers.kubernetes] |
| 127 | +namespace = "agents" |
| 128 | +grpc_endpoint = "https://openshell-gateway.agents.svc:8080" |
| 129 | +image_pull_policy = "IfNotPresent" |
| 130 | +# Use the image volume on K8s >= 1.35 (GA in 1.36); switch to "init-container" |
| 131 | +# on older clusters or where the ImageVolume feature gate is off. |
| 132 | +supervisor_sideload_method = "image-volume" |
| 133 | +``` |
| 134 | + |
| 135 | +### Docker |
| 136 | + |
| 137 | +Sandboxes run as containers on a local bridge network. The supervisor binary is bind-mounted from the host (no in-cluster image pull required); guest mTLS material is supplied as host paths. |
| 138 | + |
| 139 | +```toml |
| 140 | +[openshell] |
| 141 | +version = 1 |
| 142 | + |
| 143 | +[openshell.gateway] |
| 144 | +bind_address = "127.0.0.1:8080" |
| 145 | +log_level = "info" |
| 146 | +compute_drivers = ["docker"] |
| 147 | + |
| 148 | +supervisor_image = "ghcr.io/nvidia/openshell/supervisor:latest" |
| 149 | +guest_tls_ca = "/etc/openshell/certs/ca.pem" |
| 150 | +guest_tls_cert = "/etc/openshell/certs/client.pem" |
| 151 | +guest_tls_key = "/etc/openshell/certs/client-key.pem" |
| 152 | + |
| 153 | +[openshell.drivers.docker] |
| 154 | +network_name = "openshell-docker" |
| 155 | +# Skip the image-pull-and-extract step by pointing at a locally built binary. |
| 156 | +supervisor_bin = "/usr/local/libexec/openshell/openshell-sandbox" |
| 157 | +``` |
| 158 | + |
| 159 | +### Podman |
| 160 | + |
| 161 | +Sandboxes run as Podman containers on a user-mode bridge network. The supervisor image is mounted read-only via Podman's `type=image` mount; guest mTLS material is supplied as host paths. |
| 162 | + |
| 163 | +```toml |
| 164 | +[openshell] |
| 165 | +version = 1 |
| 166 | + |
| 167 | +[openshell.gateway] |
| 168 | +bind_address = "127.0.0.1:8080" |
| 169 | +log_level = "info" |
| 170 | +compute_drivers = ["podman"] |
| 171 | + |
| 172 | +default_image = "ghcr.io/nvidia/openshell/sandbox:latest" |
| 173 | +supervisor_image = "ghcr.io/nvidia/openshell/supervisor:latest" |
| 174 | +guest_tls_ca = "/etc/openshell/certs/ca.pem" |
| 175 | +guest_tls_cert = "/etc/openshell/certs/client.pem" |
| 176 | +guest_tls_key = "/etc/openshell/certs/client-key.pem" |
| 177 | + |
| 178 | +[openshell.drivers.podman] |
| 179 | +# Rootless socket path. For root Podman use /run/podman/podman.sock. |
| 180 | +socket_path = "/run/user/1000/podman/podman.sock" |
| 181 | +network_name = "openshell" |
| 182 | +stop_timeout_secs = 10 |
| 183 | +image_pull_policy = "missing" # Podman vocabulary: always | missing | never | newer |
| 184 | +``` |
| 185 | + |
| 186 | +### MicroVM |
| 187 | + |
| 188 | +Each sandbox runs inside its own libkrun microVM managed by the standalone `openshell-driver-vm` subprocess. Use this driver when you want stronger isolation than container namespaces alone. |
| 189 | + |
| 190 | +```toml |
| 191 | +[openshell] |
| 192 | +version = 1 |
| 193 | + |
| 194 | +[openshell.gateway] |
| 195 | +bind_address = "127.0.0.1:8080" |
| 196 | +log_level = "info" |
| 197 | +# VM is never auto-detected; an explicit entry here is required. |
| 198 | +compute_drivers = ["vm"] |
| 199 | + |
| 200 | +default_image = "ghcr.io/nvidia/openshell/sandbox:latest" |
| 201 | +guest_tls_ca = "/var/lib/openshell/guest-tls/ca.pem" |
| 202 | +guest_tls_cert = "/var/lib/openshell/guest-tls/client.pem" |
| 203 | +guest_tls_key = "/var/lib/openshell/guest-tls/client-key.pem" |
| 204 | + |
| 205 | +[openshell.drivers.vm] |
| 206 | +state_dir = "/var/lib/openshell/vm" |
| 207 | +# Where the gateway looks for the openshell-driver-vm subprocess binary. |
| 208 | +driver_dir = "/usr/local/libexec/openshell" |
| 209 | +vcpus = 2 |
| 210 | +mem_mib = 2048 |
| 211 | +krun_log_level = 1 |
| 212 | +``` |
0 commit comments