Windows Server Core Kurulum ve Yönetimi: PowerShell ile Tam Kontrol

GUI olmadan bir Windows Server yönetmek ilk başta biraz ürkütücü gelebilir. Fare tıklamaları olmadan, rengarenk arayüzler olmadan, sadece bir komut satırı penceresi ile karşı karşıyasın. Ama bu yazıyı okuduktan sonra Server Core’un aslında ne kadar güçlü ve yönetilebilir bir platform olduğunu göreceksin. Üstelik daha az saldırı yüzeyi, daha az kaynak tüketimi ve daha istikrarlı bir sistem kazanıyorsun. Haydi başlayalım.

Windows Server Core Nedir ve Neden Tercih Edilmeli

Windows Server Core, GUI bileşenleri kaldırılmış, yalnızca komut satırı ile yönetilen bir Windows Server kurulum seçeneğidir. Microsoft bu yaklaşımı Windows Server 2008’den itibaren sunuyor ve her geçen sürümle daha olgunlaşıyor.

Peki neden birisi kasıtlı olarak GUI’dan vazgeçsin? Birkaç somut neden var:

  • Daha az saldırı yüzeyi: Yüzlerce GUI bileşeni yüklü değilse, yama gerektiren, güvenlik açığı barındırabilecek bileşen sayısı dramatik şekilde azalır
  • Düşük kaynak tüketimi: Ortalama 1-2 GB daha az RAM kullanımı, disk alanında da ciddi tasarruf
  • Zorunlu otomasyon: GUI olmayınca her şeyi script ile yapmak zorundasın, bu da tekrar edilebilir ve belgelenmiş bir altyapı anlamına gelir
  • Daha az yeniden başlatma: Güncellemeler daha hızlı uygulanır, reboot sayısı azalır

Özellikle Hyper-V host’ları, dosya sunucuları, DNS/DHCP sunucuları ve web sunucuları için Server Core ideal bir seçimdir.

Kurulum Sonrası İlk Adımlar

Kurulumu bitirip ilk açılışta seni karşılayan şey bir komut istemi penceresi. Panik yok. İlk yapman gereken birkaç temel ayar var.

Bilgisayar Adını Değiştirme

# Mevcut bilgisayar adını görüntüle
hostname

# PowerShell ile yeniden adlandır
Rename-Computer -NewName "SRV-CORE-01" -Restart

IP Adresi Yapılandırması

DHCP yerine statik IP atamak production ortamında şart. Önce ağ adaptörünü bul, sonra yapılandır:

# Ağ adaptörlerini listele
Get-NetAdapter

# Statik IP ata (InterfaceIndex'i kendi değerinle değiştir)
New-NetIPAddress -InterfaceIndex 2 -IPAddress 192.168.1.50 -PrefixLength 24 -DefaultGateway 192.168.1.1

# DNS sunucusu tanımla
Set-DnsClientServerAddress -InterfaceIndex 2 -ServerAddresses ("192.168.1.10","192.168.1.11")

# Ayarları doğrula
Get-NetIPConfiguration

Domain’e Katılma

Sunucuyu domain’e almak çoğu kurumsal ortamda ilk işlerden biri:

# Domain'e katıl ve yeniden başlat
$credential = Get-Credential
Add-Computer -DomainName "sirket.local" -Credential $credential -Restart

# Katılımı doğrula
(Get-WmiObject Win32_ComputerSystem).Domain

Firewall ve Uzak Yönetim

Server Core’u uzaktan yönetebilmek için WinRM’i aktif etmen gerekiyor:

# WinRM'i başlat ve yapılandır
Enable-PSRemoting -Force

# Güvenlik duvarı kurallarını kontrol et
Get-NetFirewallRule | Where-Object {$_.DisplayName -like "*Remote*" -and $_.Enabled -eq "True"} | Select-Object DisplayName, Direction, Action

Rol ve Özellik Yönetimi

GUI olmadan rol ekleyip kaldırmak çocuk oyuncağı. Install-WindowsFeature cmdlet’i senin en iyi arkadaşın.

Temel Rol Kurulumları

# Kullanılabilir tüm rolleri listele
Get-WindowsFeature | Where-Object {$_.InstallState -eq "Available"} | Select-Object Name, DisplayName

# IIS Web Server kurulumu
Install-WindowsFeature -Name Web-Server -IncludeManagementTools -IncludeAllSubFeature

# Hyper-V kurulumu
Install-WindowsFeature -Name Hyper-V -IncludeManagementTools -Restart

# DNS Server kurulumu
Install-WindowsFeature -Name DNS -IncludeManagementTools

# DHCP Server kurulumu
Install-WindowsFeature -Name DHCP -IncludeManagementTools

# Dosya Sunucusu rolleri
Install-WindowsFeature -Name FS-FileServer, FS-DFS-Namespace, FS-DFS-Replication

# Kurulu rolleri kontrol et
Get-WindowsFeature | Where-Object {$_.InstallState -eq "Installed"} | Select-Object Name, DisplayName

Birden fazla sunucuya aynı konfigürasyonu uygulamak için önce bir sunucudan yapılandırmayı dışa aktar:

# Mevcut kurulu rolleri XML'e aktar
Get-WindowsFeature | Where-Object {$_.Installed -eq $true} | Export-Clixml -Path "C:Tempinstalled_features.xml"

# Başka bir sunucuda içe aktar ve kur
$features = Import-Clixml -Path "\dosyasunucusushareinstalled_features.xml"
$featureNames = $features | Select-Object -ExpandProperty Name
Install-WindowsFeature -Name $featureNames -IncludeManagementTools

Uzaktan Yönetim Senaryoları

Server Core’un gerçek gücü uzaktan yönetilebilirliğinde. Kendi masaüstünden tüm server’ları yönetebilirsin.

RSAT ile GUI Araçları Kullanmak

Windows 10/11 iş istasyonunda RSAT araçlarını kurunca, uzaktaki Server Core’u sanki önünde oturuyor gibi yönetebilirsin. Ama biz sysadminler script yazmanın tadını çıkaralım.

PSRemoting ile Toplu Yönetim

# Birden fazla sunucuya aynı anda bağlan
$sunucular = @("SRV-CORE-01", "SRV-CORE-02", "SRV-CORE-03")

# Paralel komut çalıştırma
Invoke-Command -ComputerName $sunucular -ScriptBlock {
    $os = Get-WmiObject Win32_OperatingSystem
    $disk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'"
    
    [PSCustomObject]@{
        Sunucu = $env:COMPUTERNAME
        UptimeSaat = [math]::Round((Get-Date - $os.ConvertToDateTime($os.LastBootUpTime)).TotalHours, 1)
        DiskBosGB = [math]::Round($disk.FreeSpace / 1GB, 2)
        RAMBosGB = [math]::Round($os.FreePhysicalMemory / 1MB, 2)
    }
}

Bu script gerçek dünyada çok işe yarıyor. Sabah işe gelince tüm sunucuların anlık durumunu tek komutla görebiliyorsun.

Servis ve Process Yönetimi

Servis İzleme ve Yönetim Scripti

Kritik servislerin çalışıp çalışmadığını düzenli kontrol etmek ve sorun varsa uyarı almak için pratik bir script:

# Kritik servisleri izle ve gerekirse yeniden başlat
$kritikServisler = @("W32Time", "DNS", "DHCP", "Netlogon", "SamSs")
$logDosyasi = "C:Logsservis_kontrol_$(Get-Date -Format 'yyyyMMdd').log"

foreach ($servis in $kritikServisler) {
    $s = Get-Service -Name $servis -ErrorAction SilentlyContinue
    
    if ($null -eq $s) {
        $mesaj = "$(Get-Date -Format 'HH:mm:ss') - UYARI: $servis servisi bulunamadi"
        Add-Content -Path $logDosyasi -Value $mesaj
        continue
    }
    
    if ($s.Status -ne "Running") {
        $mesaj = "$(Get-Date -Format 'HH:mm:ss') - HATA: $servis durdu. Yeniden baslatiliyor..."
        Add-Content -Path $logDosyasi -Value $mesaj
        
        try {
            Start-Service -Name $servis
            $mesaj = "$(Get-Date -Format 'HH:mm:ss') - BASARILI: $servis yeniden baslatildi"
        } catch {
            $mesaj = "$(Get-Date -Format 'HH:mm:ss') - KRITIK: $servis baslatılamadı! Hata: $_"
        }
        
        Add-Content -Path $logDosyasi -Value $mesaj
    } else {
        Add-Content -Path $logDosyasi -Value "$(Get-Date -Format 'HH:mm:ss') - OK: $servis calisiyor"
    }
}

Bu scripti Windows Task Scheduler’a ekleyerek her 15 dakikada bir çalıştırabilirsin. Scheduled task oluşturmak için:

# Scheduled task oluştur
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-NonInteractive -ExecutionPolicy Bypass -File C:ScriptsServisKontrol.ps1"
$trigger = New-ScheduledTaskTrigger -RepetitionInterval (New-TimeSpan -Minutes 15) -Once -At (Get-Date)
$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 5) -RestartCount 3
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest

Register-ScheduledTask -TaskName "KritikServisKontrol" -Action $action -Trigger $trigger -Settings $settings -Principal $principal -Description "Kritik servisleri 15 dakikada bir kontrol eder"

Disk ve Depolama Yönetimi

Disk Yapılandırma Scripti

Yeni bir disk eklendiğinde onu hazırlamak için tekrar eden işlemleri otomatize etmek büyük zaman kazandırır:

# Yeni eklenen diski bul, başlat ve biçimlendir
function Initialize-NewDisk {
    param(
        [Parameter(Mandatory)]
        [char]$DriveHarfi,
        
        [string]$DiskEtiketi = "Data",
        [string]$DosyaSistemi = "NTFS"
    )
    
    # Başlatılmamış diskleri bul
    $rawDiskler = Get-Disk | Where-Object {$_.PartitionStyle -eq "RAW"}
    
    if ($rawDiskler.Count -eq 0) {
        Write-Host "Baslatilacak yeni disk bulunamadi." -ForegroundColor Yellow
        return
    }
    
    foreach ($disk in $rawDiskler) {
        Write-Host "Disk $($disk.Number) islemde: $([math]::Round($disk.Size / 1GB))GB" -ForegroundColor Cyan
        
        # GPT ile başlat
        Initialize-Disk -Number $disk.Number -PartitionStyle GPT
        
        # Yeni bölüm oluştur
        $partition = New-Partition -DiskNumber $disk.Number -UseMaximumSize -DriveLetter $DriveHarfi
        
        # Biçimlendir
        Format-Volume -DriveLetter $DriveHarfi -FileSystem $DosyaSistemi -NewFileSystemLabel $DiskEtiketi -Confirm:$false
        
        Write-Host "Disk basariyla hazırlandi: $DriveHarfi`:" -ForegroundColor Green
    }
}

# Kullanım örneği
Initialize-NewDisk -DriveHarfi 'D' -DiskEtiketi "Veri_Diski" -DosyaSistemi "NTFS"

Güvenlik Yapılandırması

Server Core kullanmanın güvenlik avantajlarından tam anlamıyla yararlanmak için birkaç temel hardening adımı uygulamak gerekiyor.

Temel Güvenlik Yapılandırmaları

# Gereksiz servisleri devre dışı bırak
$gereksizServisler = @(
    "XblAuthManager",      # Xbox Live kimlik doğrulama
    "XblGameSave",         # Xbox oyun kaydetme
    "XboxNetApiSvc",       # Xbox ağ servisi
    "WSearch",             # Windows Search (sunucuda gereksiz)
    "Fax",                 # Fax servisi
    "TabletInputService"   # Tablet girdi servisi
)

foreach ($servis in $gereksizServisler) {
    $s = Get-Service -Name $servis -ErrorAction SilentlyContinue
    if ($null -ne $s) {
        Stop-Service -Name $servis -Force -ErrorAction SilentlyContinue
        Set-Service -Name $servis -StartupType Disabled
        Write-Host "$servis devre disi birakildi" -ForegroundColor Yellow
    }
}

# NTLMv1'i devre dışı bırak
Set-ItemProperty -Path "HKLM:SYSTEMCurrentControlSetControlLsa" -Name "LmCompatibilityLevel" -Value 5 -Type DWord

# SMBv1'i kapat (EternalBlue açığına karşı)
Set-SmbServerConfiguration -EnableSMB1Protocol $false -Confirm:$false

# Güvenlik duvarı profillerini yapılandır
Set-NetFirewallProfile -Profile Domain -DefaultInboundAction Block -DefaultOutboundAction Allow
Set-NetFirewallProfile -Profile Private -DefaultInboundAction Block -DefaultOutboundAction Allow
Set-NetFirewallProfile -Profile Public -DefaultInboundAction Block -DefaultOutboundAction Allow

Write-Host "Temel guvenlik yapilandirmasi tamamlandi" -ForegroundColor Green

Olay Günlüğü İzleme

Güvenlik olaylarını izlemek için basit ama etkili bir script:

# Son 24 saatteki başarısız oturum açma denemelerini raporla
$baslangic = (Get-Date).AddHours(-24)
$hataliGirisler = Get-WinEvent -FilterHashtable @{
    LogName = "Security"
    Id = 4625
    StartTime = $baslangic
} -ErrorAction SilentlyContinue

if ($hataliGirisler) {
    Write-Host "Son 24 saatte $($hataliGirisler.Count) basarisiz giris denemesi" -ForegroundColor Red
    
    $hataliGirisler | ForEach-Object {
        $xml = [xml]$_.ToXml()
        $kullanici = $xml.Event.EventData.Data | Where-Object {$_.Name -eq "TargetUserName"} | Select-Object -ExpandProperty "#text"
        $kaynak = $xml.Event.EventData.Data | Where-Object {$_.Name -eq "IpAddress"} | Select-Object -ExpandProperty "#text"
        
        [PSCustomObject]@{
            Zaman = $_.TimeCreated
            KullaniciAdi = $kullanici
            KaynakIP = $kaynak
        }
    } | Group-Object KaynakIP | Sort-Object Count -Descending | Select-Object -First 10 | Format-Table Name, Count -AutoSize
} else {
    Write-Host "Son 24 saatte basarisiz giris denemesi yok" -ForegroundColor Green
}

Güncelleme Yönetimi

Server Core’da Windows Update’i komut satırından yönetmek için PSWindowsUpdate modülünü kullanabilirsin:

# PSWindowsUpdate modülünü kur
Install-Module -Name PSWindowsUpdate -Force -SkipPublisherCheck

# Mevcut güncellemeleri listele
Get-WindowsUpdate

# Tüm güncellemeleri indir ve kur (yeniden başlatma olmadan)
Install-WindowsUpdate -AcceptAll -IgnoreReboot -Verbose

# Yalnızca güvenlik güncellemelerini kur
Install-WindowsUpdate -Category "Security Updates" -AcceptAll -AutoReboot

# Uzak sunuculara güncelleme dağıt
Invoke-WUJob -ComputerName "SRV-CORE-01","SRV-CORE-02" -Script {
    Import-Module PSWindowsUpdate
    Install-WindowsUpdate -AcceptAll -AutoReboot
} -Credential (Get-Credential) -RunNow

SConfig Aracı

Server Core ile gelen gizli bir silah: SConfig. Bir metin menüsü sunan bu araç, temel yapılandırma işlerini biraz daha erişilebilir kılıyor. Özellikle ilk kurulumda çok işe yarıyor.

# SConfig'i başlat
SConfig

SConfig ile şunları yapabilirsin:

  • 1: Domain veya çalışma grubuna katılma
  • 2: Bilgisayar adını değiştirme
  • 3: Uzak yönetimi etkinleştirme veya devre dışı bırakma
  • 4: Windows Update yapılandırması
  • 5: Windows Update ayarları
  • 6: İndirme ve yükleme güncellemeleri
  • 7: Uzak masaüstünü etkinleştirme veya devre dışı bırakma
  • 8: Ağ ayarları
  • 9: Tarih ve saat
  • 10: Telemetri ayarları
  • 11: Windows Aktivasyonu
  • 12: Oturumu kapat
  • 13: Yeniden başlat
  • 14: Kapat

Yeni başlayanlara ve hızlı değişiklik yapmam gerektiğinde ben de SConfig’e başvuruyorum. Utanılacak bir şey değil.

Performans İzleme

Server Core’da performans takibi yaparken GUI araçları olmasa da PowerShell ile oldukça detaylı veriler toplayabilirsin:

# Kapsamlı sistem performans raporu
function Get-SunucuRaporu {
    $os = Get-WmiObject Win32_OperatingSystem
    $cpu = Get-WmiObject Win32_Processor
    $diskler = Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3"
    $network = Get-NetAdapter | Where-Object {$_.Status -eq "Up"}
    
    Write-Host "=== SUNUCU PERFORMANS RAPORU ===" -ForegroundColor Cyan
    Write-Host "Sunucu: $($env:COMPUTERNAME)" -ForegroundColor White
    Write-Host "Tarih: $(Get-Date -Format 'dd.MM.yyyy HH:mm')" -ForegroundColor White
    Write-Host ""
    
    # Uptime
    $uptime = (Get-Date) - $os.ConvertToDateTime($os.LastBootUpTime)
    Write-Host "Uptime: $($uptime.Days) gun $($uptime.Hours) saat" -ForegroundColor Green
    
    # CPU
    $cpuYuk = (Get-Counter "Processor(_Total)% Processor Time").CounterSamples.CookedValue
    Write-Host "CPU Kullanim: $([math]::Round($cpuYuk, 1))%" -ForegroundColor $(if($cpuYuk -gt 80){"Red"}elseif($cpuYuk -gt 60){"Yellow"}else{"Green"})
    
    # RAM
    $toplamRAM = [math]::Round($os.TotalVisibleMemorySize / 1MB, 2)
    $bosRAM = [math]::Round($os.FreePhysicalMemory / 1MB, 2)
    $kullanilanRAM = $toplamRAM - $bosRAM
    $ramYuzde = [math]::Round(($kullanilanRAM / $toplamRAM) * 100, 1)
    Write-Host "RAM: $kullanilanRAM/$toplamRAM GB ($ramYuzde% dolu)" -ForegroundColor $(if($ramYuzde -gt 85){"Red"}elseif($ramYuzde -gt 70){"Yellow"}else{"Green"})
    
    # Diskler
    Write-Host ""
    Write-Host "DISKLER:" -ForegroundColor Cyan
    foreach ($disk in $diskler) {
        $toplamGB = [math]::Round($disk.Size / 1GB, 1)
        $bosGB = [math]::Round($disk.FreeSpace / 1GB, 1)
        $dolulukYuzde = [math]::Round((($toplamGB - $bosGB) / $toplamGB) * 100, 1)
        $renk = if($dolulukYuzde -gt 90){"Red"}elseif($dolulukYuzde -gt 75){"Yellow"}else{"Green"}
        Write-Host "  $($disk.DeviceID) - $bosGB/$toplamGB GB bos ($dolulukYuzde% dolu)" -ForegroundColor $renk
    }
}

Get-SunucuRaporu

Gerçek Dünya Senaryosu: Web Sunucusu Hazırlama

Diyelim ki production ortamı için sıfırdan bir IIS web sunucusu hazırlaman gerekiyor. Tüm öğrendiklerimizi bir araya getiren gerçekçi bir senaryo:

# Web sunucusu tam kurulum scripti
param(
    [Parameter(Mandatory)]
    [string]$SiteName,
    [int]$Port = 80,
    [string]$PhysicalPath = "C:InetpubSites"
)

# IIS ve gerekli bileşenleri kur
$iisOzellikleri = @(
    "Web-Server",
    "Web-Common-Http",
    "Web-Static-Content",
    "Web-Default-Doc",
    "Web-Http-Errors",
    "Web-Asp-Net45",
    "Web-CGI",
    "Web-Http-Logging",
    "Web-Request-Monitor",
    "Web-Http-Tracing",
    "Web-Security",
    "Web-Basic-Auth",
    "Web-Windows-Auth",
    "Web-Filtering",
    "Web-Mgmt-Tools"
)

Write-Host "IIS kuruluyor..." -ForegroundColor Cyan
Install-WindowsFeature -Name $iisOzellikleri -IncludeManagementTools | Out-Null
Write-Host "IIS kurulumu tamamlandi" -ForegroundColor Green

# Site dizinini oluştur
$sitePath = Join-Path $PhysicalPath $SiteName
if (-not (Test-Path $sitePath)) {
    New-Item -ItemType Directory -Path $sitePath -Force | Out-Null
}

# IIS'te yeni site oluştur
Import-Module WebAdministration
New-WebSite -Name $SiteName -Port $Port -PhysicalPath $sitePath -Force

# Default site'i kaldır
Remove-WebSite -Name "Default Web Site" -ErrorAction SilentlyContinue

# Uygulama havuzu yapılandır
$appPool = "AppPool_$SiteName"
New-WebAppPool -Name $appPool
Set-ItemProperty "IIS:AppPools$appPool" -Name processModel.idleTimeout -Value ([TimeSpan]::FromMinutes(0))
Set-ItemProperty "IIS:AppPools$appPool" -Name recycling.periodicRestart.time -Value ([TimeSpan]::Zero)

# Site'yi uygulama havuzuna bağla
Set-ItemProperty "IIS:Sites$SiteName" -Name applicationPool -Value $appPool

Write-Host "Site '$SiteName' port $Port uzerinde hazir: $sitePath" -ForegroundColor Green
Write-Host "Uygulama havuzu: $appPool" -ForegroundColor Green

Sonuç

Windows Server Core ilk bakışta korkutucu görünebilir ama aslında sysadmin’in en büyük yardımcısı. GUI olmadan çalışmak seni otomasyon yapmaya zorluyor ve bu zorunluluk zamanla büyük bir avantaja dönüşüyor. Bugün yazdığın bir script, yarın onlarca sunucuya aynı anda uygulanabilen bir altyapı aracı haline geliyor.

Bu yazıda ele aldığımız konuları özetlersek: İlk kurulum ve temel yapılandırma adımlarından başlayarak rol yönetimi, uzaktan yönetim senaryoları, servis izleme, disk yönetimi, güvenlik sertleştirme, güncelleme yönetimi ve performans izlemeye kadar kapsamlı bir yol haritası çizdik. Her konuda verilen script örnekleri gerçek ortamlarda kullanılabilir, ihtiyacına göre uyarlayabileceğin başlangıç noktaları.

Eğer hala “GUI olmadan nasıl yaparım?” diye düşündüğün anlar olursa, şunu hatırla: Grafik arayüzler kolaylık değil, gizlilik yaratır. Bir butona tıkladığında arka planda ne olduğunu bilmiyorsun. PowerShell ile her adımı gördüğünde, anladığında ve kontrol ettiğinde gerçek anlamda sisteme hakim oluyorsun. İşte bu yüzden Server Core seveni Server Core’u bırakmak istemez.

Yorum yapın