Store Your App Configurations with Environment Variables: A Quick Guide
Introduction
NOTE – Storing secrets in environment variables is not a security feature, in fact it is an approach to keep your secrets separate from your codebase. Browse the answers of this Stackoverflow question for details about security in environment variables.
This post is about storing application secrets and confidential configurations in environment variables. But why should we store secrets and other confidential settings this way? Because this approach keeps the sensitive information out of the codebase, which:
Reduces the risk of accidentally exposing secrets through source code repositories or version control systems.
Allows us to deploy the same codebase across environments while specifying different settings for each environment.
Allows us to change settings on the fly without modifying the application code.
Why prefix the variables?
To avoid naming conflicts, for example, two applications might use a variable named:
ConnectionString
. By prefixing application name/key to the variable, ensures that a specific application’s variables are unique.For ease of readability and maintenance by grouping all configuration keys related to a specific application together.
When using configuration builders like
.AddEnvironmentVariables("MyApp_")
in .NET, the use of prefix allows the application to load only theMyApp
specific variables and avoids accidentally picking up of variables intended for other applications.
## Connection string for application named: WayneEnterprise
WayneEnterprise_ConnectionString
## Connection string for application named: Batman
Batman_ConnectionString
Mapping environment variables with configuration classes
Configuration classes
public class AwsConfiguration
{
private const String SectionKey = "AwsConfiguration";
public String AccessKey { get; set; }
public String SecretKey { get; set; }
public EndpointConfiguration Endpoint { get; set; }
public List<String> Regions { get; set; }
public Dictionary<String, String> DetailTypes { get; set; }
}
public class EndpointConfiguration
{
public String Url { get; set; }
public Int32 Port { get; set; }
}
Naming convention for environment variables
## Simple Properties
MyAwsApp_AwsConfiguration__AccessKey
MyAwsApp_AwsConfiguration__SecretKey
## Nested Properties
MyAwsApp_AwsConfiguration__Enpoint__Url
MyAwsApp_AwsConfiguration__Enpoint__Port
## Collection/Array Properties
MyAwsApp_AwsConfiguration__Region__0
MyAwsApp_AwsConfiguration__Region__1
MyAwsApp_AwsConfiguration__Region__2
## Dictionary Properties
MyAwsApp_AwsConfiguration__DetailTypes__InProgress
MyAwsApp_AwsConfiguration__DetailTypes__Completed
## These properties will not be picked by the `.AddEnvironmentVariables("MyAwsApp_")
NOTMyAwsApp_AwsConfiguration__AccessKey
NOTMyAwsApp_AwsConfiguration__SecretKey
Understanding the delimiters
The single-underscore (_) is used with the main prefix only, while double-underscore (__) is used for complex properties.
Why not use :
as the separator? Because as per MSDN:
The
:
separator doesn’t work with environment variable hierarchical keys on all platforms. For example, the:
separator is not supported by Bash. The double underscore,__
, is:
Supported by all platforms.
Automatically replaced by a colon,
:
.
Accessing environment variables
public class Program
{
public static void Main(String[] args)
{
var builder = new ConfigurationBuilder()
//the prefix - "MyAwsApp_" will be removed from the environment variable names
.AddEnvironmentVariables("MyAwsApp_");
var configuration = builder.Build();
var awsConfiguration = configuration
.GetSection(AwsConfiguration.SectionKey)
.Get<AwsConfiguration>();
}
}
See also
Subscribe to my newsletter
Read articles from Vedant Phougat directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Vedant Phougat
Vedant Phougat
Senior Software Engineer who likes writing clean, high performing and fully tested code in C# using .NET and ASP.NET Core.