Deployment
Prerequisites
Section titled “Prerequisites”- Cloudflare account with Workers Paid plan (for Durable Objects)
- R2 bucket for git object storage
Option A: Deploy via npm Package (recommended)
Section titled “Option A: Deploy via npm Package (recommended)”No WASM build needed — pre-built binaries are included in the package.
npx gitmode init # Scaffolds worker/index.ts + wrangler.jsoncnpm installnpx gitmode deploy # Deploys to Cloudflare WorkersThe scaffolded wrangler.jsonc includes all required bindings (R2 bucket, Durable Objects, WASM rules).
Option B: Deploy from Source
Section titled “Option B: Deploy from Source”For contributors or custom builds. Requires Zig 0.15+, Binaryen, and pnpm.
# Build libgit2 for WASM (first time only)bash wasm/libgit2-wasm/build.sh
# Build WASM (if not already built)pnpm run build:wasm
# Deploy to Cloudflarewrangler deployWrangler Configuration
Section titled “Wrangler Configuration”Whether scaffolded via npx gitmode init or written manually, your wrangler.jsonc needs:
{ "name": "gitmode", "main": "./worker/index.ts", "compatibility_date": "2025-12-01", "compatibility_flags": ["nodejs_compat"], "r2_buckets": [ { "binding": "OBJECTS", "bucket_name": "gitmode-objects" } ], "durable_objects": { "bindings": [ { "name": "REPO_STORE", "class_name": "RepoStore" }, { "name": "PACK_WORKER", "class_name": "PackWorkerDO" } ] }, "migrations": [ { "tag": "v1", "new_sqlite_classes": ["RepoStore"] }, { "tag": "v2", "new_classes": ["PackWorkerDO"] } ], "rules": [ { "type": "CompiledWasm", "globs": ["**/*.wasm"], "fallthrough": false } ]}Create R2 Bucket
Section titled “Create R2 Bucket”If you haven’t created the R2 bucket yet:
wrangler r2 bucket create gitmode-objectsVerify Deployment
Section titled “Verify Deployment”After deploying, verify the server is running:
# Should return "gitmode"curl https://your-worker.your-subdomain.workers.dev/
# Initialize a repocurl -X POST https://your-worker.your-subdomain.workers.dev/api/repos/myuser/myrepo/init
# Clone itgit clone https://your-worker.your-subdomain.workers.dev/myuser/myrepo.gitCustom Domain
Section titled “Custom Domain”To use a custom domain, add a route in your Wrangler config or use the Cloudflare dashboard:
{ "routes": [ { "pattern": "git.example.com/*", "zone_name": "example.com" } ]}Limits
Section titled “Limits”| Resource | Limit |
|---|---|
| Worker request size | 100MB (Workers Paid) |
| R2 object size | 5TB per object |
| Durable Object storage | 10GB SQLite per DO |
| Durable Object CPU | 30s per request |
| R2 operations | 10M Class A / 100M Class B per month (free tier) |
For typical git repositories, these limits are more than sufficient. Large binary files (LFS) are stored as regular git objects in R2.
GitHub Actions
Section titled “GitHub Actions”To auto-deploy on push:
name: Deploy to Cloudflare Workerson: push: branches: [main] workflow_dispatch:jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: submodules: true - uses: goto-bus-stop/setup-zig@v2 with: version: 0.15.2 - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: node-version: "22" cache: "pnpm" - run: pnpm install --no-frozen-lockfile - name: Install Binaryen (wasm-opt, wasm-metadce) run: pnpm add -g binaryen - name: Build libgit2 for WASM run: bash wasm/libgit2-wasm/build.sh - name: Build WASM run: pnpm run build:wasm - name: Deploy Worker uses: cloudflare/wrangler-action@v3 with: command: deploy apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}Notes:
pnpm/action-setup@v4reads the pnpm version from thepackageManagerfield inpackage.json— do not specifyversionseparately.- The Zig toolchain and Binaryen are required for the WASM build.
- The libgit2 submodule must be checked out (
submodules: true).