Cloudflare R2 Setup Guide โ
Panduan lengkap untuk setup Cloudflare R2 (object storage) untuk file dan image uploads.
๐ Overview โ
Cloudflare R2 adalah object storage yang kompatibel dengan S3 API, dengan keuntungan:
- No egress fees - Tidak ada biaya keluar (bandwidth)
- S3 Compatible - Bisa pakai AWS SDK
- Global CDN - Otomatis terdistribusi global
- Murah - $0.015 per GB per bulan
๐ Langkah Setup โ
1. Buka Cloudflare Dashboard โ
- Login ke Cloudflare Dashboard
- Pilih account Anda
- Di sidebar, klik "R2"
2. Create Bucket โ
- Klik tombol "Create bucket"
- Masukkan Bucket name:
- Gunakan nama unik (contoh:
myapp-uploads-2024) - Hanya lowercase, numbers, dan hyphens
- Min 3, max 63 characters
- Gunakan nama unik (contoh:
- Pilih Location (opsional, default adalah Automatic):
- Automatic - Data direplikasi otomatis (recommended)
- Atau pilih region spesifik (EU, US, Asia)
- Klik "Create bucket"
3. Enable Public Access (Optional) โ
Jika file perlu diakses publik (seperti avatar):
- Klik bucket yang sudah dibuat
- Tab "Settings"
- Di bagian "Public Access", klik "Allow"
- Catat Public URL (contoh:
https://pub-abc123.r2.dev)
Note: Jika tidak di-public, file hanya bisa diakses via presigned URL.
4. Create API Token (for R2) โ
Cloudflare R2 menggunakan 2 jenis credential:
Option A: API Token (Recommended untuk development) โ
- Di sidebar R2, klik "Manage R2 API Tokens"
- Klik "Create API Token"
- Pilih permissions:
- Object Read & Write โ (untuk upload dan delete)
- Pilih bucket:
- Specific buckets โ pilih bucket Anda
- Atau All buckets
- Set TTL (expiration):
- Custom โ pilih durasi (atau leave default)
- Klik "Create API Token"
Simpan informasi ini:
Access Key ID: abc123def456...
Secret Access Key: xyz789ghi012...Penting: Secret Access Key hanya ditampilkan sekali! Simpan dengan aman.
Option B: Global API Key (Alternative) โ
Jika butuh access untuk semua buckets:
- Di sidebar utama Cloudflare, klik "My Profile"
- Tab "API Tokens"
- Klik "Create Token"
- Template: "R2 Worker"
- Atau custom token dengan permission:
- Account > Cloudflare R2 > Edit
- Klik "Continue" โ "Create Token"
5. Get Account ID โ
Account ID dibutuhkan untuk R2 API:
- Di sidebar utama (bukan R2), lihat panel kanan
- Atau klik "Workers & Pages"
- Account ID terlihat di panel kanan
Account ID: 1a2b3c4d5e6f7g8h9i0j๐ง Konfigurasi di Project โ
1. Update Environment Variables โ
Edit file .env:
# Cloudflare R2 Configuration
R2_ACCOUNT_ID=your_account_id_here
R2_ACCESS_KEY_ID=your_access_key_id
R2_SECRET_ACCESS_KEY=your_secret_access_key
R2_BUCKET_NAME=your-bucket-name
R2_PUBLIC_URL=https://pub-yourid.r2.dev2. Dapatkan Public URL โ
Jika bucket di-public:
https://pub-abc123def456.r2.devJika private, public URL tidak ada, gunakan presigned URL saja.
๐งช Testing R2 โ
Test Upload via Script โ
# Install AWS CLI (opsional, untuk testing)
pip install awscli
# Configure
aws configure --profile r2
# AWS Access Key ID: your_r2_access_key
# AWS Secret Access Key: your_r2_secret_key
# Default region: auto
# Default output: json
# Test upload
aws s3 cp test.txt s3://your-bucket/ \
--endpoint-url https://your-account-id.r2.cloudflarestorage.com \
--profile r2Test via Aplikasi โ
- Jalankan aplikasi:
npm run dev- Login ke aplikasi
- Buka Profile page
- Upload avatar
- Check browser console untuk URL gambar
๐ Struktur Folder di R2 โ
Recommended structure:
your-bucket/
โโโ avatars/
โ โโโ {user-id}/
โ โโโ avatar.webp
โโโ uploads/
โ โโโ {user-id}/
โ โโโ document.pdf
โ โโโ image.png
โโโ images/
โโโ {user-id}/
โโโ photo.webpSudah diimplementasikan di:
src/lib/storage/r2.ts- functiongenerateFileKey()src/routes/api/upload/image/+server.ts
๐ Security Best Practices โ
1. Restrict CORS (Opsional) โ
Di bucket settings:
- Tab "CORS Policy"
- Add policy:
[
{
"AllowedOrigins": ["https://yourdomain.com"],
"AllowedMethods": ["GET", "PUT"],
"AllowedHeaders": ["*"],
"MaxAgeSeconds": 3000
}
]2. Lifecycle Rules (Opsional) โ
Auto-delete old files:
- Tab "Lifecycle Rules"
- Klik "Add rule"
- Configure:
- Delete objects after 30 days (contoh untuk temporary files)
3. Access Control โ
- Jangan share Access Key dan Secret
- Gunakan Least Privilege - hanya permission yang dibutuhkan
- Rotate keys secara berkala
๐ฐ Pricing โ
| Usage | Price |
|---|---|
| Storage | $0.015 per GB per month |
| Class A Operations (upload) | $4.50 per million requests |
| Class B Operations (download) | $0.36 per million requests |
| Egress (bandwidth out) | FREE ๐ |
Free tier:
- 10 GB storage/month
- 1 million Class A operations
- 10 million Class B operations
โ ๏ธ Troubleshooting โ
"The Access Key ID you provided does not exist" โ
Penyebab:
- Access Key salah
- Key sudah di-delete
- Key expired (jika set TTL)
Solusi:
- Buat API Token baru di R2 dashboard
- Copy Access Key ID dan Secret dengan benar
"NoSuchBucket" โ
Penyebab: Bucket name salah
Solusi:
# Salah
R2_BUCKET_NAME=https://pub-xxx.r2.dev
# Benar
R2_BUCKET_NAME=my-bucket-name"Upload failed: 403 Forbidden" โ
Penyebab: Token tidak punya permission write
Solusi:
- Check API Token permissions
- Pastikan "Object Read & Write" โ
- Pastikan bucket sudah di-select
"The request signature we calculated does not match" โ
Penyebab: Secret Access Key salah
Solusi:
- Buat token baru
- Copy Secret Access Key dengan hati-hati (no spaces)
Image tidak muncul setelah upload โ
Penyebab:
- Bucket tidak public
- URL salah
Solusi:
- Check bucket Settings โ Public Access
- Jika private, gunakan presigned URL
- Check R2_PUBLIC_URL di .env
๐ Resources โ
Setelah setup selesai, aplikasi bisa upload file dan images ke R2! ๐