Services and ports
You can open a service in a Workspace from a browser or client on your machine, publish it at a public URL for others, or connect your own program to a port or socket inside the guest. This page covers each of these, starting with the kibo commands.
Overview
Choose by who needs to reach the service:
| Need | Use | Who can reach it |
|---|---|---|
| Open a web service in your local browser | kibo workspace service http | Only this machine |
Connect a local client such as psql, SSH, or VNC | kibo workspace service forward | Any process on this machine |
| Connect a web page on your machine to a port or socket | kibo workspace service bridge | Pages from one local origin |
| Show a web service to someone else | kibo exposure create | Anyone who has the address |
| Connect your own program to a port or socket | A service connection | Only the holder of the session credential |
Only a public URL needs a domain, which the deployer configures for it.
Opening an HTTP service in a local browser
The kibo workspace service http command proxies an HTTP port in the Workspace to 127.0.0.1 on your machine so you can open it in a browser. Only this machine can reach it, and the deployer does not need to configure a domain.
Proxy port 5173 in the Workspace and open the URL it prints:
kibo workspace service http "$workspace_id" --tcp-port 5173
# URL http://127.0.0.1:5173/The proxy runs until you press Ctrl-C. Connections in progress end with it.
You can leave the proxy running. The credential is renewed automatically before it expires, and you do not need to reopen the proxy after the Workspace restarts.
Parameters
| Parameter | Default | Description |
|---|---|---|
--tcp-port | Required | The port the service listens on in the Workspace |
--family | ipv4 | Use ipv6 when the service listens on ::1 |
--listen-port | Same as --tcp-port | Local port. 0 picks a free port |
Notes
- By default, the local port is the same as the port in the Workspace, so callback addresses hard-coded as
localhost:5173and CORS settings in the application keep working. - When the local port is in use, the command fails with exit code
2. Use a different--listen-port. - A service that listens only on
127.0.0.1works. You do not need to change it to listen on0.0.0.0. - The service can start after the proxy. Until it starts, requests return
502. - The proxy accepts only requests whose
Hostis127.0.0.1orlocalhostplus the local port. Any otherHostreturns403. This blocks web pages that resolve another domain to127.0.0.1. - The application sees the
Hostthe browser sent, so redirects and absolute URLs it generates come back to the local proxy. - Keep-alive, streaming responses such as SSE, and WebSocket all work.
- The proxy holds at most 32 connections to the service at the same time, counting idle, in-use, and WebSocket connections together. A request that finds none free waits for one. A WebSocket holds its connection until it closes, so 32 open WebSockets hold up every other request.
To show the service to someone else, publish a public URL.
Local port forwarding
The kibo workspace service forward command forwards a TCP port or a managed Unix socket in the Workspace to a port on 127.0.0.1 on your machine. It does not interpret the application protocol, so local clients can connect directly to services that do not use HTTP/1.1, such as databases, SSH, VNC, and gRPC.
Forward PostgreSQL on port 5432 and connect to it with psql:
kibo workspace service forward "$workspace_id" --tcp-port 5432
# Address 127.0.0.1:5432
psql -h 127.0.0.1 -p 5432 -U postgresTo connect to the desktop with a native VNC client, forward the desktop's VNC socket to local port 5900:
kibo workspace service forward "$workspace_id" \
--unix-path /run/kibotos/services/desktop/vnc.sock --listen-port 5900Forwarding runs until you press Ctrl-C. Connections in progress are reset with it.
Warning
Forwarding does not inspect the data that passes through it. Any process on your machine can connect to the port, including processes of other accounts, and web pages in a browser can send requests to it. For an HTTP service, a web page can read and write it through DNS rebinding, so use service http for HTTP services; it checks Host. The risk is the same as with kubectl port-forward and ssh -L.
Parameters
| Parameter | Default | Description |
|---|---|---|
--tcp-port | One of this or --unix-path | The port the service listens on in the Workspace |
--family | ipv4 | Use ipv6 when the service listens on ::1 |
--unix-path | One of this or --tcp-port | A Unix socket under /run/kibotos/services/ in the Workspace |
--listen-port | Same as --tcp-port; required for a Unix socket | Local port. 0 picks a free port |
Notes
- Each local connection maps to one connection in the Workspace. It is established as soon as you connect, so protocols where the server sends first (MySQL, SSH, VNC) do not wait for the client to write.
- Data in both directions is forwarded unchanged. When one side finishes writing, the other side reads EOF.
- When one side stops reading, writes from the other side wait. The connection is not closed because of this, and there is no idle timeout.
- At most 32 connections are forwarded at the same time. New connections beyond that are reset.
- When the service cannot be reached, the Workspace stops, or a connection fails midway, the local connection is reset and stderr gets a line with the reason, for example
connection from 127.0.0.1:52144 reset: unavailable: …. - The service can start after forwarding starts.
- You can leave forwarding running. The credential is renewed automatically before it expires, and you do not need to restart forwarding after the Workspace restarts.
- When the local port is in use, the command fails with exit code
2. Use a different--listen-port. - A Unix socket must be owned by root with mode
0600, and the path cannot pass through a symbolic link. Otherwise the connection fails withpermission_denied.
Local WebSocket bridge
The kibo workspace service bridge command turns one service in the Workspace into a WebSocket on 127.0.0.1, for a web page on your machine that talks to the service directly. It prints the WebSocket URL, which ends in /stream, and the address of a built-in test page that checks whether an echo service in the guest returns bytes unchanged.
Bridge port 7000 in the Workspace for a page that you serve at http://127.0.0.1:8080:
kibo workspace service bridge "$workspace_id" --tcp-port 7000 --origin http://127.0.0.1:8080- The target flags
--tcp-port,--family, and--unix-pathwork as forservice forward.--listen-portsets the local port; by default a free port is picked. - Only handshakes whose
Originequals--originare accepted. Without--origin, only the built-in test page can connect. - Each WebSocket gets its own connection to the service. Every message is binary and carries the bytes unchanged, with no opcode byte, at most 32 KiB per message. A text message closes the WebSocket.
- When the service ends its writing side, the bridge ends the connection and closes the WebSocket with
1000. The page cannot send more after that. - At most 16 WebSockets are bridged at the same time. Further handshakes return
503. - The credential is renewed automatically. The bridge runs until you press Ctrl-C, and open WebSockets close with it.
Public URLs
The kibo exposure command turns an HTTP port inside a Workspace into an https:// address that anyone who has the address can open in a browser. Use it when an Agent writes a web service in a Workspace and you need to see it directly.
Prerequisites
- The deployer has configured a domain dedicated to public URLs. See Install the Exposure gateway.
Without that domain, kibo does not list the kibo exposure commands, and creation fails.
Creating a public URL
Publish port 3000 of the Workspace for two hours:
workspace_id=workspace-example
kibo exposure create --workspace "$workspace_id" --port 3000 --ttl 2hThe url in the output is the address you can open directly or send to others. It has no trailing slash; to reach a path, append it directly.
Warning
There is no access control. Anyone with the address can access the service, with no password, origin, or IP restriction. The address is random, and that is its only protection. Do not use it to publish anything that should not be seen.
Listing and revoking
List the Exposures of a Workspace, show one, and revoke it:
kibo exposure list --workspace "$workspace_id"
kibo exposure get exposure-example
kibo exposure revoke exposure-exampleAfter revocation, the address stops serving immediately, and connections in progress end with it. Revoking again is not an error.
Notes
- The port is read on the guest loopback. A service that listens only on
127.0.0.1works. You do not need to change it to listen on0.0.0.0. When the service listens on::1, add--ipv6. - After an Exposure is revoked, its address is never given to anyone else.
--ttlis required, with a maximum of 24 hours. Serving stops automatically at expiry.- When the Workspace stops or is deleted, all its Exposures are revoked with it. After the Workspace starts again, create a new Exposure; it gets a new address.
- The only protocol is HTTP, including WebSocket and SSE. TCP, TLS passthrough, UDP, and QUIC are out of scope.
Exposure API
Programs manage public URLs through ExposureService: CreateExposure, GetExposure, ListExposures, and RevokeExposure. The server advertises the exposure.* capabilities only when the deployer has configured the dedicated domain. See Capability names.
When what you need is a byte channel for your own program rather than an address for a browser, use a service connection. It needs a credential, does not need a domain, and is not open to the internet.
With the API
A service connection connects a program to a TCP loopback port or a Unix socket inside the guest, such as VNC, Chrome DevTools, or an application port. The kibo workspace service commands and the desktop viewer page are all built on it.
Requesting a session
The first step is the same for both connection paths. When you request the data-plane session, request the SERVICE_CONNECT scope and list the targets in service_targets. For the session request itself, see Requesting a session credential.
| Target | Fields |
|---|---|
TCPLoopbackTarget | address_family, port |
UnixStreamTarget | path |
- Targets must be exact. Wildcards, port ranges, and arbitrary IPs are not supported.
- A Unix socket target follows the same rules as
--unix-path. See Local port forwarding. - The credential is valid only for the listed targets.
- The target list is part of the idempotency check.
Choosing a path
After that there are two paths with the same semantics and different encodings:
| WebSocket (default) | Bidirectional stream | |
|---|---|---|
| Endpoint | GET /v1/service on session.endpoint | ServiceConnectionService/Connect |
| Requires | An ordinary WebSocket upgrade | End-to-end HTTP/2 on every hop |
| Suited to | Deployments with an L7 reverse proxy or CDN in front; browsers | Direct deployments or deployments behind an L4 proxy |
WebSocket
Connect to a TCP port or to a Unix socket in the guest with one of these requests. The full list of parameters is in /v1/service.
GET <endpoint>/v1/service?tcp_family=ipv4&tcp_port=9222
GET <endpoint>/v1/service?unix_path=/run/kibotos/services/desktop/vnc.sockPass the credential in a header:
- Put the credential in
Authorization: Bearer. - Browsers cannot set request headers on a WebSocket handshake, so use
Sec-WebSocket-Protocol: kibotos-dp-credential.<credential>instead. The server selects the same subprotocol in the 101 response.
Warning
Do not put the credential in the query. It ends up in access logs and the Referer.
Authentication and the connection to the guest both complete before the upgrade, so a 101 response means the socket inside the guest is already connected. Failures before that are ordinary HTTP responses, with the same error body as /v1/files.
After the upgrade, bytes travel in binary frames whose first byte is an opcode, and failures arrive as close frames. For the opcodes, see Frames; for the close codes, see Close codes.
Warning
Only close code 1000 means the connection completed normally. 1001 is a failure here, although many WebSocket libraries treat it as a normal end: for example, when the service in the guest resets the connection, the server closes with 1001 and a reason starting with unavailable. Check the close code yourself.
Bidirectional streams
- Open
ServiceConnectionService/Connecttosession.endpoint. This is a Connect bidirectional stream over HTTP/2. - Send
open{target}as the first message. The target must be in the list granted to the session. After the server connects to the socket, it replies with oneconnectedmessage, and only then does data start to flow. - Send and receive raw bytes in
datamessages in both directions. Sendhalf_closeto stop writing; you cannot send request messages after that. Receivingeofmeans the peer has closed writing.
After both directions end, the RPC completes normally.
Connection limits
- A Workspace has at most 128 open service connections, and a node at most 1024, counting both paths together. Beyond that, a new connection fails with
resource_exhausted. - Both paths share the message size, dial timeout, and rate limit, and end the same way. See Limits and Notes of
/v1/service.
Connecting from a browser
Browsers trust only the system root certificates, while data-plane certificates are issued by an internal CA. A browser can connect directly only when a publicly trusted certificate sits in front of the data plane.
Without such an edge, use kibo workspace service bridge or the desktop viewer page. They turn the connection into a WebSocket on the local loopback. When the service in the guest is itself HTTP, use kibo workspace service http to proxy it directly on the local loopback; see Opening an HTTP service in a local browser.
Next steps
- Desktop: view and operate a desktop in a browser.
- Networking overview: which external addresses a Workspace can reach.
- Data plane: request session credentials for service connections.
- E2B application ports: reach ports in a sandbox through the E2B gateway.
Files
Upload, download, and delete files in the guest, and watch a directory for changes. The examples use the Go SDK, the E2B SDK, and kibo workspace file. Programs transfer file content over /v1/files and manage directories with FilesystemService; see With the API.
Desktop
A desktop Workspace runs a graphical desktop in the guest. You can view and operate it in a local browser, or script it with screenshots and keyboard and mouse input from kibo workspace desktop.