Panduan lengkap — dari 0 sampai deploy — untuk publik. No API keys, no credentials pribadi.
🌐 Bahasa: Indonesia (mixed English tech terms) 🎯 Target: Developer/pemula yang mau belajar Cloudflare ecosystem + AI Agent + Telegram Bot 📅 Last updated: 2026-07-14 👤 Author: Celebez
- Apa itu Cloudflare Workers?
- Apa itu Cloudflare Pages?
- Bindings — D1, KV, R2, Queues, Durable Objects
- Cara Deploy Workers (Manual + Wrangler CLI)
- Cara Deploy Pages
- Cara Setup AI Agent (Hermes Agent / Codex CLI)
- Cara Integrasi ke Telegram Bot
- Tips & Best Practices
- Troubleshooting Umum
- Referensi & Link
- Panduan DNS & Custom Domain
Cloudflare Workers = platform serverless dari Cloudflare yang jalanin JavaScript/TypeScript/Wasm di edge (100+ lokasi di seluruh dunia). Mirip AWS Lambda tapi:
- ✅ Jalan di edge — dekat user, latency rendah
- ✅ Cold start ~5ms — bukan detik
- ✅ Free tier: 100k request/hari
- ✅ Language: JavaScript, TypeScript, WASM, Python (via Pyodide)
- ✅ Runtime: Service Worker API + ES Modules
User Browser → Cloudflare Edge (100+ lokasi) → Worker Code → D1/KV/R2/API
| Use Case | Cocok? |
|---|---|
| API proxy / rewrite | ✅ Sangat |
| Auth middleware | ✅ |
| A/B testing | ✅ |
| Telegram bot | ✅ |
| Full web app (React) | |
| Heavy ML inference | ❌ Batas CPU 10ms/request |
- Apa itu Cloudflare Workers?
- Apa itu Cloudflare Pages?
- Bindings — D1, KV, R2, Queues, Durable Objects
- Cara Deploy Workers (Manual + Wrangler CLI)
- Cara Deploy Pages
- Cara Setup AI Agent (Hermes Agent / Codex CLI)
- Cara Integrasi ke Telegram Bot
- Tips & Best Practices
- Troubleshooting Umum
- Referensi & Link
- Panduan DNS & Custom Domain
Cloudflare Workers = serverless platform yang jalanin kode di edge network Cloudflare. Bayangin:
- ✅ Cold start ~5ms (bukan detik kayak Lambda)
- ✅ 100+ lokasi di seluruh dunia
- ✅ Free tier: 100k request/hari, 1MB source code
- ✅ Bahasa: JavaScript, TypeScript, Wasm, Python (via Pyodide)
- ✅ Runtime: Service Worker API + ES Modules
// worker.js — ES Modules format
export default {
async fetch(request, env, ctx) {
return new Response("Hello dari Cloudflare Edge! 🌍", {
headers: { "content-type": "text/plain" }
});
}
};| Feature | Service Worker | ES Module (ESM) |
|---|---|---|
| Syntax | addEventListener('fetch', event => ...) |
export default { async fetch(request, env, ctx) {...} } |
export |
❌ Tidak bisa | ✅ Bisa |
import |
❌ Manual bundling | ✅ Native |
| D1 / Queue bindings | ❌ | ✅ Wajib |
| Recommended | ❌ Lamanya | ✅ ✅ ✅ |
Cloudflare Pages = hosting static site + full-stack (via Functions). Mirip Vercel/Netlify tapi semua di edge Cloudflare.
| Aspect | Pages | Worker |
|---|---|---|
| Static assets (HTML/CSS/JS) | ✅ Otomatis | ❌ Manual embed |
| Framework support (Next, React, Svelte) | ✅ Built-in build | ❌ Manual |
| Free tier | 500 build/mo, unlimited bandwidth | 100k req/day |
| Custom domain | ✅ Free | ✅ |
Pages bisa punya backend Functions yang jalan di Workers runtime:
/pages-project/
├── public/ ← static assets (dilayarin langsung)
│ ├── index.html
│ └── style.css
└── functions/ ← backend API
├── api/
│ └── users.js
└── _middleware.js
# Build dulu
npm run build # output ke dist/
# Deploy
npx wrangler pages deploy dist/ --project-name=my-projectOutput: dapat URL https://my-project.pages.dev lalu bisa di-custom domain.
Binding = cara Workers/Pages ngakses resource Cloudflare lain. Ada 6 jenis utama:
D1 = database SQLite di Cloudflare edge. Buat nyimpen data user, settings, logs.
Contoh di wrangler.toml:
[[d1_databases]]
binding = "DB" # ← nama binding, dipakai di kode
database_name = "my-database"
database_id = "xxxx-xxxx-xxxx"Di kode Worker:
const result = await env.DB.prepare("SELECT * FROM users WHERE id = ?")
.bind(userId).first();Kegunaan: nyimpen data user, chat history, analytics, config.
Workers KV = key-value store global dengan read caching. Baca cepat, write perlu waktu replikasi (~5-60 detik).
[[kv_namespaces]]
binding = "CACHE"
id = "xxxx"await env.CACHE.get("key"); // read
await env.CACHE.put("key", "value"); // write (async)
await env.CACHE.delete("key"); // deleteKegunaan: cache API responses, config global, session tokens, rate limiting counters.
R2 = object storage no egress fee — lebih murah dari S3.
[[r2_buckets]]
binding = "BUCKET" # jangan "ASSETS" — itu reserved untuk Pages static assets
bucket_name = "my-bucket"const object = await env.BUCKET.get("file.pdf"); // "ASSETS" reserved untuk Pages assets — pakai nama binding lain (mis. BUCKET)Kegunaan: nyimpen file (gambar, video, dokumen), backup, log archives.
Queues = message queue buat async processing. Kirim pesan, Worker lain process.
[[queues.producers]]
binding = "QUEUE"
queue = "my-queue"
[[queues.consumers]]
queue = "my-queue"
max_batch_size = 10// Producer (dalam fetch handler)
await env.QUEUE.send({ userId: 123, action: "register" });
// Consumer (queue consumer handler terpisah)
export default {
async queue(batch, env) {
for (const msg of batch.messages) {
const { userId, action } = msg.body;
// process...
}
}
};Durable Objects = stateful object di edge. Punya memory sendiri, bisa nyimpen state.
[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"Kegunaan: WebSocket connections, real-time game state, coordination, locks.
echo "SECRET_VALUE" | wrangler secret put SECRET_NAME
# atau lewat dashboardKegunaan: API keys, tokens, password database — tidak bisa dibaca balik via API.
| Binding | Storage Type | Persistence | Latency | Free Tier |
|---|---|---|---|---|
| D1 | SQLite DB | ✅ Disk | ~100ms | 5GB |
| KV | Key-Value | ✅ Global cache | ~5-60ms read | 1GB |
| R2 | Object store | ✅ S3 | ~50ms | 10GB |
| Queues | Message queue | ✅ Buffer | Async | 100k msg/mo |
| Durable Objects | Stateful | ✅ RAM+disk | <1ms | Included |
| Secrets | Env vars | ✅ Config | <1ms | Unlimited |
Ada 3 cara deploy Workers:
# Install
npm install -g wrangler # atau npx wrangler
# Login (browser — perlu)
npx wrangler login
# Atau pake API Key (headless — tanpa browser)
export CLOUDFLARE_API_KEY="cfk_..." # Global API Key
export CLOUDFLARE_EMAIL="email@example.com"
# Init project
npx wrangler init my-worker --yes # bikin template
# Edit wrangler.toml
# [[d1_databases]], [[kv_namespaces]], dll
# Deploy
npx wrangler deploy # ke workers.dev
npx wrangler deploy --route "domain.com/*" # custom domain
# Test
curl https://my-worker.username.workers.dev/Kalau wrangler login error / butuh browser:
# Bunyinya kaya gini:
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/ACCT_ID/workers/scripts/SCRIPT_NAME" \
-H "X-Auth-Email: EMAIL" \
-H "X-Auth-Key: CF_API_KEY" \
-H "Content-Type: multipart/form-data; boundary=FORM" \
--data-binary @upload.binLebih detail di docs/manual-deploy.md
Contoh workflow (.github/workflows/deploy.yml):
name: Deploy Worker
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install
- run: npx wrangler deploy
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }}- Push project ke GitHub
- Login Cloudflare Dashboard → Workers & Pages → Create
- Pilih Pages → Connect Git
- Authorize → pilih repo → branch
- Set build command:
npm run build - Output directory:
dist/ - ✅ Auto-deploy setiap push
# Build
npm run build
# Deploy
npx wrangler pages deploy dist/ --project-name=my-pages
# List projects
npx wrangler pages project list- Pages project → Settings → Custom domains
- Add domain → verify DNS
- Cloudflare handles SSL auto
Hermes Agent = open-source AI agent framework. Bisa jadi:
- CLI chat assistant
- Discord/Telegram bot
- Coding assistant
- Multi-provider (Groq, OpenAI, Cloudflare, dll)
Install:
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bashCoba:
hermes chat -q "Buatkan function untuk generate angka random"Dokumentasi: hermes-agent.nousresearch.com/docs
Provider yang didukung:
- OpenAI / Groq / Claude / DeepSeek
- Cloudflare Workers AI
- NVIDIA Nemotron
- 20+ lainnya
Codex CLI = AI coding assistant dari OpenAI. Jalan di terminal, bisa:
- Baca/edit file
- Run commands
- Git operations
# Install — OpenAI Codex CLI lewat npm (BUKAN pip; "codex-cli" di PyPI itu wrapper Gemini, tool beda)
npm install -g @openai/codex
# Setup API key
export OPENAI_API_KEY="sk-..."
# Pakai
codex -p "Buatkan REST API endpoint untuk user CRUD"Kimchi = coding agent dari Cast AI. Spesialis:
- Bikin kode baru
- Refactor kode existing
- Multi-file changes
# Repo resmi: https://github.com/castai/opencode-kimchi (project Node.js, TIDAK ada install.sh)
# Ikuti panduan di README repo-nya untuk install (jangan curl|bash dari URL tak terverifikasi)
# Setup
export KIMCHI_API_KEY="castai_v1_..."
# Pakai
kimchi -p "Tambah logging ke semua endpoint"| Agent | Type | Provider | Best For |
|---|---|---|---|
| Hermes | Framework | Multi (20+) | Umum, bot, orchestrasi |
| Codex CLI | CLI agent | OpenAI | Coding assistance |
| Kimchi | CLI agent | Cast AI | Refactor & repair |
| Claude Code | CLI agent | Anthropic | Complex reasoning |
- Bot Token — dari @BotFather
- Worker atau VPS — tempat jalanin kode
- Webhook URL — endpoint public untuk receive update
// worker.js — Minimal Telegram Bot via Webhook
export default {
async fetch(request, env) {
const update = await request.json(); // dari Telegram
// Handle pesan
if (update.message?.text) {
const chatId = update.message.chat.id;
const text = update.message.text;
// Balas
await fetch(`https://api.telegram.org/bot${env.BOT_TOKEN}/sendMessage`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
chat_id: chatId,
text: `Kamu bilang: ${text}`
})
});
}
return new Response("ok");
}
};Set webhook:
curl -X POST "https://api.telegram.org/botTOKEN/setWebhook" \
-d "url=https://my-worker.workers.dev/"📦 Kode runnable ada di
examples/—worker.js(echo bot) +wrangler.tomlyang beneran bisawrangler deploy. Lihatexamples/README.md.
- Polling — Cocok buat lokal/VPS (bukan serverless)
- Long Polling — Telegram nyimpen update sampe diambil
- Gateway — Hermes Agent punya gateway untuk multi-platform
| Feature | Butuh | Notes |
|---|---|---|
| Reply inline keyboard | inline_keyboard |
UI reply di chat |
| Scheduled posts | Cron | @daily / @hourly |
| Media download | R2 + ffmpeg | Video processing |
| Database | D1 | User data, settings |
| Payment/Donate | Stripe | Payment button |
| Admin panel | Pages + D1 | Web dashboard |
- Gunakan ES Modules —
export defaultbukanaddEventListener - Batasi 1MB source — di free plan. Kalau lebih, embed di code atau pake R2
- Handle error di fetch — jangan throw langsung
- Gunakan
ctx.waitUntil()— untuk background tasks (logging, analytics)
sqlite_master+PRAGMA table_infobisa kena SQLITE_AUTH — jangan query ini di D1, pakeSELECT COUNT(*)aja- Batch query — pake
prepare()+bind(), bukan raw string - Migration — pake
wrangler d1 migrations
- Write perlu ~5-60 detik — jangan expect
getafterputlangsung - Cache read —
getdengancacheTtl> 0 - Batch —
put/getbanyak sekaligus pakePromise.all
- Jangan pernah hardcode token di kode — pake secrets atau env vars
- CORS — Set
Access-Control-Allow-Originyang strict - Rate limiting — pake KV atau Durable Objects
Worker crash pas startup. Biasanya karena:
- Circular imports (module A import B, B import A)
- Syntax error di module level
- Binding salah nama
Fix:
- Rollback ke version sebelumnya
- Test satu file dulu
- Jangan batch edit > 5 file sekaligus
Waktu deploy ESM Worker. Fix:
# Harus application/javascript+module
Content-Type: application/javascript+moduleWorker bisa query tapi error. Fix:
- Jangan pake
sqlite_masterorPRAGMA— itu gak didukung - Ganti ke
SELECT COUNT(*)
CapSolver key valid tapi error. Fix:
- Buka dashboard CapSolver → redeem key
- Atau pake alternatif (2Captcha)
Deploy udah selesai tapi belum muncul. Fix:
- Tunggu ~1-5 menit
- Cek via curl dengan
-sSL(ikuti redirect) HTTP 308= permanent redirect (BUKAN indikator sukses). Deploy sukses =200 OK. 308 wajar saat CF redirect, tapi jangan dianggap "berhasil deploy"
Worker tapi CORS blocked. Fix:
new Response(body, {
headers: { "access-control-allow-origin": "*" }
});Cloudflare bukan cuma Workers — dia juga DNS manager & CDN gratis. Panduan lengkap (record A/CNAME/MX/TXT, masukin domain, proxy 🟠, SSL, custom domain Pages/Workers, email, troubleshooting) ada di docs/dns-domain-guide.md.
Ringkasan cepat:
- Dash → Add a site → ketik domain → plan Free.
- Ganti nameserver di registrar ke punya CF (
nsa.cloudflare.com,nsb.cloudflare.com). - Tunggu Active 🟢 (cek:
dig NS example.com +short).
- 🟠 Proxied — trafik lewat edge CF, IP disembunyikan, dapat DDoS protection. Untuk web/API (port 80/443).
- ⚪ DNS only — trafik langsung ke origin. Untuk MX/email, game server, SSH.
Gratis, otomatis untuk Pages/Workers (sertifikat Google Trust Services ~2 menit).
- Pages: Custom domains → ketik
example.com→ CF buat CNAME + SSL otomatis. Apex pakai CNAME flattening. - Workers: Settings → Custom Domains (baru) atau Routes (legacy, bisa path-based).
📦 Detail + contoh curl API ada di
docs/dns-domain-guide.md.
- Cloudflare Workers Docs
- Cloudflare Pages Docs
- Wrangler CLI
- D1 Database
- Workers KV
- R2 Storage
- Queues
- Durable Objects
- curl — HTTP requests
- jq — JSON parser di CLI
- Custom Domains for Pages
- Workers Custom Domains
- Cloudflare DNS
- SSL/TLS
- Email Routing
tutorial-cloudflare-agents-bot/
├── README.md ← Ini — tutorial utama
├── docs/ ← Dokumen tambahan
│ ├── manual-deploy.md ← Deploy via REST API manual
│ ├── d1-tips.md ← D1 database tips & pitfalls
│ ├── bindings-guide.md ← Panduan lengkap bindings
│ └── dns-domain-guide.md ← DNS, nameserver, SSL, custom domain
├── examples/ ← Kode runnable (beneran bisa deploy)
│ ├── worker.js ← Telegram echo bot (ESM)
│ ├── wrangler.toml ← Config + contoh binding
│ └── README.md ← Cara jalanin
├── docs/demo-deploy.gif ← Demo animasi deploy
├── LICENSE ← MIT License
└── .gitignore ← File git
Repo ini 100% tutorial publik — tidak ada API key, credential, atau data pribadi di dalamnya. Semua contoh pake placeholder (YOUR_TOKEN, your-email@example.com, dll).
Jangan commit credentials ke git! — Udah include .gitignore untuk jaga-jaga.
Dibuat dengan ❤️ oleh Celebez — untuk komunitas, by komunitas.

