.htaccess kullanımı, paylaşımlı hosting üzerinde çalışan bir sitenin davranışını değiştirmenin en pratik yoludur. Bu dosya Apache tabanlı web sunucularında dizin düzeyinde yapılandırma yapmanızı sağlar: HTTPS zorlama, 301 yönlendirme, dizin listelemeyi kapatma, özel 404 sayfası, hotlink engelleme ve önbellek ayarlarının tamamı birkaç satırla halledilir. Sunucunun ana yapılandırma dosyasına erişiminiz yoksa elinizdeki tek kaldıraç budur.
Aşağıda hazır ve kopyalanabilir bloklar var; her birini olduğu gibi alıp alan adını değiştirerek kullanabilirsiniz. Ama önce iki şeyi netleştirelim: dosya nerede çalışır, nerede çalışmaz. Ve neden yedek almadan dokunmamanız gerekir.
.htaccess Nedir, Nerede Çalışır?#
.htaccess (hypertext access) adı noktayla başlayan, uzantısı olmayan düz bir metin dosyasıdır. Apache HTTP Server, bir dizine gelen her istekte o dizindeki ve üst dizinlerdeki .htaccess dosyalarını okur, içindeki yönergeleri ana yapılandırmanın üstüne uygular. Dosyayı kaydettiğiniz anda kurallar devreye girer; servis yeniden başlatmaya gerek yoktur.
Buradaki kritik nokta hangi sunucu yazılımını kullandığınız. Bu arada çoğu kişinin sitesinde 500 hatası çıkmasının sebebi de tam olarak bu ayrımı bilmemesi.
| Sunucu yazılımı | .htaccess desteği | Not |
|---|---|---|
| Apache 2.4 | Tam destek | Yaygın paylaşımlı hostinglerin çoğu |
| LiteSpeed / OpenLiteSpeed | Tam destek | Apache söz dizimini birebir okur, üstelik daha hızlı işler |
| Nginx | Yok | Dosya sessizce yok sayılır; kurallar sunucu bloğuna yazılır |
| Caddy | Yok | Kendi Caddyfile biçimini kullanır |
| IIS (Windows) | Yok | web.config dosyası kullanılır |
Yani Nginx çalışan bir VDS’ye .htaccess yüklemek hiçbir işe yaramaz; hata da vermez, sadece yok sayılır. Kendi sunucunuzu kuruyorsanız hangi yazılımı seçeceğinize VDS’ye Nginx veya Apache kurulumu sayfasından karar verebilirsiniz. Paylaşımlı hosting kullanıyorsanız neredeyse kesinlikle Apache ya da LiteSpeed üzerindesiniz, yani bu sayfadaki her şey sizin için geçerli.
İkinci kritik nokta AllowOverride ayarı. Sunucu yöneticisi bu ayarı None yaptıysa dosyanız hiç okunmaz; AllowOverride All ise tüm yönergeler serbesttir. Paylaşımlı hostinglerde genelde All veya buna yakın bir değer verilir. Kendi sunucunuzdaysanız ve kurallar işlemiyorsa ilk bakacağınız yer burasıdır.
.htaccess her istekte yeniden okunduğu için kendi sunucunuzda ana yapılandırmaya yazmak biraz daha hızlıdır. Ama fark ölçülebilir olmakla birlikte küçüktür ve dosyanın esnekliği çoğu senaryoda bu farka değer.Dosyayı Bulma, Oluşturma ve Yedekleme#
Dosya sitenizin kök dizinindedir. cPanel’de bu klasör public_html, kendi sunucunuzda genelde /var/www/html olur. Nokta ile başladığı için gizlidir:
- cPanel Dosya Yöneticisi: sağ üstteki Ayarlar düğmesine basın, “Gizli Dosyaları Göster (dotfiles)” kutusunu işaretleyin.
- FileZilla: Sunucu menüsünden “Gizli dosyaları göstermeye zorla” seçeneğini açın. Ayrıntı için FileZilla ile FTP bağlantısı sayfasına bakın.
- Dosya yoksa: Yeni dosya oluşturup adını
.htaccesskoyun. Windows’ta Not Defteri uzantı ekleyebilir; kaydederken dosya türünü “Tüm Dosyalar” yapın veya Notepad++ kullanın.
.htaccess.bak adıyla saklayın. Bu dosyadaki tek harflik bir hata sitenizi tamamen kapatır ve ziyaretçileriniz 500 Internal Server Error görür. Yedeğiniz varsa geri dönüş on saniye sürer, yoksa panik başlar.-
Notepad++ (kod düzenleyici)Önerilenİndir
-
FileZilla Client (FTP / SFTP)İndir
-
WinSCP (SFTP dosya aktarımı)İndir
Bağlantılar resmî kaynaklara gider. Dosyayı düzenlerken kodlamayı UTF-8 (BOM’suz) bırakın.
HTTPS ve www: Adresi Tek Biçime Sabitleme#
Bir sitenin dört farklı adresten açılabilmesi (http, https, www’li, www’siz) hem SEO açısından zararlıdır hem de oturum ve önbellek sorunları çıkarır. İkisini de tek biçime sabitlemek işin ilk adımıdır.
HTTPS zorlama#
Sertifikanız kuruluysa (değilse önce SSL sertifikası kurulumunu tamamlayın) tüm http isteklerini https’e taşıyın:
RewriteEngine On
# http -> https (tüm istekler)
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Cloudflare veya bir ters vekil sunucu arkasındaysanız
# yukarıdaki yerine bunu kullanın:
# RewriteCond %{HTTP:X-Forwarded-Proto} !https
# RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Cloudflare arkasındayken %{HTTPS} her zaman off görünebilir; o durumda ilk kural sonsuz döngüye girer ve tarayıcı “ERR_TOO_MANY_REDIRECTS” der. Yorum satırındaki alternatifi kullanın.
www ekleme veya kaldırma#
İkisinden birini seçin, ikisini birden yazmayın. Yoksa sonsuz yönlendirme döngüsü kurmuş olursunuz.
RewriteEngine On
# --- SEÇENEK A: www ekle (ornek.com -> www.ornek.com) ---
RewriteCond %{HTTP_HOST} ^ornek\.com$ [NC]
RewriteRule ^(.*)$ https://www.ornek.com/$1 [L,R=301]
# --- SEÇENEK B: www kaldır (www.ornek.com -> ornek.com) ---
# RewriteCond %{HTTP_HOST} ^www\.ornek\.com$ [NC]
# RewriteRule ^(.*)$ https://ornek.com/$1 [L,R=301]
301 Yönlendirme: Tek Sayfa ve Toplu#
301, kalıcı yönlendirme koduudur ve sıralama değerinin büyük kısmını yeni adrese taşır. Site yapısını değiştirdiğinizde, ürün adreslerini sadeleştirdiğinizde veya alan adını taşıdığınızda kullanacağınız kod budur. Geçici bir durum söz konusuysa (bakım, kampanya sayfası) 302 tercih edilir.
Tek sayfa yönlendirme#
# Aynı site içinde
Redirect 301 /eski-sayfa.html /yeni-sayfa.html
Redirect 301 /urun/eski-urun.php /urunler/yeni-urun
# Başka bir alan adına
Redirect 301 /kampanya https://www.baskasite.com/kampanya
# Geçici yönlendirme (bakım, kampanya)
Redirect 302 /magaza /bakim.html
Bu satırlar mod_alias ile çalışır ve RewriteEngine On gerektirmez. Sol taraf her zaman kökten başlayan yol olmalı, tam adres yazılmaz.
Toplu ve desenli yönlendirme#
# Bir dizinin tamamını taşı (alt sayfalar korunur)
RedirectMatch 301 ^/eski-klasor/(.*)$ /yeni-klasor/$1
# Tarih içeren blog adreslerini sadeleştir
# /blog/2024/yazi-adi -> /yazilar/yazi-adi
RedirectMatch 301 ^/blog/[0-9]{4}/(.*)$ /yazilar/$1
# Alan adının tamamını yeni alan adına taşı
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?eskisite\.com$ [NC]
RewriteRule ^(.*)$ https://www.yenisite.com/$1 [L,R=301]
# .html uzantısını adresten kaldır
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.*)$ $1.html [L]
Alan adı taşıma yaparken eski alan adının DNS kayıtlarının hâlâ eski sunucuyu göstermesi gerekir; yoksa yönlendirme çalışmaz. DNS kayıtları sayfasında A ve CNAME kaydının nasıl kontrol edileceği anlatılıyor. Alan adının kendisini devrediyorsanız domain transferi sayfası işinize yarar.
Dizin Listelemeyi Kapatma ve Dosya Erişimini Engelleme#
İçinde index.html ya da index.php olmayan bir klasöre girildiğinde Apache varsayılan olarak klasördeki tüm dosyaları listeler. Yedek dosyaları, veritabanı dökümleri ve yapılandırma dosyaları böyle sızar. Bu davranışı tek satırla kapatın.
# Dizin listelemeyi kapat
Options -Indexes
# Hangi dosyanın dizin sayfası sayılacağını belirt
DirectoryIndex index.php index.html index.htm
# Listeleme açık kalsın ama bazı türler gizlensin isterseniz:
# IndexIgnore *.bak *.sql *.log *.zip
Bunun bir üstü, doğrudan istenmemesi gereken dosyaları erişime kapatmaktır. Apache 2.4 söz dizimi Require all denied şeklindedir; çok eski bir sunucudaysanız Order allow,deny kullanılır ama artık nadiren karşılaşırsınız.
# Nokta ile başlayan hassas dosyalar
<FilesMatch "^\.(env|git|htaccess|htpasswd|user\.ini)">
Require all denied
</FilesMatch>
# Yedek, döküm, günlük ve yapılandırma uzantıları
<FilesMatch "\.(sql|bak|old|log|ini|conf|sh|swp|dist)$">
Require all denied
</FilesMatch>
# WordPress yapılandırma dosyası
<Files "wp-config.php">
Require all denied
</Files>
# Yükleme klasöründe PHP çalıştırılmasını engelle
<FilesMatch "\.(php|phtml|php5|phar)$">
Require all denied
</FilesMatch>
wp-content/uploads/ gibi kullanıcı dosyası yüklenen klasörlere ait bir .htaccess dosyasına konur. Yüklenen bir dosyanın PHP olarak çalışması, WordPress sitelerinin ele geçirilme yollarından biridir; WordPress kurulumu sayfasında bu konuya ayrıca değiniliyor.Özel 404 ve 403 Hata Sayfası#
Apache’nin varsayılan hata sayfası çıplak ve markasızdır; ziyaretçiyi siteden kopartır. Kendi tasarımınızı gösterin:
ErrorDocument 400 /hata/400.html
ErrorDocument 401 /hata/401.html
ErrorDocument 403 /hata/403.html
ErrorDocument 404 /hata/404.html
ErrorDocument 500 /hata/500.html
ErrorDocument 503 /hata/503.html
Yol her zaman siteye göre kökten yazılır: /hata/404.html doğru, hata/404.html yanlış. Tam adres (https://ornek.com/404.html) yazarsanız Apache 404 yerine 302 yönlendirme üretir; arama motorları o sayfayı “var” sanar ve indeksler. Sonra da Search Console’da “soft 404” uyarısı gelir.
404 sayfanız gerçekten 404 durum kodu dönüyor mu, tarayıcı geliştirici araçlarının Network sekmesinden bakabilirsiniz. Kod 200 görünüyorsa yolu düzeltmeniz gerekir.
Dizini Parolayla Koruma (.htpasswd)#
Yönetim paneli, geliştirme ortamı veya müşteriye özel bir klasörü herkese kapatmanın en hızlı yolu HTTP Basic Auth’tur. İki dosya gerekir: kuralları tutan .htaccess ve kullanıcı adı/parola karmasını tutan .htpasswd.
# Korunacak dizinin içindeki .htaccess dosyası
AuthType Basic
AuthName "Yetkili Girisi"
AuthUserFile /home/kullanici/.htpasswds/.htpasswd
Require valid-user
# Belirli bir IP’den gelenleri parolasız geçirmek isterseniz:
# <RequireAny>
# Require ip 203.0.113.10
# Require valid-user
# </RequireAny>
Parola dosyasını üretmek için sunucuda htpasswd komutunu kullanın. Kendi VDS’nizdeyseniz SSH ile bağlanıp şu komutu çalıştırırsınız:
# Dizini web kökünün DIŞINDA oluşturun
mkdir -p /home/kullanici/.htpasswds
# İlk kullanıcı (-c yalnızca ilk seferde, dosyayı sıfırlar)
htpasswd -c /home/kullanici/.htpasswds/.htpasswd yonetici
# Sonraki kullanıcılar için -c KULLANMAYIN
htpasswd /home/kullanici/.htpasswds/.htpasswd editor
Paylaşımlı hostingte SSH erişiminiz yoksa cPanel’in Dizin Gizliliği aracı aynı işi arayüzden yapar ve dosyaları doğru yere kendisi koyar. SSH ile çalışacaksanız SSH bağlantı rehberi giriş noktanız olsun.
AuthUserFile satırındaki yol mutlaka sunucu üzerindeki tam yol olmalıdır (/home/... ile başlar), site adresine göre göreli yol değil. Yanlış yol yazarsanız 500 hatası alırsınız. cPanel’de tam yolu Dosya Yöneticisi’nin üst çubuğunda görebilirsiniz.Hotlink (Görsel Hırsızlığı) Engelleme#
Başka siteler görsellerinizi kendi sayfalarına gömdüğünde bant genişliğini siz ödersiniz. Referrer denetimiyle bunu engelleyebilirsiniz:
RewriteEngine On
# Boş referrer’a izin ver (doğrudan erişim, bazı tarayıcılar, e-posta)
RewriteCond %{HTTP_REFERER} !^$
# Kendi alan adınız serbest
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?ornek\.com [NC]
# Arama motorları ve sosyal ağlar serbest
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?google\. [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?bing\.com [NC]
RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?facebook\.com [NC]
RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?x\.com [NC]
# Kalan herkese 403 dön
RewriteRule \.(jpg|jpeg|png|gif|webp|avif|svg)$ - [F,NC]
# 403 yerine kendi uyarı görselinizi göstermek isterseniz:
# RewriteRule \.(jpg|jpeg|png|gif|webp)$ https://www.ornek.com/hotlink.png [R,NC,L]
Arama motoru istisnalarını atlarsanız görselleriniz Google Görseller sonuçlarından düşer. Kuralı yazdıktan sonra bir görselin adresini gizli sekmede açın ve hala göründüğünü doğrulayın.
Tarayıcı Önbelleği ve Gzip ile Hızlandırma#
Statik dosyalara son kullanma tarihi vermek ve metin içeriğini sıkıştırmak, sayfa hızında en ucuz iki kazançtır. Core Web Vitals tarafındaki etkisini site hızlandırma rehberinde ölçüm örnekleriyle anlattık.
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
ExpiresByType text/html "access plus 0 seconds"
</IfModule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css text/xml
AddOutputFilterByType DEFLATE application/javascript application/json
AddOutputFilterByType DEFLATE application/xml image/svg+xml
</IfModule>
<IfModule> sarmalayıcısı önemlidir: ilgili modül sunucuda yüklü değilse blok sessizce atlanır, 500 hatası çıkmaz. HTML için önbellek süresini sıfır bırakmak da bilinçli bir tercihtir; içeriğinizi güncellediğinizde ziyaretçi eski sayfayı görmesin diye.
mod_deflate yerine Brotli devrede olabilir ve genelde gzip’ten daha iyi sıkıştırır; ayrı bir ayar yapmanız gerekmez. Önünüzde Cloudflare varsa sıkıştırma ve önbellek zaten kenar sunucularda yapılır, ama kaynak sunucudaki bu ayarlar yine de faydalıdır.Satır Sırası ve 500 Internal Server Error#
Apache dosyayı yukarıdan aşağıya okur. RewriteRule satırındaki [L] bayrağı “eşleşti, bu turda başka kural işleme” demektir. Bu yüzden yönlendirme blokları her zaman en üstte olmalıdır. WordPress kullanıyorsanız # BEGIN WordPress ile # END WordPress arasındaki bloğa dokunmayın; kendi kurallarınızı o bloğun üstüne yazın. Aksi hâlde WordPress bir güncelleme sırasında o bölümü yeniden yazar ve eklediğiniz herşey silinir.
Sıralamanın pratik özeti şöyle:
-
Önce erişim ve güvenlik#
Options -Indexes,<FilesMatch>blokları, IP kısıtlamaları. Bunlar sıraya duyarlı değildir ama üstte olması okumayı kolaylaştırır. -
Sonra kanonik yönlendirmeler#
HTTPS zorlama ve www kuralı. Ziyaretçi doğru adrese en baştan gitsin, sonraki kurallar doğru adres üzerinde çalışsın.
-
Ardından 301 yönlendirmeler#
Eski adreslerden yenilere taşıyan
RedirectveRedirectMatchsatırları. -
En sonda uygulama bloğu#
WordPress, Laravel gibi sistemlerin ön denetleyici (front controller) kuralları. Bunlar “dosya yoksa index.php’ye gönder” mantığıyla çalışır ve her isteği yakalar, o yüzden en altta durmalıdır.
500 hatası aldığınızda izleyeceğiniz yol nettir. Önce dosyayı .htaccess.bak olarak yeniden adlandırın; site açıldıysa sorunun kaynağı kesinleşti. Sonra hosting panelindeki Hata Günlükleri (error_log) bölümünü açın; Apache genellikle hatalı satırın numarasını da yazar.
| Belirti | Olası sebep | Çözüm |
|---|---|---|
| 500 Internal Server Error | Kapatılmamış <IfModule> veya <Files> bloğu | Her açılan etiketin kapanışını kontrol edin |
| 500 Internal Server Error | PHP-FPM ortamında php_value satırı | PHP ayarlarını .user.ini veya panelden yapın |
| 500 Internal Server Error | AllowOverride yönergeye izin vermiyor | Sunucu yapılandırmasını düzeltin veya sağlayıcıya yazın |
| Kurallar hiç çalışmıyor | Sunucu Nginx, dosya okunmuyor | Kuralları sunucu bloğuna taşıyın |
| ERR_TOO_MANY_REDIRECTS | www ekleme ve kaldırma kuralı birlikte yazılmış | Yalnızca birini bırakın |
| ERR_TOO_MANY_REDIRECTS | Cloudflare Flexible SSL + HTTPS zorlama | Cloudflare’de SSL modunu Full (strict) yapın |
| Yönlendirme çalışıyor ama yavaş | Zincirleme yönlendirme (http → https → www) | Tek adımda hedef adrese gönderin |
| 403 Forbidden | Require all denied fazla geniş bir desene uygulanmış | Deseni daraltın, alt dizine taşıyın |
Destek taleplerinde en sık gördüğümüz senaryo şu: kullanıcı internetten bulduğu üç ayrı bloğu üst üste yapıştırıyor, ikisi çakışıyor ve site kapanıyor. Blokları teker teker ekleyip her seferinde siteyi test etmek, hepsini birden yapıştırıp sonra hangisinin bozduğunu aramaktan çok daha hızlıdır. Kendi sunucunuzu yönetiyorsanız VDS ilk ayarlar kontrol listesinde yer alan günlük izleme adımları da bu tür sorunları erken yakalamanızı sağlar.
ornek.com ve /home/kullanici/ gibi örnek değerleri kendi bilgilerinizle değiştirmeyi unutmayın. Ayrıca alan adlarında noktayı \. biçiminde kaçırın; düzenli ifadede kaçırılmamış nokta “herhangi bir karakter” anlamına gelir ve kural beklenmedik adreslerde de eşleşir.Özetle#
.htaccess yalnızca Apache ve LiteSpeed sunucularda çalışır; Nginx bu dosyayı okumaz. Dosya sitenizin kök dizinindedir, gizli olduğu için önce görünür yapmanız gerekir ve her istekte yeniden okunduğundan kaydettiğiniz an devreye girer.
Pratikte en çok ihtiyaç duyacağınız bloklar sırasıyla şunlar: HTTPS zorlama, www kuralı, 301 yönlendirmeler, Options -Indexes, hassas dosyaların kapatılması, ErrorDocument satırları, .htpasswd ile dizin koruma, hotlink engelleme ve mod_expires + mod_deflate ikilisi. Sıralamaya dikkat edin, uygulama bloğunu en altta bırakın ve her değişiklikten önce yedek alın.
Sitenizi paylaşımlı hostingten kendi sunucunuza taşımayı düşünüyorsanız web hosting nedir sayfasıyla başlayıp VDS paketlerine göz atabilirsiniz; kendi sunucunuzda Apache yapılandırmasının tamamı sizin denetiminizde olur. Takıldığınız bir blok varsa destek ekibimize mevcut .htaccess içeriğinizle birlikte yazın, satır satır bakalım.