Beachball

Connect to a private VM

Use bb proxy to forward a loopback TCP port to a private allocation address. The client and the host terminate one userspace WireGuard session. They try direct UDP first and use an authorized opaque packet relay when direct UDP fails.

Prepare a Network and allocation

Create a Network:

bb network create --name development

Create an allocation in that Network:

bb allocation create \
  --class ephemeral-linux-x64-medium \
  --network NETWORK_ID \
  --max-lifetime 30m \
  --wait ready

The workload class must enable private ingress. bb allocation get ALLOCATION_ID shows the private IPv6 address and current generation.

Forward one TCP port

Map local port 2222 to TCP port 22 in the VM:

bb proxy ALLOCATION_ID --local-port 2222 --remote-port 22

The command generates an ephemeral WireGuard key, requests a signed connection grant, publishes its UDP candidate, and listens on 127.0.0.1:2222. It does not create an operating-system interface or require root access.

Connect from another terminal:

ssh -p 2222 ubuntu@127.0.0.1

Press Ctrl+C to close the listener and revoke the connection grant. If the scheduler is unavailable, both endpoints remove the connection when the signed grant expires.

To bind a non-loopback local address, pass --expose-local-network and confirm the address. This option exposes the forwarded port to machines that can reach that address.

Configure the client verification key

Each client profile that uses bb proxy must trust the scheduler connection-signing key:

[profiles.production-client]
endpoint = "https://scheduler.example"
audience = "client"
credential_file = "/home/alice/.config/beachball/client.token"
candidate_discovery_endpoints = ["stun.example.net:3478"]

[[profiles.production-client.connection_verification_keys]]
key_id = "connection-signing-2026-01"
public_key = "BASE64URL_ED25519_PUBLIC_KEY"

The CLI rejects an unknown signing key, a changed signature, a mismatched allocation or client key, a different transport or port, and an expired grant.

Check the guest listener

The guest service must listen on the private IPv6 address or the IPv6 wildcard address. For SSH, run this command inside the VM:

ss -lnt

The output must include the allocation address on port 22 or [::]:22. The private connection does not translate traffic to an IPv4-only listener.

Resolve connection failures

If bb proxy returns ALLOCATION_NOT_READY, wait until the allocation becomes ready. If it returns PRIVATE_INGRESS_FORBIDDEN, select a workload class that permits private ingress.

For a timeout, check these conditions:

  1. Confirm that the allocation remains ready at the same generation.
  2. Confirm that the guest listens on IPv6 and on the granted port.
  3. Confirm that the host UDP endpoint or a configured packet relay is reachable.
  4. Confirm that the connection grant has not expired or been revoked.

Each Network is a separate tenant authorization and IPv6 routing boundary. The current connection-grant API covers client-to-VM private ingress. Configurable VM-to-VM grants remain outside this release.

On this page