The /health route returns JSON status for Docker Swarm to verify container health during deployment. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
381 lines
9.0 KiB
Markdown
381 lines
9.0 KiB
Markdown
# Cloudflare Setup for Mylder Platform
|
|
|
|
## Overview
|
|
Cloudflare configuration for https://mylder.io - Next.js 16 frontend with self-hosted backend (Supabase, n8n) via Dokploy/Traefik.
|
|
|
|
**VPS:** 149.102.155.84
|
|
**Stack:** Next.js 16 → Traefik → Cloudflare CDN
|
|
|
|
## DNS Configuration
|
|
|
|
### Step 1: Add Domain to Cloudflare
|
|
1. Cloudflare Dashboard → Add Site → mylder.io
|
|
2. Update nameservers at domain registrar to Cloudflare's nameservers
|
|
|
|
### Step 2: DNS Records
|
|
|
|
| Type | Name | Target | Proxy Status | Notes |
|
|
|------|------|--------|--------------|-------|
|
|
| A | @ | 149.102.155.84 | Proxied (orange cloud) | Main site |
|
|
| A | www | 149.102.155.84 | Proxied | WWW redirect |
|
|
| A | dokploy | 149.102.155.84 | DNS Only (grey cloud) | Dokploy dashboard - skip CDN |
|
|
| A | supabase | 149.102.155.84 | DNS Only | Supabase API - skip CDN |
|
|
| A | n8n | 149.102.155.84 | DNS Only | n8n webhooks - skip CDN |
|
|
| A | gitea | 149.102.155.84 | DNS Only | Git push/pull - skip CDN |
|
|
| A | saas | 149.102.155.84 | DNS Only | Zulip chat - skip CDN |
|
|
|
|
**Key Principle:**
|
|
- **Proxied (CDN):** Frontend, static assets, public content
|
|
- **DNS Only:** Admin tools, APIs with authentication, real-time services
|
|
|
|
### Step 3: Subdomain Wildcard (Optional)
|
|
If you need dynamic subdomains (e.g., tenant.mylder.io):
|
|
```
|
|
CNAME * @ (Proxied)
|
|
```
|
|
|
|
## SSL/TLS Settings
|
|
|
|
### Encryption Mode: Full (Strict)
|
|
**Path:** SSL/TLS → Overview → Full (strict)
|
|
|
|
**Why:** Traefik already provides Let's Encrypt certificates. Full (strict) ensures end-to-end encryption:
|
|
```
|
|
Browser → Cloudflare (encrypted) → Traefik (encrypted) → App
|
|
```
|
|
|
|
### Edge Certificates
|
|
**Path:** SSL/TLS → Edge Certificates
|
|
|
|
- **Always Use HTTPS:** ON
|
|
- **Minimum TLS Version:** 1.2
|
|
- **Opportunistic Encryption:** ON
|
|
- **TLS 1.3:** ON
|
|
- **Automatic HTTPS Rewrites:** ON
|
|
- **Certificate Transparency Monitoring:** ON
|
|
|
|
### Origin Server
|
|
**Path:** SSL/TLS → Origin Server
|
|
|
|
No action needed - Traefik manages Let's Encrypt certificates automatically.
|
|
|
|
## Caching Rules
|
|
|
|
### Default Cache Levels
|
|
**Path:** Caching → Configuration
|
|
|
|
- **Caching Level:** Standard
|
|
- **Browser Cache TTL:** Respect Existing Headers
|
|
- **Always Online:** ON (serves stale content if origin is down)
|
|
|
|
### Cache Rules for Next.js
|
|
**Path:** Rules → Page Rules (legacy) or Cache Rules (new)**
|
|
|
|
#### Rule 1: Static Assets (Aggressive Caching)
|
|
```
|
|
URL Pattern: mylder.io/_next/static/*
|
|
Settings:
|
|
- Cache Level: Cache Everything
|
|
- Edge Cache TTL: 1 year
|
|
- Browser Cache TTL: 1 year
|
|
```
|
|
|
|
#### Rule 2: Images (Smart Caching)
|
|
```
|
|
URL Pattern: mylder.io/_next/image/*
|
|
Settings:
|
|
- Cache Level: Cache Everything
|
|
- Edge Cache TTL: 30 days
|
|
- Browser Cache TTL: 7 days
|
|
```
|
|
|
|
#### Rule 3: API Routes (No Cache)
|
|
```
|
|
URL Pattern: mylder.io/api/*
|
|
Settings:
|
|
- Cache Level: Bypass
|
|
```
|
|
|
|
#### Rule 4: Dynamic Pages (Smart Cache)
|
|
```
|
|
URL Pattern: mylder.io/*
|
|
Settings:
|
|
- Cache Level: Standard
|
|
- Edge Cache TTL: 2 hours
|
|
- Browser Cache TTL: 30 minutes
|
|
```
|
|
|
|
### Next.js Cache Headers
|
|
Ensure your Next.js app sets proper headers:
|
|
|
|
```typescript
|
|
// next.config.ts
|
|
const nextConfig = {
|
|
async headers() {
|
|
return [
|
|
{
|
|
source: '/_next/static/:path*',
|
|
headers: [
|
|
{
|
|
key: 'Cache-Control',
|
|
value: 'public, max-age=31536000, immutable',
|
|
},
|
|
],
|
|
},
|
|
{
|
|
source: '/_next/image/:path*',
|
|
headers: [
|
|
{
|
|
key: 'Cache-Control',
|
|
value: 'public, max-age=2592000, stale-while-revalidate=86400',
|
|
},
|
|
],
|
|
},
|
|
];
|
|
},
|
|
};
|
|
```
|
|
|
|
### Cache Purge Strategy
|
|
**Path:** Caching → Configuration → Purge Cache
|
|
|
|
- **On Deploy:** Purge Everything (via API or Dashboard)
|
|
- **On Content Update:** Purge by Tag/URL
|
|
- **Emergency:** Purge Everything button
|
|
|
|
**API Purge (for CI/CD):**
|
|
```bash
|
|
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache" \
|
|
-H "Authorization: Bearer {api_token}" \
|
|
-H "Content-Type: application/json" \
|
|
--data '{"purge_everything":true}'
|
|
```
|
|
|
|
## Speed Optimization
|
|
|
|
### Auto Minify
|
|
**Path:** Speed → Optimization
|
|
|
|
- **JavaScript:** ON
|
|
- **CSS:** ON
|
|
- **HTML:** ON
|
|
|
|
### Brotli Compression
|
|
**Path:** Speed → Optimization
|
|
|
|
- **Brotli:** ON (better than gzip)
|
|
|
|
### Early Hints
|
|
**Path:** Speed → Optimization
|
|
|
|
- **Early Hints:** ON (preload critical resources)
|
|
|
|
### Rocket Loader
|
|
**Path:** Speed → Optimization
|
|
|
|
- **Rocket Loader:** OFF (can conflict with React hydration)
|
|
|
|
### Image Optimization
|
|
**Path:** Speed → Optimization → Image Resizing
|
|
|
|
- **Polish:** Lossless (or Lossy for smaller files)
|
|
- **Mirage:** ON (lazy loading for mobile)
|
|
- **Image Resizing:** Available on Pro+ plan
|
|
|
|
**Next.js Image Optimization:**
|
|
```typescript
|
|
// next.config.ts
|
|
const nextConfig = {
|
|
images: {
|
|
formats: ['image/avif', 'image/webp'],
|
|
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048],
|
|
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
|
|
minimumCacheTTL: 2592000, // 30 days
|
|
},
|
|
};
|
|
```
|
|
|
|
## Security Settings
|
|
|
|
### SSL/TLS
|
|
- **Always Use HTTPS:** ON
|
|
- **HSTS:** Enable with max-age=31536000, includeSubDomains
|
|
|
|
### Firewall (WAF)
|
|
**Path:** Security → WAF
|
|
|
|
#### Managed Rules (Free Tier)
|
|
- **Cloudflare Managed Ruleset:** ON
|
|
- **OWASP Core Ruleset:** ON
|
|
|
|
#### Rate Limiting (Pro+ Plan)
|
|
```yaml
|
|
Rule: API Protection
|
|
If: Request URL contains /api/
|
|
Then: Rate limit 100 requests per minute per IP
|
|
```
|
|
|
|
#### Bot Fight Mode (Free)
|
|
**Path:** Security → Bots
|
|
|
|
- **Bot Fight Mode:** ON
|
|
- **Super Bot Fight Mode:** Pro+ plan
|
|
|
|
### Security Level
|
|
**Path:** Security → Settings
|
|
|
|
- **Security Level:** Medium (balance between security and UX)
|
|
|
|
### Challenge Passage
|
|
**Path:** Security → Settings
|
|
|
|
- **Challenge Passage:** 30 minutes
|
|
|
|
## Network Settings
|
|
|
|
### HTTP/2 & HTTP/3
|
|
**Path:** Network
|
|
|
|
- **HTTP/2:** ON (default)
|
|
- **HTTP/3 (QUIC):** ON (faster connections)
|
|
- **0-RTT Connection Resumption:** ON
|
|
|
|
### WebSockets
|
|
**Path:** Network
|
|
|
|
- **WebSockets:** ON (required for real-time features)
|
|
|
|
### gRPC
|
|
**Path:** Network
|
|
|
|
- **gRPC:** OFF (not needed for standard Next.js)
|
|
|
|
## Analytics & Monitoring
|
|
|
|
### Web Analytics
|
|
**Path:** Analytics & Logs → Web Analytics
|
|
|
|
- Enable Cloudflare Web Analytics (privacy-friendly, no cookie banner needed)
|
|
|
|
### Performance Monitoring
|
|
- **Core Web Vitals:** Track LCP, FID, CLS
|
|
- **Page Load Time:** Monitor at edge
|
|
|
|
### Real User Monitoring (RUM)
|
|
Add Cloudflare Zaraz or custom analytics:
|
|
```html
|
|
<!-- Cloudflare Web Analytics -->
|
|
<script defer src='https://static.cloudflareinsights.com/beacon.min.js'
|
|
data-cf-beacon='{"token": "YOUR_TOKEN"}'></script>
|
|
```
|
|
|
|
## Subdomain Configuration
|
|
|
|
Since you have multiple services, ensure proper routing:
|
|
|
|
### Traefik Labels (Dokploy Docker Compose)
|
|
```yaml
|
|
services:
|
|
app:
|
|
labels:
|
|
- "traefik.enable=true"
|
|
- "traefik.http.routers.mylder.rule=Host(`mylder.io`) || Host(`www.mylder.io`)"
|
|
- "traefik.http.routers.mylder.tls=true"
|
|
- "traefik.http.routers.mylder.tls.certresolver=letsencrypt"
|
|
```
|
|
|
|
### WWW Redirect (Cloudflare)
|
|
**Path:** Rules → Redirect Rules
|
|
|
|
```
|
|
If: Hostname equals www.mylder.io
|
|
Then: Redirect to https://mylder.io$1 (301 permanent)
|
|
```
|
|
|
|
## Testing Checklist
|
|
|
|
### DNS Propagation
|
|
```bash
|
|
dig mylder.io
|
|
nslookup mylder.io
|
|
```
|
|
|
|
### SSL Certificate
|
|
```bash
|
|
curl -I https://mylder.io
|
|
# Check for: HTTP/2 200, cf-cache-status header
|
|
```
|
|
|
|
### Cache Verification
|
|
```bash
|
|
curl -I https://mylder.io/_next/static/[hash]/[file].js
|
|
# Look for: cf-cache-status: HIT
|
|
```
|
|
|
|
### Performance
|
|
```bash
|
|
# Lighthouse
|
|
npx lighthouse https://mylder.io --view
|
|
|
|
# WebPageTest
|
|
# Visit https://www.webpagetest.org
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### 521 Error (Web Server Down)
|
|
- Check Traefik is running: `docker ps | grep traefik`
|
|
- Check Dokploy deployment status
|
|
|
|
### 522 Error (Connection Timed Out)
|
|
- Verify firewall allows Cloudflare IPs
|
|
- Check VPS security groups
|
|
|
|
### 525 Error (SSL Handshake Failed)
|
|
- Ensure SSL/TLS mode is "Full (strict)"
|
|
- Verify Traefik has valid Let's Encrypt certificate
|
|
|
|
### Cache Not Working
|
|
- Check Cache-Control headers in response
|
|
- Verify Page Rules are active
|
|
- Clear Cloudflare cache and test
|
|
|
|
### Mixed Content Warnings
|
|
- Enable "Automatic HTTPS Rewrites"
|
|
- Update hardcoded http:// URLs to https://
|
|
|
|
## Cost Optimization
|
|
|
|
### Free Plan Limits
|
|
- 100k requests/day (~3M/month)
|
|
- Unlimited bandwidth
|
|
- Basic DDoS protection
|
|
- Shared SSL certificate
|
|
- 3 Page Rules
|
|
|
|
### When to Upgrade to Pro ($20/month)
|
|
- Need more than 3 Page Rules
|
|
- Want Image Optimization (Polish, Mirage)
|
|
- Need custom SSL certificate
|
|
- Require advanced WAF rules
|
|
- Want priority support
|
|
|
|
### Enterprise Features (for future)
|
|
- Cloudflare Workers (serverless at edge)
|
|
- Load Balancing
|
|
- Argo Smart Routing
|
|
- Custom WAF rules
|
|
|
|
## Next Steps
|
|
|
|
1. **Immediate:** DNS + SSL/TLS setup
|
|
2. **Week 1:** Caching rules + performance testing
|
|
3. **Month 1:** Monitor analytics, tune cache rules
|
|
4. **Quarter 1:** Consider Workers for edge logic (see cloudflare-workers-roadmap.md)
|
|
|
|
## References
|
|
|
|
- [Cloudflare DNS Docs](https://developers.cloudflare.com/dns/)
|
|
- [Next.js Cloudflare Deployment](https://nextjs.org/docs/app/building-your-application/deploying)
|
|
- [Cloudflare Cache API](https://developers.cloudflare.com/cache/)
|