Ports and previews
Expose ports when you create a microVM and reach each one on its own HTTPS preview URL, public or private, including WebSocket connections.
A microVM gets an HTTPS preview URL for every port you expose when you create it. Use one to show a dev server, a generated app or a tool's web interface to a person or to a browser test, with no tunnel or proxy of your own.
Expose a port
List the ports in ports when you create the microVM. Ports cannot be added later, so include every port the microVM will serve. A microVM without ports works normally; it has no preview URL.
import { MicroVM } from '@gigadrive/sdk';
const vm = await MicroVM.create({ image: 'python3.13', ports: [8000] });
await vm.spawn('python', ['-m', 'http.server', '8000', '--bind', '0.0.0.0']);
const url = await vm.waitForPort(8000);
console.log(url); // https://8000-k3x9q2m7a1bz.vm.gigadrive.appvm.url(port) returns the same URL without waiting, and throws MicroVmPortNotExposedError for a port that is not in ports.
A microVM can expose up to 8 ports, each between 1 and 65535. Ports 10000 and 10001 are reserved and refused.
The preview URL
Every preview URL has the form https://<port>-<slug>.vm.gigadrive.app. The slug is a random 12-character code assigned when the microVM is created. It is not derived from the microVM's ID, so a URL cannot be guessed from an ID or from another microVM's URL. The URL stops working when the microVM stops.
Preview URLs are public by default. Anyone who has the URL can reach the port, with no sign-in. To limit them to people and programs you give a token, create the microVM with private previews.
Private previews
Set network.previews to private when you create the microVM. Its preview URLs then answer only requests that carry its preview token, and every other request gets 401. The create response includes the token as previewToken. It is shown only there, so store it.
curl https://api.gigadrive.network/microvms \
-H "Authorization: Bearer $GIGADRIVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"image": "node22", "ports": [3000], "network": {"egress": "allow", "previews": "private"}}'A request can carry the token in two ways:
- In the
x-gigadrive-preview-tokenheader. Use this from code, tests and other servers. - Once, in the
gd_preview_tokenquery parameter. The URL answers with a redirect to itself without the parameter and sets a cookie for that one preview URL, so a browser stays signed in for 24 hours without the token staying in the address bar. Share a link such ashttps://3000-k3x9q2m7a1bz.vm.gigadrive.app/?gd_preview_token=<token>with the person who should see it.
Your server never receives the token: the header and the cookie are removed before a request reaches the microVM.
To revoke access, rotate the token with POST /microvms/{id}/preview-token. The response carries a new previewToken, and the old one stops working within a second. Rotating the token of a microVM with public previews answers 400.
The setting is fixed when the microVM is created. A microVM created from a snapshot takes the setting you pass, not the snapshot's.
Listen on every interface
Preview traffic reaches the microVM over its network interface, not over localhost. A server must listen on 0.0.0.0 or :: to be reachable. Many dev servers listen on localhost by default and need a flag, for example vite --host 0.0.0.0 or next dev --hostname 0.0.0.0.
Until a server is listening, its preview URL answers 502. vm.waitForPort(port) requests the URL until the server answers, then resolves with the URL, so call it before you hand the URL to a person or a test. It gives up after 60 seconds unless you pass timeout, and fails at once if the microVM has stopped.
WebSockets
Preview URLs carry WebSocket connections as well as HTTP. Connect with wss:// and the same address:
const socket = new WebSocket('wss://8000-k3x9q2m7a1bz.vm.gigadrive.app/socket');A preview connection closes after 5 minutes without traffic, and after 4 hours in any case. A WebSocket message can be at most 4 MiB. Each microVM takes up to 256 HTTP requests and 256 WebSocket connections at once across its ports; past that, new ones answer 429 with a retry-after header.
Errors
When the platform itself answers a preview request, it returns an error page that names one of these codes. Anything else comes from your own server.
| Status | Code | Cause |
|---|---|---|
401 | EDGE_MICROVM_PREVIEW_UNAUTHORIZED | The microVM has private previews and the request has no valid preview token |
404 | EDGE_MICROVM_NOT_FOUND | No microVM has this address, or it was deleted |
404 | EDGE_MICROVM_PORT_NOT_EXPOSED | The port was not in ports when the microVM was created |
410 | EDGE_MICROVM_STOPPED | The microVM has stopped or failed, and will never answer again |
429 | EDGE_MICROVM_CONNECTION_LIMIT | The microVM has too many open connections |
502 | EDGE_MICROVM_NOT_RUNNING | The microVM is still starting, or is stopping |
502 | EDGE_MICROVM_PORT_UNREACHABLE | The microVM is running, but nothing listens on the port |
504 | EDGE_MICROVM_TIMEOUT | Your server did not start a response in time |
The 401 and 410 responses also carry the header x-gigadrive-error with their code, so a client can tell them apart from a 401 or 410 your own server returns. Stop polling a URL that answers it and create a new microVM instead.
Outbound traffic
Ports control what can reach the microVM. What the microVM itself can reach is set by network at create, and you can change it later: { "egress": "allow" }, the default, allows the public internet, and { "egress": "deny" } blocks all outbound traffic. Use deny for untrusted code that must not call out. Private network ranges are always blocked, whichever you choose.
const vm = await MicroVM.create({ image: 'python3.13', network: { egress: 'deny' } });To let a microVM reach only the services it needs, list them in allow. Each entry is a domain name, such as registry.npmjs.org, or a public IPv4 network in a.b.c.d/n form. The microVM can reach those destinations and nothing else. Use it, for example, to let an agent's code install packages from one registry while every other destination stays closed.
curl https://api.gigadrive.network/microvms \
-H "Authorization: Bearer $GIGADRIVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"image": "node22", "network": {"egress": "allow", "allow": ["registry.npmjs.org", "*.github.com", "140.82.112.0/20"]}}'An entry that starts with *. covers every subdomain of the name: *.github.com allows codeload.github.com, but not github.com itself, so list both when you need both.
A domain is allowed through name resolution. When code in the microVM looks up an allowed name, the addresses in the answer become reachable. A lookup of any other name fails, and a connection to an address that no allowed name resolved to is blocked, so connect by name rather than by a hardcoded address. Several services can share one address, for example behind a CDN; while that address is reachable for an allowed name, the microVM can reach every service on it.
You can list up to 32 entries. The service refuses:
- a network that includes a private, loopback, link-local or other reserved range;
- a top-level wildcard such as
*.com; - a URL or a port: list
api.openai.com, nothttps://api.openai.com:443; - an allowlist together with
"egress": "deny".
Names are stored in lowercase, and the response shows the allowlist as network.allow.
Change outbound traffic while it runs
Replace a microVM's egress and allow with PATCH /microvms/{id}/network, for example to install dependencies with the internet open and then run untrusted code with egress denied. The body takes the same fields and rules as network at create, without previews:
curl -X PATCH https://api.gigadrive.network/microvms/0199a7c4-5b1e-7c3d-9f20-333333333333/network \
-H "Authorization: Bearer $GIGADRIVE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"egress": "deny"}'The response is the microVM with its new network. A running microVM keeps running, and the new rules apply before the call answers:
- Connections the microVM opened that the new rules no longer allow are closed. Connections they still allow continue.
- An allowed domain that the microVM already looked up stays reachable without a new lookup.
- Preview URLs, ports and connections to them do not change.
A paused microVM gets the new rules when it resumes. A microVM that is starting, pausing, resuming or stopped answers 409 with microvm_not_running. A microVM started before this update was available answers 409 with microvm_network_update_unavailable: pause it, send the update, then resume it.
