Skip to content

Guides

Ports and private URLs

Expose a machine's ports as HTTPS URLs, keep them private with short-lived tokens, or make them public.

On this page

Any TCP port in a running machine can be served at its own HTTPS address:

text
https://<label>-<port>.<edge domain>

label is 12 random characters given to the machine the first time it exposes a port. It never changes and is never reused, even after the machine is deleted, so a URL can never reach a different machine. VMYard's edge terminates TLS and forwards to the machine; the machine is never reachable directly.

Expose a port

sh
curl -X POST "$VMYARD_API_URL/v1/machines/$MACHINE_ID/ports" \
  -H "Authorization: Bearer $VMYARD_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"port": 8080}'
FieldMeaning
port1–65535, except 22 (use an SSH key for SSH).
publictrue serves the URL to anyone. The default, false, requires a token.
localhosttrue also reaches a service that listens only on 127.0.0.1 or [::1] inside the machine.

Exposing is an operation; the port is open once it succeeds. Exposing a port that is already open replaces its public and localhost settings. A machine can have up to 16 exposed ports (409 port_limit_reached).

List ports

sh
curl "$VMYARD_API_URL/v1/machines/$MACHINE_ID/ports" \
  -H "Authorization: Bearer $VMYARD_API_KEY"
json
{
  "label": "k7f2mq3x9a1b",
  "items": [
    { "port": 8080, "public": false, "localhost": false, "url": "https://k7f2mq3x9a1b-8080.on.example.com" }
  ]
}

The list shows ports as the machine's host last confirmed them. Any member and any API key preset can read it.

Open a private port

Private ports need a token. Ask for one, valid for 1 to 3,600 seconds (900 by default):

sh
curl -X POST "$VMYARD_API_URL/v1/machines/$MACHINE_ID/ports/8080/token" \
  -H "Authorization: Bearer $VMYARD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ttl_seconds": 900}'
json
{
  "url": "https://k7f2mq3x9a1b-8080.on.example.com",
  "url_with_token": "https://k7f2mq3x9a1b-8080.on.example.com/?_token=v1.…",
  "header_token": "v1.…",
  "expires_at": "2026-10-12T06:06:01Z"
}
  • In a browser, open url_with_token. The edge checks the token, sets a cookie scoped to that one host, and redirects to url so the token leaves the address bar.
  • From code, send the token in a header:
sh
curl https://k7f2mq3x9a1b-8080.on.example.com/health \
  -H "X-Vmyard-Token: $HEADER_TOKEN"

A token opens only the one machine and port it was issued for and stops working at expires_at. Missing credentials get 401 from the edge; invalid or expired ones get 403. VMYard doesn't store tokens; issuing one is recorded with its port and expiry. Asking for a token for a port that isn't exposed is 404 port_not_exposed.

What the edge forwards

  • HTTP/1.1 requests, streamed responses (server-sent events, long polls), and WebSocket upgrades.
  • The edge sets X-Forwarded-For, X-Forwarded-Proto, and X-Forwarded-Host, and removes the token cookie and header before forwarding.
  • Idle connections close after 5 minutes without traffic by default.

Close a port

sh
curl -X DELETE "$VMYARD_API_URL/v1/machines/$MACHINE_ID/ports/8080" \
  -H "Authorization: Bearer $VMYARD_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"

Closing a port that isn't exposed makes the operation fail. Deleting a machine closes all of its ports.

Access

Exposing, closing, and issuing tokens need a running machine and Owner, Admin, or Operator access (or a use_existing key). Port changes that fail emit operation.failed; successful ones emit no webhook.