Self-host the hub
Deploy to Cloudflare
Create the D1 database, R2 bucket, Durable Objects, and cron trigger, set secrets, and deploy the hub Worker.
This page creates everything the hub needs in your Cloudflare account. You will come back to set the GitHub and Slack secrets after creating those apps.
Prepare
-
Clone the repository and install dependencies. The hub lives in the
hub/directory.git clone https://github.com/KCuppens/hookci.git cd hookci/hub npm ci -
Log in to Cloudflare.
npx wrangler login -
Create the D1 database. Wrangler prints a
database_id. Copy it.npx wrangler d1 create hookci-hub -
Create the R2 bucket for logs.
npx wrangler r2 bucket create hookci-logs
Configure wrangler.toml
Check hub/wrangler.toml in the repository for the exact file. It must define these bindings. Names the code relies on are DB, LOGS, AGENT_DO, and SLACK_DO. Resource names such as hookci-hub and hookci-logs are your choice.
name = "hookci-hub"
[[d1_databases]]
binding = "DB"
database_name = "hookci-hub"
database_id = "<your-database-id>"
[[r2_buckets]]
binding = "LOGS"
bucket_name = "hookci-logs"
[durable_objects]
bindings = [
{ name = "AGENT_DO", class_name = "AgentDO" },
{ name = "SLACK_DO", class_name = "SlackDO" },
]
[triggers]
crons = ["*/5 * * * *"]
Durable Object classes need a migration entry the first time they are deployed. If the repository’s wrangler.toml already has a [[migrations]] block for AgentDO and SlackDO, keep it unchanged. Wrangler’s new_sqlite_classes versus new_classes choice must match the repository, so do not change it.
The cron trigger runs every 5 minutes. Keep the schedule as shipped.
Apply database migrations
Migrations are SQL files in the repository. Check the migrations directory name in wrangler.toml (migrations_dir) if it is not the default.
npx wrangler d1 migrations apply hookci-hub --remote
Run the same command after every upgrade. See Operations.
Secrets
Set each secret with wrangler secret put NAME. Wrangler prompts for the value.
| Secret | What it is | Where it comes from |
|---|---|---|
GITHUB_APP_ID |
GitHub App ID | GitHub App settings page |
GITHUB_APP_PRIVATE_KEY |
App private key (PEM) | Generated on the GitHub App page |
GITHUB_CLIENT_ID |
App OAuth client ID | GitHub App settings page |
GITHUB_CLIENT_SECRET |
App OAuth client secret | GitHub App settings page |
GITHUB_WEBHOOK_SECRET |
Webhook signing secret | Value you chose when creating the app |
SLACK_CLIENT_ID |
Slack OAuth client ID | Slack App Basic Information |
SLACK_CLIENT_SECRET |
Slack OAuth client secret | Slack App Basic Information |
SLACK_SIGNING_SECRET |
Slack request signing secret | Slack App Basic Information |
TOKEN_ENC_KEYS |
Key ring for encrypting stored tokens | Generate yourself |
STATE_SIGNING_KEY |
Key for signing OAuth state | Generate yourself |
LOG_SIGNING_KEYS |
Key ring for signing log links | Generate yourself |
Generate the random values with openssl.
openssl rand -base64 32
TOKEN_ENC_KEYS and LOG_SIGNING_KEYS are key rings, so they hold more than one key to allow rotation. Check the hub source (search for the variable names in hub/src) for the exact list format before setting a value. Operations covers rotation.
npx wrangler secret put TOKEN_ENC_KEYS
npx wrangler secret put STATE_SIGNING_KEY
npx wrangler secret put LOG_SIGNING_KEYS
The GitHub and Slack values do not exist until you create those apps. A Worker deploy does not require secrets to exist, so deploy first, then create the apps, then set their secrets.
Deploy
npx wrangler deploy
Wrangler prints the Worker URL, for example https://hookci-hub.<your-subdomain>.workers.dev.
Custom domain
A stable hostname is better than workers.dev because the GitHub App, the Slack App, and every agent store it. Add a custom domain or a route in the Cloudflare dashboard (Workers, your Worker, Settings, Domains and Routes), or declare it in wrangler.toml.
routes = [
{ pattern = "hub.example.com", custom_domain = true },
]
The domain’s zone must be on your Cloudflare account. Use that URL, for example https://hub.example.com, as the hub URL in the next steps.
Continue with GitHub App.