Skip to main content
The key server can run on Cloudflare Workers instead of Docker. Workers deploy to 300+ edge locations, giving viewers sub-50ms key fetch latency worldwide — without managing containers.

When to use Workers

Quick start

Install the keys package:
Create your Worker:
Deploy with Wrangler:

Full example with authentication

Wrangler configuration

Never put MASTER_KEY or SALT in wrangler.toml. Use wrangler secret put to store them as encrypted secrets.

Endpoints

The Worker key server exposes:
The Worker key server does not include lease or presign endpoints. For leases, implement a KV-backed LeaseStore (see below). For presigned uploads, add a custom presign route (see Presign Endpoint below).

Leases on Workers

The in-memory LeaseStore does not work on Workers — each isolate has independent memory and does not share state across requests. Use Cloudflare KV or Durable Objects instead.

KV-backed lease store

Add the KV binding to wrangler.toml:

Presign endpoint

The Docker key server bundles a presign endpoint for browser uploads. On Workers, you add a custom presign route alongside the key server. The Uploader SDK requires a presignUrl to upload encrypted segments from the browser.

Use aws4fetch, not the AWS SDK

@aws-sdk/s3-request-presigner (~500 KB) does not work in Cloudflare Workers — it depends on Node.js APIs. Use aws4fetch (~2.5 KB) instead.

Full Worker with presign

This example composes createWorkerKeyServer() with a custom presign route for R2:
The presign endpoint above has no authentication — any browser from a CORS-allowed origin can generate presigned PUT URLs. This is intentionally simplified for the example. Production deployments should add an Authorization check before generating URLs.
Do not include Content-Type in the signing request headers when generating presigned URLs. Browsers may add unsigned headers to the actual PUT request, breaking the signature.

Wrangler configuration (with presign)

Deployment steps

  1. Install dependencies:
  1. Store secrets (one at a time — wrangler prompts for the value):
  1. Deploy:
  1. Verify:

How env works on Workers

Cloudflare injects env as the second argument to your Worker’s fetch handler. Values come from two sources:
  • [vars] in wrangler.toml — for non-sensitive configuration (bucket name, account ID, CORS origins)
  • wrangler secret put — for sensitive values (master key, salt, R2 credentials). Stored encrypted, not in source control.
Both are accessed the same way: env.R2_BUCKET_NAME, env.MASTER_KEY, etc.

Differences from Docker

Player configuration

The player connects to a Worker key server the same way as Docker — just point to the Worker URL:

Storage: R2

Cloudflare R2 is S3-compatible object storage with no egress fees — ideal for serving encrypted video segments. When paired with Workers, it gives you a fully Cloudflare-native deployment.

Create an R2 bucket

Enable public access

Encrypted segments need to be publicly readable so the player can fetch them:
  • r2.dev subdomain (simplest): Enable in R2 → your bucket → Settings → Public access. Segments are accessible at https://<bucket>.<accountId>.r2.dev/<key>.
  • Custom domain (production): Add a CNAME record pointing to your R2 bucket under R2 → your bucket → Settings → Custom domains.

R2 API credentials

The presign endpoint above needs S3-compatible credentials:
  1. Go to R2 → Manage R2 API Tokens → Create API Token
  2. Select Object Read & Write permission, scoped to your bucket
  3. Save the Access Key ID and Secret Access Key
  4. Store them as Worker secrets: wrangler secret put R2_ACCESS_KEY_ID and wrangler secret put R2_SECRET_ACCESS_KEY

CORS for browser uploads

When the Uploader SDK uploads encrypted segments from the browser via presigned URLs, R2 must allow the cross-origin PUT request:
For local development, add http://localhost:5173 (or your dev server port) to the origins array. Remove it before deploying to production.
For CLI uploads to R2 and caching guidance, see blindcast upload and CDN Configuration.

When to choose Docker instead

Use the Docker key server when:
  • You prefer the bundled presign endpoint (Workers require a custom route — see above)
  • You want SQLite or Postgres lease storage without custom code
  • You’re already running containers and don’t need edge latency
  • You need all endpoints in a single deployment