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.
You need to write your DB password, mail credentials, and JWT key somewhere. But where?
appsettings.json is the first thing that comes to mind. Easy, fast. But there is a big risk: this file goes to Git along with your source code. If you push to GitHub, the passwords are exposed to everyone. In team settings, everyone can see them too.
What about tools like Azure Key Vault, HashiCorp Vault, Secret Manager? These are great solutions — but there is no access on shared hosting. No SSH, no root, no service installation.
The solution is simple but effective: the environmentVariables block inside web.config.
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.
The web.config file lives on the server and does not go to Git. The environment variables you put inside it are automatically added to ASP.NET Core's configuration system and override the same keys in appsettings.json.
<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.
A common mistake when writing connection strings: a connection string that works in JSON doesn't work in XML.
The reason is simple: in JSON, backslash (\) is a special character — you need to write \\ to represent it. In XML, backslash is not a special character — you write it as \ directly.
// 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ı.When dotnet publish runs, which files are included in the publish output is controlled from the .csproj file.
Two important rules:
Never — these files may contain secrets, they should not go into the publish output.Always — the application needs this file, it must be in the publish output.<!-- .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.
What do you do when the site won't start in production or you get strange errors? No SSH, no Visual Studio debugger. The only solution: logs.
When the stdoutLogEnabled attribute is set to true, the application output is written to the logs/ folder. Find the error, fix it, then set it back to false.
<!-- Normalde: production'da kapalı -->
<aspNetCore stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" ... />
<!-- Hata ayıklarken: aç, hatayı bul, kapat -->
<aspNetCore stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" ... />