Bir web sunucusu kuruyorsunuz, her şey hazır, ama tarayıcı adres çubuğunda hâlâ o korkunç “Bağlantınız güvenli değil” uyarısı çıkıyor. Ziyaretçileriniz kaçıyor, Google sıralamanız düşüyor ve siz çaresizce ekrana bakıyorsunuz. Oysa Let’s Encrypt ve Nginx kombinasyonuyla bu sorunu ücretsiz, hızlı ve güvenilir şekilde çözebilirsiniz. Bu yazıda Nginx üzerinde SSL/TLS yapılandırmasını, Let’s Encrypt sertifika alım sürecini ve production ortamı için gerçekten işe yarayan güvenlik ayarlarını adım adım ele alacağız.
SSL/TLS Neden Bu Kadar Önemli?
HTTP trafiği düz metin olarak aktarılır. Yani aradaki herhangi bir cihaz, bu veriyi okuyabilir, değiştirebilir. Kullanıcı şifrelerinden form verilerine kadar her şey açıkta. HTTPS ise bu iletişimi şifreler, sunucunun kimliğini doğrular ve veri bütünlüğünü garanti eder.
Bunun ötesinde pratik gerekçeler de var:
- SEO avantajı: Google, HTTPS kullanan siteleri sıralamada üstte tutar
- Tarayıcı güveni: Chrome, Firefox ve Safari HTTP siteleri “güvensiz” olarak işaretler
- HTTP/2 zorunluluğu: Modern HTTP/2 protokolü pratikte yalnızca HTTPS üzerinde çalışır
- GDPR ve yasal uyumluluk: Kullanıcı verisi işliyorsanız şifreleme artık bir gereklilik
Let’s Encrypt ise tüm bu süreci ücretsiz ve otomatik hâle getiren bir sertifika otoritesidir. 2015’ten beri milyonlarca sertifika dağıtıyor ve sektörün standartlarından biri hâline geldi.
Ortamı Hazırlamak
Bu yazıda Ubuntu 22.04 LTS üzerinde çalışacağız. Nginx’in zaten kurulu olduğunu varsayıyorum. Eğer kurulu değilse:
sudo apt update
sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx
Certbot, Let’s Encrypt sertifikalarını almak ve yenilemek için kullanacağımız araçtır. Snap üzerinden kurmanızı öneririm çünkü snap paketi her zaman güncel sürümü içeriyor:
sudo apt remove certbot # Varsa eski apt sürümünü kaldır
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Kurulumu doğrulayalım:
certbot --version
# certbot 2.x.x
Firewall tarafında 80 ve 443 portlarının açık olduğundan emin olun:
sudo ufw allow 'Nginx Full'
sudo ufw status
Temel Nginx Sanal Sunucu Yapılandırması
Sertifika almadan önce domain için temel bir Nginx yapılandırması oluşturmalısınız. Certbot, domain doğrulaması için bu yapılandırmayı kullanacak.
sudo nano /etc/nginx/sites-available/orneksite.com
server {
listen 80;
listen [::]:80;
server_name orneksite.com www.orneksite.com;
root /var/www/orneksite.com/html;
index index.html index.htm index.php;
location / {
try_files $uri $uri/ =404;
}
# Certbot doğrulama dizini
location /.well-known/acme-challenge/ {
root /var/www/html;
}
access_log /var/log/nginx/orneksite.com.access.log;
error_log /var/log/nginx/orneksite.com.error.log;
}
Web dizinini oluşturun ve sembolik bağlantıyı aktif edin:
sudo mkdir -p /var/www/orneksite.com/html
sudo chown -R www-data:www-data /var/www/orneksite.com
sudo chmod -R 755 /var/www/orneksite.com
sudo ln -s /etc/nginx/sites-available/orneksite.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Let’s Encrypt Sertifikası Almak
Artık Certbot ile sertifikayı alabiliriz. İki yöntem var; birincisi Certbot’un Nginx eklentisini kullanmak (önerilen), ikincisi standalone mod.
Nginx eklentisiyle otomatik yapılandırma:
sudo certbot --nginx -d orneksite.com -d www.orneksite.com
Certbot size birkaç soru soracak: e-posta adresiniz (sertifika yenileme bildirimleri için), hizmet koşullarını kabul edip etmediğiniz ve HTTP trafiğini HTTPS’e yönlendirip yönlendirmeyeceğiniz. Son soruya “2” yani “Redirect” seçeneğini seçmenizi öneririm.
Başarılı çıktı şöyle görünür:
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/orneksite.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/orneksite.com/privkey.pem
This certificate expires on 2024-XX-XX.
Certbot, Nginx yapılandırma dosyanızı otomatik olarak günceller. Güncellenmiş dosyayı inceleyelim:
sudo cat /etc/nginx/sites-available/orneksite.com
Certbot’un eklediği satırları göreceksiniz. Ama bu otomatik yapılandırma production için yeterince güçlü değil. Şimdi onu düzgün hâle getirelim.
Production İçin Güvenli SSL Yapılandırması
Certbot’un oluşturduğu yapılandırma temel düzeyde çalışır ama günümüz güvenlik standartlarını karşılamaz. Özellikle eski TLS sürümleri ve zayıf cipher suite’ler hâlâ aktif kalabilir. Bunu düzeltelim.
Önce paylaşılan SSL parametreleri için bir snippet dosyası oluşturalım. Bu sayede her virtual host için aynı ayarları tekrar tekrar yazmak zorunda kalmayız:
sudo nano /etc/nginx/snippets/ssl-params.conf
# TLS sürümleri - TLS 1.0 ve 1.1 güvensiz, sadece 1.2 ve 1.3 kullan
ssl_protocols TLSv1.2 TLSv1.3;
# Güçlü cipher suite listesi
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256;
# Sunucunun cipher tercihine öncelik ver
ssl_prefer_server_ciphers off;
# SSL session ayarları - performans için
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
# HSTS - tarayıcıya her zaman HTTPS kullanmasını söyle
# max-age=63072000 = 2 yıl, includeSubDomains tüm alt domainleri kapsar
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# Diğer güvenlik başlıkları
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# OCSP Stapling - sertifika doğrulama hızlandırma
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
Şimdi site yapılandırmasını güncelleyelim:
sudo nano /etc/nginx/sites-available/orneksite.com
# HTTP'den HTTPS'e yönlendirme
server {
listen 80;
listen [::]:80;
server_name orneksite.com www.orneksite.com;
return 301 https://$host$request_uri;
}
# HTTPS server bloğu
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name orneksite.com www.orneksite.com;
# Sertifika dosyaları
ssl_certificate /etc/letsencrypt/live/orneksite.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/orneksite.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/orneksite.com/chain.pem;
# SSL parametrelerini dahil et
include snippets/ssl-params.conf;
# Web dizini
root /var/www/orneksite.com/html;
index index.html index.htm index.php;
location / {
try_files $uri $uri/ =404;
}
access_log /var/log/nginx/orneksite.com.access.log;
error_log /var/log/nginx/orneksite.com.error.log;
}
Yapılandırmayı test edip yükleyin:
sudo nginx -t
sudo systemctl reload nginx
Diffie-Hellman Parametrelerini Güçlendirmek
Varsayılan DH parametreleri 1024 bit olabilir, bu da zayıf kabul edilir. 2048 veya 4096 bit parametreler üretmeliyiz:
sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048
4096 bit daha güvenli ama üretimi çok uzun sürer ve performansı olumsuz etkiler. Production için 2048 bit yeterlidir.
Oluşturulan parametreyi ssl-params.conf dosyasına ekleyin:
echo "ssl_dhparam /etc/nginx/dhparam.pem;" | sudo tee -a /etc/nginx/snippets/ssl-params.conf
Sertifika Yenilemeyi Otomatikleştirmek
Let’s Encrypt sertifikaları 90 gün geçerlidir. Certbot snap paketi kurulduğunda otomatik yenileme servisi de gelir, bunu kontrol edelim:
sudo systemctl status snap.certbot.renew.timer
Yenileme işlemini manuel test edelim (gerçek sertifikaya dokunmaz):
sudo certbot renew --dry-run
Çıktıda “Congratulations, all simulated renewals succeeded” görüyorsanız otomasyon çalışıyor demektir.
Yenileme sonrası Nginx’i otomatik reload etmek için hook mekanizmasını kullanabiliriz:
sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
#!/bin/bash
# Sertifika yenilendikten sonra Nginx'i reload et
nginx -t && systemctl reload nginx
echo "$(date): Nginx reloaded after certificate renewal" >> /var/log/certbot-reload.log
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
Wildcard Sertifika Almak
Birden fazla alt domain kullanıyorsanız (api.orneksite.com, mail.orneksite.com, admin.orneksite.com gibi) her biri için ayrı sertifika almak yerine wildcard sertifika kullanabilirsiniz. Ancak wildcard sertifikalar için DNS-01 doğrulaması gerekir, HTTP doğrulaması çalışmaz.
sudo certbot certonly
--manual
--preferred-challenges dns
-d orneksite.com
-d "*.orneksite.com"
Certbot size DNS sağlayıcınıza eklemeniz gereken bir TXT kaydı verecek:
Please deploy a DNS TXT record under the name:
_acme-challenge.orneksite.com
with the following value: xxxxxxxxxxxxxxxxxxxxxxxxxxx
DNS sağlayıcınızın panelinden bu kaydı ekleyin, yayılması için 1-2 dakika bekleyin, sonra Enter’a basın. Bu işlemi her yenilemede tekrar yapmanız gerekir. Otomasyon için Cloudflare, DigitalOcean gibi sağlayıcıların API’lerini destekleyen certbot eklentileri mevcuttur.
Çoklu Domain ve Reverse Proxy Senaryosu
Gerçek dünya senaryosu: Bir sunucuda hem statik site hem de backend API servisi çalışıyor. Her ikisi de farklı domainlerde HTTPS ile erişilebilir olmalı.
Önce her iki domain için sertifika alalım:
sudo certbot certonly --nginx
-d orneksite.com
-d www.orneksite.com
-d api.orneksite.com
Şimdi API için reverse proxy yapılandırması:
sudo nano /etc/nginx/sites-available/api.orneksite.com
server {
listen 80;
server_name api.orneksite.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name api.orneksite.com;
ssl_certificate /etc/letsencrypt/live/orneksite.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/orneksite.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/orneksite.com/chain.pem;
include snippets/ssl-params.conf;
# Rate limiting - API abuse'u önlemek için
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m;
location / {
limit_req zone=api burst=10 nodelay;
# Backend Node.js uygulamasına proxy geç
proxy_pass http://127.0.0.1:3000;
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-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
# Timeout ayarları
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
access_log /var/log/nginx/api.orneksite.com.access.log;
error_log /var/log/nginx/api.orneksite.com.error.log;
}
sudo ln -s /etc/nginx/sites-available/api.orneksite.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
SSL Yapılandırmasını Test Etmek
Yapılandırmanın ne kadar güvenli olduğunu test etmek için birkaç araç kullanabilirsiniz.
SSL Labs testi (en kapsamlı): Tarayıcıdan https://www.ssllabs.com/ssltest/analyze.html?d=orneksite.com adresine gidin. A veya A+ puan almanız hedef.
Komut satırından hızlı test:
# OpenSSL ile sertifika bilgilerini görüntüle
openssl s_client -connect orneksite.com:443 -servername orneksite.com < /dev/null 2>/dev/null | openssl x509 -noout -text | grep -E "Subject:|DNS:|Not After"
# TLS 1.0 ve 1.1 devre dışı mı kontrol et
curl -v --tls-max 1.1 https://orneksite.com 2>&1 | grep -E "SSL|TLS|error"
# "SSL routines:ssl3_get_server_hello:unsupported protocol" hatası görmelisiniz
# HTTP başlıklarını kontrol et
curl -I https://orneksite.com | grep -E "Strict-Transport|X-Frame|X-Content"
testssl.sh aracı ile kapsamlı tarama:
# testssl.sh indirip çalıştır
git clone --depth 1 https://github.com/drwetter/testssl.sh.git
cd testssl.sh
./testssl.sh orneksite.com
Yaygın Sorunlar ve Çözümleri
Sertifika alma sürecinde karşılaşabileceğiniz sorunları ve çözümlerini paylaşayım.
“Too many requests” hatası: Let’s Encrypt aynı domain için haftada 5 sertifika limiti koyar. Test aşamasında --staging parametresiyle sahte sertifika alın:
sudo certbot --nginx --staging -d orneksite.com -d www.orneksite.com
DNS doğrulama başarısız: Domain DNS kayıtlarının sunucuya işaret ettiğini kontrol edin:
dig +short orneksite.com
curl -I http://orneksite.com/.well-known/acme-challenge/test
Sertifika yenilenmiyor, servis durumu kontrol et:
sudo systemctl status snap.certbot.renew.service
sudo journalctl -u snap.certbot.renew.service --since "7 days ago"
# Manuel yenileme dene
sudo certbot renew --force-renewal -d orneksite.com
Nginx “ssl_stapling” uyarısı: Chain dosyası doğru yolda değilse bu uyarı çıkar. Certbot tarafından oluşturulan chain.pem dosyasının var olduğunu doğrulayın:
ls -la /etc/letsencrypt/live/orneksite.com/
Sertifika İzleme ve Erken Uyarı
Sertifikanızın ne zaman sona ereceğini izlemek için basit bir script yazalım:
sudo nano /usr/local/bin/check-ssl-expiry.sh
#!/bin/bash
DOMAIN="orneksite.com"
THRESHOLD=30 # Kaç gün kala uyarı ver
MAILTO="[email protected]"
# Sertifika bitiş tarihini al
EXPIRY_DATE=$(openssl s_client -connect ${DOMAIN}:443 -servername ${DOMAIN} < /dev/null 2>/dev/null
| openssl x509 -noout -enddate 2>/dev/null
| cut -d= -f2)
if [ -z "$EXPIRY_DATE" ]; then
echo "HATA: ${DOMAIN} sertifikası alınamadı" | mail -s "SSL Kontrol Hatası" $MAILTO
exit 1
fi
# Kalan gün sayısını hesapla
EXPIRY_EPOCH=$(date -d "$EXPIRY_DATE" +%s)
NOW_EPOCH=$(date +%s)
DAYS_REMAINING=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
echo "${DOMAIN}: Sertifika ${DAYS_REMAINING} gün sonra sona eriyor"
if [ $DAYS_REMAINING -lt $THRESHOLD ]; then
echo "${DOMAIN} SSL sertifikası ${DAYS_REMAINING} gün içinde sona erecek!"
| mail -s "UYARI: SSL Sertifikası Yenileme Gerekli" $MAILTO
fi
sudo chmod +x /usr/local/bin/check-ssl-expiry.sh
# Crontab'a ekle - her sabah 09:00'da çalışsın
echo "0 9 * * * root /usr/local/bin/check-ssl-expiry.sh" | sudo tee /etc/cron.d/ssl-check
Nginx SSL Performans Optimizasyonu
SSL/TLS el sıkışma süreçleri CPU yoğun işlemlerdir. Yüksek trafikli sitelerde performansı artırmak için şu ayarları ekleyin:
# /etc/nginx/nginx.conf içindeki http bloğuna ekle
http {
# SSL session cache - tekrar bağlantılarda el sıkışmayı atla
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
# Keepalive bağlantıları - TCP bağlantısını tekrar kullan
keepalive_timeout 65;
keepalive_requests 100;
# Gzip sıkıştırma - HTTPS ile güvenli
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_types text/plain text/css application/json application/javascript text/xml;
}
Sonuç
Nginx üzerinde Let’s Encrypt ile güvenli ve modern bir SSL/TLS yapılandırması kurmak, bir zamanlar sertifika maliyetleri ve karmaşık kurulum süreçleri düşünüldüğünde ciddi bir engel gibi görünürdü. Artık durum çok farklı.
Bu yazıda ele aldığımız adımları özetleyecek olursak: Certbot ile sertifika almak dakikalar içinde halledilebilir. Asıl önemli olan, otomatik yenileme kancalarının doğru kurulması ve production için güçlü cipher suite, HSTS, OCSP stapling gibi güvenlik katmanlarının eklenmesidir. SSL Labs testinden A+ almak artık bir lüks değil, minimum standart olmalı.
Wildcard sertifikalar, reverse proxy yapılandırmaları ve çoklu domain senaryoları da günlük sysadmin hayatında sıkça karşılaştığınız durumlar. Bu yazıdaki şablonları başlangıç noktası olarak alıp kendi ortamınıza uyarlayabilirsiniz.
Son bir not: HSTS header’ı eklediğinizde tarayıcılar bu domaini HTTPS olmadan bir daha açmayacak. Bunu eklemeden önce yapılandırmanızın tamamen çalışır durumda olduğundan emin olun. Geri dönüşü olmayan bir adımdır.