Birden fazla web sitesini tek bir sunucuda yönetmek, sistem yöneticilerinin günlük hayatının vazgeçilmez bir parçası. Küçük bir VPS’ten kurumsal bir sunucuya kadar, Apache’nin Virtual Host özelliği bu işi hem esnek hem de yönetilebilir kılıyor. Bu yazıda gerçek dünya senaryolarıyla Apache Virtual Host yapılandırmasını en ince ayrıntısına kadar inceleyeceğiz.
Apache Virtual Host Nedir ve Neden Önemlidir?
Apache’de Virtual Host (sanal sunucu), tek bir fiziksel makine üzerinde birden fazla web sitesini barındırmanızı sağlayan mekanizmadır. Sunucunuzun tek bir IP adresi olsa bile, gelen HTTP isteğinin Host başlığına bakarak hangi sitenin içeriğini sunacağına karar verir.
İki tür Virtual Host yapılandırması vardır:
- IP tabanlı Virtual Host: Her site için ayrı bir IP adresi gerektirir, günümüzde nadiren kullanılır
- İsim tabanlı Virtual Host: Tek IP üzerinde birden fazla domain çalışır, modern kurulumların standartı budur
Bugün odaklanacağımız isim tabanlı yapılandırmadır. Bir ajans düşünün; müşterilerin sitelerini aynı sunucuda barındırıyor. Müşteri sayısı 20’ye çıktığında her biri için ayrı sunucu almak saçmalık olur. İşte Virtual Host tam burada devreye giriyor.
Ön Hazırlık ve Apache Kurulumu
Başlamadan önce sisteminizin hazır olduğundan emin olalım. Ubuntu/Debian tabanlı sistemlerde:
sudo apt update && sudo apt upgrade -y
sudo apt install apache2 -y
sudo systemctl enable apache2
sudo systemctl start apache2
sudo systemctl status apache2
CentOS/RHEL tabanlı sistemlerde ise:
sudo dnf install httpd -y
sudo systemctl enable httpd
sudo systemctl start httpd
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Apache kurulduktan sonra servis adının farklı olduğuna dikkat edin: Debian ailesinde apache2, Red Hat ailesinde httpd. Bu yazıda Ubuntu/Debian üzerinden ilerleyeceğiz ama Red Hat farkları için not düşeceğiz.
Dizin Yapısını Kurmak
Düzenli bir yapı, ileride başınızı ağrıtmaz. Her domain için kendi dizinini oluşturun:
# Site dizinlerini oluştur
sudo mkdir -p /var/www/sirket1.com/public_html
sudo mkdir -p /var/www/sirket2.com/public_html
sudo mkdir -p /var/www/blog.sirket1.com/public_html
# Log dizinlerini oluştur
sudo mkdir -p /var/www/sirket1.com/logs
sudo mkdir -p /var/www/sirket2.com/logs
# Sahipliği ayarla
sudo chown -R $USER:$USER /var/www/sirket1.com
sudo chown -R $USER:$USER /var/www/sirket2.com
# İzinleri düzenle
sudo chmod -R 755 /var/www
Şimdi test için basit HTML dosyaları oluşturalım:
echo "<h1>Sirket1.com'a Hosgeldiniz!</h1>" | sudo tee /var/www/sirket1.com/public_html/index.html
echo "<h1>Sirket2.com'a Hosgeldiniz!</h1>" | sudo tee /var/www/sirket2.com/public_html/index.html
İlk Virtual Host Yapılandırma Dosyasını Oluşturmak
Apache’de her site için ayrı bir .conf dosyası oluşturmak en iyi pratiktir. Bu dosyalar /etc/apache2/sites-available/ dizininde tutulur.
sudo nano /etc/apache2/sites-available/sirket1.com.conf
Dosyanın içeriği şöyle olsun:
<VirtualHost *:80>
ServerAdmin [email protected]
ServerName sirket1.com
ServerAlias www.sirket1.com
DocumentRoot /var/www/sirket1.com/public_html
ErrorLog /var/www/sirket1.com/logs/error.log
CustomLog /var/www/sirket1.com/logs/access.log combined
<Directory /var/www/sirket1.com/public_html>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
Buradaki direktifleri açıklayalım:
- ServerAdmin: Hata sayfalarında görünecek yönetici e-posta adresi
- ServerName: Birincil domain adı, Apache bu değere göre eşleşme yapar
- ServerAlias: Aynı siteye yönlendirilecek ek domain isimleri, birden fazla yazabilirsiniz
- DocumentRoot: Sitenin dosyalarının bulunduğu kök dizin
- ErrorLog / CustomLog: Site özelinde log dosyaları, sorun gidermede hayat kurtarır
- AllowOverride All:
.htaccessdosyalarının çalışmasına izin verir, WordPress gibi CMS’ler için şart - Options Indexes: Dizin listesi gösterimi, genellikle kapatmak istersiniz
Virtual Host’u Aktif Etmek
Apache’de siteleri aktif etmek için a2ensite komutunu kullanıyoruz:
# Siteleri aktif et
sudo a2ensite sirket1.com.conf
sudo a2ensite sirket2.com.conf
# Varsayılan siteyi kapat (isteğe bağlı ama tavsiye edilir)
sudo a2dissite 000-default.conf
# Yapılandırmayı test et
sudo apache2ctl configtest
# Apache'yi yeniden yükle
sudo systemctl reload apache2
apache2ctl configtest komutu kritik öneme sahip. Syntax hatası varsa bunu söyler ve servisi bozmadan önce fırsatınız olur. Her değişiklikten sonra bu komutu çalıştırın, bu alışkanlık sizi ciddi downtime’lardan kurtarır.
Red Hat sistemlerinde a2ensite yoktur, doğrudan /etc/httpd/conf.d/ dizinine .conf dosyası oluşturursunuz ve otomatik yüklenir.
İkinci Senaryo: Subdomain Yönetimi
Gerçek dünyada sadece farklı domainler değil, alt domainler de sık karşılaşılan ihtiyaçtır. Bir şirketin hem www.sirket.com hem api.sirket.com hem de blog.sirket.com adresleri olabilir.
sudo nano /etc/apache2/sites-available/api.sirket1.com.conf
<VirtualHost *:80>
ServerAdmin [email protected]
ServerName api.sirket1.com
DocumentRoot /var/www/api.sirket1.com/public_html
ErrorLog /var/www/api.sirket1.com/logs/error.log
CustomLog /var/www/api.sirket1.com/logs/access.log combined
# API sunucusu icin ozel ayarlar
<Directory /var/www/api.sirket1.com/public_html>
Options -Indexes
AllowOverride All
Require all granted
</Directory>
# CORS basliklarini ekle
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
</VirtualHost>
Burada Options -Indexes kullandık. Eksi işareti, dizin listelemeyi kapattığımız anlamına gelir. API endpointi için dosya listeleme kesinlikle istemezsiniz.
HTTPS ile Virtual Host Yapılandırması
2024 yılında HTTPS olmadan web sitesi olmaz. Let’s Encrypt ile ücretsiz SSL sertifikası alıp Virtual Host’a entegre edelim:
# Certbot kurulumu
sudo apt install certbot python3-certbot-apache -y
# Sertifika al ve Apache'yi otomatik yapılandır
sudo certbot --apache -d sirket1.com -d www.sirket1.com
# Tum siteler icin toplu sertifika
sudo certbot --apache -d sirket2.com -d www.sirket2.com
Certbot Apache yapılandırmanızı otomatik günceller ama manuel yapmak da isterseniz:
sudo nano /etc/apache2/sites-available/sirket1.com-ssl.conf
<VirtualHost *:443>
ServerAdmin [email protected]
ServerName sirket1.com
ServerAlias www.sirket1.com
DocumentRoot /var/www/sirket1.com/public_html
# SSL Ayarlari
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/sirket1.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/sirket1.com/privkey.pem
# Guvenli SSL Protokolleri
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
SSLHonorCipherOrder off
SSLSessionTickets off
# Guvenlik Basliklar
Header always set Strict-Transport-Security "max-age=63072000"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
ErrorLog /var/www/sirket1.com/logs/error.log
CustomLog /var/www/sirket1.com/logs/access.log combined
<Directory /var/www/sirket1.com/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
# HTTP'den HTTPS'e yonlendirme
<VirtualHost *:80>
ServerName sirket1.com
ServerAlias www.sirket1.com
Redirect permanent / https://sirket1.com/
</VirtualHost>
SSL yapılandırması için gerekli modülleri aktif etmeyi unutmayın:
sudo a2enmod ssl
sudo a2enmod headers
sudo a2enmod rewrite
sudo systemctl restart apache2
Reverse Proxy ile Virtual Host Kullanımı
Modern altyapılarda Apache sadece statik dosya sunmaz; arka planda çalışan Node.js, Python veya Java uygulamalarına trafiği iletmek için de kullanılır. Bu senaryo ajans ortamlarında çok yaygındır.
Diyelim ki app.sirket1.com adresine gelen istekleri 3000 portunda çalışan bir Node.js uygulamasına iletmek istiyorsunuz:
# Gerekli modulleri aktif et
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests
sudo nano /etc/apache2/sites-available/app.sirket1.com.conf
<VirtualHost *:80>
ServerName app.sirket1.com
ProxyPreserveHost On
ProxyRequests Off
# Tum istekleri Node.js uygulamasina ilet
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
# WebSocket destegi (gerekirse)
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/?(.*) "ws://127.0.0.1:3000/$1" [P,L]
ErrorLog /var/log/apache2/app.sirket1.com-error.log
CustomLog /var/log/apache2/app.sirket1.com-access.log combined
</VirtualHost>
Erişim Kontrolü ve Güvenlik Ayarları
Bazı Virtual Host’lar herkese açık olmamalı. Örneğin şirket içi bir yönetim paneli veya staging ortamı sadece belirli IP’lerden erişilebilir olsun:
<VirtualHost *:80>
ServerName staging.sirket1.com
DocumentRoot /var/www/staging.sirket1.com/public_html
<Directory /var/www/staging.sirket1.com/public_html>
Options -Indexes
AllowOverride All
# Sadece ofis IP'si ve VPN'den erisim
Require ip 203.0.113.50
Require ip 10.0.0.0/8
</Directory>
# Temel kimlik dogrulama ekle
<Location "/">
AuthType Basic
AuthName "Staging Ortami - Yetkili Giris"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Location>
ErrorLog /var/log/apache2/staging-error.log
CustomLog /var/log/apache2/staging-access.log combined
</VirtualHost>
Kullanıcı oluşturmak için:
# Ilk kullanici (dosyayi olusturur)
sudo htpasswd -c /etc/apache2/.htpasswd testkullanici
# Ek kullanici ekle
sudo htpasswd /etc/apache2/.htpasswd ikincikisi
Sorun Giderme: Sık Karşılaşılan Hatalar
403 Forbidden Hatası
Bu hata genellikle dizin izinlerinden kaynaklanır:
# Hata logunu kontrol et
sudo tail -f /var/log/apache2/error.log
# Dizin izinlerini kontrol et
ls -la /var/www/sirket1.com/
# Sahiplik sorunu varsa duzelt
sudo chown -R www-data:www-data /var/www/sirket1.com/public_html
sudo chmod -R 755 /var/www/sirket1.com/
404 Not Found Hatası
Virtual Host yapılandırması doğru ama site gelmiyor:
# Aktif siteleri listele
sudo apache2ctl -S
# DNS cozumlemesini test et (yerel test icin hosts dosyasini kullan)
echo "127.0.0.1 sirket1.com www.sirket1.com" | sudo tee -a /etc/hosts
# Curl ile test et
curl -H "Host: sirket1.com" http://localhost/
ServerName Uyarısı
Apache başlarken Could not reliably determine the server's fully qualified domain name uyarısı alıyorsanız:
echo "ServerName localhost" | sudo tee /etc/apache2/conf-available/servername.conf
sudo a2enconf servername
sudo systemctl reload apache2
Performans Optimizasyonu için Virtual Host Ayarları
Çok sayıda Virtual Host çalışıyorsa performans ayarlarına dikkat etmek gerekir:
sudo nano /etc/apache2/sites-available/sirket1.com.conf
Mevcut yapılandırmaya şunları ekleyin:
<VirtualHost *:443>
ServerName sirket1.com
DocumentRoot /var/www/sirket1.com/public_html
# Gzip sikistirma
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/css application/javascript
AddOutputFilterByType DEFLATE application/json application/xml
</IfModule>
# Tarayici onbellekleme
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>
# Keep-Alive
KeepAlive On
KeepAliveTimeout 5
MaxKeepAliveRequests 100
</VirtualHost>
Bu modülleri aktif edin:
sudo a2enmod deflate
sudo a2enmod expires
sudo apache2ctl configtest && sudo systemctl reload apache2
Virtual Host Durumunu İzlemek
Sunucunuzda kaç Virtual Host çalıştığını ve hangisinin hangi isteğe cevap verdiğini görmek için:
# Tum aktif Virtual Host'lari listele
sudo apache2ctl -S
# Hangi portlar dinleniyor
sudo ss -tlnp | grep apache
# Baglanti sayisini izle
sudo apache2ctl status
# Gercek zamanli log takibi
sudo tail -f /var/www/sirket1.com/logs/access.log | grep -v "bot|crawler"
apache2ctl -S komutunun çıktısı gerçekten işe yarıyor. Hangi domain’in hangi yapılandırma dosyasına bağlandığını, port çakışmaları olup olmadığını net gösteriyor. Sorun gidermede ilk başvurulacak komut bu olmalı.
Yapılandırma Yönetimi İçin Pratik İpuçları
Onlarca müşteri sitesi yönetiyorsanız bazı küçük alışkanlıklar büyük fark yaratır:
- Şablon kullanın: Standart bir
.confdosyası şablonu oluşturupsedile domain adını değiştirerek yeni site ekleyin - Sürüm kontrolü:
/etc/apache2/dizinini Git ile takip edin, her değişiklik kayıt altında olsun - Log rotasyonu:
/etc/logrotate.d/apache2dosyasını kontrol edin, log dosyaları disk doldurmaz - Düzenli test: Her Pazar gece
certbot renew --dry-runile SSL sertifika yenileme testini yapın - Yedekleme: Yeni site eklemeden önce mevcut
.confdosyalarını yedekleyin
Özellikle şablon konusunu biraz açalım. Bash scripti ile yeni site eklemeyi otomatikleştirmek mümkün:
#!/bin/bash
DOMAIN=$1
sudo mkdir -p /var/www/$DOMAIN/{public_html,logs}
sudo chown -R www-data:www-data /var/www/$DOMAIN
cat > /etc/apache2/sites-available/$DOMAIN.conf << EOF
<VirtualHost *:80>
ServerName $DOMAIN
ServerAlias www.$DOMAIN
DocumentRoot /var/www/$DOMAIN/public_html
ErrorLog /var/www/$DOMAIN/logs/error.log
CustomLog /var/www/$DOMAIN/logs/access.log combined
<Directory /var/www/$DOMAIN/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
EOF
sudo a2ensite $DOMAIN.conf
sudo apache2ctl configtest && sudo systemctl reload apache2
echo "$DOMAIN basariyla eklendi!"
Bu scripti /usr/local/bin/add-vhost.sh olarak kaydedin ve chmod +x ile çalıştırılabilir yapın. Artık yeni site eklemek tek komutla olur: sudo add-vhost.sh musteri3.com
Sonuç
Apache Virtual Host yapılandırması ilk bakışta karmaşık görünse de mantığı kavradıktan sonra son derece yönetilebilir bir sistem haline geliyor. Önemli olan tutarlı bir dosya yapısı kurmak, her değişiklik öncesi configtest yapmak ve log dosyalarını aktif olarak takip etmek.
Gerçek ortamlarda en çok zaman alan şey yapılandırmayı yazmak değil, DNS yayılmasını beklemek ve SSL sertifika sorunlarını çözmektir. Bunun için curl -H "Host: domain.com" komutu ve yerel hosts dosyası günlük araçlarınız arasına girsin.
Ajans veya hosting ortamında bu altyapıyı otomatize etmek için yazıda paylaştığımız bash scriptini ihtiyaçlarınıza göre genişletin. Birkaç düzine müşteri sitesini tek bir sunucuda sağlıklı yönetmek tamamen mümkün; önemli olan düzenli yapı ve iyi dokümantasyon. Sunucunuzu bir kaos yerine iyi organize edilmiş bir kitaplık gibi düşünün, her şeyin bir yeri olsun ve herkes o yeri bilsin.