Одна из самых частых причин инцидентов на проде это конфиг, который не зависит от окружения. Кто-то закоммитил строку подключения к боевой базе, кто-то запустил тесты против продакшн-платёжки. Паттерн Options хорош сам по себе, но без правильной иерархии конфигов он не спасёт.
.NET читает конфигурацию слоями. Каждый следующий слой перекрывает предыдущий.
В Program.cs это выглядит так:
var builder = WebApplication.CreateBuilder(args);
builder.Configuration
// 1. Базовые настройки — коммитим в репо, только безопасные дефолты
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
// 2. Настройки под окружение — Development.json коммитим, Production.json нет
.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json",
optional: true, reloadOnChange: true)
// 3. User Secrets — только для разработки, никогда не коммитим
.AddUserSecrets<Program>(optional: true)
// 4. Переменные окружения — CI/CD, Docker, Kubernetes
.AddEnvironmentVariables()
// 5. Хранилище секретов — для прода
.AddVaultSecrets(builder.Configuration);
Структура файлов:
├── appsettings.json # безопасные дефолты, коммитим
├── appsettings.Development.json # локальные настройки, коммитим
├── appsettings.Production.json # только структура без значений, коммитим
└── secrets.json # User Secrets, в .gitignore
В appsettings.Production.json пишем только заглушки, никаких реальных значений:
{
"Database": {
"ConnectionString": "CONFIGURED_IN_SECRETS_MANAGER"
},
"PaymentGateway": {
"ApiKey": "CONFIGURED_IN_SECRETS_MANAGER"
}
}Можно спрятать секреты в GitLab CI, например:
# .gitlab-ci.yml
deploy_production:
stage: deploy
script:
- dotnet publish -c Release
- ./deploy.sh
variables:
Database__ConnectionString: $PROD_DB_CONNECTION
PaymentGateway__ApiKey: $STRIPE_API_KEY
only:
- main
По итогу в репозитории будут только безопасные дефолтные значения, а все секреты вынесены.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#sharp_view