mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 13:44:54 +00:00
Generated by Spark: Should handle caprover / cloudflare cors - Check frontend and backend config. example setup: https://frontend.example.com https://backend.example.com
This commit is contained in:
10
.env.production.example
Normal file
10
.env.production.example
Normal file
@@ -0,0 +1,10 @@
|
||||
# Frontend Environment Variables (Production)
|
||||
|
||||
# Backend API URL
|
||||
VITE_BACKEND_URL=https://backend.example.com
|
||||
|
||||
# Enable backend storage (set to 'false' to use IndexedDB only)
|
||||
VITE_USE_BACKEND=true
|
||||
|
||||
# Optional: API Key for authenticated requests
|
||||
# VITE_API_KEY=your-api-key-here
|
||||
55
ROADMAP.md
55
ROADMAP.md
@@ -305,7 +305,7 @@ CodeForge is a comprehensive low-code development platform for building producti
|
||||
---
|
||||
|
||||
### Iteration 7: JSON-Driven Architecture Completion
|
||||
**Focus:** Component registry refactor, expanding JSON page system
|
||||
**Focus:** Component registry refactor, expanding JSON page system, production deployment
|
||||
|
||||
#### Completed
|
||||
- ✅ Component registry refactored to read from `component-registry.json`
|
||||
@@ -315,6 +315,10 @@ CodeForge is a comprehensive low-code development platform for building producti
|
||||
- ✅ JSON-based Lambda Designer page created
|
||||
- ✅ Experimental flags support for components
|
||||
- ✅ Configurable preload strategies per component
|
||||
- ✅ CapRover/Cloudflare CORS configuration
|
||||
- ✅ Production deployment documentation
|
||||
- ✅ Environment variable templates for frontend and backend
|
||||
- ✅ Deployment checklist and troubleshooting guides
|
||||
|
||||
#### Benefits Achieved
|
||||
- **Zero code changes** needed to add new components to registry
|
||||
@@ -322,12 +326,18 @@ CodeForge is a comprehensive low-code development platform for building producti
|
||||
- **Runtime flexibility** for enabling/disabling components
|
||||
- **Better performance** with configurable lazy loading
|
||||
- **Improved maintainability** with declarative component definitions
|
||||
- **Production-ready deployment** with proper CORS and security configuration
|
||||
|
||||
#### Key Files
|
||||
- `component-registry.json` - Centralized component metadata
|
||||
- `src/lib/component-registry.ts` - Dynamic registry loader
|
||||
- `src/components/JSONLambdaDesigner.tsx` - New JSON-based Lambda page
|
||||
- `src/config/pages/lambda-designer.json` - Lambda page schema
|
||||
- `nginx.conf` - Updated with CORS headers
|
||||
- `backend/app.py` - Enhanced Flask CORS configuration
|
||||
- `docs/CAPROVER_CLOUDFLARE_DEPLOYMENT.md` - Complete deployment guide
|
||||
- `docs/CLOUDFLARE_CONFIGURATION.md` - Cloudflare setup guide
|
||||
- `docs/DEPLOYMENT_CHECKLIST.md` - Quick reference checklist
|
||||
|
||||
---
|
||||
|
||||
@@ -366,7 +376,48 @@ CodeForge is a comprehensive low-code development platform for building producti
|
||||
|
||||
### Near-Term (Next 2-3 Iterations)
|
||||
|
||||
#### 1. Complete JSON Migration
|
||||
#### 1. CapRover/Cloudflare CORS Configuration
|
||||
**Priority:** HIGH
|
||||
**Effort:** LOW
|
||||
**Status:** ✅ COMPLETE
|
||||
|
||||
**Completed:**
|
||||
- ✅ Updated nginx.conf with proper CORS headers for frontend
|
||||
- ✅ Enhanced Flask backend with detailed CORS configuration
|
||||
- ✅ Created comprehensive deployment documentation
|
||||
- ✅ Added environment variable examples for production
|
||||
- ✅ Created CapRover captain-definition files
|
||||
- ✅ Documented Cloudflare configuration steps
|
||||
- ✅ Created deployment checklist
|
||||
- ✅ Added CORS testing procedures
|
||||
|
||||
**Files Created:**
|
||||
- `docs/CAPROVER_CLOUDFLARE_DEPLOYMENT.md` - Complete deployment guide
|
||||
- `docs/CLOUDFLARE_CONFIGURATION.md` - Cloudflare-specific settings
|
||||
- `docs/DEPLOYMENT_CHECKLIST.md` - Quick deployment checklist
|
||||
- `.env.production.example` - Frontend environment template
|
||||
- `backend/.env.production.example` - Backend environment template
|
||||
- `captain-definition` - CapRover frontend config
|
||||
- `backend/captain-definition` - CapRover backend config
|
||||
|
||||
**Configuration Details:**
|
||||
- Frontend nginx handles CORS headers for SPA routes and assets
|
||||
- Backend Flask-CORS configured for cross-origin API requests
|
||||
- Support for multiple allowed origins via environment variables
|
||||
- Preflight OPTIONS request handling
|
||||
- Credentials support for authenticated requests
|
||||
- Security headers and rate limiting guidance
|
||||
|
||||
**Benefits:**
|
||||
- ✅ Proper CORS configuration for frontend/backend separation
|
||||
- ✅ Support for https://frontend.example.com + https://backend.example.com architecture
|
||||
- ✅ Easy deployment to CapRover with Cloudflare CDN
|
||||
- ✅ Production-ready security configuration
|
||||
- ✅ Comprehensive troubleshooting documentation
|
||||
|
||||
---
|
||||
|
||||
#### 2. Complete JSON Migration
|
||||
**Priority:** HIGH
|
||||
**Effort:** MEDIUM
|
||||
**Status:** IN PROGRESS
|
||||
|
||||
20
backend/.env.production.example
Normal file
20
backend/.env.production.example
Normal file
@@ -0,0 +1,20 @@
|
||||
# Backend Environment Variables (Production)
|
||||
|
||||
# Allowed CORS origins (comma-separated)
|
||||
# Use your actual frontend domain(s)
|
||||
ALLOWED_ORIGINS=https://frontend.example.com,https://www.frontend.example.com
|
||||
|
||||
# Server Port
|
||||
PORT=5001
|
||||
|
||||
# Database path (use /data for persistent CapRover volume)
|
||||
DATABASE_PATH=/data/codeforge.db
|
||||
|
||||
# Debug mode (set to 'false' in production)
|
||||
DEBUG=false
|
||||
|
||||
# Optional: API Key for authentication
|
||||
# API_KEY=your-secure-api-key-here
|
||||
|
||||
# Optional: Rate limiting
|
||||
# RATELIMIT_STORAGE_URL=redis://localhost:6379
|
||||
@@ -7,7 +7,20 @@ from datetime import datetime
|
||||
from contextlib import contextmanager
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(app)
|
||||
|
||||
# CORS configuration for CapRover/Cloudflare deployment
|
||||
# Allow requests from frontend domain
|
||||
ALLOWED_ORIGINS = os.environ.get('ALLOWED_ORIGINS', '*').split(',')
|
||||
CORS(app,
|
||||
resources={r"/api/*": {
|
||||
"origins": ALLOWED_ORIGINS,
|
||||
"methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
||||
"allow_headers": ["Content-Type", "Authorization", "X-Requested-With"],
|
||||
"expose_headers": ["Content-Type", "X-Total-Count"],
|
||||
"supports_credentials": True,
|
||||
"max_age": 3600
|
||||
}},
|
||||
supports_credentials=True)
|
||||
|
||||
DATABASE_PATH = os.environ.get('DATABASE_PATH', '/data/codeforge.db')
|
||||
os.makedirs(os.path.dirname(DATABASE_PATH), exist_ok=True)
|
||||
|
||||
5
backend/captain-definition
Normal file
5
backend/captain-definition
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"schemaVersion": 2,
|
||||
"dockerfilePath": "./Dockerfile",
|
||||
"dockerfileLines": []
|
||||
}
|
||||
5
captain-definition
Normal file
5
captain-definition
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"schemaVersion": 2,
|
||||
"dockerfilePath": "./Dockerfile",
|
||||
"dockerfileLines": []
|
||||
}
|
||||
388
docs/CAPROVER_CLOUDFLARE_DEPLOYMENT.md
Normal file
388
docs/CAPROVER_CLOUDFLARE_DEPLOYMENT.md
Normal file
@@ -0,0 +1,388 @@
|
||||
# CapRover & Cloudflare CORS Configuration Guide
|
||||
|
||||
This guide covers deploying CodeForge with separate frontend and backend domains, properly configured for CORS.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Frontend: https://frontend.example.com (nginx serving React SPA)
|
||||
Backend: https://backend.example.com (Flask API)
|
||||
```
|
||||
|
||||
## Frontend Configuration
|
||||
|
||||
### 1. Nginx CORS Setup
|
||||
|
||||
The `nginx.conf` has been configured with proper CORS headers:
|
||||
|
||||
- **Access-Control-Allow-Origin**: Allows all origins (can be restricted)
|
||||
- **Access-Control-Allow-Methods**: GET, POST, PUT, DELETE, OPTIONS
|
||||
- **Access-Control-Allow-Headers**: All necessary headers including Authorization
|
||||
- **Preflight Handling**: OPTIONS requests are handled with 204 response
|
||||
|
||||
### 2. CapRover Frontend Setup
|
||||
|
||||
Create a new app in CapRover for the frontend:
|
||||
|
||||
```bash
|
||||
# App Settings
|
||||
App Name: codeforge-frontend
|
||||
Deployment Method: Docker Image Registry or Git
|
||||
Port: 80
|
||||
```
|
||||
|
||||
#### Environment Variables (Optional)
|
||||
```env
|
||||
# If you need to configure backend URL at build time
|
||||
VITE_BACKEND_URL=https://backend.example.com
|
||||
```
|
||||
|
||||
#### Captain Definition File
|
||||
Create `captain-definition` in project root:
|
||||
```json
|
||||
{
|
||||
"schemaVersion": 2,
|
||||
"dockerfilePath": "./Dockerfile"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Cloudflare Settings for Frontend
|
||||
|
||||
1. **SSL/TLS Mode**: Full (strict) or Full
|
||||
2. **Always Use HTTPS**: Enabled
|
||||
3. **Minimum TLS Version**: TLS 1.2
|
||||
4. **Automatic HTTPS Rewrites**: Enabled
|
||||
|
||||
#### Security Headers (Optional but Recommended)
|
||||
Go to Cloudflare Dashboard → Security → Settings → Security Headers:
|
||||
|
||||
```
|
||||
Strict-Transport-Security: max-age=31536000; includeSubDomains
|
||||
X-Content-Type-Options: nosniff
|
||||
X-Frame-Options: SAMEORIGIN
|
||||
```
|
||||
|
||||
**Note**: Don't add CORS headers in Cloudflare if nginx is already handling them.
|
||||
|
||||
## Backend Configuration
|
||||
|
||||
### 1. Flask CORS Setup
|
||||
|
||||
The backend has been configured with `flask-cors`:
|
||||
|
||||
```python
|
||||
ALLOWED_ORIGINS = os.environ.get('ALLOWED_ORIGINS', '*').split(',')
|
||||
CORS(app,
|
||||
resources={r"/api/*": {
|
||||
"origins": ALLOWED_ORIGINS,
|
||||
"methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
|
||||
"allow_headers": ["Content-Type", "Authorization", "X-Requested-With"],
|
||||
"expose_headers": ["Content-Type", "X-Total-Count"],
|
||||
"supports_credentials": True,
|
||||
"max_age": 3600
|
||||
}})
|
||||
```
|
||||
|
||||
### 2. CapRover Backend Setup
|
||||
|
||||
Create a new app in CapRover for the backend:
|
||||
|
||||
```bash
|
||||
# App Settings
|
||||
App Name: codeforge-backend
|
||||
Deployment Method: Docker Image Registry or Git
|
||||
Port: 5001 (or as configured)
|
||||
```
|
||||
|
||||
#### Environment Variables
|
||||
```env
|
||||
# Required
|
||||
ALLOWED_ORIGINS=https://frontend.example.com,https://www.frontend.example.com
|
||||
|
||||
# Optional
|
||||
PORT=5001
|
||||
DATABASE_PATH=/data/codeforge.db
|
||||
DEBUG=false
|
||||
```
|
||||
|
||||
#### Persistent Data Volume
|
||||
Enable persistent storage for SQLite database:
|
||||
```
|
||||
Container Path: /data
|
||||
Host Path: /captain/data/codeforge-backend
|
||||
```
|
||||
|
||||
#### Captain Definition File for Backend
|
||||
Create `backend/captain-definition`:
|
||||
```json
|
||||
{
|
||||
"schemaVersion": 2,
|
||||
"dockerfilePath": "./Dockerfile"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Cloudflare Settings for Backend
|
||||
|
||||
1. **SSL/TLS Mode**: Full (strict) or Full
|
||||
2. **Always Use HTTPS**: Enabled
|
||||
3. **Minimum TLS Version**: TLS 1.2
|
||||
4. **API Shield** (if available): Enable for API endpoints
|
||||
|
||||
## Frontend Code Configuration
|
||||
|
||||
### Environment-based Backend URL
|
||||
|
||||
Create `.env.production`:
|
||||
```env
|
||||
VITE_BACKEND_URL=https://backend.example.com
|
||||
VITE_USE_BACKEND=true
|
||||
```
|
||||
|
||||
### Runtime Configuration
|
||||
|
||||
The app auto-detects backend availability. Update your storage configuration:
|
||||
|
||||
```typescript
|
||||
// src/lib/storage-config.ts
|
||||
const BACKEND_URL = import.meta.env.VITE_BACKEND_URL ||
|
||||
window.RUNTIME_CONFIG?.backendUrl ||
|
||||
'http://localhost:5001'
|
||||
|
||||
const USE_BACKEND = import.meta.env.VITE_USE_BACKEND === 'true' ||
|
||||
window.RUNTIME_CONFIG?.useBackend === true
|
||||
```
|
||||
|
||||
## Testing CORS Configuration
|
||||
|
||||
### 1. Test Frontend CORS
|
||||
|
||||
```bash
|
||||
curl -X OPTIONS https://frontend.example.com \
|
||||
-H "Origin: https://other-domain.com" \
|
||||
-H "Access-Control-Request-Method: GET" \
|
||||
-v
|
||||
```
|
||||
|
||||
Expected response should include:
|
||||
```
|
||||
Access-Control-Allow-Origin: *
|
||||
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
|
||||
```
|
||||
|
||||
### 2. Test Backend CORS
|
||||
|
||||
```bash
|
||||
curl -X OPTIONS https://backend.example.com/api/storage/keys \
|
||||
-H "Origin: https://frontend.example.com" \
|
||||
-H "Access-Control-Request-Method: GET" \
|
||||
-v
|
||||
```
|
||||
|
||||
Expected response should include:
|
||||
```
|
||||
Access-Control-Allow-Origin: https://frontend.example.com
|
||||
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
|
||||
Access-Control-Allow-Credentials: true
|
||||
```
|
||||
|
||||
### 3. Test Cross-Origin Request
|
||||
|
||||
```bash
|
||||
curl -X GET https://backend.example.com/api/storage/keys \
|
||||
-H "Origin: https://frontend.example.com" \
|
||||
-v
|
||||
```
|
||||
|
||||
## Common Issues & Solutions
|
||||
|
||||
### Issue 1: CORS Error in Browser Console
|
||||
|
||||
**Error**: `No 'Access-Control-Allow-Origin' header is present`
|
||||
|
||||
**Solutions**:
|
||||
1. Verify `ALLOWED_ORIGINS` environment variable is set correctly on backend
|
||||
2. Check nginx config is properly loaded (restart CapRover app)
|
||||
3. Ensure Cloudflare is not stripping CORS headers
|
||||
|
||||
### Issue 2: Preflight Request Failing
|
||||
|
||||
**Error**: `Response to preflight request doesn't pass access control check`
|
||||
|
||||
**Solutions**:
|
||||
1. Verify OPTIONS method is allowed in both nginx and Flask
|
||||
2. Check that preflight response includes all required headers
|
||||
3. Increase `max_age` if requests are frequent
|
||||
|
||||
### Issue 3: Credentials Not Sent
|
||||
|
||||
**Error**: Cookies/credentials not sent with request
|
||||
|
||||
**Solutions**:
|
||||
1. Enable `credentials: 'include'` in fetch requests
|
||||
2. Set `supports_credentials: True` in Flask CORS config
|
||||
3. Don't use wildcard `*` for origin when credentials are needed
|
||||
|
||||
### Issue 4: Cloudflare Blocking Requests
|
||||
|
||||
**Error**: `CF-RAY` header present with 403/520 errors
|
||||
|
||||
**Solutions**:
|
||||
1. Whitelist your backend domain in Cloudflare Firewall
|
||||
2. Disable "Browser Integrity Check" temporarily for testing
|
||||
3. Check Cloudflare Security Level (set to "Low" for API endpoints)
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### 1. Restrict Origins in Production
|
||||
|
||||
Instead of `*`, specify exact origins:
|
||||
|
||||
```env
|
||||
# Backend .env
|
||||
ALLOWED_ORIGINS=https://frontend.example.com,https://www.frontend.example.com
|
||||
```
|
||||
|
||||
### 2. Use HTTPS Only
|
||||
|
||||
Ensure all requests use HTTPS. Update nginx to redirect HTTP to HTTPS:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Implement Rate Limiting
|
||||
|
||||
Add rate limiting to backend:
|
||||
|
||||
```python
|
||||
from flask_limiter import Limiter
|
||||
from flask_limiter.util import get_remote_address
|
||||
|
||||
limiter = Limiter(
|
||||
app=app,
|
||||
key_func=get_remote_address,
|
||||
default_limits=["200 per hour", "50 per minute"]
|
||||
)
|
||||
|
||||
@app.route('/api/storage/<key>', methods=['GET'])
|
||||
@limiter.limit("100 per minute")
|
||||
def get_value(key):
|
||||
# ...
|
||||
```
|
||||
|
||||
### 4. Add API Authentication
|
||||
|
||||
For production, add token-based authentication:
|
||||
|
||||
```python
|
||||
from functools import wraps
|
||||
from flask import request
|
||||
|
||||
def require_api_key(f):
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
api_key = request.headers.get('Authorization')
|
||||
if not api_key or not verify_api_key(api_key):
|
||||
return jsonify({'error': 'Unauthorized'}), 401
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
@app.route('/api/storage/<key>', methods=['PUT'])
|
||||
@require_api_key
|
||||
def set_value(key):
|
||||
# ...
|
||||
```
|
||||
|
||||
## CapRover Deployment Steps
|
||||
|
||||
### Deploy Frontend
|
||||
|
||||
1. Ensure Docker image builds successfully locally
|
||||
2. Push code to Git repository or Docker registry
|
||||
3. In CapRover:
|
||||
- Create new app: `codeforge-frontend`
|
||||
- Enable HTTPS
|
||||
- Connect custom domain: `frontend.example.com`
|
||||
- Deploy from Git/Registry
|
||||
- Verify deployment via browser
|
||||
|
||||
### Deploy Backend
|
||||
|
||||
1. Build and test backend Docker image
|
||||
2. In CapRover:
|
||||
- Create new app: `codeforge-backend`
|
||||
- Enable HTTPS
|
||||
- Connect custom domain: `backend.example.com`
|
||||
- Add environment variables (especially `ALLOWED_ORIGINS`)
|
||||
- Add persistent volume at `/data`
|
||||
- Deploy from Git/Registry
|
||||
- Verify health endpoint: `https://backend.example.com/health`
|
||||
|
||||
### Configure Cloudflare
|
||||
|
||||
1. Add DNS records for both domains (point to CapRover server)
|
||||
2. Enable Cloudflare proxy (orange cloud)
|
||||
3. Configure SSL/TLS settings
|
||||
4. Test both domains
|
||||
|
||||
## Monitoring & Debugging
|
||||
|
||||
### Check Nginx Logs (Frontend)
|
||||
```bash
|
||||
# In CapRover app terminal
|
||||
tail -f /var/log/nginx/access.log
|
||||
tail -f /var/log/nginx/error.log
|
||||
```
|
||||
|
||||
### Check Flask Logs (Backend)
|
||||
```bash
|
||||
# In CapRover app logs view or terminal
|
||||
tail -f /var/log/app.log
|
||||
```
|
||||
|
||||
### Browser DevTools
|
||||
1. Open Network tab
|
||||
2. Enable "Preserve log"
|
||||
3. Filter by domain to see cross-origin requests
|
||||
4. Check Response headers for CORS headers
|
||||
5. Look for preflight (OPTIONS) requests
|
||||
|
||||
## Example Fetch Configuration
|
||||
|
||||
### Frontend API Client
|
||||
|
||||
```typescript
|
||||
const API_BASE_URL = import.meta.env.VITE_BACKEND_URL || 'http://localhost:5001'
|
||||
|
||||
async function apiRequest(endpoint: string, options: RequestInit = {}) {
|
||||
const response = await fetch(`${API_BASE_URL}${endpoint}`, {
|
||||
...options,
|
||||
credentials: 'include', // Include cookies if needed
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...options.headers,
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`API error: ${response.statusText}`)
|
||||
}
|
||||
|
||||
return response.json()
|
||||
}
|
||||
|
||||
// Usage
|
||||
const data = await apiRequest('/api/storage/keys')
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [CapRover Documentation](https://caprover.com/docs/)
|
||||
- [Cloudflare SSL/TLS Documentation](https://developers.cloudflare.com/ssl/)
|
||||
- [Flask-CORS Documentation](https://flask-cors.readthedocs.io/)
|
||||
- [MDN CORS Guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)
|
||||
- [Nginx CORS Configuration](https://enable-cors.org/server_nginx.html)
|
||||
374
docs/CLOUDFLARE_CONFIGURATION.md
Normal file
374
docs/CLOUDFLARE_CONFIGURATION.md
Normal file
@@ -0,0 +1,374 @@
|
||||
# Cloudflare Configuration for CodeForge
|
||||
|
||||
This document outlines the recommended Cloudflare settings for deploying CodeForge with CapRover.
|
||||
|
||||
## DNS Configuration
|
||||
|
||||
### Frontend Domain
|
||||
```
|
||||
Type: A
|
||||
Name: frontend (or @)
|
||||
IPv4: <your-caprover-server-ip>
|
||||
Proxy status: Proxied (orange cloud)
|
||||
TTL: Auto
|
||||
```
|
||||
|
||||
### Backend Domain
|
||||
```
|
||||
Type: A
|
||||
Name: backend (or api)
|
||||
IPv4: <your-caprover-server-ip>
|
||||
Proxy status: Proxied (orange cloud)
|
||||
TTL: Auto
|
||||
```
|
||||
|
||||
### Optional: WWW Subdomain
|
||||
```
|
||||
Type: CNAME
|
||||
Name: www
|
||||
Target: frontend.example.com
|
||||
Proxy status: Proxied (orange cloud)
|
||||
TTL: Auto
|
||||
```
|
||||
|
||||
## SSL/TLS Settings
|
||||
|
||||
Navigate to: **SSL/TLS** → **Overview**
|
||||
|
||||
### Encryption Mode
|
||||
- **Recommended**: Full (strict)
|
||||
- **Alternative**: Full
|
||||
- **Never use**: Flexible (breaks HTTPS to origin)
|
||||
|
||||
### Edge Certificates
|
||||
Navigate to: **SSL/TLS** → **Edge Certificates**
|
||||
|
||||
- ✅ **Always Use HTTPS**: On
|
||||
- ✅ **HTTP Strict Transport Security (HSTS)**: Enable
|
||||
- Max Age: 12 months
|
||||
- Include subdomains: Yes
|
||||
- Preload: Yes (optional, but recommended)
|
||||
- ✅ **Minimum TLS Version**: TLS 1.2
|
||||
- ✅ **Opportunistic Encryption**: On
|
||||
- ✅ **TLS 1.3**: On
|
||||
- ✅ **Automatic HTTPS Rewrites**: On
|
||||
- ✅ **Certificate Transparency Monitoring**: On
|
||||
|
||||
## Firewall Rules
|
||||
|
||||
Navigate to: **Security** → **WAF** → **Firewall rules**
|
||||
|
||||
### Rule 1: Allow Backend API Requests
|
||||
```
|
||||
Rule name: Allow API Access
|
||||
Expression:
|
||||
(http.host eq "backend.example.com" and http.request.uri.path starts_with "/api/")
|
||||
Action: Allow
|
||||
```
|
||||
|
||||
### Rule 2: Rate Limit (Optional)
|
||||
```
|
||||
Rule name: API Rate Limit
|
||||
Expression:
|
||||
(http.host eq "backend.example.com" and http.request.uri.path starts_with "/api/")
|
||||
Action: Rate Limit
|
||||
Requests: 100 requests per minute
|
||||
Duration: 1 minute
|
||||
```
|
||||
|
||||
## Page Rules
|
||||
|
||||
Navigate to: **Rules** → **Page Rules**
|
||||
|
||||
### Rule 1: Backend API Caching
|
||||
```
|
||||
URL: backend.example.com/api/*
|
||||
Settings:
|
||||
- Cache Level: Bypass
|
||||
- Security Level: Medium
|
||||
- Browser Integrity Check: Off (for API)
|
||||
```
|
||||
|
||||
### Rule 2: Frontend Caching
|
||||
```
|
||||
URL: frontend.example.com/*
|
||||
Settings:
|
||||
- Cache Level: Standard
|
||||
- Browser Cache TTL: 4 hours
|
||||
- Edge Cache TTL: 2 hours
|
||||
```
|
||||
|
||||
### Rule 3: Frontend Assets Caching
|
||||
```
|
||||
URL: frontend.example.com/assets/*
|
||||
Settings:
|
||||
- Cache Level: Cache Everything
|
||||
- Edge Cache TTL: 1 month
|
||||
- Browser Cache TTL: 1 month
|
||||
```
|
||||
|
||||
## Speed Settings
|
||||
|
||||
Navigate to: **Speed** → **Optimization**
|
||||
|
||||
### Auto Minify
|
||||
- ✅ JavaScript
|
||||
- ✅ CSS
|
||||
- ✅ HTML
|
||||
|
||||
### Brotli
|
||||
- ✅ On
|
||||
|
||||
### Rocket Loader
|
||||
- ⚠️ Off (can break SPA)
|
||||
|
||||
### Mirage
|
||||
- ⚠️ Off (for modern SPAs)
|
||||
|
||||
### Polish
|
||||
- Optional: Lossy or Lossless (for images)
|
||||
|
||||
## Network Settings
|
||||
|
||||
Navigate to: **Network**
|
||||
|
||||
### HTTP/3 (with QUIC)
|
||||
- ✅ On
|
||||
|
||||
### HTTP/2
|
||||
- ✅ On
|
||||
|
||||
### 0-RTT Connection Resumption
|
||||
- ✅ On
|
||||
|
||||
### WebSockets
|
||||
- ✅ On (required for backend WebSocket connections if used)
|
||||
|
||||
### gRPC
|
||||
- Optional: On (if using gRPC)
|
||||
|
||||
## Caching Configuration
|
||||
|
||||
Navigate to: **Caching** → **Configuration**
|
||||
|
||||
### Caching Level
|
||||
- Standard
|
||||
|
||||
### Browser Cache TTL
|
||||
- 4 hours (adjust as needed)
|
||||
|
||||
### Always Online
|
||||
- ✅ On (serves cached version when origin is down)
|
||||
|
||||
### Development Mode
|
||||
- Use temporarily during testing (disables caching for 3 hours)
|
||||
|
||||
## Transform Rules (for CORS Headers)
|
||||
|
||||
Navigate to: **Rules** → **Transform Rules** → **Modify Response Header**
|
||||
|
||||
⚠️ **Important**: Only add these if nginx is NOT handling CORS headers.
|
||||
|
||||
### Add CORS Headers to Frontend
|
||||
```
|
||||
Rule name: Frontend CORS Headers
|
||||
Expression: http.host eq "frontend.example.com"
|
||||
Actions:
|
||||
Set dynamic header:
|
||||
- Header name: Access-Control-Allow-Origin
|
||||
- Value: *
|
||||
Set static header:
|
||||
- Header name: Access-Control-Allow-Methods
|
||||
- Value: GET, POST, PUT, DELETE, OPTIONS
|
||||
Set static header:
|
||||
- Header name: Access-Control-Allow-Headers
|
||||
- Value: Content-Type, Authorization
|
||||
```
|
||||
|
||||
### Add CORS Headers to Backend
|
||||
```
|
||||
Rule name: Backend CORS Headers
|
||||
Expression: http.host eq "backend.example.com"
|
||||
Actions:
|
||||
Set dynamic header:
|
||||
- Header name: Access-Control-Allow-Origin
|
||||
- Value: https://frontend.example.com
|
||||
Set static header:
|
||||
- Header name: Access-Control-Allow-Methods
|
||||
- Value: GET, POST, PUT, DELETE, OPTIONS
|
||||
Set static header:
|
||||
- Header name: Access-Control-Allow-Credentials
|
||||
- Value: true
|
||||
```
|
||||
|
||||
## Security Settings
|
||||
|
||||
Navigate to: **Security** → **Settings**
|
||||
|
||||
### Security Level
|
||||
- Medium (for production)
|
||||
- Low (for testing/development)
|
||||
|
||||
### Challenge Passage
|
||||
- 30 minutes
|
||||
|
||||
### Browser Integrity Check
|
||||
- ✅ On (for frontend)
|
||||
- ⚠️ Off (for backend API to avoid blocking legitimate API clients)
|
||||
|
||||
### Privacy Pass Support
|
||||
- ✅ On
|
||||
|
||||
## DDoS Protection
|
||||
|
||||
Navigate to: **Security** → **DDoS**
|
||||
|
||||
- Managed by Cloudflare automatically
|
||||
- No configuration needed
|
||||
- Monitor attacks in dashboard
|
||||
|
||||
## Bot Management (Enterprise/Business Plans)
|
||||
|
||||
Navigate to: **Security** → **Bots**
|
||||
|
||||
### Bot Fight Mode (Free/Pro/Business)
|
||||
- ⚠️ Off for API endpoints (can block legitimate requests)
|
||||
- ✅ On for frontend (protects against scrapers)
|
||||
|
||||
### Super Bot Fight Mode (Business+)
|
||||
- Configure to allow verified bots
|
||||
- Block definitely automated traffic
|
||||
|
||||
## Analytics & Monitoring
|
||||
|
||||
### Web Analytics
|
||||
Navigate to: **Analytics & Logs** → **Web Analytics**
|
||||
- Enable to track frontend traffic
|
||||
|
||||
### Health Checks
|
||||
Navigate to: **Traffic** → **Health Checks**
|
||||
|
||||
#### Frontend Health Check
|
||||
```
|
||||
Name: Frontend Health
|
||||
URL: https://frontend.example.com/health
|
||||
Type: HTTPS
|
||||
Method: GET
|
||||
Expected Status: 200
|
||||
Interval: 60 seconds
|
||||
```
|
||||
|
||||
#### Backend Health Check
|
||||
```
|
||||
Name: Backend Health
|
||||
URL: https://backend.example.com/health
|
||||
Type: HTTPS
|
||||
Method: GET
|
||||
Expected Status: 200
|
||||
Interval: 60 seconds
|
||||
```
|
||||
|
||||
## Origin Rules (for CapRover)
|
||||
|
||||
Navigate to: **Rules** → **Origin Rules**
|
||||
|
||||
### Set Origin to CapRover
|
||||
```
|
||||
Rule name: Forward to CapRover
|
||||
Expression: http.host in {"frontend.example.com" "backend.example.com"}
|
||||
Actions:
|
||||
- Override origin: <caprover-server-ip>
|
||||
- Override port: 443
|
||||
```
|
||||
|
||||
## Testing Cloudflare Configuration
|
||||
|
||||
### 1. Verify SSL
|
||||
```bash
|
||||
curl -I https://frontend.example.com
|
||||
# Should return: HTTP/2 200
|
||||
# Check for: strict-transport-security header
|
||||
```
|
||||
|
||||
### 2. Verify CORS
|
||||
```bash
|
||||
curl -X OPTIONS https://backend.example.com/api/storage/keys \
|
||||
-H "Origin: https://frontend.example.com" \
|
||||
-H "Access-Control-Request-Method: GET" \
|
||||
-v
|
||||
```
|
||||
|
||||
### 3. Check Caching
|
||||
```bash
|
||||
curl -I https://frontend.example.com/assets/index.js
|
||||
# Should return: cf-cache-status: HIT (after first request)
|
||||
```
|
||||
|
||||
### 4. Test Rate Limiting
|
||||
```bash
|
||||
# Run multiple times quickly
|
||||
for i in {1..150}; do
|
||||
curl https://backend.example.com/api/storage/keys
|
||||
done
|
||||
# Should eventually get rate limited
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: 520/521/522 Errors
|
||||
|
||||
**Cause**: Cloudflare can't connect to origin server
|
||||
|
||||
**Solutions**:
|
||||
1. Verify CapRover server is running
|
||||
2. Check firewall allows Cloudflare IPs
|
||||
3. Verify SSL certificate on origin
|
||||
4. Check Cloudflare SSL mode is not "Flexible"
|
||||
|
||||
### Issue: CORS Errors Still Occurring
|
||||
|
||||
**Cause**: Conflicting CORS headers from multiple sources
|
||||
|
||||
**Solutions**:
|
||||
1. Remove CORS headers from Cloudflare Transform Rules if nginx handles them
|
||||
2. Check both nginx and Flask CORS configs
|
||||
3. Use browser DevTools to see which headers are present
|
||||
|
||||
### Issue: Assets Not Caching
|
||||
|
||||
**Cause**: Cache rules not properly configured
|
||||
|
||||
**Solutions**:
|
||||
1. Verify page rules are in correct order (more specific first)
|
||||
2. Check cache level is appropriate
|
||||
3. Enable Development Mode temporarily to bypass cache
|
||||
4. Purge cache and retry
|
||||
|
||||
### Issue: API Requests Being Blocked
|
||||
|
||||
**Cause**: Bot Fight Mode or firewall rules
|
||||
|
||||
**Solutions**:
|
||||
1. Disable Bot Fight Mode for backend domain
|
||||
2. Check firewall events for blocked requests
|
||||
3. Whitelist your IP or API client user-agent
|
||||
4. Disable Browser Integrity Check for API
|
||||
|
||||
## Recommended Setup Order
|
||||
|
||||
1. ✅ Set up DNS records (A records for both domains)
|
||||
2. ✅ Configure SSL/TLS (Full or Full Strict mode)
|
||||
3. ✅ Enable HTTPS redirects and HSTS
|
||||
4. ✅ Configure firewall rules (if needed)
|
||||
5. ✅ Set up page rules for caching
|
||||
6. ✅ Configure health checks
|
||||
7. ✅ Enable speed optimizations
|
||||
8. ✅ Test thoroughly before going live
|
||||
9. ✅ Monitor analytics and logs
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [Cloudflare Support](https://support.cloudflare.com/)
|
||||
- [Cloudflare Community](https://community.cloudflare.com/)
|
||||
- [Cloudflare Developers Docs](https://developers.cloudflare.com/)
|
||||
- [Cloudflare Status](https://www.cloudflarestatus.com/)
|
||||
244
docs/DEPLOYMENT_CHECKLIST.md
Normal file
244
docs/DEPLOYMENT_CHECKLIST.md
Normal file
@@ -0,0 +1,244 @@
|
||||
# CapRover/Cloudflare Deployment Checklist
|
||||
|
||||
Quick reference guide for deploying CodeForge to CapRover with Cloudflare.
|
||||
|
||||
## Pre-Deployment
|
||||
|
||||
- [ ] CapRover server is running and accessible
|
||||
- [ ] Domains registered and pointing to Cloudflare nameservers
|
||||
- [ ] Docker is installed locally (for testing builds)
|
||||
- [ ] Git repository is ready for deployment
|
||||
|
||||
## Frontend Deployment
|
||||
|
||||
### 1. Configuration
|
||||
- [ ] Copy `.env.production.example` to `.env.production`
|
||||
- [ ] Update `VITE_BACKEND_URL` with your backend domain
|
||||
- [ ] Update `VITE_USE_BACKEND=true` if using backend
|
||||
|
||||
### 2. CapRover App Setup
|
||||
- [ ] Create new app: `codeforge-frontend`
|
||||
- [ ] Enable HTTPS in CapRover app settings
|
||||
- [ ] Connect custom domain: `frontend.example.com`
|
||||
- [ ] Configure environment variables (if any)
|
||||
|
||||
### 3. Deploy
|
||||
- [ ] Push code to Git repository
|
||||
- [ ] Deploy via CapRover (Git/Registry/Upload)
|
||||
- [ ] Wait for build to complete
|
||||
- [ ] Check build logs for errors
|
||||
|
||||
### 4. Verify
|
||||
- [ ] Visit `https://frontend.example.com`
|
||||
- [ ] Check browser console for errors
|
||||
- [ ] Verify assets load correctly
|
||||
- [ ] Test app functionality
|
||||
|
||||
## Backend Deployment
|
||||
|
||||
### 1. Configuration
|
||||
- [ ] Copy `backend/.env.production.example` to `backend/.env.production`
|
||||
- [ ] Update `ALLOWED_ORIGINS` with frontend domains
|
||||
- [ ] Set `DEBUG=false` for production
|
||||
- [ ] Configure `DATABASE_PATH=/data/codeforge.db`
|
||||
|
||||
### 2. CapRover App Setup
|
||||
- [ ] Create new app: `codeforge-backend`
|
||||
- [ ] Enable HTTPS in CapRover app settings
|
||||
- [ ] Connect custom domain: `backend.example.com`
|
||||
- [ ] Add environment variables:
|
||||
- [ ] `ALLOWED_ORIGINS=https://frontend.example.com`
|
||||
- [ ] `PORT=5001`
|
||||
- [ ] `DATABASE_PATH=/data/codeforge.db`
|
||||
- [ ] `DEBUG=false`
|
||||
- [ ] Configure persistent volume:
|
||||
- [ ] Container path: `/data`
|
||||
- [ ] Label: `backend-data`
|
||||
|
||||
### 3. Deploy
|
||||
- [ ] Deploy backend via CapRover
|
||||
- [ ] Wait for build to complete
|
||||
- [ ] Check build logs for errors
|
||||
|
||||
### 4. Verify
|
||||
- [ ] Visit `https://backend.example.com/health`
|
||||
- [ ] Should return: `{"status": "ok", "timestamp": "..."}`
|
||||
- [ ] Test API endpoint: `https://backend.example.com/api/storage/keys`
|
||||
- [ ] Check response includes CORS headers
|
||||
|
||||
## Cloudflare Configuration
|
||||
|
||||
### DNS
|
||||
- [ ] Add A record for frontend pointing to CapRover server IP
|
||||
- [ ] Add A record for backend pointing to CapRover server IP
|
||||
- [ ] Enable proxy (orange cloud) for both records
|
||||
|
||||
### SSL/TLS
|
||||
- [ ] Set encryption mode to "Full (strict)" or "Full"
|
||||
- [ ] Enable "Always Use HTTPS"
|
||||
- [ ] Enable HSTS (optional but recommended)
|
||||
- [ ] Set minimum TLS version to 1.2
|
||||
|
||||
### Speed & Caching
|
||||
- [ ] Enable Auto Minify (JS, CSS, HTML)
|
||||
- [ ] Enable Brotli compression
|
||||
- [ ] Disable Rocket Loader (can break SPA)
|
||||
- [ ] Configure page rules:
|
||||
- [ ] Backend API: Cache Level = Bypass
|
||||
- [ ] Frontend: Cache Level = Standard
|
||||
- [ ] Frontend Assets: Cache Everything, TTL = 1 month
|
||||
|
||||
### Security
|
||||
- [ ] Set security level to "Medium"
|
||||
- [ ] Disable "Browser Integrity Check" for backend
|
||||
- [ ] Configure firewall rules (if needed)
|
||||
- [ ] Set up rate limiting (optional)
|
||||
|
||||
### Health Checks
|
||||
- [ ] Add health check for frontend: `https://frontend.example.com/health`
|
||||
- [ ] Add health check for backend: `https://backend.example.com/health`
|
||||
|
||||
## Testing
|
||||
|
||||
### CORS Testing
|
||||
```bash
|
||||
# Test backend CORS
|
||||
curl -X OPTIONS https://backend.example.com/api/storage/keys \
|
||||
-H "Origin: https://frontend.example.com" \
|
||||
-H "Access-Control-Request-Method: GET" \
|
||||
-v
|
||||
|
||||
# Expected: Access-Control-Allow-Origin header in response
|
||||
```
|
||||
|
||||
### SSL Testing
|
||||
```bash
|
||||
# Test SSL
|
||||
curl -I https://frontend.example.com
|
||||
curl -I https://backend.example.com
|
||||
|
||||
# Expected: HTTP/2 200 with security headers
|
||||
```
|
||||
|
||||
### Functionality Testing
|
||||
- [ ] Open frontend in browser
|
||||
- [ ] Open DevTools → Network tab
|
||||
- [ ] Test creating/reading/updating data
|
||||
- [ ] Verify API calls to backend succeed
|
||||
- [ ] Check for CORS errors in console
|
||||
- [ ] Test on multiple browsers (Chrome, Firefox, Safari)
|
||||
- [ ] Test on mobile devices
|
||||
|
||||
### Performance Testing
|
||||
- [ ] Run Lighthouse audit on frontend
|
||||
- [ ] Check page load times
|
||||
- [ ] Verify assets are cached (cf-cache-status: HIT)
|
||||
- [ ] Test from multiple geographic locations
|
||||
|
||||
## Post-Deployment
|
||||
|
||||
### Monitoring
|
||||
- [ ] Set up Cloudflare alerts for downtime
|
||||
- [ ] Monitor CapRover logs for errors
|
||||
- [ ] Check health endpoints regularly
|
||||
- [ ] Review Cloudflare Analytics
|
||||
|
||||
### Backups
|
||||
- [ ] Verify database backups are working
|
||||
- [ ] Test database restore procedure
|
||||
- [ ] Export project data via API
|
||||
- [ ] Document backup schedule
|
||||
|
||||
### Documentation
|
||||
- [ ] Document custom configuration
|
||||
- [ ] Update team on deployment URLs
|
||||
- [ ] Create runbook for common issues
|
||||
- [ ] Document rollback procedure
|
||||
|
||||
## Rollback Procedure
|
||||
|
||||
If deployment fails:
|
||||
|
||||
1. [ ] Check CapRover logs for errors
|
||||
2. [ ] Review Cloudflare Firewall events
|
||||
3. [ ] Disable Cloudflare proxy temporarily (gray cloud)
|
||||
4. [ ] Test direct connection to CapRover server
|
||||
5. [ ] Revert to previous Docker image
|
||||
6. [ ] Re-enable Cloudflare proxy after fix
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Frontend loads but API calls fail
|
||||
- Check CORS configuration in backend
|
||||
- Verify `ALLOWED_ORIGINS` environment variable
|
||||
- Check Cloudflare firewall isn't blocking requests
|
||||
- Verify backend domain is accessible
|
||||
|
||||
### 502/520 Errors
|
||||
- Check CapRover app is running
|
||||
- Verify SSL certificates are valid
|
||||
- Check Cloudflare SSL mode (should be Full or Full Strict)
|
||||
- Verify origin server accepts connections on port 443
|
||||
|
||||
### Assets not loading
|
||||
- Check nginx configuration is correct
|
||||
- Verify Vite build completed successfully
|
||||
- Check Cloudflare caching rules
|
||||
- Purge Cloudflare cache and retry
|
||||
|
||||
### Database not persisting
|
||||
- Verify persistent volume is mounted
|
||||
- Check `DATABASE_PATH` environment variable
|
||||
- Verify `/data` directory has write permissions
|
||||
- Check CapRover volume configuration
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Frontend URL
|
||||
```
|
||||
https://frontend.example.com
|
||||
```
|
||||
|
||||
### Backend URL
|
||||
```
|
||||
https://backend.example.com
|
||||
```
|
||||
|
||||
### Health Endpoints
|
||||
```
|
||||
Frontend: https://frontend.example.com/health
|
||||
Backend: https://backend.example.com/health
|
||||
```
|
||||
|
||||
### API Base URL
|
||||
```
|
||||
https://backend.example.com/api
|
||||
```
|
||||
|
||||
### CapRover Apps
|
||||
```
|
||||
Frontend: codeforge-frontend
|
||||
Backend: codeforge-backend
|
||||
```
|
||||
|
||||
## Support Resources
|
||||
|
||||
- **CapRover Docs**: https://caprover.com/docs/
|
||||
- **Cloudflare Docs**: https://developers.cloudflare.com/
|
||||
- **Project Docs**: `/docs/CAPROVER_CLOUDFLARE_DEPLOYMENT.md`
|
||||
- **Cloudflare Config**: `/docs/CLOUDFLARE_CONFIGURATION.md`
|
||||
|
||||
## Emergency Contacts
|
||||
|
||||
Document your team's contact information:
|
||||
|
||||
- DevOps Lead: _____________
|
||||
- Backend Developer: _____________
|
||||
- Frontend Developer: _____________
|
||||
- CapRover Admin: _____________
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: [Date]
|
||||
**Deployed By**: [Name]
|
||||
**Deployment Date**: [Date]
|
||||
22
nginx.conf
22
nginx.conf
@@ -7,6 +7,23 @@ server {
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
|
||||
# CORS headers for frontend
|
||||
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
|
||||
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
|
||||
|
||||
# Handle preflight requests
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
|
||||
add_header 'Access-Control-Max-Age' 1728000;
|
||||
add_header 'Content-Type' 'text/plain; charset=utf-8';
|
||||
add_header 'Content-Length' 0;
|
||||
return 204;
|
||||
}
|
||||
}
|
||||
|
||||
location /health {
|
||||
@@ -18,6 +35,11 @@ server {
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
|
||||
# CORS for assets
|
||||
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
|
||||
}
|
||||
|
||||
gzip on;
|
||||
|
||||
Reference in New Issue
Block a user