# CloudFlare Setup Guide

This guide covers setting up CloudFlare for Orion, 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 Orion

```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: `orion-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 Orion

```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=orion-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 | `orion-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 orion | 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**
