Why CDN for a PHP Site

A Content Delivery Network caches your static assets (CSS, JS, images) on servers worldwide, serving them from the location closest to the visitor. For a PHP CMS like JekCMS, the CDN also caches HTML pages — turning a 200ms PHP response into a 20ms edge cache hit.

We use Cloudflare's free plan for all 12 JekCMS sites. The free plan includes: CDN with global edge locations, SSL certificate, DDoS protection, and basic page rules. That covers 95% of what a CMS needs.

DNS and SSL Setup

Point your domain's nameservers to Cloudflare. Enable "Full (Strict)" SSL mode — this ensures encryption both between the visitor and Cloudflare, and between Cloudflare and your origin server. Never use "Flexible" SSL — it leaves the connection between Cloudflare and your server unencrypted.

Page Rules for Admin

The admin panel must never be cached. Create a page rule: example.com/admin/* → Cache Level: Bypass, Disable Performance. This ensures admin pages always hit the origin server with fresh data.

Similarly, API endpoints should bypass cache: example.com/api/* → Cache Level: Bypass.

Real IP Restoration

When Cloudflare proxies requests, the client's real IP is in CF-Connecting-IP header instead of REMOTE_ADDR. JekCMS restores the real IP in bootstrap:

// includes/bootstrap.php
if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
}

This is critical for rate limiting and security logging — without it, all requests appear to come from Cloudflare's IP addresses.

Cache Purge API

When content changes in the admin panel, we purge the Cloudflare cache for that specific URL:

function purgeCloudflareCache(array $urls): bool {
    $zoneId = get_setting('cloudflare_zone_id');
    $apiToken = get_setting('cloudflare_api_token');
    if (!$zoneId || !$apiToken) return false;

    $ch = curl_init("https://api.cloudflare.com/client/v4/zones/{$zoneId}/purge_cache");
    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST => 'POST',
        CURLOPT_POSTFIELDS => json_encode(['files' => $urls]),
        CURLOPT_HTTPHEADER => [
            "Authorization: Bearer {$apiToken}",
            'Content-Type: application/json',
        ],
        CURLOPT_RETURNTRANSFER => true,
    ]);
    $response = curl_exec($ch);
    curl_close($ch);
    return json_decode($response, true)['success'] ?? false;
}

Performance Results

Before Cloudflare vs After Cloudflare for kriptogetiri.com (one of our highest-traffic sites):

  • TTFB: 380ms → 45ms (88% improvement for cached pages)
  • Page load: 2.1s → 0.9s (57% improvement)
  • Bandwidth: 45GB/month → 12GB/month origin (73% offloaded to CDN)
  • DDoS protection: Blocked 3 attacks in the first month (previously would have taken the site down)

The free Cloudflare plan has been sufficient for all our sites. The only limitation is 3 page rules on the free plan, but we only need 2 (admin bypass and API bypass).