How to Set Up Cloudflare for WordPress: Speed, Security & Free CDN
Full Cloudflare configuration for WordPress — caching rules, SSL, image delivery, and security.
In This Guide
Cloudflare + WordPress: The Complete Setup Guide for Speed and Security
Cloudflare sits between your visitors and your hosting server — caching content, blocking malicious traffic, and serving your site from datacenters close to each visitor. When configured correctly alongside good WordPress hosting, Cloudflare can cut page load times significantly and block the vast majority of automated attacks before they reach your server. When configured incorrectly, it causes redirect loops, breaks admin functionality, and makes debugging difficult.
Here's how to do it right.
How Cloudflare Works With WordPress
When a visitor requests your site, the request hits Cloudflare's network first. Cloudflare checks its cache — if the page is cached, it serves it directly from the nearest datacenter without the request ever reaching your server. If it's not cached (or can't be cached), Cloudflare forwards the request to your origin server, returns the response to the visitor, and caches it for future requests.
For WordPress specifically:
- Static assets (images, CSS, JavaScript) are almost always cacheable and served from Cloudflare's edge
- HTML pages can be cached for logged-out visitors, but require careful configuration to avoid caching logged-in user content
- Admin pages (/wp-admin/) should never be cached or intercepted by Cloudflare rules
Understanding this distinction — what gets cached, what shouldn't — is the foundation of a correct Cloudflare + WordPress setup.
Initial Setup
Point DNS to Cloudflare
- Create a Cloudflare account and add your domain
- Cloudflare scans your existing DNS records
- Verify the records are correct (A record for your domain and www pointing to your server IP)
- Update your domain's nameservers at your registrar to Cloudflare's nameservers
- Propagation takes up to 48 hours, typically under 2 hours
DNS records with the orange cloud icon route through Cloudflare. Records with a grey cloud icon are "DNS only" — they resolve directly to your server. Your main A records should be orange (proxied).
SSL/TLS Configuration
This is where most problems originate. Cloudflare supports four SSL modes:
Off: No HTTPS. Never use this.
Flexible: Cloudflare connects to your server over HTTP even if your visitor uses HTTPS. Convenient but insecure — traffic between Cloudflare and your server is unencrypted. Creates redirect loops if WordPress is configured to force HTTPS.
Full: Cloudflare connects to your server over HTTPS but doesn't validate the certificate. Works with self-signed certificates.
Full (Strict): Cloudflare connects to your server over HTTPS and validates the certificate. Requires a valid certificate on your origin server.
Use Full (Strict). This is the correct setting. Your hosting platform should provision a valid Let's Encrypt certificate automatically. If it does, Full (Strict) works immediately and provides end-to-end encryption.
Setting SSL to "Flexible" while WordPress is configured to redirect HTTP to HTTPS creates an infinite redirect loop: Cloudflare sends HTTP to your server, WordPress redirects to HTTPS, Cloudflare sends HTTP again, repeat until the browser gives up.
Force HTTPS with Cloudflare
Enable "Always Use HTTPS" in Cloudflare's SSL/TLS settings. This redirects all HTTP requests to HTTPS at Cloudflare's edge, before the request reaches your server.
Also enable "Automatic HTTPS Rewrites" — this changes http:// links on your page to https:// without touching your database, reducing mixed content warnings from hard-coded HTTP URLs.
WordPress Configuration for Cloudflare
Correct WordPress URL Settings
With Cloudflare proxying your site, your server sees requests from Cloudflare's IP addresses, not from visitors' actual IPs. WordPress needs to know it's behind a proxy:
// wp-config.php
// Tell WordPress the site is using HTTPS even though origin may be HTTP
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
// Set the home and site URL to HTTPS
define('WP_HOME', 'https://yourdomain.com');
define('WP_SITEURL', 'https://yourdomain.com');
Without $_SERVER['HTTPS'] = 'on', WordPress thinks requests are HTTP even when they arrive over HTTPS via Cloudflare. This causes admin login issues and SSL-related plugin errors.
The Cloudflare WordPress Plugin
Install the official Cloudflare WordPress plugin. It does two important things:
- Cache purging: When you publish or update content, the plugin automatically purges the Cloudflare cache for that URL so visitors see fresh content
- IP restoration: Rewrites
$_SERVER['REMOTE_ADDR']to show the visitor's real IP instead of Cloudflare's IP, so your security plugins and analytics see accurate data
Without IP restoration, every request appears to come from Cloudflare's IP addresses. WordPress security plugins that block IPs after failed logins will block Cloudflare instead of the actual attacker.
Caching Configuration
What to Cache
Cloudflare caches static assets (images, CSS, JS, fonts) by default based on file extension. The harder question is whether to cache HTML pages.
Option 1: Cache only static assets (default)
Cloudflare's default behavior caches static files but not HTML. Every page request goes to your origin server. This still helps significantly (images and assets load from edge), but doesn't reduce server load for page requests.
Option 2: Cache HTML for logged-out visitors (Page Rules)
Using Cloudflare Page Rules, you can configure full HTML caching for your public site while bypassing cache for admin areas and logged-in users:
Rule 1: yourdomain.com/wp-admin/*
Cache Level: Bypass
Rule 2: yourdomain.com/wp-login.php
Cache Level: Bypass
Rule 3: yourdomain.com/*
Cache Level: Cache Everything
Edge Cache TTL: 4 hours
This serves cached HTML to logged-out visitors from Cloudflare's edge, reducing origin server requests dramatically for content-heavy sites.
The WooCommerce complication: WooCommerce stores cart state in cookies. A logged-out user with items in their cart must not receive a cached version of the cart page from a previous visitor's session. Add additional bypass rules:
Rule for WooCommerce:
yourdomain.com/cart/* → Cache Level: Bypass
yourdomain.com/checkout/* → Cache Level: Bypass
yourdomain.com/my-account/* → Cache Level: Bypass
Cookie contains "woocommerce_items_in_cart" → Cache Level: Bypass
Cloudflare's Workers or Cache Rules (on paid plans) allow more sophisticated logic for cookie-based cache bypass.
Cache Purging
After publishing new content, Cloudflare's cached version is stale until its TTL expires. With the Cloudflare WordPress plugin installed, publishing a post automatically purges the cache for that URL.
Manual purge when needed:
- Cloudflare dashboard → Caching → Configuration → Purge Everything (full cache purge)
- Or purge specific URLs for targeted invalidation
Security Configuration
Firewall Rules for WordPress
Cloudflare's WAF (Web Application Firewall) includes managed rule sets for WordPress. On the Pro plan and above, enable:
- WordPress rules — blocks common WordPress attack patterns
- PHP attack rules — blocks PHP injection attempts
- Common attack patterns
For the free plan, create custom firewall rules:
Block common WordPress attack paths:
Expression: (http.request.uri.path contains "wp-login.php" and not ip.src in {your-office-ip})
Action: Challenge (CAPTCHA)
Block XML-RPC (if you don't use it):
Expression: (http.request.uri.path contains "xmlrpc.php")
Action: Block
Block exploit scanners:
Expression: (http.user_agent contains "sqlmap") or (http.user_agent contains "nikto") or (http.user_agent contains "masscan")
Action: Block
Rate Limiting
Cloudflare rate limiting (included in all plans with limits) protects your login page from brute force:
Create a rate limit rule:
- Path: /wp-login.php
- Threshold: 10 requests per minute per IP
- Action: Block for 1 hour
This blocks brute-force login attempts before they reach WordPress, at Cloudflare's edge, without consuming your server resources.
Bot Fight Mode
Enable "Bot Fight Mode" in Cloudflare's Security settings. This challenges requests from known bot IPs — scrapers, credential stuffers, vulnerability scanners. Most legitimate visitors won't notice; bots either fail the challenge or are blocked.
Performance Settings
Speed Optimizations
In Cloudflare's Speed settings, enable:
Auto Minify: Minifies HTML, CSS, and JavaScript files in transit. WordPress plugins like WP Rocket also do this — if you're already minifying, disable Cloudflare minification to avoid double-processing.
Brotli: Enables Brotli compression (more efficient than gzip). Enable this — it's free compression savings.
Rocket Loader: Cloudflare's JavaScript loading optimization. Defers non-critical JavaScript to improve perceived load time. Test this carefully — some JavaScript-heavy themes and plugins break with Rocket Loader. If your site shows JS errors after enabling it, disable it.
Polish and Image Optimization
On Pro plans: Cloudflare Polish converts images to WebP for supported browsers and compresses them. If you're not already serving WebP images through a WordPress plugin, this is a valuable optimization — you get WebP delivery without touching your theme or plugins.
HTTP/3 and 0-RTT
Enable HTTP/3 (QUIC) in Cloudflare's Network settings. Modern browsers negotiate HTTP/3 automatically. The benefit is most visible for visitors on mobile connections with variable latency — QUIC handles packet loss more gracefully than TCP.
0-RTT Connection Resumption reduces connection overhead for returning visitors. Enable it. The negligible replay attack risk is offset by the performance benefit for most sites.
Diagnosing Cloudflare Problems
Is Cloudflare Serving the Request?
Check the response headers:
curl -I https://yourdomain.com
Look for CF-Ray header — its presence confirms the request went through Cloudflare.
cf-cache-status tells you what Cloudflare did:
- HIT — served from Cloudflare cache
- MISS — not cached, request went to origin
- BYPASS — cache bypass rule applied
- EXPIRED — was cached but expired
- DYNAMIC — Cloudflare determined it's not cacheable
Fixing the Admin Login Loop
Symptom: /wp-admin/ redirects infinitely.
Cause: Usually SSL mode set to "Flexible" combined with WordPress HTTPS redirects.
Fix:
1. Set SSL/TLS mode to "Full (Strict)"
2. Add a bypass rule: yourdomain.com/wp-admin/* → Disable Performance
If the loop persists:
// wp-config.php — add above the "require" line at the bottom
$_SERVER['HTTPS'] = 'on';
Cloudflare is Caching the Wrong Content
Symptom: Logged-in users see cached content from logged-out sessions.
Fix: Review Page Rules for the caching configuration. Verify that any "Cache Everything" rule has a cookie-based bypass for wordpress_logged_in_* cookies.
In Cloudflare Cache Rules (newer interface):
If Cookie contains "wordpress_logged_in" → Set Cache Level: Bypass
Real Visitor IPs Not Showing in WordPress
Symptom: All traffic in WordPress, analytics, and security plugins appears to come from the same IP (Cloudflare's).
Fix: Install the Cloudflare WordPress plugin (automatic fix) or add to wp-config.php:
if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
}
Cloudflare sends the real visitor IP in the CF-Connecting-IP header. Reading it and setting it as REMOTE_ADDR restores correct behavior for all WordPress IP-aware functionality.
The Full Picture
Cloudflare and good WordPress hosting aren't alternatives — they're complementary. Cloudflare handles edge caching, DDoS mitigation, and global content distribution. Your hosting handles PHP execution, database queries, and the dynamic core of WordPress.
Getting both right means: content served from Cloudflare's edge for static requests, fast TTFB from well-resourced origin hosting for dynamic requests, and automated security at both layers. That combination is what makes a WordPress site fast and resilient regardless of where in the world visitors come from.
Get WordPress Hosting That Actually Performs
Isolated containers, git deployment, CLI management, and auto-SSL. No plugin restrictions, no visit limits.
Start WordPress FreePowered by WHMCompleteSolution