Web sitenizin yüklenme hızı, hem kullanıcı deneyimi hem de SEO açısından kritik öneme sahip. Sunucudan tarayıcıya giden her kilobayt, özellikle mobil kullanıcılar için değerli. İşte bu noktada sıkıştırma devreye giriyor. Nginx üzerinde Gzip ve Brotli yapılandırması yaparak sayfa ağırlığını ciddi ölçüde düşürebilir, sunucu bant genişliği kullanımını azaltabilir ve kullanıcılarınıza daha hızlı bir deneyim sunabilirsiniz. Bu yazıda hem Gzip hem de Brotli’yi gerçek dünya senaryolarıyla nasıl yapılandıracağınızı adım adım ele alacağız.
Gzip ve Brotli Nedir, Neden İkisi Birden?
Gzip, onlarca yıldır web sunucularında kullanılan, evrensel tarayıcı desteğine sahip bir sıkıştırma algoritmasıdır. Hemen her tarayıcı Gzip’i anlar ve destekler. Bu yüzden geriye dönük uyumluluk açısından vazgeçilmezdir.
Brotli ise Google tarafından 2015 yılında geliştirilen ve Gzip’e kıyasla çok daha iyi sıkıştırma oranları sunan modern bir algoritmadır. Özellikle metin tabanlı içeriklerde Gzip’e göre yüzde 20-26 daha iyi sıkıştırma sağlar. Chrome, Firefox, Edge ve Safari gibi modern tarayıcıların tamamı Brotli’yi destekler.
Peki neden ikisini birden yapılandıralım? Çünkü tarayıcı, sunucuya istek gönderirken Accept-Encoding başlığıyla hangi sıkıştırma yöntemlerini desteklediğini belirtir. Nginx, bu başlığa bakarak en uygun algoritmayı seçer. Modern tarayıcılara Brotli, eski tarayıcılara Gzip sunar. Böylece hem maksimum performans hem de tam uyumluluk elde edersiniz.
Ön Koşullar ve Sistem Kontrolü
Gzip, Nginx’in standart kurulumunda hazır gelir. Brotli içinse ngx_brotli modülü gereklidir. Başlamadan önce sisteminizin durumunu kontrol edelim.
# Nginx versiyonunu ve derlenmiş modülleri kontrol et
nginx -V 2>&1 | grep -o with-[a-z_]* | sort
# Brotli modülünün yüklü olup olmadığını kontrol et
nginx -V 2>&1 | grep -i brotli
# Mevcut Nginx konfigürasyonunu test et
nginx -t
# Sistemdeki Nginx paket bilgisini görüntüle
dpkg -l nginx* 2>/dev/null || rpm -qa | grep nginx
Eğer Brotli modülü çıktıda görünmüyorsa iki seçeneğiniz var: ya Brotli desteğiyle önceden derlenmiş bir Nginx paketi kullanırsınız ya da Nginx’i kaynak koddan kendiniz derlersiniz.
Brotli Modülünü Yükleme
Ubuntu/Debian Sistemlerde
Ubuntu ve Debian üzerinde libnginx-mod-http-brotli-filter ve libnginx-mod-http-brotli-static paketleri çoğu zaman resmi depolardan veya Nginx’in kendi deposundan gelmez. En pratik yol nginx.org’un resmi deposunu kullanmaktır.
# Nginx resmi deposunu ekle (Ubuntu 22.04 için)
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg]
http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx"
| sudo tee /etc/apt/sources.list.d/nginx.list
sudo apt update
sudo apt install nginx
# Brotli için dinamik modül paketini yükle
sudo apt install libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static
CentOS/RHEL/Rocky Linux Sistemlerde
# EPEL ve Nginx resmi reposunu ekle
sudo dnf install epel-release
sudo dnf install nginx
# Brotli modülünü derlemek için gerekli bağımlılıklar
sudo dnf install gcc gcc-c++ make cmake git pcre-devel openssl-devel
zlib-devel gd-devel libxslt-devel perl-devel perl-ExtUtils-Embed
GeoIP-devel brotli-devel
# ngx_brotli modülünü klonla
git clone --recurse-submodules https://github.com/google/ngx_brotli.git /tmp/ngx_brotli
# Nginx kaynak kodunu indir (mevcut versiyonunuzla eşleştirin)
NGINX_VERSION=$(nginx -v 2>&1 | grep -o '[0-9.]*$')
wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz -P /tmp/
cd /tmp && tar xzf nginx-${NGINX_VERSION}.tar.gz
# Sadece modülü derle (--add-dynamic-module)
cd /tmp/nginx-${NGINX_VERSION}
./configure --with-compat --add-dynamic-module=/tmp/ngx_brotli
make modules
# Derlenen modülleri kopyala
sudo cp objs/ngx_http_brotli_filter_module.so /etc/nginx/modules/
sudo cp objs/ngx_http_brotli_static_module.so /etc/nginx/modules/
Nginx Ana Yapılandırmasına Modülleri Yükleme
Brotli modüllerini derleme ya da paket kurulumu yoluyla aldıktan sonra nginx.conf dosyasına yüklemeniz gerekir.
# /etc/nginx/nginx.conf dosyasının en üstüne ekleyin
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Gzip yapılandırması
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/xml+rss
application/atom+xml
image/svg+xml
font/truetype
font/opentype
application/vnd.ms-fontobject;
# Brotli yapılandırması
brotli on;
brotli_comp_level 6;
brotli_static on;
brotli_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml
application/xml+rss
application/atom+xml
image/svg+xml
font/truetype
font/opentype
application/vnd.ms-fontobject;
include /etc/nginx/conf.d/*.conf;
}
Yapılandırma Parametrelerinin Detaylı Açıklaması
Gzip Parametreleri
- gzip on: Gzip sıkıştırmayı etkinleştirir. Varsayılan olarak kapalıdır.
- gzip_vary on: Yanıt başlığına
Vary: Accept-Encodingekler. CDN ve proxy’lerin sıkıştırılmış ile sıkıştırılmamış yanıtları ayrı önbelleğe alması için şarttır. - gzip_proxied any: Proxy üzerinden gelen tüm istekler için sıkıştırmayı etkinleştirir.
expired,no-cache,no-store,private,authgibi değerler de kullanılabilir. - gzip_comp_level 6: Sıkıştırma seviyesidir. 1 en hızlı (az sıkıştırma), 9 en yavaş (çok sıkıştırma) anlamına gelir. 6, hız ve sıkıştırma dengesi için ideal değerdir. Production’da 4-6 arası önerilir.
- gzip_buffers 16 8k: Sıkıştırma için kullanılacak tampon sayısını ve boyutunu belirtir. 16 adet 8KB tampon kullanır.
- gzip_http_version 1.1: Minimum HTTP versiyonu belirtir. HTTP/1.0 ile gzip kullanımında sorunlar çıkabilir, 1.1 güvenli seçenektir.
- gzip_min_length 256: Byte cinsinden minimum yanıt boyutunu belirtir. Bundan küçük yanıtlar sıkıştırılmaz. Çok küçük dosyaları sıkıştırmak zaman kaybı olabilir.
- gzip_types: Sıkıştırılacak MIME tiplerini listeler.
text/htmlher zaman dahildir, tekrar yazmanıza gerek yok.
Brotli Parametreleri
- brotli on: Dinamik Brotli sıkıştırmayı etkinleştirir. İstekler gerçek zamanlı olarak sıkıştırılır.
- brotli_comp_level 6: Sıkıştırma seviyesi. 0-11 arası değer alır. Yüksek değerler daha iyi sıkıştırma ama daha fazla CPU kullanımı demektir. 4-6 arası production için idealdir.
- brotli_static on: Önceden sıkıştırılmış
.bruzantılı dosyaları sunar. Eğerdosya.css.brvarsa, dinamik sıkıştırma yapmak yerine bu dosyayı doğrudan sunar. CPU tasarrufu sağlar. - brotli_types: Gzip ile aynı mantık geçerlidir. Sıkıştırılacak MIME tipleri burada belirtilir.
Önceden Sıkıştırılmış Dosya Oluşturma (Pre-compression)
Dinamik sıkıştırma her istekte CPU kullanır. Statik varlıklar için deployment sırasında önceden sıkıştırılmış dosyalar oluşturmak çok daha verimlidir.
# Mevcut statik dosyaları Brotli ile sıkıştır
find /var/www/html -type f ( -name "*.css" -o -name "*.js" -o -name "*.html" -o -name "*.svg" ) |
while read file; do
brotli --best -f "$file" -o "${file}.br"
echo "Sıkıştırıldı: ${file}.br"
done
# Gzip için de aynısını yap
find /var/www/html -type f ( -name "*.css" -o -name "*.js" -o -name "*.html" -o -name "*.svg" ) |
while read file; do
gzip -k -9 -f "$file"
echo "Sıkıştırıldı: ${file}.gz"
done
# Boyut karşılaştırması
ls -lh /var/www/html/assets/app.js*
Bu scripti CI/CD pipeline’ınıza veya deploy hook’unuza ekleyerek her deployment’ta otomatik çalıştırabilirsiniz.
Gerçek Dünya Senaryosu: Nginx Virtual Host Yapılandırması
Tipik bir production web sitesi için örnek bir sanal host yapılandırması:
# /etc/nginx/conf.d/example.com.conf
server {
listen 443 ssl http2;
server_name example.com www.example.com;
root /var/www/example.com/public;
index index.html index.php;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Statik varlıklar için agresif sıkıştırma ve uzun cache
location ~* .(css|js|svg|xml)$ {
gzip_static on;
brotli_static on;
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary "Accept-Encoding";
}
# Fontlar için
location ~* .(woff|woff2|ttf|eot|otf)$ {
brotli_static on;
gzip_static on;
expires 1y;
add_header Cache-Control "public, immutable";
add_header Access-Control-Allow-Origin "*";
}
# JSON API endpoint'leri için
location /api/ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# API yanıtlarını sıkıştır
gzip on;
gzip_min_length 1000;
gzip_types application/json;
brotli on;
brotli_min_length 1000;
brotli_types application/json;
}
# HTML dosyaları
location / {
try_files $uri $uri/ /index.html;
gzip_static on;
brotli_static on;
}
}
Reverse Proxy Senaryosu
Nginx’i bir uygulama sunucusu (Node.js, Gunicorn, PHP-FPM) önünde reverse proxy olarak kullandığınızda, backend yanıtlarını da sıkıştırabilirsiniz.
# /etc/nginx/conf.d/nodejs-app.conf
upstream nodejs_backend {
server 127.0.0.1:3000;
keepalive 32;
}
server {
listen 443 ssl http2;
server_name app.example.com;
# Global sıkıştırma ayarları bu server block için
gzip on;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_comp_level 5;
gzip_min_length 500;
gzip_types
text/plain
text/css
application/json
application/javascript
text/xml
application/xml;
brotli on;
brotli_comp_level 5;
brotli_types
text/plain
text/css
application/json
application/javascript
text/xml
application/xml;
location / {
proxy_pass http://nodejs_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_bypass $http_upgrade;
# Proxy buffer ayarları sıkıştırma verimliliğini etkiler
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
}
}
Sıkıştırmanın Test Edilmesi
Yapılandırmayı doğruladıktan sonra gerçekten çalışıp çalışmadığını test etmek kritik önem taşır.
# Nginx konfigürasyonunu test et ve yeniden yükle
nginx -t && systemctl reload nginx
# Gzip sıkıştırmasını test et
curl -H "Accept-Encoding: gzip" -I https://example.com/assets/app.css
# Brotli sıkıştırmasını test et
curl -H "Accept-Encoding: br" -I https://example.com/assets/app.css
# Her iki algoritmayı birden teklif et (tarayıcı gibi)
curl -H "Accept-Encoding: br, gzip, deflate" -I https://example.com/
# Sıkıştırılmış içeriği indir ve boyutu karşılaştır
curl -H "Accept-Encoding: gzip" -s -o /tmp/compressed.css https://example.com/assets/app.css
curl -s -o /tmp/uncompressed.css https://example.com/assets/app.css
ls -lh /tmp/compressed.css /tmp/uncompressed.css
# İçerik kodlamasını header'dan kontrol et
curl -H "Accept-Encoding: br, gzip" -sI https://example.com/ | grep -i "content-encoding"
Başarılı bir Brotli yanıtında content-encoding: br, Gzip yanıtında ise content-encoding: gzip görmeniz gerekir.
Sık Karşılaşılan Sorunlar ve Çözümleri
Çift Sıkıştırma Sorunu
Eğer backend uygulamanız (Node.js, Python vb.) zaten Gzip uyguluyorsa ve Nginx de üstüne sıkıştırma yapmaya çalışıyorsa, bozuk yanıtlar alabilirsiniz. Bunu engellemek için:
# Backend zaten sıkıştırmışsa Nginx tekrar sıkıştırmasın
location /api/ {
proxy_pass http://backend;
# Sıkıştırılmış yanıtları olduğu gibi geç
proxy_set_header Accept-Encoding "";
# Nginx tarafında sıkıştırmayı bu location için kapat
gzip off;
brotli off;
}
Vary Header Eksikliği ve CDN Sorunları
CDN veya proxy katmanı kullanıyorsanız Vary: Accept-Encoding header’ı olmazsa olmazdır. Aksi halde CDN, sıkıştırılmış bir yanıtı sıkıştırma desteklemeyen bir tarayıcıya sunabilir.
# Tüm sıkıştırılmış yanıtlara Vary header'ı ekle
add_header Vary "Accept-Encoding" always;
Küçük Dosyalar için Sıkıştırma Devre Dışı
100 byte’lık bir dosyayı sıkıştırmak hem işlemci kaynağı harcar hem de bazen dosyayı daha büyük yapabilir. gzip_min_length ve brotli_min_length değerlerini doğru ayarlayın. Genellikle 256-1000 byte arası bir değer idealdir.
Görüntü Dosyalarını Sıkıştırmayın
JPEG, PNG, WebP, GIF gibi görüntü formatları zaten kendi sıkıştırma algoritmalarını içerir. Bu dosyaları Gzip veya Brotli ile tekrar sıkıştırmak hem CPU kaynağı harcar hem de dosya boyutunu artırabilir. gzip_types ve brotli_types listelerinizde asla image/jpeg, image/png gibi tipler bulunmamalıdır.
Performans İzleme ve Log Analizi
Sıkıştırmanın ne kadar bant genişliği tasarrufu sağladığını ölçmek için Nginx log formatını özelleştirin.
# nginx.conf içinde log formatını zenginleştir
log_format compression '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'gzip_ratio=$gzip_ratio '
'encoding=$sent_http_content_encoding '
'length=$content_length';
access_log /var/log/nginx/access.log compression;
Log dosyasını analiz etmek için:
# Brotli kullanım oranını kontrol et
grep "encoding=br" /var/log/nginx/access.log | wc -l
# Gzip kullanım oranını kontrol et
grep "encoding=gzip" /var/log/nginx/access.log | wc -l
# Ortalama gzip sıkıştırma oranı
awk '/gzip_ratio=/ {split($NF,a,"="); sum+=a[2]; count++} END {print "Ortalama oran:", sum/count}'
/var/log/nginx/access.log
# Son 100 istek için encoding dağılımı
tail -100 /var/log/nginx/access.log | grep -oP 'encoding=K[^s]+' | sort | uniq -c
Güvenlik Notları
BREACH saldırısı, HTTPS üzerinde Gzip sıkıştırma ile birlikte ortaya çıkabilen bir side-channel saldırısıdır. Bu saldırıya karşı önlem olarak CSRF token’larının her istekte değiştirilmesi ve hassas sayfalar için sıkıştırmanın devre dışı bırakılması önerilir.
# Hassas sayfalar için sıkıştırmayı devre dışı bırak
location /admin/ {
gzip off;
brotli off;
# diğer ayarlar...
}
location /account/ {
gzip off;
brotli off;
}
Sonuç
Nginx üzerinde Gzip ve Brotli yapılandırması, düşük maliyetli ama yüksek etkili bir performans optimizasyonudur. Doğru yapılandırıldığında metin tabanlı varlıklarda yüzde 60-80 boyut azalması elde edebilirsiniz. Bunu pratiğe dökersek; 500KB’lık bir JavaScript dosyası, Brotli ile 100-150KB’a kadar inebilir. Bu, özellikle mobil kullanıcılar için sayfa yükleme süresine doğrudan yansır.
Önerilen yaklaşım şu şekilde özetlenebilir: Modern tarayıcılar için Brotli, eski tarayıcılar için Gzip’i aktif tutun, statik varlıklar için deployment sürecinde önceden sıkıştırılmış dosyalar hazırlayın, brotli_static on ve gzip_static on direktiflerini kullanarak CPU tasarrufu sağlayın, görüntü ve video dosyalarını asla sıkıştırma listesine dahil etmeyin ve CDN kullanıyorsanız Vary: Accept-Encoding header’ının doğru iletildiğinden emin olun.
Bu yapılandırmayı production’a almadan önce nginx -t ile her zaman test edin ve değişiklikleri kademeli olarak hayata geçirin. Core Web Vitals metriklerinizi ve bant genişliği kullanımınızı izlemeye devam ederek optimizasyonun etkisini somut olarak ölçebilirsiniz.