Overview

VM Networking

Oblien VMs 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 VM can reach any other VM - even within the same account. Network paths must be explicitly opened.

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


Network isolation by default

Every VM 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 VM can make outbound requests to the internet (install packages, call external APIs), but nothing can connect to it - not the gateway, not other VMs, not even VMs owned by the same account.

Inbound access requires explicit configuration:

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

How the firewall works

Each VM has a per-VM 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 VM 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 VM cannot reach the internet, other VMs, or any external service
  • Internal-only VMs that need to be called must receive inbound links instead

VM-to-VM communication

When VM A needs to call VM 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 vm 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 VM 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 VM A's ID to B's private_link_ids. The platform resolves A's VM 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 VM A can now reach B directly over the private network.

// Running inside vm 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 VM 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 VM 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 VM-to-VM

Agent orchestration

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

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

Microservice testing

Spin up separate VMs 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 VM. A central service VM connects to each tenant's VM 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 VM. The pipeline controller VM 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 (vm.oblien.com)Direct (10.x.x.x:9990)
FromAnywhere on the internetInside another VM
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 serversVM-to-VM 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 VM 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
  • Runtime API - Use the VM runtime APIs (files, exec, terminal, search)
  • Security & Privacy - Full isolation model, encryption, and operational security