You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: architecture/gateway.md
+12-6Lines changed: 12 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -107,23 +107,25 @@ The gateway boots in `cli::run_cli` (`crates/openshell-server/src/cli.rs`) and p
107
107
-`docker` constructs `openshell-driver-docker` in-process and manages local containers labeled with the configured sandbox namespace.
108
108
-`vm` spawns the standalone `openshell-driver-vm` binary as a local compute-driver process, resolves it from `--driver-dir`, conventional libexec install paths, or a sibling of the gateway binary, connects to it over a Unix domain socket, and keeps the libkrun/rootfs runtime out of the gateway binary.
109
109
3. Build `ServerState` (shared via `Arc<ServerState>` across all handlers), including a fresh `SupervisorSessionRegistry`.
110
-
4.**Spawn background tasks**:
110
+
4. Resume persisted sandboxes that were stopped during the previous gateway shutdown.
111
+
5.**Spawn background tasks**:
111
112
-`ComputeRuntime::spawn_watchers` -- consumes the compute-driver watch stream, republishes platform events, and runs a periodic `ListSandboxes` snapshot reconcile.
112
113
-`ssh_tunnel::spawn_session_reaper` -- sweeps expired or revoked SSH session tokens from the store hourly.
113
114
-`supervisor_session::spawn_relay_reaper` -- sweeps orphaned pending relay channels every 30 seconds.
114
-
5. Create `MultiplexService`.
115
-
6. Bind `TcpListener` on `config.bind_address`.
116
-
7. Optionally create `TlsAcceptor` from cert/key files.
117
-
8. Enter the accept loop: for each connection, spawn a tokio task that optionally performs a TLS handshake, then calls `MultiplexService::serve()`.
115
+
6. Create `MultiplexService`.
116
+
7. Bind the primary gateway listener and any compute-driver requested listeners. Docker requests the Docker bridge gateway address with the normal gateway port, so sandbox containers can call back over the bridge without joining the host network.
117
+
8. Bind optional health and metrics listeners.
118
+
9. Optionally create `TlsAcceptor` from cert/key files.
119
+
10. Spawn a task per gateway listener. Each accepted connection optionally performs a TLS handshake, then calls `MultiplexService::serve()`.
118
120
119
121
## Configuration
120
122
121
123
All configuration is via CLI flags with environment variable fallbacks. The `--db-url` flag is required.
122
124
123
125
| Flag | Env Var | Default | Description |
124
126
|------|---------|---------|-------------|
127
+
|`--bind-address`|`OPENSHELL_BIND_ADDRESS`|`127.0.0.1`| IP address for gateway, health, and metrics listeners. Container deployments pass `0.0.0.0` explicitly. |
125
128
|`--port`|`OPENSHELL_SERVER_PORT`|`8080`| TCP listen port |
126
-
|`--bind-address`|`OPENSHELL_BIND_ADDRESS`|`0.0.0.0`| Address for the main gateway listener |
|`--tls-cert`|`OPENSHELL_TLS_CERT`| None | Path to PEM certificate file |
129
131
|`--tls-key`|`OPENSHELL_TLS_KEY`| None | Path to PEM private key file |
@@ -136,6 +138,7 @@ All configuration is via CLI flags with environment variable fallbacks. The `--d
136
138
|`--sandbox-image`|`OPENSHELL_SANDBOX_IMAGE`| None | Default container image for sandbox pods |
137
139
|`--grpc-endpoint`|`OPENSHELL_GRPC_ENDPOINT`| None | gRPC endpoint reachable from within the cluster (for supervisor callbacks) |
138
140
|`--drivers`|`OPENSHELL_DRIVERS`|`kubernetes`| Compute backend to use. Current options are `kubernetes`, `docker`, and `vm`. |
141
+
|`--docker-network-name`|`OPENSHELL_DOCKER_NETWORK_NAME`|`openshell-docker`| Docker bridge network that local Docker sandboxes join |
139
142
|`--vm-driver-state-dir`|`OPENSHELL_VM_DRIVER_STATE_DIR`|`target/openshell-vm-driver`| Host directory for VM sandbox rootfs, console logs, and runtime state |
140
143
|`--driver-dir`|`OPENSHELL_DRIVER_DIR`| unset | Override directory for `openshell-driver-vm`. When unset, the gateway searches `~/.local/libexec/openshell`, `/usr/libexec/openshell`, `/usr/local/libexec/openshell`, `/usr/local/libexec`, then a sibling binary. |
141
144
|`--vm-krun-log-level`|`OPENSHELL_VM_KRUN_LOG_LEVEL`|`1`| libkrun log level for VM helper processes |
@@ -608,6 +611,9 @@ The gateway reaches the sandbox exclusively through the supervisor-initiated `Co
608
611
The Docker driver (`crates/openshell-driver-docker/src/lib.rs`) is an in-process compute backend for local standalone gateways. It creates one Docker container per sandbox, labels each container with `openshell.ai/managed-by=openshell`, `openshell.ai/sandbox-id`, `openshell.ai/sandbox-name`, and `openshell.ai/sandbox-namespace`, and bind-mounts a Linux `openshell-sandbox` supervisor binary into the container.
609
612
610
613
-**Create**: Pulls or validates the sandbox image according to `sandbox_image_pull_policy`, creates a labeled container, mounts the supervisor binary and optional TLS material, and starts the container with the supervisor as entrypoint.
614
+
-**Bridge networking**: Ensures a local Docker bridge network exists (`openshell-docker` by default) and starts every sandbox container on that network instead of using `network_mode=host`.
615
+
-**Gateway callback routing**: On native Linux Docker, injects `host.openshell.internal` with the bridge gateway IP and reports that bridge gateway IP plus the normal gateway port to `run_server()` as an extra listener. If the primary listener already binds the wildcard address for that port, the extra address is covered and is not bound a second time. On Docker Desktop, the bridge gateway IP belongs to Docker Desktop's VM rather than the macOS/Windows host, so the driver maps `host.openshell.internal` to Docker's `host-gateway` alias and does not request an extra listener. `OPENSHELL_ENDPOINT` inside Docker sandboxes uses the configured scheme and points at `host.openshell.internal:<gateway-port>` in both cases.
616
+
-**Environment ownership**: Merges template and spec environment first, then overwrites driver-owned supervisor variables, including `PATH`, `OPENSHELL_ENDPOINT`, `OPENSHELL_SANDBOX_ID`, `OPENSHELL_SSH_SOCKET_PATH`, and `OPENSHELL_SANDBOX_COMMAND`. This keeps privileged supervisor setup from resolving helper binaries through a user-controlled search path.
611
617
-**List/Get/Watch**: Reads labeled containers in the configured sandbox namespace and derives driver-native sandbox status from Docker state plus supervisor relay readiness.
612
618
-**Stop**: Stops the matching labeled container without deleting it.
613
619
-**Delete**: Force-removes the matching labeled container.
Copy file name to clipboardExpand all lines: architecture/sandbox-custom-containers.md
+5-6Lines changed: 5 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,7 +9,7 @@ The `--from` flag accepts four kinds of input:
9
9
| Input | Example | Behavior |
10
10
|-------|---------|----------|
11
11
|**Community sandbox name**|`--from openclaw`| Resolves to `ghcr.io/nvidia/openshell-community/sandboxes/openclaw:latest`|
12
-
|**Dockerfile path**|`--from ./Dockerfile`| Builds the image, pushes it into the cluster, then creates the sandbox |
12
+
|**Dockerfile path**|`--from ./Dockerfile`| Builds the imageinto the host Docker daemon, then creates the sandbox |
13
13
|**Directory with Dockerfile**|`--from ./my-sandbox/`| Uses the directory as the build context |
14
14
|**Full image reference**|`--from myregistry.com/img:tag`| Uses the image directly |
15
15
@@ -33,8 +33,7 @@ The community registry prefix defaults to `ghcr.io/nvidia/openshell-community/sa
33
33
When `--from` points to a Dockerfile or directory, the CLI:
34
34
35
35
1. Builds the image locally via the Docker daemon (respecting `.dockerignore`).
36
-
2. Pushes it into the cluster's containerd runtime using `docker save` / `ctr import`.
37
-
3. Creates the sandbox with the resulting image tag.
36
+
2. Creates the sandbox with the resulting local image tag.
38
37
39
38
## How It Works
40
39
@@ -107,18 +106,18 @@ The `openshell-sandbox` supervisor adapts to arbitrary environments:
107
106
|----------|-----------|
108
107
| Unified `--from` flag | Single entry point for community names, Dockerfiles, directories, and image refs — removes the need to know registry paths |
109
108
| Community name resolution | Bare names like `openclaw` expand to the GHCR community registry, making the common case simple |
110
-
| Auto build+push for Dockerfiles | Eliminates the two-step `image push` + `create` workflow for local development |
109
+
| Auto build for Dockerfiles | Eliminates the two-step `docker build` + `create` workflow for local Docker-backed development |
111
110
|`OPENSHELL_COMMUNITY_REGISTRY` env var | Allows organizations to host their own community sandbox registry |
112
111
| hostPath side-load | Supervisor binary lives on the node filesystem — no init container, no emptyDir, no extra image pull. Faster pod startup. |
113
112
| Read-only mount in agent | The supervisor binary is mounted read-only, and the startup seccomp prelude blocks the remount syscalls that would otherwise reopen it for writes once privileged bootstrap has completed. |
114
113
| Command override | Ensures `openshell-sandbox` is the entrypoint regardless of the image's default CMD |
115
114
| Clear `run_as_user/group` for custom images | Prevents startup failure when the image lacks the default `sandbox` user |
116
115
| Non-fatal log file init |`/var/log/openshell.log` may be unwritable in arbitrary images; falls back to stdout |
117
-
|`docker save` / `ctr import` for push | Avoids requiring a registry for local dev; images land directly in the k3s containerd store|
116
+
|Host Docker image store | Dockerfile sources build into the host Docker daemon and are referenced by local image tag.|
118
117
| Optional `iptables` for bypass detection | Core network isolation works via routing alone (`iproute2`); `iptables` only adds fast-fail (`ECONNREFUSED`) and diagnostic LOG entries. Making it optional avoids hard failures in minimal images that lack `iptables` while giving better UX when it is available. |
119
118
120
119
## Limitations
121
120
122
121
- Distroless / `FROM scratch` images are not supported (the supervisor needs glibc and `/proc`)
123
122
- Missing `iproute2` (or required capabilities) blocks startup in proxy mode because namespace isolation is mandatory
124
-
-The supervisor binary must be present on the k3s node at `/opt/openshell/bin/openshell-sandbox` (embedded in the cluster image at build time)
123
+
-Kubernetes gateways require images to be available to the cluster runtime. Dockerfile sources build into the host Docker daemon only; use a registry image reference when the selected gateway cannot access the host Docker image store.
0 commit comments