Caddy ile Let’s Encrypt Wildcard Sertifika Kurulumu
Wildcard sertifikalar, özellikle çok sayıda subdomain yöneten sistem yöneticileri için büyük bir nimet. Her subdomain için ayrı ayrı sertifika almak, yönetmek ve yenilemek yerine tek bir *.example.com sertifikasıyla tüm subdomainleri kapsamak hem operasyonel yükü azaltıyor hem de konfigürasyonu sadeleştiriyor. Caddy bu konuda oldukça yetenekli, ancak wildcard sertifikalar Let’s Encrypt’in DNS-01 challenge mekanizmasını gerektirdiğinden biraz farklı bir kurulum süreci izliyoruz. Hadi adım adım bakalım.
Wildcard Sertifika Neden Farklı?
Let’s Encrypt’in standart HTTP-01 challenge’ı, domainin sahibi olduğunuzu kanıtlamak için web sunucunuzun belirli bir URL’e erişilebilir olmasını gerektirir. Wildcard sertifikalar içinse bu yöntem çalışmaz. *.example.com için hangi IP’yi kontrol edecek? Bu yüzden DNS-01 challenge devreye girer.
DNS-01 challenge’da Let’s Encrypt size özel bir TXT kaydı değeri verir, siz bunu DNS’e yazarsınız, Let’s Encrypt kontrol eder ve sertifikayı imzalar. Bu sürecin otomatik çalışması için Caddy’nin DNS sağlayıcınızın API’sine erişmesi gerekir.
Bu süreçte dikkat etmeniz gereken birkaç nokak var:
- DNS sağlayıcısı desteği: Cloudflare, Route53, DigitalOcean gibi popüler sağlayıcıların Caddy eklentileri mevcut
- API token güvenliği: DNS değişikliği yapabilecek bir token üretip güvenli saklamanız gerekiyor
- Propagasyon süresi: DNS değişikliklerinin yayılması birkaç dakika alabilir, bu normal
Ortam Hazırlığı
Bu yazıda Cloudflare’i kullanacağız çünkü en yaygın tercih bu. Ancak mantık tüm sağlayıcılar için aynı, sadece eklenti adı ve konfigürasyon parametreleri değişiyor.
Sisteminizde Caddy’nin standart paket yöneticisi sürümü kurulu olsa bile wildcard sertifika için DNS eklentisi içeren özel bir Caddy binary’sine ihtiyacınız var. Varsayılan Caddy kurulumu bu eklentileri içermiyor.
xcaddy ile Özel Caddy Binary Derleme
xcaddy aracı, Caddy’yi istediğiniz eklentilerle birlikte derlemenizi sağlar. Önce Go kurulu olmalı:
# Go kurulumu (1.21+ gerekli)
wget https://go.dev/dl/go1.21.5.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
# Go sürümünü doğrula
go version
Ardından xcaddy’yi kurup özel binary’yi derleyelim:
# xcaddy kurulumu
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
export PATH=$PATH:$(go env GOPATH)/bin
# Cloudflare DNS eklentisiyle Caddy derle
xcaddy build
--with github.com/caddy-dns/cloudflare
# Derlenen binary'yi sistem dizinine taşı
sudo mv caddy /usr/bin/caddy
sudo chmod +x /usr/bin/caddy
# Doğrula
caddy version
caddy list-modules | grep cloudflare
Eğer Route53 veya başka bir sağlayıcı kullanıyorsanız eklenti adını değiştirmeniz yeterli:
# Route53 için
xcaddy build --with github.com/caddy-dns/route53
# DigitalOcean için
xcaddy build --with github.com/caddy-dns/digitalocean
# Bunları aynı anda da ekleyebilirsiniz
xcaddy build
--with github.com/caddy-dns/cloudflare
--with github.com/caddy-dns/route53
Cloudflare API Token Oluşturma
Cloudflare paneline gidip My Profile > API Tokens > Create Token yolunu izleyin. “Edit zone DNS” şablonunu kullanın ve şu yetkileri verin:
- Zone > DNS > Edit: DNS kayıtlarını düzenleyebilmek için
- Zone > Zone > Read: Zone bilgisini okuyabilmek için
- Zone Resources: Sadece ilgili domain’e kısıtlayın, tüm hesaba izin vermeyin
Token’ı oluşturduktan sonra güvenli bir yere kaydedin, bir daha göremezsiniz.
Caddyfile ile Wildcard Konfigürasyonu
Şimdi asıl konfigürasyona gelelim. Caddy’nin konfigürasyon dosyası genellikle /etc/caddy/Caddyfile konumunda bulunur:
# Önce dizin yapısını oluşturalım
sudo mkdir -p /etc/caddy
sudo mkdir -p /var/log/caddy
sudo chown -R caddy:caddy /var/log/caddy
Temel wildcard konfigürasyonu şöyle görünür:
# /etc/caddy/Caddyfile
{
# Global seçenekler
email [email protected]
# Staging ortamı için (test ederken rate limit'e takılmamak için)
# acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}
*.example.com, example.com {
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}
# Subdomain bazlı yönlendirme
@app host app.example.com
@api host api.example.com
@blog host blog.example.com
@admin host admin.example.com
handle @app {
reverse_proxy localhost:3000
}
handle @api {
reverse_proxy localhost:8080
}
handle @blog {
reverse_proxy localhost:4000
}
handle @admin {
reverse_proxy localhost:9000
}
# Varsayılan (eşleşmeyen subdomain'ler için)
handle {
respond "Bu subdomain henüz yapılandırılmamış." 404
}
}
Bu konfigürasyonda dikkat edin: hem *.example.com hem de example.com yazdık. Wildcard sertifika yalnızca subdomainleri kapsar, ana domain’i kapsamaz. İkisini birlikte listeleyerek tek sertifikada her ikisini de dahil ediyoruz.
Environment Variable ile API Token Yönetimi
API token’ı doğrudan Caddyfile’a yazmak güvenlik açısından kötü bir pratik. Environment variable kullanmak çok daha sağlıklı:
# /etc/caddy/caddy.env dosyası oluştur
sudo tee /etc/caddy/caddy.env > /dev/null << 'EOF'
CLOUDFLARE_API_TOKEN=your_cloudflare_api_token_here
EOF
# Dosya izinlerini güvenli hale getir
sudo chmod 600 /etc/caddy/caddy.env
sudo chown caddy:caddy /etc/caddy/caddy.env
Systemd servis dosyasını bu environment dosyasını okuyacak şekilde güncelle:
# Override dosyası oluştur
sudo systemctl edit caddy
Açılan editöre şunu yazın:
[Service]
EnvironmentFile=/etc/caddy/caddy.env
Kaydedip çıkın, ardından:
sudo systemctl daemon-reload
sudo systemctl restart caddy
Gerçek Dünya Senaryosu: Mikroservis Altyapısı
Diyelim ki bir startup için altyapı yönetiyorsunuz ve onlarca mikroservis var. Her biri farklı bir subdomain üzerinden erişilebilir olacak. Bu senaryoda wildcard sertifika hayat kurtarır:
{
email [email protected]
# Caddy'nin otomatik HTTPS'ini tüm siteler için etkinleştir
auto_https on
}
*.startup.com, startup.com {
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
# Sertifika yenileme için DNS propagasyon bekleme süresi
propagation_timeout 2m
}
# Ana site
@root host startup.com, www.startup.com
handle @root {
reverse_proxy localhost:3000
}
# Kullanıcı dashboard
@dashboard host dashboard.startup.com
handle @dashboard {
reverse_proxy localhost:3001
}
# Kimlik doğrulama servisi
@auth host auth.startup.com
handle @auth {
reverse_proxy localhost:3002
# CORS header'ları
header {
Access-Control-Allow-Origin "https://dashboard.startup.com"
Access-Control-Allow-Methods "GET, POST, OPTIONS"
}
}
# Dosya yükleme servisi
@uploads host uploads.startup.com
handle @uploads {
reverse_proxy localhost:3003
# Büyük dosyalar için timeout artır
request_body {
max_size 500MB
}
}
# Webhook endpoint'leri
@webhooks host webhooks.startup.com
handle @webhooks {
reverse_proxy localhost:3004
}
# Status sayfası
@status host status.startup.com
handle @status {
root * /var/www/status
file_server
}
# Tanımsız subdomain'lere yönlendirme
handle {
redir https://startup.com{uri} permanent
}
}
Sertifika Yönetimi ve Takibi
Caddy sertifika yenilemeyi tamamen otomatik yapıyor ancak bu sürecin düzgün çalıştığını takip etmek iyi bir pratik:
# Mevcut sertifikalara bak
sudo caddy certificates
# Sertifika dizinini kontrol et
sudo ls -la /var/lib/caddy/.local/share/caddy/certificates/
# Caddy log'larını izle
sudo journalctl -u caddy -f
# Belirli bir zaman dilimine ait log'lara bak
sudo journalctl -u caddy --since "2024-01-01" --until "2024-01-02"
Sertifika durumunu izlemek için basit bir script yazabilirsiniz:
#!/bin/bash
# /usr/local/bin/check-caddy-cert.sh
DOMAIN="example.com"
WARN_DAYS=14
CERT_DIR="/var/lib/caddy/.local/share/caddy/certificates"
# Wildcard sertifika dosyasını bul
CERT_FILE=$(find $CERT_DIR -name "*.crt" | xargs grep -l "*.${DOMAIN}" 2>/dev/null | head -1)
if [ -z "$CERT_FILE" ]; then
echo "HATA: $DOMAIN için sertifika bulunamadı"
exit 2
fi
# Sona erme tarihini al
EXPIRY=$(openssl x509 -enddate -noout -in "$CERT_FILE" | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
echo "Sertifika: $DOMAIN"
echo "Son geçerlilik: $EXPIRY"
echo "Kalan gün: $DAYS_LEFT"
if [ $DAYS_LEFT -lt $WARN_DAYS ]; then
echo "UYARI: Sertifika $DAYS_LEFT gün içinde sona eriyor!"
exit 1
fi
echo "Durum: OK"
exit 0
# Script'i çalıştırılabilir yap ve test et
sudo chmod +x /usr/local/bin/check-caddy-cert.sh
/usr/local/bin/check-caddy-cert.sh
Çoklu Domain için Wildcard Sertifika
Birden fazla domain yönetiyorsanız her biri için ayrı wildcard bloku tanımlayabilirsiniz:
{
email [email protected]
}
# Birinci domain
*.example.com, example.com {
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}
@shop host shop.example.com
handle @shop {
reverse_proxy localhost:3000
}
handle {
reverse_proxy localhost:8080
}
}
# İkinci domain (farklı Cloudflare hesabı veya token)
*.seconddomain.com, seconddomain.com {
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN_SECOND}
}
@app host app.seconddomain.com
handle @app {
reverse_proxy localhost:4000
}
handle {
root * /var/www/seconddomain
file_server
}
}
Sorun Giderme
Wildcard sertifika kurulumunda en sık karşılaşılan sorunlara bakalım.
DNS propagasyon sorunu: Challenge TXT kaydı oluşturulup doğrulanmadan önce DNS’te yayılmamış olabilir. Varsayılan bekleme süresi kısa geliyorsa:
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
propagation_timeout 5m
propagation_delay 30s
}
API token yetkisi yetersiz: Caddy log’larında “forbidden” veya “authentication error” görüyorsanız token’ın doğru zone’a erişim iznine sahip olduğunu kontrol edin.
Rate limit: Let’s Encrypt’in üretim ortamında haftalık sertifika limitleri var. Test sırasında mutlaka staging ortamını kullanın:
# Staging sertifikası oluşturmak için geçici test
caddy run --config /etc/caddy/Caddyfile.staging
Staging Caddyfile’da global options bloğuna şunu ekleyin:
{
acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}
Eski sertifika önbelleği: Bazen Caddy eski sertifika bilgilerini önbellekte tutuyor. Temizlemek için:
# Caddy'yi durdur
sudo systemctl stop caddy
# Sertifika önbelleğini temizle (dikkatli olun, yeniden alınacak)
sudo rm -rf /var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/
# Caddy'yi yeniden başlat
sudo systemctl start caddy
# Log'ları izle
sudo journalctl -u caddy -f
Güvenlik Sertleştirmesi
Wildcard sertifika kullandığınızda tüm subdomainlerin aynı sertifika altında olduğunu unutmayın. Bu nedenle ek güvenlik katmanları eklemek önemli:
*.example.com, example.com {
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
# Minimum TLS sürümü
protocols tls1.2 tls1.3
# Güvenli cipher suite'ler
ciphers TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
}
# Güvenlik header'ları (tüm subdomain'ler için geçerli)
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options nosniff
X-Frame-Options DENY
Referrer-Policy strict-origin-when-cross-origin
# Sunucu bilgisini gizle
-Server
}
# Admin panel'e IP kısıtlaması
@admin host admin.example.com
handle @admin {
@allowed_ips remote_ip 192.168.1.0/24 10.0.0.0/8
handle @allowed_ips {
reverse_proxy localhost:9000
}
handle {
respond "Erişim reddedildi." 403
}
}
}
Caddy’yi Systemd ile Yönetme
Caddy servisinin doğru şekilde yapılandırıldığından emin olun:
# Servis durumunu kontrol et
sudo systemctl status caddy
# Konfigürasyonu test et (syntax hatası var mı?)
sudo caddy validate --config /etc/caddy/Caddyfile
# Konfigürasyonu yeniden yükle (downtime olmadan)
sudo systemctl reload caddy
# Veya Caddy'nin kendi komutuyla
sudo caddy reload --config /etc/caddy/Caddyfile
# Boot'ta otomatik başlat
sudo systemctl enable caddy
Önemli bir not: systemctl reload ile systemctl restart arasındaki fark önemli. reload Caddy’nin yeni konfigürasyonu kesintisiz yüklemesini sağlar, restart ise kısa süreli downtime yaratır. Wildcard sertifika konfigürasyonu değişikliklerinde reload tercih edin.
Sonuç
Caddy ile wildcard sertifika yönetimi, ilk kurulum aşamasında biraz daha fazla efor gerektiriyor: özel binary derleme, DNS eklentisi ekleme, API token yönetimi. Ancak bu efor karşılığını kısa sürede veriyor. Onlarca subdomain yönetirken her biri için ayrı sertifika takip etmek yerine tek bir wildcard sertifikanın otomatik yenilendiğini bilmek gerçekten rahatlık verici.
Üretim ortamına geçmeden önce mutlaka staging ortamında test edin, API token’larınızı minimum yetki prensibiyle oluşturun ve sertifika durumunu izleyen basit scriptler çalıştırın. Caddy’nin otomatik yenileme mekanizması güvenilir olsa da “güven ama doğrula” prensibiyle hareket etmek sysadmin’in değişmeyen kurallarından biri.
DNS-01 challenge’ın güzel yanlarından biri de sunucunuzun 80/443 portlarının dışarıya açık olmasını gerektirmemesi. İç ağdaki ya da firewall arkasındaki sunucular için bile geçerli bir sertifika alabiliyorsunuz, bu da wildcard sertifikaları bazı senaryolarda HTTP-01’e göre çok daha esnek kılıyor.
