Bind environment variables to config struct with viper


Context

As part of a CLI application, I have integrated viper to manage the different configuration streams to customize the behavior of the app (e.g, a config file, flags and environment variables).

The CLI loads by default the configuration from a yaml file, and I wanted to offer the ability to override these settings with the equivalent environment variables. To accomplish this, I tried using the AutomaticEnv function without result. It turns out that it only takes into account the environment variables when viper is invoked with the Get method, not when your using Unmarshal to a config file.

Solution

There are several workarounds:

  • Use BindEnv to manually link the desired environment variables before unmarshalling:
if err := viper.BindEnv("VARIABLE"); err != nil {
    return err
}
viper.Unmarshal(conf) // Where conf is a struct to hold your configuration
  • Use SetDefault to declare a default value for the key. That allows the unmarshalling operation to take into account the existing environment variable:
viper.SetDefault("VARIABLE", "default")
viper.Unmarshal(conf) // Where conf is a struct to hold your configuration
  • There are some more advanced suggestions, including some that will automate this behavior for all environment variables without having to use BindEnv or SetDefault. You can check those in the linked Github issue below

References

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer’s view in any way.