Code Sandbox / Remote Browser
Code Sandbox (sandbox-service) and Remote Browser (browser-service) are two optional advanced services, off by default. Both log in via the platform’s OAuth flow. This page covers enabling them, OAuth client auto-registration, and public-URL overrides for external-ingress scenarios.
The two services
Section titled “The two services”| Service | Capability | Dependency |
|---|---|---|
| Code Sandbox | Lets agents run code and serve temporary web previews | The third-party OpenSandbox (you install it yourself; the platform points at it via OPENSANDBOX_URL) |
| Remote Browser | Lets agents drive a real browser while users watch live over WebRTC | The bundled TURN relay (coturn), enabled together with BROWSER_ENABLED |
In the configuration generator, toggle the corresponding module to produce a values.env with these sections, or set SANDBOX_ENABLED / BROWSER_ENABLED to true by hand.
Enabling
Section titled “Enabling”Set the relevant values.env toggle to true, fill in the required fields, and the next install.sh applies it:
# Code SandboxSANDBOX_ENABLED=trueSANDBOX_NODE_PORT=30086SANDBOX_JWT_SECRET= # openssl rand -hex 32SANDBOX_SERVICE_KEY= # openssl rand -hex 32, shared between browser and sandbox
# Remote Browser (incl. TURN)BROWSER_ENABLED=trueBROWSER_NODE_PORT=30085BROWSER_JWT_SECRET= # openssl rand -hex 32TURN_HOST= # public / LAN IP browsers can reach, requiredTURN_AUTH_SECRET= # openssl rand -hex 32SANDBOX_JWT_SECRET / BROWSER_JWT_SECRET are each service’s session signing key; SANDBOX_SERVICE_KEY is the shared key the browser uses to call the sandbox (reused by the browser when both modules are on). For TURN_HOST and its troubleshooting, see Ingress Integration and “Debugging” below.
Installing OpenSandbox
Section titled “Installing OpenSandbox”Code Sandbox is powered by OpenSandbox (github.com/alibaba/OpenSandbox), a third-party component the platform installer does not install for you. When SANDBOX_ENABLED=true, install.sh deploys nap-sandbox and assumes OpenSandbox is already installed and reachable at OPENSANDBOX_URL.
Install OpenSandbox (controller + server) from its upstream Helm charts, then point the platform at it:
git clone https://github.com/alibaba/OpenSandbox && cd OpenSandbox/kubernetes/chartshelm dependency build opensandboxhelm install opensandbox ./opensandbox \ --namespace nap --create-namespace \ -f <path-to>/optional/sandbox/opensandbox-values.yamlRunning OpenSandbox in the nap namespace lets the platform’s default OPENSANDBOX_URL resolve. If you install OpenSandbox into its own namespace, set OPENSANDBOX_URL explicitly (e.g. http://opensandbox-server.opensandbox-system.svc:80). See the self-host README “Enabling Code Sandbox” for the full reference, including mounting the platform’s sandbox pod template.
OAuth client auto-registration
Section titled “OAuth client auto-registration”Both services log in via the platform OAuth flow with fixed client_ids (sandbox-service / browser-service) — they are PKCE public clients with no client_secret. These clients must exist in the control plane’s oauth_clients table, or GET /api/oauth/authorize returns 400 invalid_client at login.
After seeding the admin, install.sh runs a nap-seed-oauth-clients Job that auto-registers these two rows based on the enabled modules — no manual creation on the “applications” page. The registered redirect_uri is the same origin the service computes its own callback from, so they don’t drift:
| client_id | Default redirect_uri |
|---|---|
sandbox-service | http://<TOS_HOST>:<SANDBOX_NODE_PORT>/api/auth/callback |
browser-service | http://<TOS_HOST>:<BROWSER_NODE_PORT>/api/auth/callback |
The Job is idempotent: after changing a NodePort or public URL, re-running install.sh (or install.sh --seed-only) syncs the redirect_uris automatically.
Optional: public-URL override
Section titled “Optional: public-URL override”Service addresses are derived from the NodePort by default. When you expose the services through your own ingress / a custom domain (typically INGRESS_MODE=external, see Ingress Integration), the NodePort-form address is neither externally correct nor matches the OAuth callback. Override it with *_PUBLIC_URL:
SANDBOX_PUBLIC_URL=https://sandbox.example.comBROWSER_PUBLIC_URL=https://browsers.example.comThe override feeds both the service’s own callback address and the registered redirect_uri, keeping them in sync. Leave it blank to keep the original NodePort behavior, which doesn’t affect existing deployments. The address has no trailing slash.
Debugging
Section titled “Debugging”- Login redirect reports
400 invalid_client— the matching row is missing inoauth_clients. Confirm the seed Job ran and succeeded:kubectl -n <ns> logs job/nap-seed-oauth-clients; the log printsregistered "sandbox-service" → .... Re-run manually:install.sh --seed-only. - Login callback reports
400 invalid_redirect_uri— the registeredredirect_uridoesn’t match the service’s actual callback address. Common when external ingress is configured but*_PUBLIC_URLisn’t set, or a NodePort changed without re-seeding. Set*_PUBLIC_URLand re-runinstall.sh --seed-only. - Browser shows no video / black screen — usually TURN can’t be reached. Verify
TURN_HOSTis an IP the browser side can actually reach (kubelet auto-detect is unreliable on multi-NIC nodes, so set it explicitly), and that coturn is ready:kubectl -n <ns> get pod -l app=coturn. - Sandbox won’t start — first check whether OpenSandbox is installed:
kubectl -n <ns> get pod -l app.kubernetes.io/name=opensandbox.