Cloudflare can provide Azure-hosted WordPress sites with edge security, TLS, DNS proxying, compression and static asset caching—without requiring Azure Front Door.
This KloudStack Labs review documents a working configuration using Cloudflare directly in front of an Azure App Service. WordPress uploads are served from the App Service’s local persistent storage; Azure Blob Storage is not used in this configuration.
Blob Storage integration and media offloading will be covered in a separate review.
Architecture
The resulting request path is:
Visitor → Cloudflare → Azure App Service
Cloudflare provides the public edge layer, while Azure App Service remains the application origin.
The configuration includes:
- Cloudflare proxied DNS
- Cloudflare edge TLS
- Full (strict) TLS between Cloudflare and Azure
- An Azure App Service custom domain
- A Cloudflare Origin CA certificate installed in App Service
- Azure access restrictions allowing only Cloudflare
- Cloudflare WAF and WordPress security rules
- Static asset caching
- WordPress and W3 Total Cache controlling HTML freshness
- Local WordPress media under
/wp-content/uploads/
Why consider Cloudflare instead of Azure Front Door?
Azure Front Door is a capable global edge service, but it can add significant cost and operational complexity to smaller WordPress environments.
Cloudflare provides many of the same core capabilities:
- Global reverse proxy
- CDN caching
- Managed TLS
- HTTP/2 and HTTP/3
- Brotli and gzip compression
- DDoS protection
- Web Application Firewall capabilities
- Redirect rules
- Rate limiting
- Origin protection
For this lab, removing Azure Front Door produced a simpler path:
Cloudflare → Azure App Service
It also eliminated the additional Front Door hop and associated configuration.
This is not necessarily the correct architecture for every workload. Azure Front Door remains useful when an application needs Azure-native routing across multiple regions, Private Link origins, advanced load balancing or other Azure-specific integrations.
Before starting
You will need:
- An Azure App Service running WordPress
- A custom domain
- The domain’s DNS zone managed by Cloudflare
- Access to Azure App Service custom domains, certificates and networking
- Access to the WordPress administrator
- W3 Total Cache or another WordPress caching solution, if required
Take a copy of the existing DNS records and document the current origin before making changes.
If replacing Azure Front Door, retain the existing Front Door configuration during the initial validation period so it remains available as a rollback path.
1. Add the Azure App Service custom domain
Azure App Service must recognise the public hostname that Cloudflare will use when connecting to the origin.
In the Azure portal:
- Open the App Service.
- Select Custom domains.
- Select Add custom domain.
- Enter the apex domain, such as
example.com. - Complete domain ownership validation.
- Add the domain to the App Service.
Azure may request an asuid TXT record to validate ownership.
During a reverse-proxy migration, Azure may warn that the domain does not have a matching A record pointing directly to App Service. Domain ownership can still be validated through the TXT record.
After adding the domain, it may initially display No binding until a certificate is uploaded and bound.
Microsoft documents the general process in Set up an existing custom domain in Azure App Service.
2. Create a Cloudflare Origin CA certificate
Cloudflare needs to validate the certificate presented by Azure App Service when using Full (strict) encryption.
A Cloudflare Origin CA certificate can be used when the origin is designed to receive traffic only through Cloudflare.
In Cloudflare:
- Open the domain.
- Go to SSL/TLS → Origin Server.
- Select Create certificate.
- Generate an RSA 2048 private key and certificate.
- Include the apex and wildcard hostnames:
example.com*.example.com
- Select an appropriate validity period.
- Create the certificate.
- Save the certificate and private key securely.
Cloudflare displays the private key only during certificate creation. Treat it as a production secret.
A Cloudflare Origin CA certificate is trusted by Cloudflare but not by ordinary web browsers. If Cloudflare proxying is disabled, visitors may receive an untrusted certificate warning when connecting directly to the origin.
See Cloudflare Origin CA certificates for additional details.
3. Convert the certificate into a PFX file
Azure App Service expects a password-protected PFX certificate for a bring-your-own-certificate binding.
Cloudflare provides the certificate and private key in PEM format, so they must be packaged into a PFX file before uploading to App Service.
This can be completed with OpenSSL.
The resulting PFX should include:
- The Cloudflare Origin CA certificate
- The matching private key
- The relevant Cloudflare Origin CA chain
- A strong export password
Do not store the plaintext private key in a synchronised Desktop or OneDrive folder.
Move the files into a protected location, such as:
C:\Users\<username>\AppData\Local\KloudStack\Cloudflare-Origin
For a production KloudStack implementation, certificate generation, PFX packaging, secure storage, binding and expiry monitoring should be automated. The private key and PFX should be stored in Azure Key Vault or another suitable secrets platform.
4. Upload and bind the certificate in Azure
In the App Service:
- Go to Certificates.
- Open Bring your own certificates (.pfx).
- Select Add certificate.
- Upload the PFX.
- Supply the PFX password.
- Return to Custom domains.
- Select Add binding for the domain.
- Choose the uploaded certificate.
- Use an SNI SSL binding.
The custom domain should now display:
- Status: Secured
- Binding type: SNI SSL
- Certificate: the uploaded Cloudflare Origin certificate
Azure’s certificate-binding process is documented in Secure a custom domain with TLS in Azure App Service.
5. Restrict App Service access to Cloudflare
Without access restrictions, someone who discovers the Azure App Service origin could bypass Cloudflare and connect directly to the application.
Azure App Service access restrictions can be used to allow Cloudflare’s public proxy ranges and deny unmatched traffic.
In Azure:
- Open App Service → Networking.
- Open Access restrictions.
- Select Enabled from select virtual networks and IP addresses.
- Add allow rules covering Cloudflare’s current IPv4 ranges.
- Add allow rules covering Cloudflare’s current IPv6 ranges.
- Leave Unmatched rule action set to Deny.
- Save the configuration.
Cloudflare publishes its current ranges on its Cloudflare IP addresses page.
Cloudflare recommends allowing its published ranges and blocking other origin traffic to prevent visitors from bypassing its security layer. See Protect your origin server for the associated guidance.
Important operational requirement
Cloudflare’s address ranges are not represented by an Azure service tag.
A production platform should therefore:
- Retrieve the official ranges automatically
- Compare them with the Azure access restrictions
- Apply additions or removals safely
- Record changes
- Alert if synchronisation fails
Hard-coded Cloudflare ranges should not be assumed to remain unchanged indefinitely.
After applying the rules, direct access to the default azurewebsites.net hostname may return 403 Forbidden. This is expected if it does not meet an allow rule.
Azure documents access-rule ordering and implicit denial behaviour in Set up Azure App Service access restrictions.
6. Configure Cloudflare DNS
Create or update proxied Cloudflare DNS records for the public domain.
For example:
Type: CNAME
Name: @
Target: example-app.azurewebsites.net
Proxy status: Proxied
For www:
Type: CNAME
Name: www
Target: example-app.azurewebsites.net
Proxy status: Proxied
The orange-cloud status must be enabled for traffic to pass through Cloudflare.
Keep required validation TXT records, including Azure asuid records. They may be needed if the custom domain must be revalidated or recreated later.
7. Configure SSL/TLS
In Cloudflare, set:
SSL/TLS encryption mode: Full (strict)
This provides encryption across both parts of the connection:
- Browser to Cloudflare
- Cloudflare to Azure App Service
Full (strict) also validates the origin certificate. Cloudflare documents this in Full (strict) SSL/TLS encryption.
Recommended supporting settings include:
- Always Use HTTPS: On
- Minimum TLS version: TLS 1.2
- TLS 1.3: On
- Automatic HTTPS Rewrites: On, where required
- HTTP/2: On
- HTTP/3: On
- HTTP/2 to Origin: On
Avoid enabling HSTS until HTTPS has been fully validated across every required hostname. Incorrect HSTS configuration can make recovery difficult because browsers retain the policy.
8. Redirect www to the apex domain
Cloudflare Redirect Rules can perform the redirect without sending the request to WordPress.
Example match:
Hostname equals www.example.com
Example dynamic destination:
concat("https://example.com", http.request.uri.path)
Configure the rule to:
- Preserve the query string
- Return HTTP 301
- Remain active
This results in:
https://www.example.com/path/?query=value
redirecting to:
https://example.com/path/?query=value
The redirect is processed at Cloudflare’s edge and does not consume App Service resources.
9. Use Cloudflare for static assets—not WordPress HTML
Our initial lab configuration used a Cloudflare Cache Rule to cache public WordPress HTML at the edge.
While this produced CF-Cache-Status: HIT, it created an important content-management problem: after publishing a post, the homepage could remain stale until Cloudflare was manually purged.
The official Cloudflare WordPress plugin includes Automatic Cache Management. Cloudflare states that it uses WordPress hooks to purge associated URLs when posts, pages, attachments or comments change.
However, in our test, it did not reliably invalidate HTML cached through our modern Cloudflare Cache Rule.
The safe baseline was therefore:
- Disable the custom Public WordPress HTML Cache Rule.
- Keep WordPress dynamic bypass protections.
- Allow Cloudflare to cache supported static files normally.
- Let WordPress and W3 Total Cache manage HTML/page caching.
After making this change:
Homepage: CF-Cache-Status: DYNAMIC
Post HTML: CF-Cache-Status: DYNAMIC
Static assets: CF-Cache-Status: HIT after warming
Publishing or updating a post then updated the homepage without requiring a manual Cloudflare purge.
This is essential for a managed customer environment. Site editors should not need to understand or manually operate a CDN cache whenever content changes.
Cloudflare documents its plugin behaviour in Cloudflare WordPress Plugin Automatic Cache Management.
10. Configure W3 Total Cache
For the no-Blob-Storage configuration:
- W3TC CDN functionality should be disabled.
- Existing Blob Storage or CDN hostname rewriting should be removed.
- Page cache can remain enabled.
- Browser cache can remain enabled, subject to review.
- Object cache should be reviewed separately based on the WordPress architecture.
- Empty all W3TC caches after changing CDN settings.
Media should resolve through normal WordPress paths such as:
https://example.com/wp-content/uploads/2026/07/image.jpg
It should not use an old rewritten Blob route such as:
https://example.com/blob-prefix/wp-content/uploads/2026/07/image.jpg
After changing W3TC CDN settings:
- Empty all W3TC caches.
- Purge Cloudflare once.
- Clear generated theme or page-builder assets if required.
- Inspect the resulting HTML.
- Confirm images use
/wp-content/uploads/. - Check the browser Network panel for 404 responses.
Browser caching warning
A Cloudflare purge does not remove files already stored in visitors’ browser caches.
If static media is given a long browser lifetime and an image is replaced using the same filename, some visitors may continue seeing the old image.
The preferred strategy is to use immutable or versioned asset URLs:
logo-v2.png
rather than repeatedly overwriting:
logo.png
11. Install the Cloudflare WordPress plugin
The official Cloudflare WordPress plugin can be installed for settings management and cache-purge integration.
Use a restricted Cloudflare API token rather than the Global API Key.
Limit the token to:
- The required Cloudflare account
- The specific customer zone
- Only the permissions needed by the plugin
Relevant permissions may include:
- Zone: Read
- Zone Analytics: Read
- Zone Settings: Edit
- Cache Purge: Purge
- DNS: Read
Do not scope a customer WordPress token to every account and every zone.
Avoid client-IP restrictions unless the App Service outbound addresses are known and operationally stable. WordPress makes API calls from Azure, not from the administrator’s browser.
The plugin can remain enabled for static asset purging and Cloudflare integration. It should not be considered sufficient evidence that every custom HTML caching rule will be invalidated correctly.
12. Add WordPress security rules
Cloudflare can block common malicious requests before they reach PHP or consume App Service CPU.
Block PHP execution in uploads
Example expression:
starts_with(http.request.uri.path, "/wp-content/uploads/")
and http.request.uri.path contains ".php"
Action:
Block
WordPress uploads should not normally contain executable PHP files.
Block sensitive WordPress and development files
Examples include:
/.env
/.git
/wp-config.php
/wp-content/debug.log
/phpinfo.php
/composer.json
/composer.lock
Action:
Block
Rate-limit authentication requests
Match:
/wp-login.php
/xmlrpc.php
Apply a per-IP rate limit suitable for the application.
Be careful not to make the threshold so restrictive that legitimate administrators or integrations are blocked.
13. Restore the original visitor IP
When Cloudflare proxies traffic, Azure App Service sees Cloudflare as the network source.
Cloudflare provides the original visitor address in headers such as:
CF-Connecting-IP
X-Forwarded-For
The origin web server and WordPress security tools must be configured to trust these headers only when the request originates from an approved Cloudflare address.
For an Nginx-based WordPress container, this generally requires:
real_ip_header CF-Connecting-IP;
real_ip_recursive on;
along with set_real_ip_from entries for Cloudflare’s current ranges.
This should be managed from the same source used to maintain App Service access restrictions.
After configuration, verify that:
- Nginx access logs contain the visitor IP.
- WordPress sees the visitor IP.
- Wordfence sees the visitor IP.
- Application Insights records the visitor IP appropriately.
- Rate-limiting logic does not treat every visitor as one Cloudflare address.
14. Validate the configuration
Do not rely only on what the dashboards display.
Test the live site and inspect the response headers.
Expected HTML response
server: cloudflare
cf-cache-status: DYNAMIC
Expected warmed static asset response
server: cloudflare
cf-cache-status: HIT
Depending on the client’s request headers, static resources may also return:
content-encoding: br
or:
content-encoding: gzip
Additional tests
Confirm that:
- The apex domain loads over HTTPS.
wwwredirects to the apex domain.- Paths and query strings survive the redirect.
- WordPress login remains uncached.
/wp-admin/remains uncached./wp-json/remains uncached.- Logged-in sessions remain uncached.
- Static CSS, JavaScript, fonts and images are cached.
- A PHP request inside uploads receives a Cloudflare 403.
- Sensitive file requests receive a Cloudflare 403.
- A normal nonexistent file reaches the origin and returns 404.
- The Azure Front Door headers no longer appear.
- The default App Service hostname remains inaccessible externally.
- Publishing a post updates the homepage without a manual Cloudflare purge.
Final architecture
The completed lab configuration is:
Visitor
↓
Cloudflare DNS, TLS, WAF, redirects and static CDN
↓
Azure App Service access restrictions
↓
WordPress on Azure App Service
↓
Local persistent WordPress uploads
WordPress HTML remains dynamic at Cloudflare, while static resources benefit from Cloudflare’s distributed edge network.
What worked well
The Cloudflare and Azure App Service integration successfully provided:
- A simpler edge architecture
- Full strict end-to-end TLS
- Direct Cloudflare-to-App-Service delivery
- Origin access restrictions
- Static asset caching
- Brotli and gzip compression
- HTTP/2 and HTTP/3
- Edge redirects
- WordPress-specific WAF rules
- Authentication rate limiting
- Immediate WordPress publishing without manual CDN purging
What still needs further review
This configuration intentionally serves media from App Service storage.
For larger or multi-instance WordPress deployments, the next review should cover:
- Azure Blob Storage media offloading
- A dedicated media hostname
- Cloudflare in front of Azure Blob Storage
- URL and origin routing
- Cache invalidation for replaced media
- W3 Total Cache integration
- Private containers or signed access
- Cross-origin headers
- Image optimisation
- Storage redundancy
- Migration of existing media
- Multi-instance upload consistency
The preferred long-term media path may look like:
Visitor → media.example.com → Cloudflare → Azure Blob Storage
This separates application traffic from media delivery while retaining Cloudflare as the public CDN layer.
Conclusion
Cloudflare can operate effectively as the public edge for WordPress running on Azure App Service without Azure Front Door or Azure Blob Storage.
The most important lesson from the lab was not to assume that edge-cached WordPress HTML will always be invalidated correctly.
For the initial KloudStack baseline, the reliable configuration is:
- Cloudflare for DNS, proxying, TLS, WAF and static assets
- Azure App Service as the protected origin
- W3 Total Cache for WordPress HTML caching
- Cloudflare HTML responses left dynamic
- WordPress media served from local App Service storage
This provides meaningful CDN and security benefits without making content publishing dependent on manual Cloudflare cache purges.
Next KloudStack Labs review: Cloudflare with Azure Blob Storage for WordPress media delivery.

Leave a Reply