Ana Sayfa Hakkımda Dersler Blog Mikrofonda İletişim Projeler
Dersler DEPLOY · C#

Shared Hosting'de Secret Yönetimi — web.config Yöntemi

9 dk okuma · Emre Ulutabak
1
Neden appsettings.json yetmez?

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.

💡
appsettings.json Git'e gider. Şifre koyma. web.config'i .gitignore'a ekle veya production'da ayrı tut.
2
web.config environmentVariables

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.

xml
<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>
💡
TrustServerCertificate=True: shared hosting'de SQL Server SSL sertifika doğrulaması sorun çıkarır. Bu olmadan bağlantı hatası alırsın.
3
XML ve JSON escape farkı

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.

json
// appsettings.json — JSON'da \\ gerekir
{
  "ConnectionStrings": {
    "DefaultConnection": "Server=.\\SQLEXPRESS;Database=MyDb;..."
  }
}
xml
<!-- web.config — XML'de tek \ yeterli -->
<environmentVariable name="ConnectionStrings__DefaultConnection"
  value="Server=.\SQLEXPRESS;Database=MyDb;..." />
💡
XML'de tek \, JSON'da çift \\. Bunu karıştırırsan bağlantı kurulamaz ama hata mesajı seni yanıltabilir.
4
CopyToPublishDirectory ayarı

dotnet publish çalıştığında hangi dosyaların publish çıktısına dahil edileceği .csproj dosyasından kontrol edilir.

İki önemli kural:

  • appsettings.Production.json ve appsettings.Development.jsonNever — bu dosyalar sırlar içerebilir, publish çıktısına gitmesin.
  • private.key gibi dosyalarAlways — uygulama bu dosyaya ihtiyaç duyuyor, publish çıktısında olmalı.
xml
<!-- .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>
5
stdoutLogEnabled — production log

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.

xml
<!-- Normalde: production'da kapalı -->
<aspNetCore stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" ... />

<!-- Hata ayıklarken: aç, hatayı bul, kapat -->
<aspNetCore stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" ... />
💡
stdoutLogEnabled=true yaptıktan sonra siteye bir istek gönder, sonra FTP'den logs/ klasörüne bak. Hata mesajı orada.
💡
Hata bulduktan sonra stdoutLogEnabled'ı tekrar false yap. Açık kalırsa log dosyaları disk doldurana kadar büyür.
6
Mini quiz
MİNİ QUIZ
appsettings.Production.json için CopyToPublishDirectory değeri ne olmalıdır?
Always — her zaman publish'e gitsin
Never — publish çıktısına gitmesin
PreserveNewest — değiştiyse gitsin
Bu ayar .csproj'da yapılamaz