Wildcard sertifika ihtiyacı her sysadmin’in eninde sonunda karşılaştığı bir durum. *.sirketim.com gibi tek bir sertifikayla onlarca subdomain’i kapatmak istiyorsun, ama Let’s Encrypt’in standart HTTP challenge yöntemi buna izin vermiyor. Çünkü wildcard sertifikalar için DNS-01 challenge zorunlu. Bu yazıda sıfırdan başlayarak DNS challenge ile wildcard sertifika almanın tüm adımlarını, otomasyonunu ve production’da karşılaşacağın sorunların çözümlerini ele alacağız.
DNS-01 Challenge Neden Gerekli?
Let’s Encrypt’in sertifika verme mantığı şu soruya dayanıyor: “Bu domain gerçekten sana ait mi?” HTTP challenge için .well-known/acme-challenge/ dizinine bir dosya koyuyorsun, Let’s Encrypt bunu doğruluyor. Basit ve etkili, ama wildcard için işe yaramıyor.
Düşün: *.sirketim.com için HTTP challenge yapılacak olsa hangi IP’ye istek atacak? app.sirketim.com mu, api.sirketim.com mu? Belli bir subdomain yok, dolayısıyla HTTP doğrulaması mantıksal olarak mümkün değil.
DNS-01 challenge ise farklı çalışıyor. Let’s Encrypt sana bir token veriyor, sen bu token’ı _acme-challenge.sirketim.com adlı bir TXT kaydı olarak DNS’e ekliyorsun, Let’s Encrypt bu kaydı doğruluyor. Domain’in DNS’ine yazabiliyorsan zaten domain sahibisin, başka kanıta gerek yok.
Gereksinimler ve Ortam Hazırlığı
Başlamadan önce şunları netleştirmek lazım:
- DNS sağlayıcın API erişimine izin veriyor mu? (Cloudflare, Route53, DigitalOcean, Namecheap vb.)
- Certbot veya acme.sh kurulu mu?
- Root veya sudo yetkisi var mı?
- Python 3.6+ sistemde mevcut mu?
Ben bu yazıda Certbot ve acme.sh için örnekler vereceğim. İkisi de yaygın kullanılıyor, hangisinin daha uygun olduğuna göre seçim yapabilirsin. Genellikle acme.sh’ı tercih ediyorum çünkü root gerektirmiyor ve DNS provider desteği çok daha geniş.
Certbot Kurulumu
# Ubuntu/Debian
sudo apt update
sudo apt install certbot python3-certbot-dns-cloudflare -y
# RHEL/CentOS/Rocky Linux
sudo dnf install epel-release -y
sudo dnf install certbot python3-certbot-dns-cloudflare -y
# Snap üzerinden (her distro)
sudo snap install --classic certbot
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-cloudflare
acme.sh Kurulumu
# Root olmadan kullanıcı dizinine kurulum
curl https://get.acme.sh | sh -s [email protected]
# Kurulumdan sonra shell'i yenile
source ~/.bashrc
# Veya direkt çalıştır
~/.acme.sh/acme.sh --version
acme.sh kurulumu ~/.acme.sh/ dizinine yapılır ve cronjob otomatik eklenir. Temiz ve bağımsız bir kurulum.
Cloudflare ile DNS Challenge Kurulumu
Cloudflare en yaygın kullanılan DNS sağlayıcılarından biri ve API desteği çok iyi. Önce API token oluşturuyoruz.
Cloudflare API Token Oluşturma
Cloudflare dashboard’unda şu yolu izle:
- Profile > API Tokens > Create Token
- “Edit zone DNS” template’ini seç
- Zone Resources kısmında ilgili domain’ini seç
- Token’ı oluştur ve kaydet
Bu token’ı güvenli bir yerde sakla, bir daha göremeyeceksin.
Certbot ile Cloudflare DNS Challenge
# Cloudflare credentials dosyası oluştur
sudo mkdir -p /etc/letsencrypt/cloudflare
sudo nano /etc/letsencrypt/cloudflare/credentials.ini
Dosya içeriği şöyle olmalı:
# /etc/letsencrypt/cloudflare/credentials.ini
dns_cloudflare_api_token = BURAYA_CLOUDFLARE_API_TOKEN_GELECEK
Dosya izinlerini sıkılaştır, bu kritik:
sudo chmod 600 /etc/letsencrypt/cloudflare/credentials.ini
sudo chown root:root /etc/letsencrypt/cloudflare/credentials.ini
Şimdi wildcard sertifikayı al:
sudo certbot certonly
--dns-cloudflare
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini
--dns-cloudflare-propagation-seconds 60
-d "sirketim.com"
-d "*.sirketim.com"
--email [email protected]
--agree-tos
--non-interactive
--dns-cloudflare-propagation-seconds 60 parametresi önemli. DNS değişikliklerinin yayılması zaman alıyor, bu süreyi beklemesini söylüyoruz. Cloudflare genellikle çok hızlı ama diğer sağlayıcılarda bu değeri 120 veya daha yüksek tutmak gerekebilir.
Başarılı olursa sertifikalar şurada olacak:
- Sertifika:
/etc/letsencrypt/live/sirketim.com/fullchain.pem - Private key:
/etc/letsencrypt/live/sirketim.com/privkey.pem
acme.sh ile DNS Challenge
acme.sh’ın güzel yanı çok daha fazla DNS provider’ı desteklemesi. Cloudflare, Route53, DNSPod, Namecheap, GoDaddy hepsi var.
# Cloudflare API bilgilerini environment variable olarak set et
export CF_Token="CLOUDFLARE_API_TOKEN_BURAYA"
export CF_Account_ID="CLOUDFLARE_ACCOUNT_ID_BURAYA"
# Wildcard sertifika al
~/.acme.sh/acme.sh --issue
--dns dns_cf
-d sirketim.com
-d "*.sirketim.com"
--keylength 4096
# Sertifikaları istediğin dizine kopyala (deploy)
~/.acme.sh/acme.sh --install-cert
-d sirketim.com
--cert-file /etc/ssl/sirketim/cert.pem
--key-file /etc/ssl/sirketim/key.pem
--fullchain-file /etc/ssl/sirketim/fullchain.pem
--reloadcmd "systemctl reload nginx"
acme.sh API bilgilerini ~/.acme.sh/account.conf dosyasına kaydeder, sonraki renewal’larda tekrar girmen gerekmez.
Route53 ile DNS Challenge
AWS kullanıyorsan Route53 entegrasyonu da oldukça yaygın. IAM politikasını doğru ayarlamak kritik.
Önce IAM policy oluştur:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:GetChange",
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/ZONE_ID_BURAYA",
"arn:aws:route53:::change/*"
]
},
{
"Effect": "Allow",
"Action": [
"route53:ListHostedZones",
"route53:ListHostedZonesByName"
],
"Resource": "*"
}
]
}
Certbot ile Route53 kullanımı:
sudo apt install python3-certbot-dns-route53 -y
# AWS credentials ayarla
sudo mkdir -p /root/.aws
sudo nano /root/.aws/credentials
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
sudo certbot certonly
--dns-route53
--dns-route53-propagation-seconds 120
-d "sirketim.com"
-d "*.sirketim.com"
--email [email protected]
--agree-tos
Route53’te DNS değişiklikleri bazen Cloudflare’den yavaş yayıldığı için propagation seconds’ı 120 tutuyorum.
Nginx ile Wildcard Sertifikayı Kullanmak
Sertifikayı aldıktan sonra web sunucuna entegre etmek gerekiyor. Nginx için örnek konfigürasyon:
# /etc/nginx/sites-available/wildcard-ssl.conf
# HTTP'yi HTTPS'e yönlendir
server {
listen 80;
server_name sirketim.com *.sirketim.com;
return 301 https://$host$request_uri;
}
# Ana domain
server {
listen 443 ssl http2;
server_name sirketim.com;
ssl_certificate /etc/letsencrypt/live/sirketim.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sirketim.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
add_header Strict-Transport-Security "max-age=63072000" always;
root /var/www/sirketim;
index index.html;
}
# Subdomainler için wildcard kullanımı
server {
listen 443 ssl http2;
server_name app.sirketim.com;
ssl_certificate /etc/letsencrypt/live/sirketim.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sirketim.com/privkey.pem;
# SSL ayarları yukarıdakiyle aynı...
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Nginx’i test et ve yeniden yükle:
sudo nginx -t && sudo systemctl reload nginx
Otomatik Yenileme Kurulumu
Let’s Encrypt sertifikaları 90 gün geçerli. Otomatik yenileme olmazsa bir gün sertifikan expire olur ve telefon zili durmuyor. Bunu otomasyona bağlamak şart.
Certbot ile Otomatik Yenileme
Certbot kurulumunda genellikle systemd timer veya cronjob otomatik oluşuruluyor. Kontrol et:
# Systemd timer kontrolü
systemctl status certbot.timer
# Timer aktif değilse etkinleştir
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer
# Manuel test yap (sertifika yenilenmez, sadece test eder)
sudo certbot renew --dry-run
Eğer systemd timer yoksa cron kullan:
sudo crontab -e
# Her gün saat 03:30'da renewal kontrolü yap
30 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
acme.sh Otomatik Yenileme
acme.sh kurulumu sırasında otomatik cronjob ekler ama kontrol etmekte fayda var:
crontab -l | grep acme
# Çıktı şöyle bir şey olmalı:
# 0 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
Renewal sonrası nginx’i yeniden yüklemek için hook ayarla:
~/.acme.sh/acme.sh --install-cert
-d sirketim.com
--reloadcmd "systemctl reload nginx"
Bu komut çalıştırıldıktan sonra her renewal’da otomatik olarak nginx reload edilecek.
Manuel DNS Challenge (API Erişimi Olmadığında)
Bazı DNS sağlayıcıları API sunmuyor veya corporate ortamlarda DNS yönetimi başka bir ekipte. Bu durumda manuel yöntem kullanmak zorundayız. Zahmetli ama işe yarıyor.
sudo certbot certonly
--manual
--preferred-challenges dns
-d "sirketim.com"
-d "*.sirketim.com"
--email [email protected]
--agree-tos
Bu komutu çalıştırınca certbot durup sana bir şey söyleyecek:
Please deploy a DNS TXT record under the name:
_acme-challenge.sirketim.com
with the following value:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Once this is deployed, press Enter to continue
DNS sağlayıcının paneline git, bu TXT kaydını ekle, yayılmasını bekle (dig TXT _acme-challenge.sirketim.com ile kontrol edebilirsin), sonra Enter’a bas.
Önemli bir not: Manuel yöntemde otomatik yenileme çalışmıyor. 90 günde bir bu işlemi tekrarlamak gerekiyor. Eğer mümkünse API erişimine geçmeye çalış.
Sertifika Durumunu İzleme ve Monitoring
Production’da sertifika expiry’sini mutlaka izlemen lazım. Bir gece saat 02:00’de “SSL expired” diyen kullanıcı mesajları almak istemezsin.
# Sertifika bilgilerini görüntüle
sudo certbot certificates
# Tek bir sertifikanın expiry tarihini kontrol et
openssl x509 -in /etc/letsencrypt/live/sirketim.com/fullchain.pem -noout -dates
# Remote bir domain için SSL kontrolü
echo | openssl s_client -connect sirketim.com:443 -servername sirketim.com 2>/dev/null |
openssl x509 -noout -dates
# Kaç gün kaldığını hesapla
echo | openssl s_client -connect sirketim.com:443 -servername sirketim.com 2>/dev/null |
openssl x509 -noout -checkend 2592000 && echo "30 günden fazla var" || echo "30 günden az kaldı!"
Basit bir monitoring scripti:
#!/bin/bash
# /usr/local/bin/ssl-check.sh
DOMAIN="sirketim.com"
WARN_DAYS=30
ALERT_EMAIL="[email protected]"
EXPIRY_DATE=$(echo | openssl s_client -connect ${DOMAIN}:443 -servername ${DOMAIN} 2>/dev/null |
openssl x509 -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "${EXPIRY_DATE}" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 ))
if [ $DAYS_LEFT -lt $WARN_DAYS ]; then
echo "UYARI: ${DOMAIN} sertifikasi ${DAYS_LEFT} gün içinde expire oluyor!" |
mail -s "SSL Sertifika Uyarisi: ${DOMAIN}" ${ALERT_EMAIL}
echo "Kritik: ${DAYS_LEFT} gün kaldı"
else
echo "OK: ${DOMAIN} için ${DAYS_LEFT} gün kaldı"
fi
chmod +x /usr/local/bin/ssl-check.sh
# Cron'a ekle - her sabah 09:00'da çalışsın
echo "0 9 * * * /usr/local/bin/ssl-check.sh" | sudo crontab -
Sık Karşılaşılan Sorunlar ve Çözümleri
DNS Propagation Sorunu
En sık karşılaşılan sorun bu. Let’s Encrypt TXT kaydını doğrulayamıyor çünkü henüz yayılmamış.
# TXT kaydının yayılıp yayılmadığını kontrol et
dig TXT _acme-challenge.sirketim.com @8.8.8.8
dig TXT _acme-challenge.sirketim.com @1.1.1.1
# Yayılana kadar döngü
while ! dig TXT _acme-challenge.sirketim.com @8.8.8.8 | grep -q "acme-challenge"; do
echo "Bekleniyor..."
sleep 10
done
echo "DNS yayıldı!"
Cloudflare’de propagation genellikle 30-60 saniye içinde oluyor ama bazı sağlayıcılarda 5-15 dakika beklemek gerekebilir.
Rate Limit Sorunu
Let’s Encrypt’in rate limitleri var:
- Aynı domain için haftada 5 sertifika
- Aynı IP’den saatte 10 başarısız istek
Test aşamasında --staging parametresini kullan:
sudo certbot certonly
--dns-cloudflare
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini
-d "sirketim.com"
-d "*.sirketim.com"
--staging
Staging ortamında rate limit yok, her şey production gibi çalışıyor sadece sertifika tarayıcılar tarafından güvenilir değil.
Permissions Sorunu
acme.sh root olmayan kullanıcıyla çalışırken /etc/ssl/ gibi dizinlere yazamayabilir:
# Sertifika dizini oluştur ve izin ver
sudo mkdir -p /etc/ssl/sirketim
sudo chown $USER:$USER /etc/ssl/sirketim
# Veya deploy hook'u sudo ile çalıştır
~/.acme.sh/acme.sh --install-cert
-d sirketim.com
--fullchain-file /etc/ssl/sirketim/fullchain.pem
--key-file /etc/ssl/sirketim/key.pem
--reloadcmd "sudo systemctl reload nginx"
Eski TXT Kayıtlarının Temizlenmesi
Birden fazla renewal denemesi yaptıysan DNS’te eski _acme-challenge TXT kayıtları birikmiş olabilir. Bunlar doğrulama hatasına yol açabilir. DNS panelinden gereksiz olanları sil ya da Cloudflare API ile temizle.
Gerçek Dünya Senaryosu: Mikroservis Ortamı
Şirkette 15-20 farklı subdomain’iniz var: api.sirketim.com, app.sirketim.com, admin.sirketim.com, staging.sirketim.com ve benzeri. Her biri için ayrı sertifika almak yerine tek wildcard sertifikayla hepsini yönetiyorsunuz.
Nginx’te merkezi bir SSL konfigürasyon dosyası oluştur:
# /etc/nginx/ssl-params.conf
ssl_certificate /etc/letsencrypt/live/sirketim.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sirketim.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_stapling on;
ssl_stapling_verify on;
Her servis konfigürasyonuna sadece include /etc/nginx/ssl-params.conf; ekle. Sertifika yenilendiğinde tek yerden yönetim sağlanıyor.
Yeni bir servis eklediğinde sadece Nginx konfigürasyonu oluşturuyorsun, sertifika işine gerek yok:
# Yeni subdomain için hızlıca nginx konfig
cat > /etc/nginx/sites-available/newservice.sirketim.com << 'EOF'
server {
listen 443 ssl http2;
server_name newservice.sirketim.com;
include /etc/nginx/ssl-params.conf;
location / {
proxy_pass http://localhost:8080;
}
}
EOF
ln -s /etc/nginx/sites-available/newservice.sirketim.com /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
Bu kadar. Wildcard sertifika zaten *.sirketim.com için geçerli, DNS’te A kaydını ekle, Nginx konfigürasyonunu yaz, bitti.
Sonuç
DNS challenge ile wildcard sertifika almak ilk bakışta karmaşık görünüyor ama bir kez doğru kurulumu yaptıktan sonra son derece temiz bir yapı ortaya çıkıyor. Cloudflare veya Route53 kullanıyorsan API entegrasyonu ile birkaç saatte her şeyi otomasyona bağlayabilirsin.
Önemli noktaları tekrarlayalım:
- API erişimi: Mümkünse DNS sağlayıcının API’sini kullan, manuel yöntem sürdürülebilir değil
- Staging ortamı: Geliştirme ve test aşamasında
--stagingparametresini kullan, rate limit’e takılmaktan kurtulursun - Dosya izinleri: API token ve credentials dosyalarına
chmod 600uygula, bu güvenlik açısından kritik - Monitoring: Sertifika expiry’sini mutlaka izle, bir script veya external monitoring servisi kur
- Propagation süresi: DNS değişikliklerinin yayılması için yeterli bekleme süresi tanı
- Otomatik yenileme: Renewal hook’larını nginx/apache reload içerecek şekilde yapılandır
Microservis mimarilerinde wildcard sertifikanın getirdiği operasyonel kolaylık çok ciddi. Yeni bir subdomain eklediğinde artık “şimdi sertifikayı da alayım” diye düşünmüyorsun. Bu hem zaman kazandırıyor hem de sertifika yönetimi karmaşıklığını büyük ölçüde azaltıyor.