IIS ile Let’s Encrypt Ücretsiz SSL Sertifikası Kurulumu
Windows ortamında IIS çalıştırıyorsanız ve SSL sertifikası işi hâlâ manuel, yıllık ödeme gerektiren bir süreç olarak devam ediyorsa, bu yazı tam size göre. Yıllarca ticari sertifika satın alarak, sona erme tarihlerini takvime işaretleyerek ve zaman zaman sertifika yenilemeyi unutup gece yarısı panikleyerek geçirilen deneyimlerden sonra Let’s Encrypt’e geçmek gerçekten bir özgürleşme hissi veriyor. IIS ile bu işi yapmak Linux kadar akıcı olmasa da doğru araçlarla oldukça yönetilebilir hale geliyor.
Let’s Encrypt ve Win-ACME Nedir
Let’s Encrypt, Internet Security Research Group (ISRG) tarafından işletilen, tamamen ücretsiz ve otomatik sertifika yetkilisi. 90 günlük sertifikalar veriyor ve bu kısa ömrü telafi etmek için otomasyonu teşvik ediyor. Linux dünyasında Certbot bu işi çok iyi yapıyor; Windows tarafında ise en olgun ve güvenilir araç win-acme (eski adıyla wacs).
Win-ACME, ACME protokolünü destekleyen açık kaynak bir istemci. IIS entegrasyonu built-in geliyor, sertifika bağlamayı otomatik yapıyor ve Windows Görev Zamanlayıcı üzerinden otomatik yenileme kurabiliyor. Hâlâ PowerShell ile elle uğraşmak isteyenler için Posh-ACME de güzel bir alternatif, ona da değineceğiz.
Ön Gereksinimler
Başlamadan önce birkaç şeyin yerinde olması gerekiyor:
- Windows Server 2012 R2 veya üzeri (2019/2022 önerilen)
- IIS 8.5 veya üzeri kurulu ve çalışıyor olmalı
- 80 ve 443 portları dışarıdan erişilebilir olmalı
- DNS kayıtları sunucunuza yönlenmiş olmalı
- Yönetici yetkisi (win-acme’yi yönetici olarak çalıştırmanız gerekecek)
Let’s Encrypt doğrulama sürecinde http-01 challenge kullanıyorsa 80 numaralı porta dışarıdan erişmesi gerekiyor. Eğer 80 portu kapalıysa DNS challenge’a geçmeniz gerekir, bunu da ilerleyen bölümlerde ele alacağız.
Win-ACME Kurulumu
Önce win-acme’yi indirip kuralım. GitHub releases sayfasından en son sürümü alıyoruz.
# PowerShell ile indirme (yönetici olarak çalıştırın)
$url = "https://github.com/win-acme/win-acme/releases/download/v2.2.9.1701/win-acme.v2.2.9.1701.x64.trimmed.zip"
$dest = "C:Toolswin-acme.zip"
Invoke-WebRequest -Uri $url -OutFile $dest
# Zip dosyasını aç
Expand-Archive -Path $dest -DestinationPath "C:Toolswin-acme" -Force
# Klasöre geç
Set-Location "C:Toolswin-acme"
İndirme tamamlandıktan sonra C:Toolswin-acme klasöründe wacs.exe dosyasını göreceksiniz. Bunu PATH’e eklemenizi öneririm, her seferinde tam yol yazmak yorucu.
# PATH'e ekle (isteğe bağlı ama önerilen)
$currentPath = [Environment]::GetEnvironmentVariable("Path", "Machine")
$newPath = $currentPath + ";C:Toolswin-acme"
[Environment]::SetEnvironmentVariable("Path", $newPath, "Machine")
IIS Site Yapılandırması
Win-ACME’yi çalıştırmadan önce IIS’te sitenizin düzgün yapılandırılmış olduğundan emin olun. HTTP binding üzerinden sitenize dışarıdan erişilebildiğini test edin.
# IIS modülünü yükle
Import-Module WebAdministration
# Mevcut siteleri listele
Get-Website | Select-Object Name, State, PhysicalPath, @{N="Bindings";E={$_.bindings.Collection}}
# Belirli bir sitenin binding'lerini kontrol et
Get-WebBinding -Name "VarsayilanWebSitesi"
Eğer HTTP binding yoksa ekleyin:
# HTTP binding ekle (80 portu)
New-WebBinding -Name "VarsayilanWebSitesi" -Protocol "http" -Port 80 -HostHeader "www.sirketiniz.com"
New-WebBinding -Name "VarsayilanWebSitesi" -Protocol "http" -Port 80 -HostHeader "sirketiniz.com"
İlk Sertifika Alma: Interaktif Mod
Win-ACME’nin güzel yanlarından biri interaktif modda adım adım ilerleyebilmeniz. Yeni başlayanlar için bu modu kullanmanızı öneririm, ne yaptığını görmek açısından öğretici.
# Yönetici PowerShell veya CMD'de çalıştırın
cd C:Toolswin-acme
.wacs.exe
Karşınıza şöyle bir menü gelecek:
N: Create certificate (default settings)
M: Create certificate (full options)
R: Run renewals (>0 currently due)
A: Manage renewals (1 total)
O: More options...
Q: Quit
Please choose from the menu:
N seçeneği çoğu senaryo için yeterli. Devam ettiğinizde mevcut IIS sitelerinizi listeleyen bir ekran gelecek, oradan ilgili siteyi seçiyorsunuz. Sonra e-posta adresinizi giriyorsunuz (Let’s Encrypt sertifika sorunlarını bu adrese bildiriyor), son kullanıcı sözleşmesini kabul ediyorsunuz ve işlem başlıyor.
Başarılı bir çıktı şuna benziyor:
[INF] Authorizing identifier www.sirketiniz.com using http-01 validation
[INF] Downloading token to C:inetpubwwwroot.well-knownacme-challengeabc123...
[INF] Authorization result: valid
[INF] Requesting certificate [IIS] sirketiniz.com
[INF] Store with CertificateStore...
[INF] Installing certificate in the certificate store
[INF] Adding/updating https binding for www.sirketiniz.com:443
[INF] Scheduled task for renewal configured
Komut Satırından Otomatik Sertifika Alma
Interaktif mod güzel ama production ortamlarda, özellikle birden fazla sunucu yönetiyorsanız, her şeyin script’e dökülmesi gerekiyor. Win-ACME bunu --unattended parametresiyle destekliyor.
# Tek komutla sertifika alma (IIS sitesi için)
.wacs.exe `
--target iis `
--siteid 1 `
--installation iis `
--emailaddress "[email protected]" `
--accepttos `
--unattended
# Wildcard sertifika için (DNS challenge gerektirir)
.wacs.exe `
--target manual `
--host "*.sirketiniz.com,sirketiniz.com" `
--validation dns-01 `
--validationmode dns-01 `
--emailaddress "[email protected]" `
--accepttos `
--unattended
Buradaki parametreleri açıklayayım:
- –target iis: IIS sitesini kaynak olarak kullan
- –siteid 1: IIS site ID’si (Get-Website ile öğrenebilirsiniz)
- –installation iis: Sertifikayı IIS’e otomatik bağla
- –emailaddress: Bildirim e-postası
- –accepttos: Kullanım koşullarını otomatik kabul et
- –unattended: Kullanıcı girişi bekleme
Çoklu Domain Senaryosu
Gerçek dünyada genellikle tek domain için değil, hem apex domain hem de www subdomain için sertifika lazım oluyor. Hatta bazı durumlarda birden fazla subdomain aynı sertifikaya girmesi gerekiyor.
# Birden fazla domain için SAN sertifikası
.wacs.exe `
--target manual `
--host "sirketiniz.com,www.sirketiniz.com,api.sirketiniz.com,portal.sirketiniz.com" `
--webroot "C:inetpubwwwroot" `
--installation iis `
--issiteids 1 `
--emailaddress "[email protected]" `
--accepttos `
--unattended
Dikkat: Let’s Encrypt tek sertifikada maksimum 100 domain adı destekliyor ama haftada aynı domain kombinasyonu için 5 sertifika limiti var. Test yaparken staging ortamını kullanın.
# Staging ortamı (gerçek sertifika değil, test için)
.wacs.exe `
--baseuri "https://acme-staging-v02.api.letsencrypt.org/directory" `
--target iis `
--siteid 1 `
--installation iis `
--emailaddress "[email protected]" `
--accepttos `
--unattended
Otomatik Yenileme Yapılandırması
90 günlük sertifikalar için yenilemeyi unutmak felaket olabilir. Win-ACME kurulum sırasında Windows Görev Zamanlayıcı’ya otomatik görev ekliyor, ama bunu doğrulamak iyi bir alışkanlık.
# Zamanlanmış görevi kontrol et
Get-ScheduledTask -TaskName "win-acme*" | Select-Object TaskName, State, @{N="NextRun";E={$_.Triggers[0].StartBoundary}}
# Manuel yenileme testi (gerçekten yenilemez, sadece kontrol eder)
.wacs.exe --renew --baseuri "https://acme-v02.api.letsencrypt.org/directory"
# Tüm bekleyen yenilemeleri çalıştır
.wacs.exe --renew --force
Zamanlanmış görev ayarlarına bakmak isterseniz:
# Görev detaylarını görüntüle
$task = Get-ScheduledTask -TaskName "win-acme renew (acme-v02.api.letsencrypt.org)"
$task.Actions
$task.Triggers
# Görevin ne zaman çalışacağını gör
$taskInfo = Get-ScheduledTaskInfo -TaskName "win-acme renew (acme-v02.api.letsencrypt.org)"
$taskInfo.NextRunTime
Varsayılan olarak win-acme her sabah sertifikaları kontrol ediyor ve 30 günden az süresi kalanları yeniliyor. Bu pencereyi değiştirmek isterseniz settings.json dosyasında RenewalDays parametresiyle oynayabilirsiniz.
Posh-ACME ile PowerShell Tabanlı Yaklaşım
Bazı ekipler her şeyi PowerShell ile yönetmeyi tercih ediyor. Posh-ACME bu ihtiyacı karşılayan güçlü bir modül. Özellikle CI/CD pipeline’larına entegre edilmesi gereken senaryolarda daha esnek.
# Posh-ACME modülünü kur
Install-Module -Name Posh-ACME -Scope AllUsers -Force
# Let's Encrypt sunucusunu seç (staging ile başlayın)
Set-PAServer LE_STAGE # Test için
# Set-PAServer LE_PROD # Production için
# Yeni sertifika al
$pArgs = @{
Domain = @("sirketiniz.com", "www.sirketiniz.com")
Contact = "[email protected]"
AcceptTOS = $true
PfxPass = "GucluBirSifre123!"
}
New-PACertificate @pArgs
Sertifikayı IIS’e bağlamak için ek adımlar gerekiyor:
# Posh-ACME ile alınan sertifikayı IIS'e bağla
$cert = Get-PACertificate
# Sertifikayı Windows sertifika deposuna aktar
$pfxPath = $cert.PfxFile
$pfxPass = ConvertTo-SecureString "GucluBirSifre123!" -AsPlainText -Force
$certImport = Import-PfxCertificate -FilePath $pfxPath -CertStoreLocation "Cert:LocalMachineMy" -Password $pfxPass
# IIS HTTPS binding'e ata
$thumbprint = $certImport.Thumbprint
$siteName = "VarsayilanWebSitesi"
$hostname = "sirketiniz.com"
# Mevcut HTTPS binding'i kaldır
Remove-WebBinding -Name $siteName -Protocol "https" -Port 443 -HostHeader $hostname -ErrorAction SilentlyContinue
# Yeni binding ekle
New-WebBinding -Name $siteName -Protocol "https" -Port 443 -HostHeader $hostname -SslFlags 1
# Sertifikayı binding'e bağla
$bind = Get-WebBinding -Name $siteName -Protocol "https" -Port 443 -HostHeader $hostname
$bind.AddSslCertificate($thumbprint, "My")
Write-Host "Sertifika basariyla IIS'e baglandi: $thumbprint"
HTTP’den HTTPS’e Yönlendirme
Sertifikayı aldıktan sonra HTTP trafiğini HTTPS’e yönlendirmeyi unutmayın. IIS’te bu işi URL Rewrite modülüyle yapıyoruz.
# URL Rewrite kurulu mu kontrol et
Get-Module -ListAvailable -Name WebAdministration
Get-WebConfiguration "system.webServer/rewrite" -PSPath "IIS:"
# web.config dosyasına yönlendirme kuralı ekle
$webConfigPath = "C:inetpubwwwrootweb.config"
$rewriteRule = @"
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="HTTP to HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
"@
$rewriteRule | Out-File -FilePath $webConfigPath -Encoding UTF8
URL Rewrite modülü yoksa Web Platform Installer veya doğrudan Microsoft’un sitesinden kurabilirsiniz. Bu adımı atlamayın; hem SEO açısından hem de güvenlik açısından kritik.
Sorun Giderme
Sahada en sık karşılaşılan sorunlar ve çözümleri:
Challenge doğrulama hatası: http-01 challenge sırasında Let’s Encrypt sunucusu .well-known/acme-challenge/ yoluna erişemiyorsa bu hata çıkar. IIS’te bu klasörün anonim erişime açık olduğunu, 80 portunun dışarıdan ulaşılabilir olduğunu ve güvenlik duvarında blok olmadığını kontrol edin.
# .well-known klasörünü test et
$testUrl = "http://sirketiniz.com/.well-known/acme-challenge/test"
try {
$response = Invoke-WebRequest -Uri $testUrl -UseBasicParsing
Write-Host "Erisim basarili: $($response.StatusCode)"
} catch {
Write-Host "Erisim hatasi: $($_.Exception.Message)"
}
# IIS'te anonymous authentication kontrolü
Get-WebConfigurationProperty -Filter "system.webServer/security/authentication/anonymousAuthentication" `
-PSPath "IIS:SitesVarsayilanWebSitesi" -Name "enabled"
Sertifika deposu erişim hatası: Eğer win-acme çalışırken “Access denied to certificate store” hatası alıyorsanız, mutlaka yönetici olarak çalıştırdığınızdan emin olun.
# Mevcut kullanıcının yönetici mi olduğunu kontrol et
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
$isAdmin = $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
Write-Host "Yonetici mi: $isAdmin"
Yenileme sonrası eski sertifika kalmış: Bazen yenileme çalışıyor ama IIS’te eski sertifika görünüyor. Bu durumda binding’i elle güncelleyin ve IIS’i yeniden başlatın.
# IIS'i yeniden başlat
Restart-Service -Name "W3SVC"
# Sertifika son kullanma tarihini kontrol et
Get-ChildItem -Path "Cert:LocalMachineMy" |
Where-Object {$_.Subject -like "*sirketiniz.com*"} |
Select-Object Subject, NotAfter, Thumbprint |
Sort-Object NotAfter -Descending
Wildcard Sertifika ve DNS Challenge
Bazı durumlarda 80 portunu açamazsınız ya da wildcard sertifika lazım. Bu senaryoda DNS challenge kullanıyorsunuz. Ancak bu yaklaşım DNS sağlayıcınızın API’sini gerektiriyor.
# Cloudflare DNS kullanıyorsanız
.wacs.exe `
--target manual `
--host "*.sirketiniz.com,sirketiniz.com" `
--validation dns-01 `
--validationmode dns-01 `
--dnscreatescript "C:Scriptsdns-create.bat" `
--dnsdeletescript "C:Scriptsdns-delete.bat" `
--emailaddress "[email protected]" `
--accepttos
# dns-create.bat içeriği (örnek)
# @echo off
# curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns/records" ^
# -H "Authorization: Bearer TOKEN" ^
# -H "Content-Type: application/json" ^
# --data "{"type":"TXT","name":"%1","content":"%2","ttl":120}"
DNS challenge manuel olarak da yapılabiliyor ama otomasyonu bozuyor. Eğer API desteği olan bir DNS sağlayıcı kullanıyorsanız (Cloudflare, Route53, Azure DNS vb.) bu entegrasyonu kurmaya değer.
Sonuç
IIS ile Let’s Encrypt kombinasyonu başlangıçta Linux’taki kadar pürüzsüz gelmiyor ama win-acme sayesinde işler düşündüğünüzden çok daha iyi yürüyor. Temel akış şu: win-acme’yi indirip kurun, interaktif modda bir tur atıp ne yaptığını anlayın, ardından her şeyi script’e dökün ve zamanlanmış görevi doğrulayın.
Production’a geçmeden önce staging ortamında test etmeyi ihmal etmeyin, rate limit’e çarpmanın sıkıntısını yaşamak istemezsiniz. HTTP’den HTTPS’e yönlendirmeyi, sertifika yenileme bildirimlerini ve HSTS başlıklarını da ekleyince işi doğru düzgün tamamlamış olursunuz.
Ticari sertifika için yıllık bütçe ayırmaktan, sona erme tarihlerini kovalamaktan, satıcı portal güreşlerinden kurtulmak gerçekten rahatlatıcı. 90 günlük kısa ömür ilk bakışta dezavantaj gibi görünse de otomasyonu zorunlu kıldığı için aslında daha disiplinli bir yönetim alışkanlığı kazandırıyor.
