Cloudflare Worker Handbook¶
This document serves as the official handbook for the qubital-upload-pipeline Cloudflare Worker configuration. Its purpose is to listen for webhooks from a LiveKit instance, process egress_ended events received, retrieve recorded video files from a Cloudflare R2 bucket, and upload them to YouTube, updating Google Sheets and Slack upon success.
This handbook covers project structure, deployment, configuration, and troubleshooting common issues.
1. Overview¶
Project Structure
The project is a pnpm monorepo with the following key components:
- package.json (Root): Contains workspace definitions and high-level scripts for deploying specific workers
- pkg/upload-worker/: The directory for this specific worker
- package.json: Defines worker-specific dependencies and scripts. The name field here is what pnpm --filter uses
- wrangler.toml: Configuration for the deployed worker service name, compatibility dates, and local-only variables
- pkg/shared/: A shared library for common code like types and middleware
2. Prerequisites & Credential Gathering¶
Wrangler is the official CLI tool for managing Cloudflare Workers. It is a devDependency in our project, so it will be installed automatically with our other project dependencies.
Requirements: - Node.js (≥22) - pnpm package manager
2.1. Cloudflare¶
-
Cloudflare Account: You need an active account.
-
R2 Bucket: Go to R2 in the dashboard and create a new bucket (e.g., my-project-recordings) with default options. Note the bucket name.
-
R2 API Token:
-
Go to R2 → Manage R2 API Tokens
- Click Create API Token
- Give it a name and select Read & Write permissions
- Click Create API Token and copy the Account ID, Access Key ID, and Secret Access Key. Store them securely
Gather all this information as you'll need: - Bucket name - Access Key ID (key) - Secret Access Key (secret) - Region (set to auto)
Important
Save the R2 endpoint without the extension in the URL (e.g., https://123abc.r2.cloudflarestorage.com). DO NOT add /your-storage-name at the end, as it will break the upload process by searching for a nested folder that doesn't exist.
2.2. LiveKit¶
-
LiveKit Cloud Project: You need an active project.
-
API Credentials:
-
In your LiveKit Cloud project, go to Settings → Keys
- Copy the API Key and API Secret. Store them securely
- Copy the Host / URL (e.g., wss://my-project.livekit.cloud)
Gather all this information as you'll need: - LiveKit API Key - LiveKit API Secret - LiveKit URL
3. Cloudflare Configuration & Deployment¶
This phase connects your code to the Cloudflare platform.
3.1. Create the Worker Project¶
- In the Cloudflare dashboard, go to Workers & Pages
- Click Create application → Import a Repository
- Select your GitHub repository
- In the build settings, choose Cloudflare Workers as the framework
Build Settings:
- Build command: (leave empty)
- Deploy command: pnpm install && pnpm deploy:upload:staging
-
Root directory: /
-
Click Save and Deploy
Note: The first deployment will fail because it's missing environment variables. This is expected.
3.2. Configure Environment Variables & Secrets¶
- Go to your newly created worker's Settings → Variables and Secrets
- All credentials and configuration must be set in the dashboard
- Secrets (e.g., API keys, auth tokens) must be encrypted by checking the Secret box
Warning
A typo or a missing variable here is the #1 cause of deployment failures. Double-check everything. When deploying with GitHub automation, it will remove all plain text vars, so we put all vars as Secrets.
4. Connecting LiveKit¶
The final step is to tell LiveKit where to send its webhooks.
Setup Steps
- Go to your project in the LiveKit Cloud Dashboard
- Navigate to Settings → Webhooks
- Click Add Webhook
- Webhook URL: Enter the URL of your deployed worker:
https://qubital-upload-pipeline-staging.your-subdomain.workers.dev/livekit/webhook
Warning
When you configure the webhook in the LiveKit Cloud dashboard, you must provide the full, complete URL to your worker's endpoint. For this project, the correct format is:
https://
Be sure to include the /livekit/webhook path at the end, as this is the specific route our Hono application is listening on.
5. Final Deployment and Verification¶
Deployment Steps
- Commit all your code changes (like the wrangler.jsonc name update) and push to your GitHub repository's staging branch
- This will trigger a new deployment in the Cloudflare dashboard
- Watch the deployment log. It should now succeed
End-to-End Test
Perform the following test to verify everything is working:
- Start a LiveKit session in your application
- Trigger a recording via your Go backend
- Stop the recording
- Wait a minute or two
- Check for:
- A new unlisted video on your YouTube channel
- A new row in your Google Sheet
- A notification in your Slack channel
Appendix: Troubleshooting¶
Common Issues
Seeing an OLD BUILD?
Solution: Go to Settings → Builds & deployments → Clear build cache in Cloudflare and retry the deployment.
Deployment Fails with Reserved Command Errors?
Solution: Ensure your worker's deploy script is not named deploy or publish (e.g., use deploy:wrangler).
Worker Fails with "Resolved credential object is not valid"?
Solution: You are missing one or more secrets/variables in the Cloudflare dashboard settings. Double-check all required environment variables.
Worker Fails with "NoSuchKey" from R2?
Solution: This means the file wasn't found. Check that: - Your LiveKit Server's config.yaml is pointing to the correct R2 bucket - Your Go backend's filepath template is a relative path (e.g., out/...)