Overview

Workspace Networking

Oblien workspaces run as isolated microVMs. Each VM gets its own virtual network interface and private IP on the 10.x.x.x internal network. By default, no workspace can reach any other workspace - even within the same account. Network paths must be explicitly opened.

This page explains the isolation model, how to connect workspaces, and when direct VM-to-VM communication is useful.


Network isolation by default

Every workspace starts network-dark on the inbound side:

SettingDefaultEffect
ingress[]No inbound sources allowed
ingress_ports[]No inbound ports open
public_accessfalseGateway/internet cannot reach the VM
allow_internettrueOutbound internet is allowed
egress[]Unrestricted outbound (when internet is on)

This means a freshly created workspace can make outbound requests to the internet (install packages, call external APIs), but nothing can connect to it - not the gateway, not other workspaces, not even workspaces owned by the same account.

Inbound access requires explicit configuration:

  • Gateway access (external) → enable public_access: true + open port
  • Workspace-to-workspace (internal) → create a private link + open port

How the firewall works

Each VM has a per-workspace firewall enforced at the host level. The firewall controls:

Ingress (inbound)

Traffic is dropped unless all of the following match:

  1. Source is in the ingress list - either a specific IP, a CIDR range, or the host keyword (set automatically when public_access: true)
  2. Port is in the ingress_ports list - only ports you explicitly open are reachable

If either condition fails, the connection is dropped. The workspace is invisible to the caller.

Egress (outbound)

When allow_internet is true:

  • All outbound traffic is allowed by default
  • If egress contains entries, only those hosts are reachable
  • DNS resolution still works regardless of egress rules

When allow_internet is false:

  • All outbound traffic is blocked
  • The workspace cannot reach the internet, other workspaces, or any external service
  • Internal-only workspaces that need to be called must receive inbound links instead

Workspace-to-workspace communication

When workspace A needs to call workspace B (run commands, read files, query an API), you set up a private link from A to B. This is a directed network rule - it tells B's firewall to accept connections from A's IP.

Setup flow

1. Enable the internal server on workspace B
2. Create a private link: A → B (on B's network config)
3. Get B's raw connection token and private IP
4. From inside A, call B directly at http://10.x.x.x:9990

What happens at each step

Step 1 - Enable the server on workspace B. This starts the HTTP server on port 9990 inside B's VM and automatically opens port 9990 in B's ingress_ports.

await ws.apiAccess.enable('ws_b');

Step 2 - Create a private link. Add workspace A's ID to B's private_link_ids. The platform resolves A's workspace ID to its internal IP and adds it to B's firewall ingress list.

await ws.network.update('ws_b', {
  private_link_ids: ['ws_a'],
});

Step 3 - Get the connection details. Retrieve B's raw token and private IP so A can authenticate.

const raw = await ws.apiAccess.rawToken('ws_b');
// raw.token = "a1b2c3d4e5f6..."
// raw.ip = "10.40.0.12"
// raw.port = 9990

Step 4 - Call from inside A. Code running inside workspace A can now reach B directly over the private network.

// Running inside workspace A
const res = await fetch('http://10.40.0.12:9990/exec', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${raw.token}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ cmd: ['npm', 'test'] }),
});

What's protected

LayerProtection
NetworkFirewall drops traffic unless source IP is in ingress and port is in ingress_ports
AuthenticationEvery request requires Authorization: Bearer <token> - even on the private network
DirectionLinks are one-directional. A → B does not imply B → A
IsolationVMs run in separate KVM instances. No shared memory, filesystem, or process space
ResolutionYou send workspace IDs, not raw IPs. The platform resolves and configures the firewall automatically

Adding ws_a to B's private_link_ids means A can reach B. It does not mean B can reach A. If you need bidirectional communication, create links in both directions:

// A can reach B
await ws.network.update('ws_b', { private_link_ids: ['ws_a'] });

// B can reach A
await ws.network.update('ws_a', { private_link_ids: ['ws_b'] });

A workspace can receive connections from multiple sources:

await ws.network.update('ws_target', {
  private_link_ids: ['ws_agent_1', 'ws_agent_2', 'ws_orchestrator'],
});

The firewall adds all resolved IPs to the ingress list. Any of them can reach the target.


When to use workspace-to-workspace

Agent orchestration

An orchestrator workspace delegates tasks to worker workspaces. Each worker runs in its own isolated VM - a task crash or resource exhaustion doesn't affect the orchestrator or other workers.

Orchestrator (ws_orch)
  ├── Worker A (ws_a) - running tests
  ├── Worker B (ws_b) - building container
  └── Worker C (ws_c) - deploying

The orchestrator creates private links to each worker, sends commands via the Exec API, and streams output via SSE.

Microservice testing

Spin up separate workspaces for frontend, backend, and database. Link them together and test the full stack with real network boundaries - not localhost aliases.

Multi-tenant isolation

Give each tenant their own workspace. A central service workspace connects to each tenant's workspace on demand, runs operations, and disconnects. Tenants never see each other's IPs or data.

CI/CD pipeline stages

Each pipeline stage runs in a separate workspace. The pipeline controller workspace links to each stage, pushes code, runs builds, and collects artifacts - each stage is fully isolated and disposable.


Gateway vs. direct - when to use which

Gateway (workspace.oblien.com)Direct (10.x.x.x:9990)
FromAnywhere on the internetInside another workspace
LatencyHigher (gateway decodes JWT, routes to VM)Lower (direct TCP, no intermediary)
AuthGateway JWT (signed, contains routing info)Raw connection token (simple hex string)
Network requirementpublic_access: true on targetPrivate link from caller to target
Use caseExternal apps, SDK, CI/CD, MCP serversWorkspace-to-workspace orchestration
IP exposureNever - JWT embeds the IP internallyYou get the IP from the raw token endpoint

Use the gateway when calling from outside the Oblien network (your app, CI pipeline, local development). Use direct connections when calling from inside another workspace for lower latency and no gateway overhead.


Further reading

  • Network API - Configure firewall rules and private links
  • API Access - Enable the internal server and manage tokens
  • Internal API - Use the workspace runtime APIs (files, exec, terminal, search)
  • Security & Privacy - Full isolation model, encryption, and operational security