How to Configure Apache to Use a Content Delivery Network (CDN)

How to configure Apache to use a Content Delivery Network (CDN)

I still remember the moment I realized my server in one region was serving visitors on the other side of the world with painfully slow load times — sometimes 3-4 seconds just for the first byte. That’s when I finally sat down and properly integrated a CDN in front of my Apache server, and the difference was night and day.

What a CDN Actually Does

A Content Delivery Network is a globally distributed network of servers (edge nodes) that cache and serve your content from a location physically closer to each visitor. Instead of every request traveling all the way to your origin server, most requests get served from a nearby edge node.

For an Apache-hosted website, the CDN typically sits in front of your server as a reverse proxy layer, handling:

  • Static asset caching (images, CSS, JavaScript, fonts).
  • DDoS mitigation and traffic filtering.
  • SSL/TLS termination at the edge.
  • Sometimes full-page caching for anonymous visitors.

Popular CDN providers include Cloudflare, Amazon CloudFront, Fastly, and BunnyCDN. The configuration principles are similar across all of them, though I’ll use Cloudflare as my primary example since it’s the most widely adopted.

Why This Matters

  • Faster global load times: Visitors get content from a nearby edge location instead of a potentially distant origin server.
  • Reduced origin server load: Your Apache server handles far fewer requests directly, since cached content is served from the edge.
  • Better resilience: CDNs absorb traffic spikes and many types of attacks before they ever reach your server.
  • Improved SEO: Page speed is a ranking factor, and CDNs reliably improve Core Web Vitals metrics like Largest Contentful Paint.

Prerequisites

  • A working Apache installation with your site already live.
  • A domain name with DNS you can modify (or that’s managed through your CDN provider directly, as is the case with Cloudflare).
  • Root or sudo access to adjust Apache configuration.
  • An account with your chosen CDN provider.

Step 1: Point Your DNS to the CDN

For Cloudflare specifically, this means changing your domain’s nameservers to Cloudflare’s nameservers, then adding your DNS records (A, CNAME, etc.) inside the Cloudflare dashboard with the “proxy” (orange cloud) status enabled.

For CDNs like CloudFront that work via CNAME rather than full DNS takeover, you’d instead:

  1. Create a CloudFront distribution pointing to your Apache server as the “origin.”
  2. Update your DNS CNAME record to point to the CloudFront distribution’s domain name.

Step 2: Configure Apache to Trust the CDN’s Forwarded Headers

This is the step people miss most often, and it causes a specific, annoying bug: every visitor’s IP address in your Apache logs shows up as the CDN’s IP instead of the real visitor’s IP.

CDNs pass the original visitor IP through the X-Forwarded-For header. To recover the real IP in your logs and in PHP’s $_SERVER['REMOTE_ADDR'], install mod_remoteip:

sudo a2enmod remoteip

Then configure it. For Cloudflare specifically, you need to trust Cloudflare’s published IP ranges:

RemoteIPHeader CFConnecting-IP
RemoteIPTrustedProxy 173.245.48.0/20
RemoteIPTrustedProxy 103.21.244.0/22
RemoteIPTrustedProxy 103.22.200.0/22
RemoteIPTrustedProxy 103.31.4.0/22
RemoteIPTrustedProxy 141.101.64.0/18
RemoteIPTrustedProxy 108.162.192.0/18
RemoteIPTrustedProxy 190.93.240.0/20
RemoteIPTrustedProxy 188.114.96.0/20
RemoteIPTrustedProxy 197.234.240.0/22
RemoteIPTrustedProxy 198.41.128.0/17
RemoteIPTrustedProxy 162.158.0.0/15
RemoteIPTrustedProxy 104.16.0.0/13
RemoteIPTrustedProxy 104.24.0.0/14
RemoteIPTrustedProxy 172.64.0.0/13
RemoteIPTrustedProxy 131.0.72.0/22

Cloudflare’s IP list changes occasionally, so check their official IP ranges page periodically and update this list.

Then update your log format to use the resolved IP:

LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" cdn_combined
CustomLog ${APACHE_LOG_DIR}/access.log cdn_combined

Step 3: Set Proper Cache-Control Headers

CDNs rely heavily on HTTP caching headers to decide what to cache and for how long. Without explicit headers, many CDNs fall back to conservative defaults that under-cache your content.

Enable mod_expires and mod_headers:

sudo a2enmod expires headers

Add cache rules to your virtual host or a .htaccess file:

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType image/jpeg "access plus 1 month"
    ExpiresByType image/png "access plus 1 month"
    ExpiresByType image/svg+xml "access plus 1 month"
    ExpiresByType text/css "access plus 1 week"
    ExpiresByType application/javascript "access plus 1 week"
    ExpiresByType text/html "access plus 1 hour"
</IfModule>

<IfModule mod_headers.c>
    Header set Cache-Control "public, max-age=604800"
</IfModule>

Be more conservative with HTML caching (or skip it entirely) if your pages are dynamic and personalized per user.

Step 4: Handle SSL Correctly

Most CDNs offer a “Flexible,” “Full,” or “Full (Strict)” SSL mode. I strongly recommend Full (Strict) — this means the connection between the CDN and your origin server is also encrypted and properly validated, not just the connection between the visitor and the CDN.

To support this, install a valid SSL certificate on your Apache server (Let’s Encrypt works great here):

sudo certbot --apache -d example.com -d www.example.com

Some CDNs, like Cloudflare, also offer “Origin Certificates” specifically designed for this CDN-to-origin connection, which can simplify certificate management.

Step 5: Avoid Redirect Loops

A classic mistake: if your Apache config forces HTTPS redirects and your CDN is also forcing HTTPS, you can end up in an infinite redirect loop, especially under “Flexible” SSL mode where the CDN-to-origin connection is actually plain HTTP.

If you see ERR_TOO_MANY_REDIRECTS, switch your CDN’s SSL mode to “Full” or “Full (Strict)” rather than “Flexible,” so the CDN itself connects to your origin over HTTPS, matching what your Apache redirect rules expect.

Real-World Use Cases

  • Global audience blogs and media sites: Serving images and video thumbnails from edge locations close to readers worldwide.
  • E-commerce platforms: Reducing origin load during flash sales by letting the CDN absorb the bulk of static asset requests.
  • API-heavy applications: Using CDN edge caching for cacheable GET endpoints while passing through POST/PUT requests directly to origin.
  • DDoS-prone sites: Leaning on the CDN’s traffic filtering to absorb attacks before they reach the Apache server at all.

Troubleshooting Common Issues

Problem: Real visitor IPs show as the CDN’s IP in logs. This means mod_remoteip isn’t configured correctly, or you haven’t updated your LogFormat to use %a (the module-adjusted client IP) instead of the raw connection IP.

Problem: Changes to my site don’t show up for visitors. The CDN is likely serving a cached version. Purge the cache through your CDN provider’s dashboard or API after deployments.

Problem: Infinite redirect loop after enabling the CDN. Check your SSL mode — see Step 5 above. Nine times out of ten, this is a mismatch between your CDN’s SSL mode and your Apache HTTPS redirect rules.

Problem: Dynamic, personalized pages are being cached and shown to the wrong users. Make sure pages with personalized content send Cache-Control: private, no-store or similar headers so the CDN doesn’t cache them at all.

Common Mistakes to Avoid

  • Forgetting to configure mod_remoteip, breaking IP-based logging, rate limiting, and analytics.
  • Using “Flexible” SSL mode long-term instead of properly securing the CDN-to-origin connection.
  • Caching dynamic or user-specific content without proper cache-control headers, leaking one user’s data to another.
  • Not setting up a cache purge step in your deployment pipeline, leading to stale content complaints.
  • Ignoring the CDN provider’s specific IP ranges when configuring trusted proxies, causing IP spoofing vulnerabilities.

Security Best Practices

  • Always use Full (Strict) SSL mode between CDN and origin in production.
  • Restrict direct access to your origin server’s IP address where possible (many CDNs support “origin lock” firewall rules) so attackers can’t bypass the CDN entirely.
  • Keep your trusted proxy IP list current, since an outdated list can allow header spoofing from IPs no longer owned by the CDN.
  • Enable Web Application Firewall (WAF) features most CDNs offer, adding another layer of protection in front of Apache.

Performance Optimization Tips

  • Enable Brotli or Gzip compression at the CDN edge layer in addition to (or instead of) Apache’s own mod_deflate.
  • Use image optimization features many CDNs offer (like Cloudflare Polish) to automatically serve modern formats like WebP or AVIF.
  • Set long cache lifetimes for immutable assets (versioned CSS/JS filenames) so they’re cached aggressively without risk of serving stale content.
  • Monitor cache hit ratios through your CDN dashboard — a low hit ratio usually signals a caching configuration problem worth investigating.

Frequently Asked Questions

Do I need to change my Apache configuration if I only cache images and static assets? Even in that limited case, I’d still recommend setting up mod_remoteip for accurate logging, since all traffic passes through the CDN once DNS is proxied.

Will a CDN work with dynamic PHP applications? Yes, though the CDN will typically only cache static assets and specific whitelisted dynamic responses unless you configure full-page caching rules explicitly.

Can I use a CDN with a self-signed SSL certificate on my origin? Some CDNs allow this under “Full” (non-strict) mode, but I’d recommend a proper certificate (Let’s Encrypt is free) for “Full (Strict)” mode instead.

How do I purge the CDN cache after a deployment? Most providers offer a dashboard purge button as well as an API endpoint you can call from your CI/CD pipeline for automated purging.

Summary and Key Takeaways

Configuring Apache to work well behind a CDN isn’t just about pointing DNS somewhere else — it requires a few deliberate adjustments to make sure logging, SSL, and caching all behave correctly.

The essentials to remember:

  1. Point your DNS to the CDN (nameserver change or CNAME, depending on provider).
  2. Install and configure mod_remoteip so real visitor IPs show up correctly in your logs.
  3. Set explicit Cache-Control and Expires headers so the CDN caches efficiently.
  4. Use Full (Strict) SSL mode between the CDN and your origin server.
  5. Watch out for redirect loops caused by SSL mode mismatches.

Once set up properly, a CDN is one of the most impactful, low-maintenance performance upgrades you can make to an Apache-hosted site.

References

Total
2
Shares

Leave a Reply

Previous Post
How to use Apache's mod_proxy for reverse proxying

How to Use Apache’s mod_proxy for Reverse Proxying

Next Post
How to reduce Apache's memory usage

How to Reduce Apache’s Memory Usage

Related Posts