MetorialDocs

Networking

Expose ports with access tokens or publicly, and restrict outbound traffic with firewalls.

Servers inside a machine are reachable over HTTPS, either with a short-lived access token or publicly. Outbound traffic is open by default, and firewalls let you limit it to the addresses you allow.

What you'll learn

  • How to reach a port with an access token
  • How to make a port public
  • How to restrict outbound traffic with firewalls

Before you start

Reach a port

Every port gets its own HTTPS URL. Your server must listen on 0.0.0.0, since servers bound to localhost can't receive outside traffic.

By default, a port only accepts requests that carry an access token in the Metorial-Sandbox-Token header. Generate a token and the URLs for the ports you need:

metorial-admin sandbox machines access ports $MACHINE --ports '[3000]' --ttl-seconds 3600

Use --ports '"*"' to get a token that works for every port.

{
  "object": "sandbox.machine.access",
  "token": "…",
  "ports": [3000],
  "urls": {
    "ports": { "3000": "https://<machine-host>.metorial.run" }
  },
  "expires_at": "2026-10-16T15:00:00.000Z"
}
curl -H "Metorial-Sandbox-Token: $TOKEN" https://<machine-host>.metorial.run/health

Tokens last one hour by default and up to 24 hours. In the dashboard, open the machine and use Generate URL to get a link for a port.

Tip

The SDK's connect() adds and refreshes the token for you. See Connect with the SDK.

Make a port public

Public ports accept requests without a token. Use them for webhooks, previews you share with people, or anything else that can't send a header.

metorial-admin sandbox machines update $MACHINE --public-ports '[3000]'
await metorial.sandbox.machines.update(machineId, { publicPorts: [3000] });

The port keeps the same URL. Anyone with the URL can reach it, so put your own authentication in front of anything sensitive. To make the port private again, update public_ports without it.

Restrict outbound traffic

Machines can reach any public address on the internet until you attach a firewall. A firewall bundles one or more network policies, and each policy holds rules. You can reuse the same firewall across many machines.

Once a machine has a firewall, outbound traffic is denied unless an allow rule matches it. When rules overlap, the one with the higher priority decides, so a deny rule can carve exceptions out of a broader allow rule. Private, loopback, link-local, and reserved addresses are always blocked, with or without a firewall.

Create a network policy

This policy allows HTTPS to GitHub's address range:

metorial-admin network policies create --name allow-github --rules '[
  {
    "effect": "allow",
    "direction": "egress",
    "cidrs": ["140.82.112.0/20"],
    "ports": [{ "from": 443, "to": 443 }],
    "description": "GitHub over HTTPS"
  }
]'

Save the policy ID from the output as POLICY.

Create a firewall

metorial-admin network firewalls create --name agent-egress --network-policy-ids $POLICY

Save the firewall ID as FIREWALL. Pass several policy IDs separated by commas to combine them.

Attach it to a machine

metorial-admin sandbox machines update $MACHINE --firewall-ids $FIREWALL

The rules apply to running machines right away, without a restart. Pass --firewall-ids to machines create to start a machine with a firewall from the first boot.

In the SDK, attach firewalls you've created with firewallIds (firewall_ids in Python) on machines.create or machines.update.

Rule fields

FieldDescription
effectallow or deny
directionegress for outbound traffic. Machines ignore ingress rules.
cidrsIP ranges in CIDR notation. Domain names aren't supported.
portsPort ranges as { "from": 443, "to": 443 }. Leave out to match every port.
priorityHigher numbers win when rules overlap
enabledTurns a rule off without deleting it
descriptionA note for your team

The firewalls on a machine can open at most 98 address ranges in total, and each port range on an address counts separately. To allow all outbound traffic again, detach the firewall or add an allow rule for 0.0.0.0/0 and ::/0 on every port.

Firewalls belong to Network Access and also protect integrations and providers. List the firewalls on a machine with metorial-admin network firewalls list --machine-id $MACHINE.