HotupdaterHot Updater
OperateConsole deployment

Cloudflare

Deploy the console on Workers using your existing D1 database and R2 bucket.

Prerequisites

Complete Basics first. This guide uses native D1/R2 bindings.

Copy the Worker example

cp examples/cloudflare/console.config.ts.example console.config.ts
cp examples/cloudflare/wrangler.jsonc wrangler.jsonc

Build the configuration from the Worker's bindings for each request, with d1Database and r2Storage from @hot-updater/cloudflare/worker. Import apiKeys, insights, and remoteConfig from @hot-updater/server/plugins, and set plugins: [apiKeys(), insights(), remoteConfig()] to match the managed server. Install these runtime packages:

npm install @hot-updater/cloudflare @hot-updater/server

Then sign in to Wrangler, which the console repository includes:

npx wrangler login
npx wrangler whoami

Connect your resources

Edit the root wrangler.jsonc using your existing OTA backend's values:

FieldSet to
nameA new console Worker name
account_idYour Cloudflare account ID
vars.BETTER_AUTH_URLYour public console HTTPS origin
vars.BUCKET_NAMEYour existing R2 bucket name
d1_databases[0]Your existing D1 database name and ID
r2_buckets[0].bucket_nameThe same R2 bucket name

The default origin is https://<worker-name>.<account-subdomain>.workers.dev. Register its OAuth callback, or use your custom domain consistently.

To find resource names and IDs:

npx wrangler d1 list
npx wrangler r2 bucket list

Reuse the existing production resources; no new database or console-specific migration is needed. Local preview uses a separate database that needs initialization below.

Add secrets

Create the ignored .secrets.production.json:

.secrets.production.json
{
  "BETTER_AUTH_SECRET": "REPLACE_WITH_RANDOM_SECRET",
  "HOT_UPDATER_CONSOLE_ALLOWED_EMAILS": "owner@example.com",
  "GITHUB_CLIENT_ID": "REPLACE_WITH_CLIENT_ID",
  "GITHUB_CLIENT_SECRET": "REPLACE_WITH_CLIENT_SECRET"
}

Fill the values from sign-in setup.

chmod 600 .secrets.production.json

For Google, replace the GitHub pair in this file and wrangler.jsonc → secrets.required.

Build and deploy

npm run cf:typegen
npm run test:type
npm run build:cloudflare
npx wrangler deploy --dry-run
npm run test:cloudflare
npx wrangler deploy --secrets-file .secrets.production.json

Wrangler reports the deployed URL. Open it and follow Verify the deployment.

Edit only the root Wrangler config, then rebuild. Deployment uses Nitro's generated config automatically; do not pass the root file with --config.

Local preview

Copy the example and fill in local OAuth credentials, secrets, and BETTER_AUTH_URL=http://localhost:3000:

cp examples/cloudflare/.dev.vars.example .dev.vars
npm run build:cloudflare
npx wrangler d1 execute DB --local --file node_modules/@hot-updater/cloudflare/sql/bundles.sql
npm run preview:cloudflare

Run these commands from the console checkout root. The SQL file ships with @hot-updater/cloudflare and initializes the local DB binding that preview uses with the tables of core, Insights, API keys, and Remote Config. For a server with other plugins, apply the migration that hot-updater db generate writes for them instead. Repeat initialization if you clear the local Wrangler state.

Register the localhost OAuth callback. Preview uses separate local D1/R2 data by default; it does not copy production bundles or reports. See D1 local development.

See Nitro on Cloudflare and Worker secrets.

On this page