Cloudflare CDN ile İçerik Optimizasyonu: Kapsamlı Rehber

Cloudflare’i ilk kurduğumda “DNS yönetimi yapan bir araç” olarak düşünüyordum. Yanılmışım tabii. Yıllar içinde fark ettim ki Cloudflare, doğru yapılandırıldığında sitenizin performansını kökten değiştirebilen, güvenlik katmanı ekleyen ve bant genişliği maliyetlerinizi ciddi ölçüde düşüren bir platform. Bu yazıda Cloudflare CDN’i sysadmin perspektifinden ele alacağız: teorik anlatım değil, gerçek dünyada çalışan yapılandırmalar ve pratik ipuçları.

Cloudflare CDN Nedir ve Nasıl Çalışır?

Cloudflare, kullanıcılarla origin sunucunuz arasına giren bir ters proxy ağıdır. Dünya genelinde 300’den fazla PoP (Point of Presence) noktasıyla, içeriği kullanıcıya en yakın data merkezinden sunar. Türkiye’deki bir kullanıcı sitenize girdiğinde, istek doğrudan Amerika’daki sunucunuza gitmez; İstanbul’daki Cloudflare node’una gider. İçerik cache’lenmişse oradan döner, değilse Cloudflare origin’inize istek atar, cevabı alır ve kullanıcıya iletir.

Bu yapının sysadmin olarak size sağladığı somut avantajlar:

  • Bant genişliği tasarrufu: Origin sunucunuza giden istek sayısı dramatik biçimde düşer
  • DDoS koruması: Volumetric saldırılar Cloudflare edge’inde absorbe edilir
  • SSL sonlandırma: SSL handshake yükü Cloudflare’e taşınır
  • Bot yönetimi: Kötü botlar origin’e ulaşmadan filtrelenir
  • Analytics: Her istek hakkında detaylı log ve metrik

Cloudflare’in en temel çalışma mantığını anlamak için önce DNS kayıtlarınızı Cloudflare’e taşımanız gerekiyor. Proxy modunda (turuncu bulut ikonu) olan kayıtlar CDN’den geçer, gri bulut ikonundakiler ise sadece DNS çözümlemesi yapar.

Cloudflare API ile Otomasyon

Cloudflare’i web arayüzünden yapılandırmak başlangıç için yeterli, ancak production ortamlarında her şeyi API üzerinden yönetmek şart. Hem tekrarlanabilirlik hem de versiyon kontrolü açısından bu kritik.

Önce API token’ınızı alın ve temel bağlantıyı test edin:

# API token ile hesap bilgilerini çek
export CF_API_TOKEN="your_api_token_here"
export CF_ZONE_ID="your_zone_id_here"

curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" 
     -H "Authorization: Bearer $CF_API_TOKEN" 
     -H "Content-Type: application/json"

Zone ID’nizi bulmak için:

# Tüm zone'ları listele
curl -X GET "https://api.cloudflare.com/client/v4/zones" 
     -H "Authorization: Bearer $CF_API_TOKEN" 
     -H "Content-Type: application/json" | jq '.result[] | {name: .name, id: .id}'

Cloudflare ayarlarını toplu yönetmek için bir bash script yazalım. Bu script, production geçişlerinde benim en çok kullandığım araçlardan biri:

#!/bin/bash
# cloudflare-config.sh - Zone bazlı Cloudflare yapılandırma scripti

CF_API_TOKEN="${CF_API_TOKEN:?'CF_API_TOKEN degiskeni tanimli degil'}"
CF_ZONE_ID="${CF_ZONE_ID:?'CF_ZONE_ID degiskeni tanimli degil'}"
BASE_URL="https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID"

cf_api() {
    local method=$1
    local endpoint=$2
    local data=$3
    
    curl -s -X "$method" 
         -H "Authorization: Bearer $CF_API_TOKEN" 
         -H "Content-Type: application/json" 
         ${data:+-d "$data"} 
         "$BASE_URL$endpoint"
}

# SSL modunu Full (Strict) yap
echo "SSL modu ayarlaniyor..."
cf_api PATCH "/settings/ssl" '{"value":"strict"}' | jq '.success'

# Always Use HTTPS aktif et
echo "Always HTTPS aktif ediliyor..."
cf_api PATCH "/settings/always_use_https" '{"value":"on"}' | jq '.success'

# Minimum TLS versiyonu 1.2 yap
echo "Min TLS 1.2 ayarlaniyor..."
cf_api PATCH "/settings/min_tls_version" '{"value":"1.2"}' | jq '.success'

# HTTP/2 aktif et
echo "HTTP/2 aktif ediliyor..."
cf_api PATCH "/settings/http2" '{"value":"on"}' | jq '.success'

# Brotli compression aktif et
echo "Brotli aktif ediliyor..."
cf_api PATCH "/settings/brotli" '{"value":"on"}' | jq '.success'

echo "Yapilandirma tamamlandi."

Cache Yönetimi ve Optimizasyon Stratejileri

Cache yönetimi Cloudflare’in en güçlü özelliği ama aynı zamanda en çok hata yapılan alan. Yanlış cache kuralları ya sitenizi yavaşlatır ya da kullanıcılara eski içerik gösterir.

Cache-Control Header’larını Doğru Ayarlamak

Origin sunucunuzun gönderdiği Cache-Control header’ları Cloudflare’in davranışını doğrudan etkiler. Nginx örneği:

# /etc/nginx/conf.d/cache-headers.conf

server {
    listen 80;
    server_name example.com;
    
    # Statik dosyalar icin agresif cache
    location ~* .(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable, max-age=31536000";
        add_header X-Content-Type-Options nosniff;
    }
    
    # HTML sayfalar - kisa sure cache, revalidation ile
    location ~* .html$ {
        expires 1h;
        add_header Cache-Control "public, must-revalidate, max-age=3600";
    }
    
    # API endpoint'leri hic cache'leme
    location /api/ {
        add_header Cache-Control "no-store, no-cache, must-revalidate";
        add_header Pragma no-cache;
    }
    
    # Kullanici bazli icerik - kesinlikle cache'leme
    location /dashboard/ {
        add_header Cache-Control "private, no-store";
    }
}

Cloudflare Cache Rules ile Granular Kontrol

Cloudflare’in yeni Page Rules sisteminin yerini alan Cache Rules, çok daha esnek bir yapı sunuyor. API üzerinden cache rule oluşturalım:

#!/bin/bash
# cache-rules.sh - Cloudflare cache kurallarini ayarla

# Statik asset'ler icin edge cache TTL'i 1 yil yap
curl -s -X POST 
     "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/rulesets/phases/http_request_cache_settings/entrypoint" 
     -H "Authorization: Bearer $CF_API_TOKEN" 
     -H "Content-Type: application/json" 
     -d '{
       "name": "Cache Optimizasyon Kurallari",
       "rules": [
         {
           "description": "Statik dosyalar - 1 yil cache",
           "expression": "(http.request.uri.path.extension in {"jpg" "jpeg" "png" "gif" "css" "js" "woff" "woff2"})",
           "action": "set_cache_settings",
           "action_parameters": {
             "cache": true,
             "edge_ttl": {
               "mode": "override_origin",
               "default": 31536000
             },
             "browser_ttl": {
               "mode": "override_origin",
               "default": 86400
             }
           }
         },
         {
           "description": "API - hic cache etme",
           "expression": "(http.request.uri.path matches "^/api/")",
           "action": "set_cache_settings",
           "action_parameters": {
             "cache": false
           }
         }
       ]
     }' | jq '.success'

Cache Purge Otomasyonu

Deploy sonrası cache temizleme işlemini CI/CD pipeline’ınıza entegre etmelisiniz. İşte benim kullandığım yaklaşım:

#!/bin/bash
# purge-cache.sh - Deploy sonrasi akilli cache temizleme

CF_API_TOKEN="${CF_API_TOKEN:?}"
CF_ZONE_ID="${CF_ZONE_ID:?}"
DOMAIN="${DOMAIN:?}"

# Tum cache'i temizle (dikkatli kullanin, origin'i yorar)
purge_all() {
    echo "Tum cache temizleniyor..."
    curl -s -X POST 
         "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/purge_cache" 
         -H "Authorization: Bearer $CF_API_TOKEN" 
         -H "Content-Type: application/json" 
         -d '{"purge_everything": true}' | jq '.success'
}

# Sadece degisen dosyalari temizle (tercih edilen yontem)
purge_files() {
    local files=("$@")
    local urls=()
    
    for file in "${files[@]}"; do
        urls+=(""https://$DOMAIN/$file"")
    done
    
    local url_list=$(IFS=,; echo "${urls[*]}")
    
    echo "Secili dosyalar temizleniyor: ${files[*]}"
    curl -s -X POST 
         "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/purge_cache" 
         -H "Authorization: Bearer $CF_API_TOKEN" 
         -H "Content-Type: application/json" 
         -d "{"files": [$url_list]}" | jq '.success'
}

# Git diff ile degisen dosyalari bul ve purge et
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD -- public/)

if [ -n "$CHANGED_FILES" ]; then
    purge_files $CHANGED_FILES
else
    echo "Degisen dosya bulunamadi, tam purge yapiliyor..."
    purge_all
fi

Workers ile Edge Computing

Cloudflare Workers, JavaScript/WebAssembly kodunuzu Cloudflare edge’inde çalıştırmanızı sağlar. Bu, origin sunucunuza hiç gitmeden karmaşık iş mantığı uygulayabileceğiniz anlamına gelir. Gerçek dünyadan bir örnek vereyim: A/B testing için kullandığım bir Worker:

// ab-test-worker.js
// Cloudflare Worker olarak deploy edilecek

addEventListener('fetch', event => {
    event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
    const url = new URL(request.url)
    
    // Sadece ana sayfa icin A/B test uygula
    if (url.pathname !== '/') {
        return fetch(request)
    }
    
    // Cookie'den mevcut variant'i kontrol et
    const cookie = request.headers.get('Cookie') || ''
    const variantMatch = cookie.match(/ab_variant=([ab])/)
    
    let variant
    if (variantMatch) {
        variant = variantMatch[1]
    } else {
        // Yeni kullanici - rastgele variant ata
        variant = Math.random() < 0.5 ? 'a' : 'b'
    }
    
    // Variant'a gore farkli URL'e istek at
    const targetUrl = variant === 'b' 
        ? `${url.origin}/v2/` 
        : url.toString()
    
    const response = await fetch(targetUrl, request)
    const newResponse = new Response(response.body, response)
    
    // Cookie set et
    newResponse.headers.append(
        'Set-Cookie', 
        `ab_variant=${variant}; Path=/; Max-Age=86400; SameSite=Lax`
    )
    
    // Analytics icin header ekle
    newResponse.headers.set('X-AB-Variant', variant)
    
    return newResponse
}

Bu Worker’ı deploy etmek için Wrangler CLI kullanıyoruz:

# Wrangler kurulumu
npm install -g wrangler

# Cloudflare hesabina giris
wrangler login

# Worker'i deploy et
wrangler deploy ab-test-worker.js --name ab-test-worker

# Log'lari canli izle
wrangler tail ab-test-worker

Gerçek Dünya Senaryosu: E-ticaret Sitesi Optimizasyonu

Geçen yıl, Türkiye’de orta ölçekli bir e-ticaret sitesinin Cloudflare geçişini yönettim. Site, özellikle kampanya dönemlerinde ciddi yavaşlama yaşıyordu. İşte uyguladığımız yapılandırma:

Origin Sunucu Koruması

#!/bin/bash
# Cloudflare IP'lerini iptables ile beyaz listeye al
# Sadece Cloudflare'den gelen trafiği kabul et

# Mevcut kurallari temizle
iptables -F INPUT

# Loopback'e izin ver
iptables -A INPUT -i lo -j ACCEPT

# Established baglantilara izin ver
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# SSH'a her yerden izin ver (sonra kisitlayabilirsiniz)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# Cloudflare IPv4 adresleri (guncel liste icin https://www.cloudflare.com/ips-v4)
CF_IPS=(
    "173.245.48.0/20"
    "103.21.244.0/22"
    "103.22.200.0/22"
    "103.31.4.0/22"
    "141.101.64.0/18"
    "108.162.192.0/18"
    "190.93.240.0/20"
    "188.114.96.0/20"
    "197.234.240.0/22"
    "198.41.128.0/17"
    "162.158.0.0/15"
    "104.16.0.0/13"
    "104.24.0.0/14"
    "172.64.0.0/13"
    "131.0.72.0/22"
)

for ip in "${CF_IPS[@]}"; do
    iptables -A INPUT -p tcp -s "$ip" --dport 80 -j ACCEPT
    iptables -A INPUT -p tcp -s "$ip" --dport 443 -j ACCEPT
done

# Diger tum HTTP/HTTPS trafiklerini engelle
iptables -A INPUT -p tcp --dport 80 -j DROP
iptables -A INPUT -p tcp --dport 443 -j DROP

echo "Firewall kurallari uygulanmistir."

# Kaydet
iptables-save > /etc/iptables/rules.v4

Bu yapılandırmayla origin sunucuya doğrudan erişim engellendi. Tüm trafik Cloudflare üzerinden geçmek zorunda kaldı.

Dinamik İçerik için Akıllı Cache

E-ticaret sitelerinin en büyük sorunu, giriş yapmış kullanıcılar için kişisel içeriklerin yanlışlıkla cache’lenmesidir. Bunu önlemek için Cache Rules içinde cookie bazlı bypass tanımladık:

# Oturum cookie'si varsa cache'i bypass et
curl -s -X POST 
     "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/rulesets/phases/http_request_cache_settings/entrypoint" 
     -H "Authorization: Bearer $CF_API_TOKEN" 
     -H "Content-Type: application/json" 
     -d '{
       "name": "E-commerce Cache Kurallari",
       "rules": [
         {
           "description": "Giris yapan kullanici - cache bypass",
           "expression": "(http.cookie contains "session_token") or (http.cookie contains "user_logged_in")",
           "action": "set_cache_settings",
           "action_parameters": {
             "cache": false
           }
         },
         {
           "description": "Urun sayfasi - 10 dakika cache",
           "expression": "(http.request.uri.path matches "^/urun/")",
           "action": "set_cache_settings",
           "action_parameters": {
             "cache": true,
             "edge_ttl": {
               "mode": "override_origin",
               "default": 600
             }
           }
         }
       ]
     }' | jq '.success'

Cloudflare Analytics ile Performans İzleme

Cloudflare’in sağladığı metrikleri düzenli olarak izlemek ve raporlamak için basit bir monitoring scripti:

#!/bin/bash
# cf-analytics.sh - Cloudflare analitik raporu

CF_API_TOKEN="${CF_API_TOKEN:?}"
CF_ZONE_ID="${CF_ZONE_ID:?}"

# Son 24 saatin istatistiklerini cek
SINCE=$(date -u -d '24 hours ago' '+%Y-%m-%dT%H:%M:%SZ')
UNTIL=$(date -u '+%Y-%m-%dT%H:%M:%SZ')

echo "=== Cloudflare 24 Saatlik Rapor ==="
echo "Donem: $SINCE - $UNTIL"
echo ""

STATS=$(curl -s -X GET 
    "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/analytics/dashboard?since=$SINCE&until=$UNTIL&continuous=true" 
    -H "Authorization: Bearer $CF_API_TOKEN" 
    -H "Content-Type: application/json")

# Toplam istek sayisi
TOTAL_REQ=$(echo "$STATS" | jq '.result.totals.requests.all')
CACHED_REQ=$(echo "$STATS" | jq '.result.totals.requests.cached')
CACHE_HIT_RATE=$(echo "scale=2; $CACHED_REQ * 100 / $TOTAL_REQ" | bc)

echo "Toplam Istek: $TOTAL_REQ"
echo "Cache'lenen: $CACHED_REQ"
echo "Cache Hit Orani: %$CACHE_HIT_RATE"
echo ""

# Bant genisligi
TOTAL_BW=$(echo "$STATS" | jq '.result.totals.bandwidth.all')
CACHED_BW=$(echo "$STATS" | jq '.result.totals.bandwidth.cached')
BW_SAVED=$(echo "scale=2; $CACHED_BW / 1073741824" | bc)

echo "Tasarruf Edilen Bant Genisligi: ${BW_SAVED} GB"

# Tehdit istatistikleri
THREATS=$(echo "$STATS" | jq '.result.totals.threats.all')
echo "Engellenen Tehdit: $THREATS"

Yaygın Hatalar ve Çözümleri

Yıllar içinde Cloudflare yapılandırmalarında sık karşılaştığım sorunları not etmek istedim:

Error 521 – Web Server Is Down: Origin sunucunuz çalışıyor ama Cloudflare bağlanamıyor. Büyük ihtimalle firewall’ınız Cloudflare IP’lerini bloke ediyor. Yukarıdaki iptables scriptini çalıştırın.

Redirect Loop: SSL modunu “Flexible” yapıp origin sunucunuzda HTTP’yi HTTPS’e yönlendirince oluşur. SSL modunu “Full” veya “Full (Strict)” yapın, sonra origin’deki redirect’i kaldırın.

Cache’lenmeyen İçerik: cf-cache-status: BYPASS veya DYNAMIC görüyorsanız origin’inizin Set-Cookie header’ı gönderip göndermediğini kontrol edin. Cloudflare, Set-Cookie içeren cevapları varsayılan olarak cache’lemez.

Yüksek TTFB Hızına Rağmen: Cloudflare önünüzde olduğu halde TTFB yüksekse Argo Smart Routing’i aktif etmeyi düşünün. Origin’e giden trafiği optimize edilmiş rotalar üzerinden yönlendirir.

Development Modunu Unutmak: Test amaçlı “Development Mode” açıp production’da unutmak klasik bir hata. Bu mod 3 saat sonra otomatik kapanıyor ama yine de bir alarm kurmanızı öneririm.

Sonuç

Cloudflare CDN’i doğru yapılandırmak tek seferlik bir iş değil. Siteniz büyüdükçe, trafik örüntüleri değiştikçe ve yeni özellikler eklendikçe cache stratejinizi ve güvenlik kurallarınızı güncellemeniz gerekiyor. Başlangıç için şu sıralamayı öneririm: önce DNS geçişini yapın ve temel SSL ayarlarını doğrulayın, sonra cache kurallarını ekleyin ve hit oranını izleyin, ardından firewall kurallarıyla origin’inizi koruma altına alın, son olarak Workers gibi gelişmiş özellikleri keşfedin.

En önemli metrik cache hit oranıdır. Bu oran yüzde 70’in altındaysa yapılandırmanızda bir sorun var demektir. Yüzde 85 üzeri iyi, yüzde 90 üzeri ise mükemmel sayılabilir. Analytics verilerini düzenli takip edin, anomalilere hemen müdahale edin ve her değişikliği test ortamında önce deneyin.

Cloudflare’in ücretsiz planı bile küçük ve orta ölçekli siteler için son derece yeterli. Pro ve Business planları ise daha granular kontrol, gelişmiş WAF kuralları ve öncelikli destek sunuyor. Kendi deneyimlerimden yola çıkarak söylüyorum: Cloudflare’e geçiş yaptıktan sonra hiçbir müşterim “eski haline dönelim” demedi.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir