← Back to Home

WordPress Cloudflare CDN + Nginx Origin Server Complete Setup Guide

WordPressCloudflareCDNNginxAPO

Adding Cloudflare as a CDN in front of your WordPress origin server is a standard speed optimization—but the configuration has hidden traps. SSL certificate mode选错 causes redirect loops, Nginx doesn't recognize real visitor IPs breaking your security plugins, and APO caching conflicts with WooCommerce shopping carts.

This article covers 5 real configuration pitfalls with copy-paste commands.

Why WordPress Needs Cloudflare CDN

Every WordPress page visit queries the database. Even with Nginx FastCGI caching, TTFB stays high when servers are geographically distant. According to Google Web.dev, TTFB accounts for 40% of LCP—slow TTFB means worse Google rankings.

Cloudflare free plan includes:

APO caches entire WordPress HTML pages at the edge. Cloudflare claims up to 300% speed improvement—particularly effective for blog-style static-dominant content.

Pitfall 1: Flexible SSL Mode Causes Redirect Loop

Symptom: Browser shows "Too many redirects" error.

Cause: Cloudflare SSL mode set to Flexible while Nginx enforces HTTPS redirects. Flexible mode means Cloudflare-to-origin is HTTP. Origin sees HTTP and redirects to HTTPS, Cloudflare sends HTTP again → infinite loop.

Solution: Cloudflare Dashboard → SSL/TLS → Encryption Mode → set to Full or Full (strict).

# Full: origin can use self-signed or Let's Encrypt cert
# Full (strict): must be trusted CA certificate only

Generate Let's Encrypt cert for origin (recommended):

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com --noninteractive

Then in Nginx config, remove the HTTP→HTTPS forced redirect:

# DELETE or comment this out, or you'll get a redirect loop
# server {
#     listen 80;
#     server_name yourdomain.com;
#     return 301 https://$server_name$request_uri;
# }

Instead, enforce HTTPS via Cloudflare Dashboard → SSL/TLS → Always Use HTTPS = On.

Pitfall 2: Nginx Doesn't See Real Visitor IP — Security Plugins Useless

Symptom: Wordfence shows all visits from Cloudflare IP ranges, geographic blocking and IP whitelisting completely fail.

Cause: Cloudflare is a reverse proxy. Every request's src IP becomes Cloudflare's IPs (103.21.x.x, 104.16.x.x etc). Nginx by default doesn't see the real visitor IP.

Solution: Enable ngx_http_realip_module in Nginx to restore real IPs.

Create /etc/nginx/cloudflare.conf:

# Cloudflare IPv4
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.7.0/24;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
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;
# Cloudflare 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:fb48::/32;

real_ip_header CF-Connecting-IP;

Include this in your nginx.conf http { } block:

http {
    include /etc/nginx/cloudflare.conf;
    # ... other config
}
sudo nginx -t && sudo systemctl reload nginx

After this, logs show real visitor IPs instead of Cloudflare IPs, and IP-based security plugins like Wordfence work properly.

Cloudflare IP ranges may change over time. Use a weekly cron to auto-update:

# /etc/cron.weekly/cloudflare-realip-update
curl -s https://www.cloudflare.com/ips-v4 | sed 's/$/;/' > /tmp/cf_ips
curl -s https://www.cloudflare.com/ips-v6 | sed 's/$/;/' >> /tmp/cf_ips
# merge into set_real_ip_from lines in cloudflare.conf

Pitfall 3: APO Conflicts With WooCommerce Cart State

Symptom: APO enabled, customers add to cart fine, but checkout often shows empty cart; order status pages are broken.

Cause: APO caches HTML pages containing cart state. When User A visits, their cart is cached as static HTML. User B gets User A's cart content.

Solutions:

1. WordPress Dashboard → Cloudflare plugin → Page Rules, exclude dynamic routes:

/checkout/*
/cart/*
/my-account/*
/?add-to-cart=*

2. Or in wp-config.php, use environment variables to bypass APO on dynamic routes:

// Disable APO caching for WooCommerce dynamic pages
if (isset($_COOKIE['woocommerce_cart_hash']) ||
    isset($_COOKIE['woocommerce_items_in_cart'])) {
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    header('X-Cache-Level: off');
}

3. If you don't use WooCommerce, APO works great as-is for pure blogs—automatic static HTML caching, significant performance boost.

Pitfall 4: Authenticated Origin Pulls Cause 400 Bad Request

Symptom: After enabling "Authenticated Origin Pulls", site returns 400 Bad Request: No required SSL certificate was sent.

**Cause**: Cloudflare's Authenticated Origin Pulls uses mTLS mutual authentication. Origin Nginx must configure Cloudflare's CA certificate to accept requests from Cloudflare. Without ssl_client_certificate configured, connections are rejected.

Solution:

1. Download Cloudflare Origin Pull CA cert:

sudo mkdir -p /etc/cloudflare
sudo curl -o /etc/cloudflare/cloudflare-origin-pull-ca.pem \
  https://developers.cloudflare.com/ssl/static/authenticated_origin_pull_ca.pem

2. Enable client certificate verification in Nginx site config:

server {
    listen 443 ssl;
    server_name yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
    ssl_client_certificate /etc/cloudflare/cloudflare-origin-pull-ca.pem;
    ssl_verify_client on;  # enable mTLS verification

    # ... other config
}

3. Cloudflare Dashboard确认: SSL/TLS → Origin Server → check Authenticated Origin Pulls

4. Verify: sudo nginx -t && sudo systemctl reload nginx

⚠️ If you get 400 errors, make sure Cloudflare SSL/TLS mode is Full or Full(strict)—Flexible mode does NOT support Origin Pulls.

Pitfall 5: APO Caching Slows Down WordPress Admin

Symptom: Frontend is blazing fast after APO, but /wp-admin operations feel sluggish; publishing a post still shows old content.

Cause: APO caches entire site HTML by default, including /wp-admin management pages. When you publish posts or update plugins, Cloudflare still serves stale cached pages.

Solution:

Exclude wp-admin from Cloudflare proxy cache in Nginx config:

location /wp-admin/ {
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    # explicitly no-cache
    proxy_no_cache 1;
    proxy_cache_bypass 1;
    add_header X-Cache-Level "bypass";
}

Alternatively, use Cloudflare plugin (free version) Cache Rules to explicitly exclude /wp-admin paths.

Complete Configuration Checklist

Check ItemStatus
Cloudflare SSL mode = Full/Full(strict)
Nginx has NO HTTP→HTTPS redirect (Cloudflare handles this)
Nginx cloudflare.conf included, nginx -t passed
Real IP visible in access.log
WooCommerce dynamic routes excluded from APO
Authenticated Origin Pulls has ssl_client_certificate configured
/wp-admin path has no-cache headers set

Next Steps

With Cloudflare configured, you can continue optimizing:

👉 Join MiniMax API Beta, get AI model inference tokens: https://platform.minimaxi.com/subscribe/token-plan?code=E5yur9NOub&source=link

📌 This article was AI-assisted generated and human-reviewed | TechPassive — An AI-driven content testing site focused on real tool reviews

🔗 Recommended Tools

These are carefully selected tools. Using our affiliate links supports us to keep producing quality content:

☁️ DigitalOcean Cloud ⚡ Vultr VPS 📚 WordPress Books 🔍 WordPress SEO Books 🌐 Web Hosting Books 🐳 Docker Books 🐧 Linux Books 🐍 Python Books 💰 Affiliate Marketing 💵 Passive Income Books 🖥️ Server Books ☁️ Cloud Computing Books 🚀 DevOps Books ⭐ MiniMax Token Plan
← Back to Home