Ports
Publish a guest port at its own https hostname — private by default, credential shown once.
A published port answers at its own https hostname, which reaches exactly that one port on exactly that one machine.
Expose
const preview = await machine.ports.expose(3000, { name: "dev-server" });
preview.url; // https://k3f9x2q7m1.preview.raster.sh
preview.access_url; // the one-shot credentialed link
preview.secret; // the raw secretpreview = machine.ports.expose(3000, name="dev-server")
preview["url"] # https://k3f9x2q7m1.preview.raster.sh
preview["access_url"] # the one-shot credentialed link
preview["secret"] # the raw secretThe port is the one inside the machine, not a host port. Nothing has to be listening yet — exposing before starting the server is the ordinary order, and the URL reports the machine as unavailable until something answers:
const preview = await machine.ports.expose(3000);
await machine.terminal.execShell("cd /tmp/site && python3 -m http.server 3000 &");preview = machine.ports.expose(3000)
machine.terminal.exec_shell("cd /tmp/site && python3 -m http.server 3000 &")Exposing a port that is already published returns the preview that exists rather than a second hostname for one service, so a retry converges.
Private by default
await machine.ports.expose(3000, { access: "public" }); // no credential at allmachine.ports.expose(3000, access="public") # no credential at allpublic is a deliberate act with a deliberate name. An agent that exposes a port so a person can
look at it should have to say that is what it meant, and someone reading a list should be able to
see which of their services are on the open internet without opening each one.
The secret is shown once
secret and access_url are present only in the response to the call that created the
preview. There is no way to read them afterwards — a value the product can hand back on request
is a value that lives in every log and cache the response passes through, exactly like an API key.
access_url trades the secret for a host-scoped cookie, which is what makes a private preview
openable in a browser at all: a person cannot set an Authorization header on an address bar.
List, get, unexpose
for await (const p of machine.ports.list()) console.log(p.port, p.url, p.last_request_at);
const one = await machine.ports.get(preview.id);
await machine.ports.unexpose(preview.id);for p in machine.ports.list():
print(p["port"], p["url"], p["last_request_at"])
one = machine.ports.get(preview["id"])
machine.ports.unexpose(preview["id"])On a later read, secret and access_url are null.
unexpose stops the URL immediately, and that hostname is never issued again. A hostname that
came back would resurrect every link and bookmark pointing at it, aimed at whatever that port
serves next.
Deployment requirement
Publishing needs a preview domain configured on the deployment, with wildcard DNS and a wildcard
certificate under it. Without one the API raises unsupported_operation rather than handing back a
URL that resolves nowhere.
Bytes served through a preview count as egress. See billing.