Configuration can go nuts: CMS 8.1 setup needs 200+ files to be edited by hand:

Neither connection strings, nor custom features are in included yet; things get more complicated in reality.
Lifebuoy: configuration roles
A few enthusiasts simplified configuration task solely to in 9+ series:
<settings role:require="Standalone" environment:require="Production">
<setting name="X" set:value="Y"/>
</settings>
Next era: containers and configuration
Docker eliminates the need in 14+ steps to run the Sitecore. All you have to do is to cook an image of your changes on top of vendor image (like layered cake) & play it anywhere.
Dilemma: the same image in different environments = same files; but still have different connection strings / features …. How?
Environment variables
Latest Sitecore is capable of fetching configuration values from environment variables:

Amazingly, there is no way out-of-the-box to see running values!
Showconfig shows only sitecore
node, while role:define
, search:define
live inside web.config. Moreover, web.config will have an outdated value when environment variable was picked.
Baking solution to see running values
Let’s bake the page to show all roles/definitions, including custom ones:
- Sitecore role (Standalone, CD, CM..)
- Indexing engine used (SOLR, AzureSearch..)
- Any custom layer (f.e.
security:define
ormyproject.environment:define
)
[AllowDependencyInjection]
public class ShowRoles : AdminPage
{
private readonly IConfigurationRulesContext _configRulesContext;
public ShowRoles() { /* Dummy to make ASP.NET happy. */ }
public ShowRoles(IConfigurationRulesContext configRulesContext) => _configRulesContext = configRulesContext;
protected void Page_Load(object sender, EventArgs e)
{
CheckSecurity();
Response.Write("<html><body>");
Response.Write("<h3>Sitecore rule definitions</h3>");
var names = _configRulesContext.GetRuleDefinitionNames();
foreach (var name in names)
{
var values = _configRulesContext.GetRuleDefinitionValue(name);
Write(name, values);
}
}
private void Write(string group, IReadOnlyCollection<string> elements)
{
Response.Write($"<h4>{group}</h4>");
elements = (elements ?? Array.Empty<string>()).Where(element => !string.IsNullOrWhiteSpace(element))
.ToArray();
if (elements.Any())
{
foreach (var element in elements)
{
Response.Write($"<p>{element}</p>");
}
}
else
{
Response.Write("<p>No elements in the group.</p>");
}
}
Demo compose file looks as:
environment:
SITECORE_APPSETTINGS_ROLE:DEFINE: Standalone
SITECORE_APPSETTINGS_SEARCH:DEFINE: Solr
SITECORE_APPSETTINGS_MYPROJECT.ENVIRONMENT:DEFINE: Development
Gotcha: Not all settings were applied
myproject.environment
is not applied; environment-specific
config is always ON:

Container variables are there, though:

Are environment variables visible to Sitecore process?
Response.Write("<h3>Environment variables</h3>");
var environmentVariables = Environment.GetEnvironmentVariables();
foreach (string variable in environmentVariables.Keys)
{
var values = new[] { environmentVariables[variable] as string };
Write(variable, values);
}
Yes, the missing setting is exposed as environment variable:

How come value is not picked by Sitecore?
Short answer – that is life. Adding the dummy into web.config makes variable be picked:



The current implementation requires app:key
to present in config to be replaced in runtime. And yes, there is no way to check if it is picked 😉
Summary
A lack of configuration assemble traceability leads to huge investigation effort when things do not work well. File-based configuration can no longer be trusted in containerized deployments; at the same time there is no source of truth to verify its correctness.
Nice post! Have you seen this? https://docs.microsoft.com/en-us/aspnet/config-builder#mode
You can use “Greedy” mode, then keys which are not defined in your Web.config file will be added as well, so no need for dummy records 😉
LikeLike
Thanks Vitalii, you are right, ‘greedy’ mode might do the trick. However there is still no way to verify the running config, which is disappointing…
LikeLike