Modern web uygulamalarında sayfa yüklenme hızı artık bir lüks değil, zorunluluk. Google’ın Core Web Vitals metriklerine baktığında, sıkıştırma oranlarının doğrudan LCP ve FID skorlarını etkilediğini görüyorsun. Caddy, bu konuda hem kullanım kolaylığı hem de performans açısından oldukça güçlü seçenekler sunuyor. Bu yazıda Caddy’nin yerleşik sıkıştırma middleware’ini ve Brotli desteğini gerçek dünya senaryolarıyla ele alacağız.
Sıkıştırma Neden Bu Kadar Önemli?
Bir web sunucusu yapılandırması üzerinde çalışırken sıkıştırmayı atlamak, arabanın camını açık bırakarak klima açmak gibidir. Sunucudan istemciye giden her kilobyte, hem bant genişliği maliyetine hem de gecikmeye çevrilir.
Tipik bir senaryo düşün: 500KB’lık bir JavaScript dosyen var. Gzip ile bu yaklaşık 180KB’a iner. Brotli ile ise 150KB veya daha altına düşebilir. Mobil kullanıcılar için bu fark, 3 saniyelik yükleme ile 1.5 saniyelik yükleme arasındaki farktır.
Caddy bu konuda özel bir yere sahip, çünkü:
- Gzip ve Zstandard desteği yerleşik olarak geliyor
- Brotli desteği için ayrı bir modül gerekiyor ama entegrasyonu temiz
- Yapılandırma sözdizimi diğer sunuculara kıyasla çok daha sade
- HTTPS ile birlikte çalışırken ek yapılandırma gerektirmiyor
Caddy’nin Varsayılan Sıkıştırma Davranışı
Caddy kurulu geldiğinde encode direktifi ile sıkıştırma middleware’ini aktifleştirebilirsin. Varsayılan olarak hiçbir sıkıştırma aktif değildir, yani açıkça belirtmen gerekir.
Temel bir Caddyfile ile başlayalım:
# /etc/caddy/Caddyfile
example.com {
encode gzip zstd
root * /var/www/html
file_server
}
Bu yapılandırmada encode direktifi hem gzip hem de Zstandard’ı aktifleştirir. Caddy, istemcinin Accept-Encoding başlığına bakarak hangisini desteklediğine karar verir ve buna göre sıkıştırma uygular.
Yapılandırmayı test etmek için:
# Caddy yapılandırmasını doğrula
caddy validate --config /etc/caddy/Caddyfile
# Servisi yeniden başlat
sudo systemctl reload caddy
# curl ile sıkıştırma başlıklarını kontrol et
curl -I -H "Accept-Encoding: gzip, deflate, br" https://example.com
Dönen başlıklarda Content-Encoding: gzip veya Content-Encoding: zstd görmelisin.
encode Direktifinin Detaylı Yapılandırması
encode direktifi sandığından daha fazla seçenek sunuyor. Minimum sıkıştırma boyutu, sıkıştırma seviyesi ve hangi content type’ların sıkıştırılacağı gibi parametreleri ayarlayabilirsin.
example.com {
encode {
gzip 6
zstd
minimum_length 1024
match {
header Content-Type text/plain*
header Content-Type text/html*
header Content-Type text/css*
header Content-Type application/javascript*
header Content-Type application/json*
header Content-Type application/xml*
header Content-Type image/svg+xml*
}
}
root * /var/www/html
file_server
}
Bu yapılandırmada dikkat edilmesi gereken noktalar:
- gzip 6: Gzip sıkıştırma seviyesi 1-9 arasında ayarlanabilir. 6 iyi bir denge noktası. 9 maksimum sıkıştırma ama CPU yükü yüksek, 1 hız odaklı ama daha az sıkıştırma
- minimum_length 1024: 1KB’dan küçük dosyaları sıkıştırma. Küçük dosyalarda sıkıştırma bazen dosyayı büyütebilir
- match bloğu: Sadece belirtilen content type’lara sıkıştırma uygula. Zaten sıkıştırılmış PNG, JPEG gibi dosyalara sıkıştırma uygulamak boşuna CPU harcar
Brotli Desteği: Kurulum ve Entegrasyon
Brotli, Google tarafından geliştirilen ve özellikle metin tabanlı içerikler için gzip’e göre %15-25 daha iyi sıkıştırma oranı sunan bir algoritmadır. Caddy’nin standart dağıtımında Brotli yoktur, ancak xcaddy aracıyla Brotli modülünü derleyerek ekleyebilirsin.
xcaddy ile Brotli Modülü Derleme
Önce xcaddy aracını yükle:
# Go kurulu olduğunu varsayıyoruz
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
# xcaddy'nin PATH'te olduğunu kontrol et
xcaddy version
Brotli modülüyle birlikte Caddy’yi derle:
# Brotli desteğiyle Caddy derle
xcaddy build
--with github.com/ueffel/caddy-brotli
# Derlenen binary'yi yerleştir
sudo mv caddy /usr/bin/caddy
# İzinleri ayarla
sudo chmod +x /usr/bin/caddy
sudo setcap cap_net_bind_service=+ep /usr/bin/caddy
# Versiyonu ve modülleri doğrula
caddy version
caddy list-modules | grep brotli
Eğer caddy list-modules çıktısında http.encoders.br görüyorsan, Brotli modülü başarıyla yüklenmiştir.
Brotli ile Caddyfile Yapılandırması
Brotli modülü kurulduktan sonra yapılandırma oldukça basit:
example.com {
encode {
br
gzip 6
zstd
minimum_length 1024
}
root * /var/www/html
file_server
}
Caddy burada içerik müzakeresi (content negotiation) yaparak istemcinin Accept-Encoding başlığındaki tercihe göre en uygun algoritmayı seçer. Modern tarayıcılar Brotli’yi desteklediğinden, masaüstü ve mobil kullanıcıların büyük çoğunluğu otomatik olarak Brotli sıkıştırmasından yararlanır.
Brotli kurulumunu test etmek için:
# Brotli desteğini curl ile test et
curl -I -H "Accept-Encoding: br" https://example.com
# Detaylı başlık bilgisi al
curl -v -H "Accept-Encoding: br, gzip, deflate"
https://example.com 2>&1 | grep -i "content-encoding"
# Sıkıştırma öncesi ve sonrası boyut karşılaştırması
curl -s -H "Accept-Encoding: br" https://example.com | wc -c
curl -s https://example.com | wc -c
Gerçek Dünya Senaryosu 1: PHP Uygulaması için Caddy
Bir Laravel uygulaması çalıştırdığını varsay. JSON API yanıtları, HTML sayfaları ve statik dosyalar içeriyor. Bu senaryo için kapsamlı bir yapılandırma:
app.example.com {
encode {
br
gzip 6
zstd
minimum_length 512
match {
header Content-Type application/json*
header Content-Type text/html*
header Content-Type text/plain*
header Content-Type text/css*
header Content-Type application/javascript*
header Content-Type application/xml*
header Content-Type image/svg+xml*
header Content-Type font/woff*
header Content-Type font/ttf*
header Content-Type application/font-woff*
}
}
root * /var/www/laravel/public
php_fastcgi unix//run/php/php8.2-fpm.sock
file_server
# Statik dosyalar için cache header
@static {
file
path *.css *.js *.png *.jpg *.jpeg *.gif *.ico *.svg *.woff *.woff2
}
header @static Cache-Control "public, max-age=31536000, immutable"
# API route'ları için sıkıştırma önceliği Brotli
@api {
path /api/*
}
header @api Content-Type "application/json; charset=utf-8"
}
Bu yapılandırmada dikkat et: font dosyalarını da sıkıştırma listesine ekledim. WOFF2 zaten sıkıştırılmış bir format olduğundan bu satırı çıkarabilirsin, ama TTF ve OTF için sıkıştırma anlamlı bir boyut tasarrufu sağlar.
Gerçek Dünya Senaryosu 2: Reverse Proxy Arkasındaki Node.js Uygulaması
Caddy’yi bir Node.js uygulamasının önüne reverse proxy olarak koyduğunda, sıkıştırmayı Caddy tarafında yapmak uygulamanın CPU yükünü azaltır:
api.example.com {
encode {
br
gzip 5
zstd
minimum_length 256
}
# Node.js uygulama sıkıştırma yapmasın diye başlık ekle
header_up Accept-Encoding "identity"
reverse_proxy localhost:3000 {
header_up Host {upstream_hostport}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
health_uri /health
health_interval 30s
health_timeout 5s
}
# Güvenlik başlıkları
header {
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
-Server
}
}
header_up Accept-Encoding "identity" satırı kritik bir nokta. Eğer bu satırı eklemezsen, Node.js uygulaması kendi sıkıştırmasını yapabilir ve Caddy ikinci kez sıkıştırmaya çalışabilir. Bu hem gereksiz CPU kullanımına yol açar hem de bazen hatalı yanıtlara neden olabilir.
Sıkıştırma Performansını İzleme
Sıkıştırmanın gerçekten çalışıp çalışmadığını ve ne kadar etki yarattığını ölçmek için birkaç yöntem var.
Caddy’nin varsayılan loglama formatı JSON olduğundan, log analizini kolaylaştırabilirsin:
# Caddy log yapılandırması - /etc/caddy/Caddyfile
{
log {
output file /var/log/caddy/access.log {
roll_size 100mb
roll_keep 10
}
format json
level INFO
}
}
example.com {
log {
output file /var/log/caddy/example.com.log
format json
}
encode {
br
gzip 6
zstd
minimum_length 1024
}
root * /var/www/html
file_server
}
Log dosyasından sıkıştırma etkinliğini analiz etmek için:
# Content-Encoding başlıklarını loglardan çek
cat /var/log/caddy/example.com.log |
python3 -c "
import sys, json
stats = {}
for line in sys.stdin:
try:
log = json.loads(line)
enc = log.get('resp_headers', {}).get('Content-Encoding', ['none'])[0]
stats[enc] = stats.get(enc, 0) + 1
except:
pass
for k, v in sorted(stats.items(), key=lambda x: -x[1]):
print(f'{k}: {v}')
"
# Gerçek zamanlı istek izleme
tail -f /var/log/caddy/example.com.log |
grep -o '"Content-Encoding":"[^"]*"'
JSON Config ile İleri Seviye Yapılandırma
Caddyfile yerine JSON konfigürasyonunu tercih ediyorsan, encode middleware’i şöyle tanımlayabilirsin:
# Caddy JSON config'i API üzerinden uygula
curl -X POST "http://localhost:2019/load"
-H "Content-Type: application/json"
-d '{
"apps": {
"http": {
"servers": {
"myserver": {
"listen": [":443"],
"routes": [
{
"match": [{"host": ["example.com"]}],
"handle": [
{
"handler": "encode",
"encodings": {
"br": {},
"gzip": {"level": 6},
"zstd": {}
},
"minimum_length": 1024,
"prefer": ["br", "zstd", "gzip"]
},
{
"handler": "file_server",
"root": "/var/www/html"
}
]
}
]
}
}
}
}
}'
prefer alanı önemli: Brotli destekleyen istemcilere önce Brotli teklif et, desteklemeyenlere Zstandard, en son olarak Gzip. Bu şekilde algoritma öncelik sıralamasını açıkça belirleyebilirsin.
Önceden Sıkıştırılmış Dosyalar ile Precompression
Caddy’nin çok işe yarayan bir özelliği de önceden sıkıştırılmış dosyaları sunma yeteneği. Webpack veya build pipeline’ın .gz ve .br uzantılı dosyalar üretiyorsa, Caddy bunları gerçek zamanlı sıkıştırma yerine doğrudan sunabilir. Bu hem CPU’yu rahatlatır hem de daha tutarlı yanıt süreleri sağlar.
example.com {
root * /var/www/dist
file_server {
precompressed br gzip
}
# Gerçek zamanlı sıkıştırma da aktif tut
# (önceden sıkıştırılmış dosya yoksa devreye girer)
encode {
br
gzip 6
zstd
minimum_length 1024
}
}
Build sürecinde dosyaları önceden sıkıştırmak için:
# Tüm statik dosyaları gzip ve brotli ile sıkıştır
find /var/www/dist -type f
( -name "*.html" -o -name "*.css" -o -name "*.js"
-o -name "*.json" -o -name "*.svg" -o -name "*.xml" ) |
while read file; do
# Gzip ile sıkıştır
gzip -k -9 "$file"
# Brotli ile sıkıştır (brotli paketi kurulu olmalı)
brotli -k -q 11 "$file"
echo "Sıkıştırıldı: $file"
done
# Sonuçları kontrol et
ls -lh /var/www/dist/*.js* | head -20
Bu yöntemde brotli komut satırı aracını kullanabilmek için sisteme kurman gerekir:
# Ubuntu/Debian
sudo apt install brotli
# RHEL/CentOS
sudo dnf install brotli
Yaygın Hatalar ve Çözümleri
Sıkıştırma yapılandırmasında karşılaşılan sorunlar genellikle birkaç kaynaktan gelir.
Çifte sıkıştırma problemi: Reverse proxy arkasında uygulama sunucusu da sıkıştırma yapıyorsa, istemci çözümleyemeyeceği bir içerik alabilir. Çözümü yukarıda gösterdim: header_up Accept-Encoding "identity" ile upstream’e sıkıştırma yapmamasını söyle.
HTTPS olmadan Brotli çalışmaz: Brotli, HTTP/2 ile birlikte tasarlanmıştır ve tarayıcılar Brotli desteğini sadece HTTPS bağlantılarda aktifleştirir. Caddy zaten otomatik HTTPS sağladığından bu genellikle sorun olmaz, ama test ortamında düz HTTP kullanıyorsan Brotli yanıtı göremeyebilirsin.
Küçük dosyalarda sıkıştırma olumsuz etki yaratıyor: minimum_length parametresini atlama. 512 byte’tan küçük dosyaları sıkıştırmak, sıkıştırma header overhead’ı nedeniyle dosyayı büyütebilir.
# Mevcut sıkıştırma yapılandırmasını kontrol et
caddy validate --config /etc/caddy/Caddyfile
# Canlı yapılandırmayı API üzerinden görüntüle
curl http://localhost:2019/config/ | python3 -m json.tool | grep -A 20 "encode"
# Belirli bir URL'de sıkıştırma çalışıyor mu?
curl -sv -H "Accept-Encoding: br, gzip" https://example.com/app.js 2>&1 |
grep -E "(content-encoding|content-length|< HTTP)"
Sonuç
Caddy ile sıkıştırma yapılandırması, Nginx veya Apache’ye kıyasla çok daha az karmaşık. Temel encode direktifi ile dakikalar içinde gzip ve Zstandard sıkıştırmasını aktifleştirebilir, biraz daha emek harcayarak xcaddy ile Brotli desteğini de ekleyebilirsin.
Gerçek dünya uygulamalarında önerdiğim yapılandırma sıralaması şu şekilde:
- Önce
encodedirektifini ekle, gzip ile başla - minimum_length’i ayarla, küçük dosyaları sıkıştırmadan muaf tut
- Content-type filtrelemesi yap, zaten sıkıştırılmış binary dosyaları hariç tut
- Üretim ortamına geçmeden önce xcaddy ile Brotli modülünü derle ve ekle
- Build pipeline’ın varsa precompressed dosyalarla gerçek zamanlı sıkıştırma maliyetini ortadan kaldır
- Reverse proxy kullanıyorsan upstream sıkıştırmasını kapat
Performans ölçümlerini unutma. Sıkıştırma aktifleştirdikten sonra sayfa ağırlığını ve TTFB değerlerini kaydet. Gerçek etkiyi görmeden “yeterli” olduğuna karar verme. Çoğu durumda metin tabanlı içeriklerde %60-70 boyut azalması bekleyebilirsin; bu küçük bir konfigürasyon değişikliği için oldukça ciddi bir kazanım.