Beachball

Configuration

The root secret

The scheduler needs one secret, BEACHBALL_SECRET: at least 32 characters of random data, for example openssl rand -base64 32. Everything else derives from it with HMAC-SHA-256:

Derived valueUsed for
Internal object keyAuthenticates requests between Durable Objects
Credential issuer keyIssues host credentials at enrollment
Connection-signing keyEd25519 key that signs private-network connection grants
Bootstrap credentialAdministrator and default client when no identities are configured
Default ULA prefixRFC 4193 /48 for private networks when none is configured

celld 0.5 and later have no secret store, so the secret and the manifest travel as Wrangler vars in the deployed config: node scripts/scheduler-deploy-config.mjs --secret-file FILE [--manifest FILE] writes scheduler/.deploy.wrangler.json for celld deploy; delete it afterwards. The value is then stored in the deployment record in the fleet bucket, whose credentials already grant control of the whole fleet. pnpm dev does this for you.

Rotating the root secret rotates all of them: hosts must join again and clients must fetch the new connection verification key. The public verification keys are published at GET /v1/.well-known/beachball.

The deployment manifest

DEPLOYMENT_MANIFEST is optional JSON. Every key is optional; unknown keys are rejected so that a typo fails loudly. An empty manifest ({}) and no manifest are the same deployment.

KeyDefaultNotes
region"default"Hosts join this region.
deploymentId"beachball"
releaseVersion"development"Included in exported alerts.
publicApiOriginnoneWhen set, readiness also probes this origin's celld health.
admissionsEnabledtrue
bootstrapCredentialtrue when no controllers and no operators are configured
controllers[]Client identities; see below.
operators[]Operator identities; see below.
workloadClassesone default classSee below.
hostEnrollment.autoActivatetruefalse keeps new hosts draining until bb host activate.
images.manifestBaseUrlnoneWhere hosts fetch signed image manifests; hosts can also set it.
images.trustedPublicKeys[]Image-signing keys hosts trust.
images.allowOcitrueAccept container image references (ubuntu:26.04) that hosts build themselves; false accepts only signed images.
images.registryUrlnoneThe image registry (ADR 0008); classes with registryImages ask it who may boot an image.
networking.ulaPrefixderived
networking.dnsServers[]Private IPv6 resolvers.
networking.additionalVerificationKeys[]Retired signing keys clients should still accept.
networking.relayno relays, not requiredPacket relay fallback.
limits.*10 000 allocations, 1 000 hosts, 100 requests/s, 64 KiB payloads
retention.*30 days (hosts: 90)
health.healthyHeartbeatSeconds / lostHeartbeatSeconds30 / 90
metricsfalsePer-request API metrics in the operations object.
auditSinknoneWithout a sink, audit records stay in the scheduler.
alertDestinations[]

Identities

A controller (client) needs only clientId and the SHA-256 of its token:

{ "controllers": [{ "clientId": "ci", "sha256": "…" }] }

tenantId defaults to the clientId, allowedWorkloadClasses to ["*"], and the credential never expires unless expiresAt is set. Operators need operatorId and sha256; role defaults to administrator.

Workload classes

A class needs only a name. Omitted fields take the default class values:

FieldDefault
cpuMillis / memoryMiB / ephemeralDiskMiB1000 / 1024 / 4096
maxCpuMillis / maxMemoryMiB / maxEphemeralDiskMiBthe class values; the built-in default class allows up to 64 000 / 256 GiB / 1 TiB
imageRefnone: requests name an image
pinImagefalse: requests may choose another signed image
maxLifetimeSeconds / clientLeaseSeconds86 400 / 600
allowedClients / allowedNetworks["*"]
privateIngresstrue
registryImagesfalse: an image other than imageRef needs no registry check
platformEndpoints[]: host services reachable at the guest gateway, such as registry (ADR 0008)

A request may set image, cpuMillis, memoryMiB, and ephemeralDiskMiB up to the class maximums. An image is either a signed Beachball image (name@sha256:<digest>, a single-segment name) or a container image reference, which a host that joined with --oci-kernel pulls and builds with its own signing key. Hosts boot only images signed by a key they trust; set pinImage: true to restrict a class to its imageRef, or images.allowOci: false to refuse container references. A class with registryImages: true also boots images the image registry converted, but only those it says belong to the caller's tenant.

Production

A production deployment typically adds explicit controllers and operators (which turns the bootstrap credential off), a stable networking.ulaPrefix, images, an auditSink, and alertDestinations. deploy/production-manifest.example.json shows every section.

On this page