DB şifreni, mail hesabını, JWT anahtarını bir yere yazman gerekiyor. Ama nereye?
appsettings.json ilk akla gelen yer. Kolay, hızlı. Ama büyük bir riski var: bu dosya kaynak kodunla birlikte Git'e gider. GitHub'a push edersen, şifreler herkese açık olur. Takım çalışmasında da herkes görebilir.
Peki Azure Key Vault, HashiCorp Vault, Secret Manager gibi araçlar? Bunlar harika çözümler — ama shared hosting'de erişim yok. SSH yok, root yok, servis kurma yok.
Çözüm basit ama etkili: web.config içindeki environmentVariables bloğu.
web.config dosyası sunucuda yaşar, Git'e gitmez. İçine koyduğun environment variable'lar, ASP.NET Core'un configuration sistemine otomatik olarak eklenir ve appsettings.json'daki aynı key'leri ezer.
<aspNetCore processPath="dotnet" arguments=".\MyApp.dll"
stdoutLogEnabled="false"
stdoutLogFile=".\logs\stdout"
hostingModel="outofprocess">
<environmentVariables>
<!-- DB bağlantısı — şifre burada, appsettings.json'da değil -->
<environmentVariable name="ConnectionStrings__DefaultConnection"
value="Server=.\SQLEXPRESS;Database=MyDb;User Id=sa;Password=Sifre123;TrustServerCertificate=True;" />
<!-- Mail sunucusu ayarları -->
<environmentVariable name="EmailSettings__SmtpServer" value="smtp.brevo.com" />
<environmentVariable name="EmailSettings__Port" value="587" />
<environmentVariable name="EmailSettings__Username" value="kullanici@ornek.com" />
<environmentVariable name="EmailSettings__Password" value="MailSifresi" />
<!-- JWT — private key dosyasının yolu -->
<environmentVariable name="Jwt__PrivateKeyPath" value="private.key" />
</environmentVariables>
</aspNetCore>
Connection string yazarken sık karşılaşılan bir hata: JSON'da çalışan connection string XML'de çalışmıyor.
Sebebi basit: JSON'da backslash (\) özel karakterdir, kendisini temsil etmek için \\ yazmak gerekir. XML'de ise backslash özel karakter değildir — olduğu gibi \ yazılır.
// appsettings.json — JSON'da \\ gerekir
{
"ConnectionStrings": {
"DefaultConnection": "Server=.\\SQLEXPRESS;Database=MyDb;..."
}
}
<!-- web.config — XML'de tek \ yeterli -->
<environmentVariable name="ConnectionStrings__DefaultConnection"
value="Server=.\SQLEXPRESS;Database=MyDb;..." />
dotnet publish çalıştığında hangi dosyaların publish çıktısına dahil edileceği .csproj dosyasından kontrol edilir.
İki önemli kural:
Never — bu dosyalar sırlar içerebilir, publish çıktısına gitmesin.Always — uygulama bu dosyaya ihtiyaç duyuyor, publish çıktısında olmalı.<!-- .csproj -->
<ItemGroup>
<!-- Sırlar içerebilir — publish'e gitmesin -->
<Content Update="appsettings.Production.json">
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</Content>
<Content Update="appsettings.Development.json">
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</Content>
<!-- JWT imzalamak için gerekli — publish'e gitsin -->
<Content Include="private.key">
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
</Content>
</ItemGroup>
Production'da site açılmıyorsa ya da garip hatalar varsa ne yaparsın? SSH yok, Visual Studio debugger yok. Tek çözüm: log.
stdoutLogEnabled attribute'u true yapılırsa uygulama çıktısı logs/ klasörüne yazılır. Hatayı bul, düzelt, sonra tekrar false yap.
<!-- Normalde: production'da kapalı -->
<aspNetCore stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" ... />
<!-- Hata ayıklarken: aç, hatayı bul, kapat -->
<aspNetCore stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" ... />