1 ![viper logo](https://cloud.githubusercontent.com/assets/173412/10886745/998df88a-8151-11e5-9448-4736db51020d.png)
3 Go configuration with fangs!
5 Many Go projects are built using Viper including:
7 * [Hugo](http://gohugo.io)
8 * [EMC RexRay](http://rexray.readthedocs.org/en/stable/)
9 * [Imgur’s Incus](https://github.com/Imgur/incus)
10 * [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack)
11 * [Docker Notary](https://github.com/docker/Notary)
12 * [BloomApi](https://www.bloomapi.com/)
13 * [doctl](https://github.com/digitalocean/doctl)
14 * [Clairctl](https://github.com/jgsqware/clairctl)
16 [![Build Status](https://travis-ci.org/spf13/viper.svg)](https://travis-ci.org/spf13/viper) [![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![GoDoc](https://godoc.org/github.com/spf13/viper?status.svg)](https://godoc.org/github.com/spf13/viper)
21 Viper is a complete configuration solution for Go applications including 12-Factor apps. It is designed
22 to work within an application, and can handle all types of configuration needs
23 and formats. It supports:
26 * reading from JSON, TOML, YAML, HCL, and Java properties config files
27 * live watching and re-reading of config files (optional)
28 * reading from environment variables
29 * reading from remote config systems (etcd or Consul), and watching changes
30 * reading from command line flags
32 * setting explicit values
34 Viper can be thought of as a registry for all of your applications
39 When building a modern application, you don’t want to worry about
40 configuration file formats; you want to focus on building awesome software.
41 Viper is here to help with that.
43 Viper does the following for you:
45 1. Find, load, and unmarshal a configuration file in JSON, TOML, YAML, HCL, or Java properties formats.
46 2. Provide a mechanism to set default values for your different
47 configuration options.
48 3. Provide a mechanism to set override values for options specified through
50 4. Provide an alias system to easily rename parameters without breaking existing
52 5. Make it easy to tell the difference between when a user has provided a
53 command line or config file which is the same as the default.
55 Viper uses the following precedence order. Each item takes precedence over the
58 * explicit call to Set
65 Viper configuration keys are case insensitive.
67 ## Putting Values into Viper
69 ### Establishing Defaults
71 A good configuration system will support default values. A default value is not
72 required for a key, but it’s useful in the event that a key hasn’t been set via
73 config file, environment variable, remote configuration or flag.
78 viper.SetDefault("ContentDir", "content")
79 viper.SetDefault("LayoutDir", "layouts")
80 viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})
83 ### Reading Config Files
85 Viper requires minimal configuration so it knows where to look for config files.
86 Viper supports JSON, TOML, YAML, HCL, and Java Properties files. Viper can search multiple paths, but
87 currently a single Viper instance only supports a single configuration file.
88 Viper does not default to any configuration search paths leaving defaults decision
91 Here is an example of how to use Viper to search for and read a configuration file.
92 None of the specific paths are required, but at least one path should be provided
93 where a configuration file is expected.
96 viper.SetConfigName("config") // name of config file (without extension)
97 viper.AddConfigPath("/etc/appname/") // path to look for the config file in
98 viper.AddConfigPath("$HOME/.appname") // call multiple times to add many search paths
99 viper.AddConfigPath(".") // optionally look for config in the working directory
100 err := viper.ReadInConfig() // Find and read the config file
101 if err != nil { // Handle errors reading the config file
102 panic(fmt.Errorf("Fatal error config file: %s \n", err))
106 ### Watching and re-reading config files
108 Viper supports the ability to have your application live read a config file while running.
110 Gone are the days of needing to restart a server to have a config take effect,
111 viper powered applications can read an update to a config file while running and
114 Simply tell the viper instance to watchConfig.
115 Optionally you can provide a function for Viper to run each time a change occurs.
117 **Make sure you add all of the configPaths prior to calling `WatchConfig()`**
121 viper.OnConfigChange(func(e fsnotify.Event) {
122 fmt.Println("Config file changed:", e.Name)
126 ### Reading Config from io.Reader
128 Viper predefines many configuration sources such as files, environment
129 variables, flags, and remote K/V store, but you are not bound to them. You can
130 also implement your own required configuration source and feed it to viper.
133 viper.SetConfigType("yaml") // or viper.SetConfigType("YAML")
135 // any approach to require this configuration into your program.
136 var yamlExample = []byte(`
151 viper.ReadConfig(bytes.NewBuffer(yamlExample))
153 viper.Get("name") // this would be "steve"
156 ### Setting Overrides
158 These could be from a command line flag, or from your own application logic.
161 viper.Set("Verbose", true)
162 viper.Set("LogFile", LogFile)
165 ### Registering and Using Aliases
167 Aliases permit a single value to be referenced by multiple keys
170 viper.RegisterAlias("loud", "Verbose")
172 viper.Set("verbose", true) // same result as next line
173 viper.Set("loud", true) // same result as prior line
175 viper.GetBool("loud") // true
176 viper.GetBool("verbose") // true
179 ### Working with Environment Variables
181 Viper has full support for environment variables. This enables 12 factor
182 applications out of the box. There are four methods that exist to aid working
186 * `BindEnv(string...) : error`
187 * `SetEnvPrefix(string)`
188 * `SetEnvKeyReplacer(string...) *strings.Replacer`
190 _When working with ENV variables, it’s important to recognize that Viper
191 treats ENV variables as case sensitive._
193 Viper provides a mechanism to try to ensure that ENV variables are unique. By
194 using `SetEnvPrefix`, you can tell Viper to use add a prefix while reading from
195 the environment variables. Both `BindEnv` and `AutomaticEnv` will use this
198 `BindEnv` takes one or two parameters. The first parameter is the key name, the
199 second is the name of the environment variable. The name of the environment
200 variable is case sensitive. If the ENV variable name is not provided, then
201 Viper will automatically assume that the key name matches the ENV variable name,
202 but the ENV variable is IN ALL CAPS. When you explicitly provide the ENV
203 variable name, it **does not** automatically add the prefix.
205 One important thing to recognize when working with ENV variables is that the
206 value will be read each time it is accessed. Viper does not fix the value when
207 the `BindEnv` is called.
209 `AutomaticEnv` is a powerful helper especially when combined with
210 `SetEnvPrefix`. When called, Viper will check for an environment variable any
211 time a `viper.Get` request is made. It will apply the following rules. It will
212 check for a environment variable with a name matching the key uppercased and
213 prefixed with the `EnvPrefix` if set.
215 `SetEnvKeyReplacer` allows you to use a `strings.Replacer` object to rewrite Env
216 keys to an extent. This is useful if you want to use `-` or something in your
217 `Get()` calls, but want your environmental variables to use `_` delimiters. An
218 example of using it can be found in `viper_test.go`.
223 SetEnvPrefix("spf") // will be uppercased automatically
226 os.Setenv("SPF_ID", "13") // typically done outside of the app
228 id := Get("id") // 13
231 ### Working with Flags
233 Viper has the ability to bind to flags. Specifically, Viper supports `Pflags`
234 as used in the [Cobra](https://github.com/spf13/cobra) library.
236 Like `BindEnv`, the value is not set when the binding method is called, but when
237 it is accessed. This means you can bind as early as you want, even in an
240 For individual flags, the `BindPFlag()` method provides this functionality.
245 serverCmd.Flags().Int("port", 1138, "Port to run Application server on")
246 viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
249 You can also bind an existing set of pflags (pflag.FlagSet):
254 pflag.Int("flagname", 1234, "help message for flagname")
257 viper.BindPFlags(pflag.CommandLine)
259 i := viper.GetInt("flagname") // retrieve values from viper instead of pflag
262 The use of [pflag](https://github.com/spf13/pflag/) in Viper does not preclude
263 the use of other packages that use the [flag](https://golang.org/pkg/flag/)
264 package from the standard library. The pflag package can handle the flags
265 defined for the flag package by importing these flags. This is accomplished
266 by a calling a convenience function provided by the pflag package called
276 "github.com/spf13/pflag"
281 // using standard library "flag" package
282 flag.Int("flagname", 1234, "help message for flagname")
284 pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
286 viper.BindPFlags(pflag.CommandLine)
288 i := viper.GetInt("flagname") // retrieve value from viper
296 Viper provides two Go interfaces to bind other flag systems if you don’t use `Pflags`.
298 `FlagValue` represents a single flag. This is a very simple example on how to implement this interface:
301 type myFlag struct {}
302 func (f myFlag) HasChanged() bool { return false }
303 func (f myFlag) Name() string { return "my-flag-name" }
304 func (f myFlag) ValueString() string { return "my-flag-value" }
305 func (f myFlag) ValueType() string { return "string" }
308 Once your flag implements this interface, you can simply tell Viper to bind it:
311 viper.BindFlagValue("my-flag-name", myFlag{})
314 `FlagValueSet` represents a group of flags. This is a very simple example on how to implement this interface:
317 type myFlagSet struct {
321 func (f myFlagSet) VisitAll(fn func(FlagValue)) {
322 for _, flag := range flags {
328 Once your flag set implements this interface, you can simply tell Viper to bind it:
332 flags: []myFlag{myFlag{}, myFlag{}},
334 viper.BindFlagValues("my-flags", fSet)
337 ### Remote Key/Value Store Support
339 To enable remote support in Viper, do a blank import of the `viper/remote`
342 `import _ "github.com/spf13/viper/remote"`
344 Viper will read a config string (as JSON, TOML, YAML or HCL) retrieved from a path
345 in a Key/Value store such as etcd or Consul. These values take precedence over
346 default values, but are overridden by configuration values retrieved from disk,
347 flags, or environment variables.
349 Viper uses [crypt](https://github.com/xordataexchange/crypt) to retrieve
350 configuration from the K/V store, which means that you can store your
351 configuration values encrypted and have them automatically decrypted if you have
352 the correct gpg keyring. Encryption is optional.
354 You can use remote configuration in conjunction with local configuration, or
357 `crypt` has a command-line helper that you can use to put configurations in your
358 K/V store. `crypt` defaults to etcd on http://127.0.0.1:4001.
361 $ go get github.com/xordataexchange/crypt/bin/crypt
362 $ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json
365 Confirm that your value was set:
368 $ crypt get -plaintext /config/hugo.json
371 See the `crypt` documentation for examples of how to set encrypted values, or
374 ### Remote Key/Value Store Example - Unencrypted
377 viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001","/config/hugo.json")
378 viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop"
379 err := viper.ReadRemoteConfig()
382 ### Remote Key/Value Store Example - Encrypted
385 viper.AddSecureRemoteProvider("etcd","http://127.0.0.1:4001","/config/hugo.json","/etc/secrets/mykeyring.gpg")
386 viper.SetConfigType("json") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop"
387 err := viper.ReadRemoteConfig()
390 ### Watching Changes in etcd - Unencrypted
393 // alternatively, you can create a new viper instance.
394 var runtime_viper = viper.New()
396 runtime_viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001", "/config/hugo.yml")
397 runtime_viper.SetConfigType("yaml") // because there is no file extension in a stream of bytes, supported extensions are "json", "toml", "yaml", "yml", "properties", "props", "prop"
399 // read from remote config the first time.
400 err := runtime_viper.ReadRemoteConfig()
403 runtime_viper.Unmarshal(&runtime_conf)
405 // open a goroutine to watch remote changes forever
408 time.Sleep(time.Second * 5) // delay after each request
410 // currently, only tested with etcd support
411 err := runtime_viper.WatchRemoteConfig()
413 log.Errorf("unable to read remote config: %v", err)
417 // unmarshal new config into our runtime config struct. you can also use channel
418 // to implement a signal to notify the system of the changes
419 runtime_viper.Unmarshal(&runtime_conf)
424 ## Getting Values From Viper
426 In Viper, there are a few ways to get a value depending on the value’s type.
427 The following functions and methods exist:
429 * `Get(key string) : interface{}`
430 * `GetBool(key string) : bool`
431 * `GetFloat64(key string) : float64`
432 * `GetInt(key string) : int`
433 * `GetString(key string) : string`
434 * `GetStringMap(key string) : map[string]interface{}`
435 * `GetStringMapString(key string) : map[string]string`
436 * `GetStringSlice(key string) : []string`
437 * `GetTime(key string) : time.Time`
438 * `GetDuration(key string) : time.Duration`
439 * `IsSet(key string) : bool`
441 One important thing to recognize is that each Get function will return a zero
442 value if it’s not found. To check if a given key exists, the `IsSet()` method
447 viper.GetString("logfile") // case-insensitive Setting & Getting
448 if viper.GetBool("verbose") {
449 fmt.Println("verbose enabled")
452 ### Accessing nested keys
454 The accessor methods also accept formatted paths to deeply nested keys. For
455 example, if the following JSON file is loaded:
460 "address": "localhost",
477 Viper can access a nested field by passing a `.` delimited path of keys:
480 GetString("datastore.metric.host") // (returns "127.0.0.1")
483 This obeys the precedence rules established above; the search for the path
484 will cascade through the remaining configuration registries until found.
486 For example, given this configuration file, both `datastore.metric.host` and
487 `datastore.metric.port` are already defined (and may be overridden). If in addition
488 `datastore.metric.protocol` was defined in the defaults, Viper would also find it.
490 However, if `datastore.metric` was overridden (by a flag, an environment variable,
491 the `Set()` method, …) with an immediate value, then all sub-keys of
492 `datastore.metric` become undefined, they are “shadowed” by the higher-priority
495 Lastly, if there exists a key that matches the delimited key path, its value
496 will be returned instead. E.g.
500 "datastore.metric.host": "0.0.0.0",
502 "address": "localhost",
517 GetString("datastore.metric.host") // returns "0.0.0.0"
522 Extract sub-tree from Viper.
524 For example, `viper` represents:
539 subv := viper.Sub("app.cache1")
552 func NewCache(cfg *Viper) *Cache {...}
555 which creates a cache based on config information formatted as `subv`.
556 Now it’s easy to create these 2 caches separately as:
559 cfg1 := viper.Sub("app.cache1")
560 cache1 := NewCache(cfg1)
562 cfg2 := viper.Sub("app.cache2")
563 cache2 := NewCache(cfg2)
568 You also have the option of Unmarshaling all or a specific value to a struct, map,
571 There are two methods to do this:
573 * `Unmarshal(rawVal interface{}) : error`
574 * `UnmarshalKey(key string, rawVal interface{}) : error`
582 PathMap string `mapstructure:"path_map"`
589 t.Fatalf("unable to decode into struct, %v", err)
595 Viper comes ready to use out of the box. There is no configuration or
596 initialization needed to begin using Viper. Since most applications will want
597 to use a single central repository for their configuration, the viper package
598 provides this. It is similar to a singleton.
600 In all of the examples above, they demonstrate using viper in its singleton
603 ### Working with multiple vipers
605 You can also create many different vipers for use in your application. Each will
606 have its own unique set of configurations and values. Each can read from a
607 different config file, key value store, etc. All of the functions that viper
608 package supports are mirrored as methods on a viper.
616 x.SetDefault("ContentDir", "content")
617 y.SetDefault("ContentDir", "foobar")
622 When working with multiple vipers, it is up to the user to keep track of the
627 Q: Why not INI files?
629 A: Ini files are pretty awful. There’s no standard format, and they are hard to
630 validate. Viper is designed to work with JSON, TOML or YAML files. If someone
631 really wants to add this feature, I’d be happy to merge it. It’s easy to specify
632 which formats your application will permit.
634 Q: Why is it called “Viper”?
636 A: Viper is designed to be a [companion](http://en.wikipedia.org/wiki/Viper_(G.I._Joe))
637 to [Cobra](https://github.com/spf13/cobra). While both can operate completely
638 independently, together they make a powerful pair to handle much of your
639 application foundation needs.
641 Q: Why is it called “Cobra”?
643 A: Is there a better name for a [commander](http://en.wikipedia.org/wiki/Cobra_Commander)?