Skip to content

Self-Hosting botfighter

botfighter runs entirely on Cloudflare's free tier: Workers, D1, KV, and Pages. No servers to manage. Estimated setup time: 20 minutes.

Prerequisites

  • Cloudflare account (free tier works)
  • Node.js 18+ installed
  • Wrangler CLI: npm install -g wrangler@4

Step 1 — Authenticate

bash
wrangler login

Step 2 — Clone the repo

bash
git clone https://github.com/JustaRsearchGuy/botfighter.git
cd botfighter

Step 3 — Create D1 database

bash
wrangler d1 create botfighter-db

Copy the database_id from the output. Open worker/wrangler.toml and replace the database_id value with it.

Step 4 — Create KV namespace

bash
wrangler kv namespace create BOTFIGHTER_KV

Copy the id from the output. In worker/wrangler.toml, replace the KV id value with it.

Step 5 — Run database migrations

bash
cd worker
wrangler d1 migrations apply botfighter-db --local   # test locally first
wrangler d1 migrations apply botfighter-db            # apply to production

This creates the following tables: sites, detections, hourly_stats, bot_rules, passkeys, magic_links, leaderboard_cache.

Step 6 — Set required secrets

bash
# Token hashing salt — generate with: openssl rand -hex 32
printf "YOUR_RANDOM_32_CHAR_STRING" | wrangler secret put OWNER_SALT --name botfighter-worker

# Admin secret — used to gate passkey registration and admin API routes
printf "YOUR_ADMIN_SECRET" | wrangler secret put ADMIN_SECRET --name botfighter-worker

Keep OWNER_SALT secret and never change it after launch — changing it invalidates all existing owner tokens.

Step 7 — Set optional secrets

bash
# Resend — for magic link email login (get API key at resend.com, "Sending access" permission)
printf "re_YOUR_KEY" | wrangler secret put RESEND_API_KEY --name botfighter-worker

# Kit/ConvertKit — subscribe new registrants to your mailing list
printf "YOUR_KIT_KEY" | wrangler secret put KIT_API_SECRET --name botfighter-worker
printf "YOUR_FORM_ID" | wrangler secret put KIT_FORM_ID --name botfighter-worker

# Restrict dashboard CORS to your custom domain (optional)
printf "https://dash.yourdomain.com" | wrangler secret put DASHBOARD_ORIGIN --name botfighter-worker

Step 8 — Deploy the Worker

bash
cd worker   # if not already there
npm install
wrangler deploy

Note the Worker URL (e.g. https://botfighter-worker.YOUR-SUBDOMAIN.workers.dev).

Step 9 — Deploy the dashboard

bash
cd ../dashboard
npm install
VITE_API_URL=https://YOUR-WORKER-URL npm run build
wrangler pages deploy dist --project-name botfighter-dashboard

Step 10 — Register your admin passkey

This gives you access to the admin dashboard (all sites, delete, etc.).

Open your deployed dashboard and click "Register a passkey (first-time setup)". Enter your ADMIN_SECRET, then complete Face ID / Touch ID enrollment.

Once registered you can sign in with the passkey button.

Step 11 — Register your first site

Go to the dashboard and click Get started free →, or register via the API:

bash
curl -X POST https://YOUR-WORKER-URL/admin/register-public \
  -H "Content-Type: application/json" \
  -d '{"domain": "yourdomain.com", "email": "you@yourdomain.com"}'

Response:

json
{
  "site_id": "yourdomain-com",
  "domain": "yourdomain.com",
  "owner_token": "abc123...",
  "snippet": "<script src=\"...\">"
}

Save the owner_token — it is shown only once. You can use it as the Bearer token to access your site's dashboard, or use magic link login if you provided an email.

Step 12 — Add the snippet to your site

Paste before </body> on every page:

html
<script
  src="https://YOUR-WORKER-URL/botfighter.js"
  data-site="YOUR-SITE-ID"
  data-api="https://YOUR-WORKER-URL"
  data-honeypot="true">
</script>

Step 13 — Verify

bash
curl https://YOUR-WORKER-URL/health
# → {"ok":true,"version":"0.1.0"}

Open the dashboard, sign in, and you should see your site listed.

Logging in as a public user

Users who registered with an email can sign in via magic link:

  1. Click Sign in with email → on the login screen
  2. Enter the email used during registration
  3. Click the link in the email → auto-logged into their site dashboard

The magic link expires in 15 minutes and is single-use. Sessions last 30 days.

Updating

bash
git pull
cd worker && wrangler deploy
cd ../dashboard && npm run build && wrangler pages deploy dist

Free tier limits (Cloudflare)

ResourceFree limitTypical botfighter usage
Workers requests100,000/day~1 req per page view
D1 reads5M rows/dayLow — aggregates reduce reads
D1 writes100K rows/day1 per visit (capped per site)
KV reads100K/day2–3 per visit
KV writes1K/daySessions + rate limits
PagesUnlimitedDashboard only

For sites with >100k daily visitors, consider a paid Workers plan or lower DAILY_DETECTION_CAP:

bash
printf "5000" | wrangler secret put DAILY_DETECTION_CAP --name botfighter-worker

Open source under MIT License.