Go live
Deployment reference
Every owner input in detail, the checks a deploy runs, hosting on workers.dev and an independent heartbeat.
On this page
Lamp uses distinct public page and operator application hosts. Each has its own
home page: the page host's / is the company's public status page, and the app
host's / is the Lamp landing page beside sign-in and the operator app. Its deployment
commands provision a real D1 database, R2 bucket and Queue by environment name,
apply migrations, initialize the first operator and page settings, build the
Worker and publish the emitted artifact. rer deploy runs all of these;
pnpm run setup:cloudflare runs the provisioning alone. (pnpm run setup is the
local first-owner setup.)
Owner inputs
Supply CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN for the intended account.
The token needs Worker deployment, D1, R2, Queues and custom-hostname access,
including Zone Workers Routes read/write permission for both hosts’ zones.
Account Worker access alone can upload the artifact but cannot attach its hosts. Configure LAMP_PAGE_HOST, LAMP_APP_HOST,
LAMP_PAGE_NAME, LAMP_PAGE_TAGLINE, LAMP_PAGE_TIMEZONE, LAMP_ACCENT_COLOR,
SETUP_OPERATOR_EMAIL, MAIL_FROM_ADDRESS, MAIL_DKIM_SELECTOR,
MAIL_PROVIDER_API_KEY, SUBSCRIBER_TOKEN_SECRET and WEBHOOK_SIGNING_SECRET.
The two token secrets must each contain at least 32 characters. Keep their
original values when restoring so existing subscriber tokens and webhook
signatures remain valid. Store owner inputs outside committed source.
Optionally set OWNER_DISPLAY_NAME to the first owner's name (1–120 characters).
It is used only when setup creates the first operator; existing owners keep their
name and access. Without it, the native command retains its Setup operator name.
MAIL_PROVIDER selects resend (default, preserving existing deployments) or
sendgrid. Both use MAIL_PROVIDER_API_KEY; map an existing provider-specific
credential into that environment variable without writing it into source.
Likewise map the verified sender address into MAIL_FROM_ADDRESS. The sender
domain must publish SPF, DMARC and a DKIM key at the chosen selector. Setup checks
those records before provisioning. It does not prove DKIM's header coverage or
recipient delivery: verify those against a received message.
For SendGrid set SENDGRID_WEBHOOK_PUBLIC_KEY to its base64 P-256 public key and
configure the signed Event Webhook URL as
https://<LAMP_PAGE_HOST>/, with delivered, bounce, dropped
and spamreport events enabled. For Resend, set RESEND_WEBHOOK_SECRET and use the
same URL. Without the selected provider's verification key this endpoint rejects
callbacks; API acceptance alone does not mark recipient delivery.
SendGrid requests explicitly disable click, open, subscription and analytics
tracking. Verify the received message has no added tracking and that DKIM's h=
list covers List-Unsubscribe and List-Unsubscribe-Post before claiming one-click
mailbox-provider support. A provider setting or received message that fails these
checks is a release blocker, not a reason to claim the behavior locally.
Deployment and checks
pnpm install --frozen-lockfile
pnpm exec playwright install chromium
rer deploy --dry-run --environment staging
rer deploy --environment productionDry run compiles and validates generated configuration without changing Cloudflare. Real deploy first runs setup and verification. Setup does not create a placeholder Worker or publish secrets separately. Deploy writes a private temporary secrets file, publishes the real Worker with it, removes that file even after failure, then checks the application host's health with a bounded request. It checks real D1/R2/Queue reachability, not mail delivery. The public host must also be exercised with actual published content, subscription and signed provider receipts.
The GitHub workflow builds and retains lamp-worker-<commit> without deployment
credentials. node scripts/ packages a completed
pnpm build into delivery-artifact/: Worker modules and
static assets only, using the delivery service's ArtifactBundle schema. It does
not carry resource authority, secrets, migration instructions or trustworthy source
identity. The independent delivery service validates the run and retained bytes,
then applies the approved resource plan. Its authority must live outside the
editable application build job. Artifact creation alone does not deploy Lamp.
Direct owner deployment remains available with rer deploy.
Native workers.dev deployment
Custom domains remain the default. To use the account's existing Workers subdomain without custom DNS, set LAMP_HOSTING=workers-dev. Set LAMP_RESOURCE_PREFIX to an explicit lowercase resource namespace (letters, digits and hyphens, at most 47 characters). If omitted, it is lamp-<environment>; the environment defaults to production.
The app host is exactly <prefix>. and the page host exactly <prefix>-page., with your account's Workers subdomain as <subdomain>; any other names are refused. For a prefix my-status and the Workers subdomain my-account, set:
export LAMP_HOSTING=workers-dev
export LAMP_RESOURCE_PREFIX=my-status
export LAMP_APP_HOST=my-status.my-account.workers.dev
export LAMP_PAGE_HOST=my-status-page.my-account.workers.dev
rer deployConfigure the remaining inputs from the README deployment table before running these commands. Find the account subdomain in Cloudflare Workers settings; setup verifies it against the authenticated account before creating resources. It never changes account-level subdomain settings. The app Worker is named exactly the prefix; the public Worker adds -page. D1 adds -db, R2 adds -files, and the queue adds -jobs. The generated config records the supplied account ID. Deployment records preserve actual resource names for archive and sign-in commands.
Both Workers serve the same compiled source and retain the configured host checks: operator paths on the public hostname return 404, and operator APIs on the app hostname require a session. The app Worker owns the scheduled jobs, queue consumer and snapshot Durable Object. The public Worker uses that same object and storage without a second scheduler or consumer. The command deploys the app Worker first, then the public Worker. Keep the prefix reserved for this installation, and remove both Workers when retiring it.
This mode is supported by native rer deploy. The independent delivery artifact contract describes one Worker; it does not package this two-Worker topology.
Independent external heartbeat
Set LAMP_HEARTBEAT_URL to the public HTTPS ping URL of the owner's chosen external heartbeat service. It is off when omitted. Keep this capability URL secret. LAMP_ defaults to 5. Configure the service's expected interval and grace period to match; the service sends the alarm when pings stop. Choose the receiving mailbox and phone on infrastructure independent of this hosting provider.
The minute cron sends an empty GET only on the heartbeat interval grid, after scheduled work completes and /health verifies D1, R2 and Queue. Failed dependencies and the hosting-move EFFECTS_PAUSED=1 hold stop pings. No subscriber, incident, page, visitor or owner data travels. A successful ping establishes the service acknowledged that ping; it does not prove human receipt. This watch does not provide standby hosting.
This page is drawn from OPERATIONS.md in the repository. Edit it on GitHub.