Files
orion/docs/deployment/cloudflare.md
Samir Boulahtit ff5b395cdd feat: add Sentry, Cloudflare R2, and CloudFlare CDN integrations
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>
2026-01-11 19:44:59 +01:00

300 lines
6.8 KiB
Markdown

# 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
1. Create a CloudFlare account at [cloudflare.com](https://cloudflare.com)
2. Add your domain and follow the setup wizard
3. 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
# .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-Ray` header
---
## SSL/TLS Configuration
### Recommended: Full (Strict) Mode
1. Go to **SSL/TLS** > **Overview**
2. Select **Full (strict)**
3. This requires a valid SSL certificate on your origin server
### Origin Certificates
For the origin server, you can use:
1. **Let's Encrypt** (recommended for VPS):
```bash
sudo certbot --nginx -d yourdomain.com
```
2. **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
1. Go to **R2** in CloudFlare dashboard
2. Click **Create bucket**
3. Name: `wizamart-media`
4. Location: Choose region closest to your users
### Create API Token
1. Go to **R2** > **Manage R2 API Tokens**
2. Create new token with:
- Permission: Object Read & Write
- Bucket: Select your bucket
3. Save the **Access Key ID** and **Secret Access Key**
### Configure Wizamart
```env
# .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:
1. Go to **R2** > Your bucket > **Settings**
2. Enable **Public Access**
3. Note the public URL: `https://your-bucket.account-id.r2.dev`
Or use a custom domain:
1. Go to **R2** > Your bucket > **Settings** > **Custom Domains**
2. Add `media.yourdomain.com`
3. Update `.env`:
```env
R2_PUBLIC_URL=https://media.yourdomain.com
```
---
## Security Settings
### WAF Rules (Free Tier)
Enable these managed rules:
1. **CloudFlare Managed Ruleset** - Basic protection
2. **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
1. Go to **Security** > **Bots**
2. Enable **Bot Fight Mode**
---
## Nginx Configuration for CloudFlare
When using CloudFlare proxy, update Nginx to trust CloudFlare IPs:
```nginx
# /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
1. **Check headers** in browser DevTools:
- `CF-Ray` header should be present
- `CF-Cache-Status` shows caching status
2. **Test from command line**:
```bash
curl -I https://yourdomain.com/static/css/main.css
# Should see CF-Ray and CF-Cache-Status headers
```
### Check R2 is Working
1. **Upload a test file** via the admin media library
2. **Check the URL** - should point to R2 or your custom domain
3. **Verify in CloudFlare dashboard** - file should appear in bucket
### Check Real IP Logging
With `CLOUDFLARE_ENABLED=true`:
```bash
# 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**