Production quick wins for improved observability and scalability: Sentry Error Tracking: - Add sentry-sdk[fastapi] dependency - Initialize Sentry in main.py with FastAPI/SQLAlchemy integrations - Add Celery integration for background task error tracking - Feature-flagged via SENTRY_DSN (disabled when empty) Cloudflare R2 Storage: - Add boto3 dependency for S3-compatible API - Create storage_service.py with StorageBackend abstraction - LocalStorageBackend for development (default) - R2StorageBackend for production cloud storage - Feature-flagged via STORAGE_BACKEND setting CloudFlare CDN/Proxy: - Create middleware/cloudflare.py for CF header handling - Extract real client IP from CF-Connecting-IP - Support CF-IPCountry for geo features - Feature-flagged via CLOUDFLARE_ENABLED setting Documentation: - Add docs/deployment/cloudflare.md setup guide - Update infrastructure.md with dev vs prod requirements - Add enterprise upgrade checklist for scaling beyond 1000 users - Update installation.md with new environment variables All features are optional and disabled by default for development. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
6.8 KiB
CloudFlare Setup Guide
This guide covers setting up CloudFlare for Wizamart, including CDN, proxy, WAF, and R2 storage.
Overview
CloudFlare provides:
| Feature | Benefit |
|---|---|
| CDN | Global edge caching for static assets |
| Proxy | Hide origin IP, DDoS protection |
| WAF | Web Application Firewall (basic rules free) |
| R2 | S3-compatible object storage (~$5/mo) |
| SSL | Free SSL certificates |
Quick Start
1. Add Your Domain to CloudFlare
- Create a CloudFlare account at cloudflare.com
- Add your domain and follow the setup wizard
- Update your domain's nameservers to CloudFlare's
2. Configure DNS Records
Create these DNS records (with proxy enabled - orange cloud):
| Type | Name | Content | Proxy |
|---|---|---|---|
| A | @ | Your server IP | ✅ Proxied |
| A | www | Your server IP | ✅ Proxied |
| A | api | Your server IP | ✅ Proxied |
| CNAME | media | your-bucket.r2.dev | ✅ Proxied |
3. Enable CloudFlare in Wizamart
# .env
CLOUDFLARE_ENABLED=true
This enables the CloudFlare middleware to:
- Extract real client IPs from
CF-Connecting-IP - Read client country from
CF-IPCountry - Track requests via
CF-Rayheader
SSL/TLS Configuration
Recommended: Full (Strict) Mode
- Go to SSL/TLS > Overview
- Select Full (strict)
- This requires a valid SSL certificate on your origin server
Origin Certificates
For the origin server, you can use:
-
Let's Encrypt (recommended for VPS):
sudo certbot --nginx -d yourdomain.com -
CloudFlare Origin Certificate (15-year free cert):
- Go to SSL/TLS > Origin Server
- Create Certificate
- Install on your server
Caching Configuration
Page Rules for Static Assets
Create page rules for optimal caching:
Rule 1: Static Assets
- URL:
*yourdomain.com/static/* - Setting: Cache Level → Cache Everything
- Setting: Edge Cache TTL → 1 month
Rule 2: Uploads
- URL:
*yourdomain.com/uploads/* - Setting: Cache Level → Cache Everything
- Setting: Edge Cache TTL → 1 week
Rule 3: API (No Cache)
- URL:
*yourdomain.com/api/* - Setting: Cache Level → Bypass
Cache Rules (New Interface)
Or use the newer Cache Rules:
Expression: (http.request.uri.path starts with "/static/")
Action: Cache eligible → Override → 30 days
Cloudflare R2 Storage
Create R2 Bucket
- Go to R2 in CloudFlare dashboard
- Click Create bucket
- Name:
wizamart-media - Location: Choose region closest to your users
Create API Token
- Go to R2 > Manage R2 API Tokens
- Create new token with:
- Permission: Object Read & Write
- Bucket: Select your bucket
- Save the Access Key ID and Secret Access Key
Configure Wizamart
# .env
STORAGE_BACKEND=r2
R2_ACCOUNT_ID=your_account_id
R2_ACCESS_KEY_ID=your_access_key
R2_SECRET_ACCESS_KEY=your_secret_key
R2_BUCKET_NAME=wizamart-media
Enable Public Access (Optional)
For direct public access to uploaded files:
- Go to R2 > Your bucket > Settings
- Enable Public Access
- Note the public URL:
https://your-bucket.account-id.r2.dev
Or use a custom domain:
- Go to R2 > Your bucket > Settings > Custom Domains
- Add
media.yourdomain.com - Update
.env:R2_PUBLIC_URL=https://media.yourdomain.com
Security Settings
WAF Rules (Free Tier)
Enable these managed rules:
- CloudFlare Managed Ruleset - Basic protection
- OWASP Core Ruleset - SQL injection, XSS protection
Rate Limiting
Create rate limiting rules for the API:
- URL:
/api/* - Rate: 100 requests per minute
- Action: Challenge or Block
Bot Fight Mode
- Go to Security > Bots
- Enable Bot Fight Mode
Nginx Configuration for CloudFlare
When using CloudFlare proxy, update Nginx to trust CloudFlare IPs:
# /etc/nginx/conf.d/cloudflare.conf
# CloudFlare IP ranges
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
# IPv6
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;
real_ip_header CF-Connecting-IP;
Environment Variables Reference
| Variable | Description | Default |
|---|---|---|
CLOUDFLARE_ENABLED |
Enable CF header processing | false |
STORAGE_BACKEND |
Storage backend (local or r2) |
local |
R2_ACCOUNT_ID |
CloudFlare account ID | - |
R2_ACCESS_KEY_ID |
R2 API access key | - |
R2_SECRET_ACCESS_KEY |
R2 API secret key | - |
R2_BUCKET_NAME |
R2 bucket name | wizamart-media |
R2_PUBLIC_URL |
Custom public URL for R2 | - |
Verification
Check CloudFlare is Working
-
Check headers in browser DevTools:
CF-Rayheader should be presentCF-Cache-Statusshows caching status
-
Test from command line:
curl -I https://yourdomain.com/static/css/main.css # Should see CF-Ray and CF-Cache-Status headers
Check R2 is Working
- Upload a test file via the admin media library
- Check the URL - should point to R2 or your custom domain
- Verify in CloudFlare dashboard - file should appear in bucket
Check Real IP Logging
With CLOUDFLARE_ENABLED=true:
# Check application logs
journalctl -u wizamart | grep "real_ip"
Troubleshooting
521 Error (Web Server Down)
- Ensure your origin server is running
- Check firewall allows CloudFlare IPs
- Verify SSL certificate is valid
522 Error (Connection Timed Out)
- Check origin server is responding
- Verify port 443 is open
- Check server isn't overloaded
525 Error (SSL Handshake Failed)
- Ensure origin has valid SSL certificate
- Try CloudFlare Origin Certificate
- Check SSL mode is correct (Full vs Full Strict)
R2 Access Denied
- Verify API token has correct permissions
- Check bucket name is correct
- Ensure bucket policy allows the operation
Cost Estimate
| Service | Free Tier | Paid Usage |
|---|---|---|
| CDN | Unlimited | Free |
| WAF | Basic rules | $20/mo for advanced |
| R2 Storage | 10 GB/mo | $0.015/GB |
| R2 Requests | 10M Class A, 10M Class B | $0.36/M, $0.0036/M |
| SSL | Free | Free |
Typical monthly cost for small-medium site: ~$5-15