In my practice I have to switch between environments quite often. This happens due to different reasons. I have environments like: dev, sqa1, sqa2, uat. One environment might be under deployment and you need to switch to another, working one. Sometimes some bug can be reproduced on a particular environment and you switch to it to reproduce it locally under debugger using database and external servers from that environment. Potentially you can have dev.yaml, sqa1.yaml, sqa2.yaml, uat.yaml files in your git repo and replace appsettings.yaml with the one you need. This approach has major drawback: you can occasionally push default configuration change into repo. To avoid that you can use dotnet user-secrets feature.
Just add user secrets config source to your console application (you don't need to add it explicitly for aspnet app; it is already there).
builder.Configuration
// other config sources
.AddUserSecrets<Program>()
After that you can add secret to project secrete store like
dotnet user-secrets --id your-project-id set "STORAGE:HOST" "cassndra.rke4.dev"
You also need to specify secrete id in csproj like
<Project>
<PropertyGroup>
<UserSecretsId>your-project-id</UserSecretsId>
</PropertyGroup>
...
</Project>
dotnet configuration manager will load it using standard ":" separator delimiter.
Then, for switching between environments I created secret.txt files with values like "KEY1=VALUE1" and created script to load them:
#!/usr/bin/env zsh
# Reads lines like `MODES:HOST=sftp01.sqa` from secrets.txt and runs:
# dotnet user-secrets --id trader-analytics set "MODES:HOST" "sftp01.sqa"
#
# After all secrets are applied, waits for Enter, then clears them and lists
# the (now empty) secret store to confirm.
#
set -euo pipefail
SECRETS_FILE="${0:A:h}/secrets.txt"
USER_SECRETS_ID="${USER_SECRETS_ID:-your-project-id}"
if [[ ! -f "$SECRETS_FILE" ]]; then
print -u2 "error: $SECRETS_FILE not found"
exit 1
fi
process_line() {
local line="$1"
# Trim leading/trailing whitespace
line="${line##[[:space:]]##}"
line="${line%%[[:space:]]##}"
# Skip blanks and comments
[[ -z "$line" || "$line" == \#* ]] && return 0
if [[ "$line" != *=* ]]; then
print -u2 "skip (no '='): $line"
return 0
fi
local key="${line%%=*}"
local value="${line#*=}"
if [[ -z "$key" ]]; then
print -u2 "skip (empty key): $line"
return 0
fi
print -r -- "+ dotnet user-secrets --id $USER_SECRETS_ID set \"$key\" \"$value\""
dotnet user-secrets --id "$USER_SECRETS_ID" set "$key" "$value"
}
while IFS= read -r line || [[ -n "$line" ]]; do
process_line "$line"
done < "$SECRETS_FILE"
print
print -- "All secrets applied. Press Enter to clear them..."
read -r _
print -- "+ dotnet user-secrets --id $USER_SECRETS_ID clear"
dotnet user-secrets --id "$USER_SECRETS_ID" clear
print -- "+ dotnet user-secrets --id $USER_SECRETS_ID list"
dotnet user-secrets --id "$USER_SECRETS_ID" list
Top comments (0)