By the end of this tutorial, you will have an Energon host with dedicated D1 and R2 resources, separate hub and content origins, and an agent plugin bound to that deployment. An individual can run it for personal agent work; an organization can operate it for team handoffs. You need a Cloudflare Workers Paid account, control of two hostnames, and a GitHub fork. Complete the steps in order because the runtime identity, storage bindings, and install coordinates must agree before anyone connects.
Deploy an Energon host
Bind the runtime and plugin to one instance
Energon’s runtime and its agent plugin describe the same instance from opposite sides. Wrangler tells the Worker which origins and policies to expose; skill:init tells agents which origin and token environment to use. Establishing the operator-owned fork first keeps those names aligned and prevents users from installing the upstream placeholder plugin.
Prerequisites
- A fork whose
originpoints at a repository controlled by the instance operator. - Cloudflare Workers Paid and permission to create D1, R2, Access, and custom domains.
- Two distinct hostnames, such as
energon.company.exampleandcontent.energon.company.example. - A decision on allowed email domains, retention, token lifetime, and default write policy.
1. Install dependencies and create unique resources
Run these from the operator’s fork. The names remain energon because the checked-in deployment workflow expects them; the resources themselves must belong only to this instance.
npm install
npx wrangler r2 bucket create energon
npx wrangler d1 create energonCopy the D1 identifier printed by Wrangler into wrangler.toml:
[[d1_databases]]
binding = "DB"
database_name = "energon"
database_id = "PASTE_D1_DATABASE_ID_HERE"
migrations_dir = "migrations"
[[r2_buckets]]
binding = "BUCKET"
bucket_name = "energon"2. Render the instance plugin
Replace the three replace-... values before running this example. The slug must be lowercase kebab-case, and the repository must be the operator’s fork.
INSTANCE_SLUG=replace-with-instance-slug
INSTANCE_DOMAIN=replace.with.instance.domain
INSTANCE_REPO=replace-with-owner/energon
npm run skill:init -- \
--name "$INSTANCE_SLUG" \
--origin "https://energon.$INSTANCE_DOMAIN" \
--repo "$INSTANCE_REPO"
npm run skill:render -- --checkThe name identifies this deployment wherever an agent uses it. For example, --name personal produces personal-energon and PERSONAL_ENERGON_TOKEN, while --name acme produces acme-energon and ACME_ENERGON_TOKEN. Init writes the corresponding plugin directory, marketplace catalogs, and instance-skill.json. Commit those generated files in the fork.
3. Align Wrangler identity and policy
Set both origins and copy the rendered identity into [vars]. The content origin must be different from the hub origin.
[vars]
PUBLIC_ORIGIN = "https://energon.company.example"
CONTENT_ORIGIN = "https://content.energon.company.example"
TOKEN_ENV = "EXAMPLE_COMPANY_ENERGON_TOKEN"
SKILL_NAME = "example-company-energon"
MARKETPLACE_NAME = "example-company-energon"
MARKETPLACE_REPO = "example-org/energon"
ALLOW_UNLIMITED_RETENTION = "true"
DEFAULT_TTL = "never"
MAX_TTL = "never"
WRITE_POLICY = "instance"
ALLOW_UNLIMITED_TOKENS = "true"
ALLOWED_EMAIL_DOMAINS = "company.example"The values above illustrate a trusted organization configuration. A personal instance commonly keeps expiring content, owner-only writes, and finite tokens instead. Review Configure instance policy before copying either operating profile into a real deployment.
4. Attach domains and set Access paths
Attach both custom domains to the Worker. Put Cloudflare Access only on the human hub paths:
- Allow with sign-in:
/,/account*,/about,/stats,/setup,/tokens. - Bypass on the hub:
/v1*,/health,/llms.txt,/favicon.svg,/static*. - Bypass on the content hostname:
/{handle}/s/*and/{handle}/f/*.
Do not put Access on the content hostname. Agents need /v1 to remain reachable with API tokens, and public content URLs need to open without inheriting a human’s hub session.
5. Enable the guarded deployment workflow
Add these GitHub Actions secrets to the operator’s fork:
CLOUDFLARE_API_TOKEN
CLOUDFLARE_ACCOUNT_IDSet the repository variable ENABLE_PRODUCTION_DEPLOY to the exact string true. With it unset, pushes still run tests but do not deploy. On a push to main, the workflow generates types, typechecks, lints, runs unit and Worker tests, applies remote D1 migrations, and only then deploys the Worker.
6. Verify the instance
After the guarded workflow succeeds, use the configured hub origin:
curl -fsS https://energon.company.example/v1/health
curl -fsS https://energon.company.example/v1/helpThe health response should be {"ok":true}. In the help response, confirm the hub origin, rendered skill name, token environment, install line, retention policy, token lifetime policy, and capacity limits. Then open the hub in a browser and verify that Access admits only the intended personal identity or organization members.
Stop conditions
Never reuse another instance’s D1 database id or R2 bucket. If either binding points at shared storage, stop before deployment, create new operator-controlled resources, and update wrangler.toml.
Never deploy with the same hub and content origin. If the host reports content_origin_not_configured, attach a second custom hostname, set CONTENT_ORIGIN, and keep Access off that hostname.
Run skill:init only in the operator’s fork. If git remote origin still points at tmchow/energon, correct the remote or pass --repo replace-with-owner/energon, rerender, and commit the resulting marketplace files.
Migrations must run before the Worker deploys. Prefer the checked-in GitHub Actions job. Do not use a cloud agent to run wrangler login, modify d1_migrations, or execute ad hoc SQL against production.
Verify the complete boundary
The deployment is ready for use only when all five pieces agree: dedicated catalog and object storage, an Access-protected human hub, API-token agent routes, a separate content origin, and the instance plugin committed in the fork. Continue with Configure instance policy, and review Upgrade and recover before the first upstream merge.