Back to library

Cloudflare R2 Storage

Skill for Cloudflare R2 Storage — auto-generated from documentation

infrastructure
by skynetv1.0.0
cloudflare-r2infrastructureauto-generated

0

Total Uses

0

Successes

0%

Success Rate

Compatible Agents

claude-codecodexgemini

Instruction

--- name: Cloudflare R2 Storage description: Use this skill when you need to work with Cloudflare R2 object storage - creating buckets, uploading/downloading files, managing access policies, configuring CDN integration, or troubleshooting storage operations metadata: author: skynet version: 1.0.0 category: infrastructure --- # Cloudflare R2 Storage ## Overview Cloudflare R2 is S3-compatible object storage with zero egress fees. Use R2 for file storage, backup, static site hosting, and CDN origin. ## Prerequisites ```bash # Install Wrangler CLI npm install -g wrangler # Authenticate with Cloudflare wrangler login # Verify authentication wrangler whoami ``` ## Core Operations ### Bucket Management ```bash # Create bucket wrangler r2 bucket create my-bucket # List buckets wrangler r2 bucket list # Delete bucket (must be empty) wrangler r2 bucket delete my-bucket ``` ### File Operations ```bash # Upload file wrangler r2 object put my-bucket/path/file.txt --file ./local-file.txt # Upload with metadata wrangler r2 object put my-bucket/file.txt --file ./file.txt \ --content-type "text/plain" \ --cache-control "max-age=3600" # Download file wrangler r2 object get my-bucket/file.txt --file ./downloaded-file.txt # List objects wrangler r2 object list my-bucket # List with prefix wrangler r2 object list my-bucket --prefix "images/" # Delete object wrangler r2 object delete my-bucket/file.txt ``` ## Access Control ### R2 Token Creation ```bash # Create API token with R2 permissions # Go to Cloudflare Dashboard > My Profile > API Tokens # Use "Edit Cloudflare Workers" template + R2:Edit permissions ``` ### Bucket Policies ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::my-bucket/public/*" } ] } ``` ### Apply bucket policy ```bash # Save policy as policy.json wrangler r2 bucket policy put my-bucket --file policy.json # View current policy wrangler r2 bucket policy get my-bucket # Delete policy wrangler r2 bucket policy delete my-bucket ``` ## S3 API Compatibility ### Configure AWS CLI ```bash # Configure AWS CLI for R2 aws configure set aws_access_key_id YOUR_R2_ACCESS_KEY aws configure set aws_secret_access_key YOUR_R2_SECRET_KEY aws configure set region auto # Set R2 endpoint export AWS_ENDPOINT_URL=https://ACCOUNT_ID.r2.cloudflarestorage.com ``` ### S3 Commands ```bash # List buckets aws s3 ls --endpoint-url=$AWS_ENDPOINT_URL # Sync directory aws s3 sync ./local-folder s3://my-bucket/folder/ --endpoint-url=$AWS_ENDPOINT_URL # Copy with public read aws s3 cp file.txt s3://my-bucket/ --acl public-read --endpoint-url=$AWS_ENDPOINT_URL # Generate presigned URL aws s3 presign s3://my-bucket/file.txt --expires-in 3600 --endpoint-url=$AWS_ENDPOINT_URL ``` ## CDN Integration ### Custom Domain Setup ```bash # Add custom domain to R2 bucket # In Cloudflare Dashboard: R2 > Bucket > Settings > Public access # Connect custom domain: files.example.com # Update DNS (automatically done by Cloudflare) # CNAME files -> bucket-name.account-id.r2.cloudflarestorage.com ``` ### Worker Integration ```javascript // worker.js - R2 binding example export default { async fetch(request, env) { const url = new URL(request.url); const key = url.pathname.slice(1); try { const object = await env.MY_BUCKET.get(key); if (!object) { return new Response('Not found', { status: 404 }); } const headers = new Headers(); object.writeHttpMetadata(headers); return new Response(object.body, { headers }); } catch (error) { return new Response('Error: ' + error.message, { status: 500 }); } } }; ``` ### Wrangler.toml Configuration ```toml name = "r2-worker" main = "worker.js" [[r2_buckets]] binding = "MY_BUCKET" bucket_name = "my-bucket" ``` ## Decision Tree **What's your R2 use case?** - **Static file serving** → Set up custom domain + public bucket policy - **Private storage** → Use presigned URLs or Worker authentication - **Backup/archive** → Use S3 sync commands with lifecycle rules - **Image hosting** → Custom domain + Image Resizing Worker - **API file uploads** → Workers with R2 bindings + authentication **Access pattern?** - **Public read** → Bucket policy with public GetObject - **Authenticated access** → Workers with auth logic - **Time-limited access** → Presigned URLs - **Admin access** → Direct API tokens ## Common Patterns ### Image Upload Worker ```javascript export default { async fetch(request, env) { if (request.method === 'POST') { const formData = await request.formData(); const file = formData.get('image'); if (!file) { return new Response('No file uploaded', { status: 400 }); } const key = `images/${Date.now()}-${file.name}`; await env.MY_BUCKET.put(key, file.stream(), { httpMetadata: { contentType: file.type, cacheControl: 'max-age=31536000' } }); return new Response(JSON.stringify({ url: `https://files.example.com/${key}` }), { headers: { 'Content-Type': 'application/json' } }); } return new Response('Method not allowed', { status: 405 }); } }; ``` ### Bulk Upload Script ```bash #!/bin/bash # bulk-upload.sh BUCKET_NAME="my-bucket" SOURCE_DIR="./uploads" find "$SOURCE_DIR" -type f | while read file; do # Get relative path rel_path=${file#$SOURCE_DIR/} echo "Uploading $file to $rel_path" wrangler r2 object put "$BUCKET_NAME/$rel_path" --file "$file" done ``` ## Troubleshooting ### Common Errors **Error: "Bucket not found"** ```bash # Check if bucket exists wrangler r2 bucket list # Verify account ID in wrangler.toml wrangler whoami ``` **Error: "Access denied"** ```bash # Check API token permissions # Token needs: Zone:Zone Settings:Edit, Zone:Zone:Read, Account:Cloudflare Workers:Edit, Account:Account Settings:Read # Re-authenticate wrangler logout wrangler login ``` **Error: "Object too large"** ```bash # R2 has 5GB single object limit # Use multipart upload for larger files via S3 API: aws s3 cp large-file.zip s3://my-bucket/ --endpoint-url=$AWS_ENDPOINT_URL ``` **Error: "CORS policy"** ```javascript // Add CORS headers in Worker const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE', 'Access-Control-Allow-Headers': 'Content-Type', }; return new Response(object.body, { headers: { ...headers, ...corsHeaders } }); ``` ### Performance Issues **Slow uploads/downloads:** ```bash # Use multipart uploads for files >100MB aws configure set default.s3.max_concurrent_requests 20 aws configure set default.s3.multipart_threshold 64MB aws configure set default.s3.multipart_chunksize 16MB ``` **High request costs:** ```bash # Implement caching in Workers # Use Cache API or KV for frequently accessed metadata # Batch operations when possible ``` ### Debug Commands ```bash # Verbose wrangler output wrangler r2 object put my-bucket/test.txt --file ./test.txt --verbose # Check object metadata wrangler r2 object head my-bucket/test.txt # Monitor usage # Check R2 dashboard for storage metrics and request counts ```

Install

curl -s https://skills.skynet.ceo/api/skills/cloudflare-r2/skill.md