Make the whole configuration settable from the environment - #7
Open
jmeekhof wants to merge 1 commit into
Open
Conversation
dns.provider had no environment binding. viper.AutomaticEnv() was in
play but no key replacer was configured, so it looked for a variable
literally named "DNS.PROVIDER" and DNS_PROVIDER never mapped to the
nested key. Because Config.Validate() hard-requires dns.provider, a
configuration file was mandatory even when every other setting was
supplied through the environment - which is awkward for container
deployments that otherwise need no file at all.
The README's own "Environment Variables" example showed this: it had to
pass --dns-provider as a flag alongside the exported variables.
- Register a strings.NewReplacer(".", "_") key replacer so nested keys
are addressable as DNS_PROVIDER, LOGGING_LEVEL and so on.
- Bind every configuration key explicitly, including the app.* and
logging.* settings which were also unreachable. AutomaticEnv only
resolves keys viper already knows about, so relying on it alone makes
the set of settings that work from the environment hard to predict.
- The AWS settings keep AWS_PROFILE and AWS_REGION rather than moving to
the DNS_ROUTE53_* names the replacer would otherwise imply.
- Document the full key-to-variable mapping in the README.
Adds a test that unmarshals and validates a configuration built purely
from environment variables, with no file present.
This was referenced Aug 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
dns.providerhas no environment binding.cmd.gobindsTAILSCALE_API_KEY,TAILSCALE_TAILNET,DNS_ZONE_ID,DNS_DOMAIN,CLOUDFLARE_API_TOKEN,AWS_PROFILE,AWS_REGIONand thePIHOLE_*pair — but neverdns.provider.viper.AutomaticEnv()doesn't cover the gap, because no key replacer is configured: viper looks for a variable literally namedDNS.PROVIDER, soDNS_PROVIDERnever maps to the nested key.Since
Config.Validate()hard-requiresdns.provider, a config file is mandatory even when every other setting comes from the environment. For a container deployment that otherwise needs no file, that means bind-mounting a file containing a single line.The README's own "Environment Variables" section shows the symptom — it has to pass the provider as a flag alongside the exported variables:
The same gap silently affects
app.workers,app.poll_interval,app.required_tags,logging.levelandlogging.format, none of which were bound either.What changed
strings.NewReplacer(".", "_")key replacer, so nested keys are addressable asDNS_PROVIDER,LOGGING_LEVELand so on.AutomaticEnvonly resolves keys viper already knows about, which makes the set of settings that actually work from the environment hard to predict; an explicit table means the mapping is the same whether or not a config file was loaded, and it's greppable.AWS_PROFILEandAWS_REGIONare kept rather than moving to theDNS_ROUTE53_*names the replacer would otherwise imply — those are the conventional names and the AWS SDK reads them anyway.--dns-providerflag from the env-only examples.No behaviour changes for existing config files or flags; precedence is unchanged (an explicitly-set flag still wins over the environment).
Tests
Adds
cmd_test.go, which unmarshals and validates a configuration built purely from environment variables with no file present. Against the current binding set that test fails with exactly the reported symptom:go build ./...,go vet ./...andgo test ./...all pass.