work in progress
diff --git a/viper.go b/viper.go
index e658a8e..8f2b60a 100644
--- a/viper.go
+++ b/viper.go
@@ -5,13 +5,15 @@
 
 // Viper is a application configuration system.
 // It believes that applications can be configured a variety of ways
-// via flags, ENVIRONMENT variables, configuration files.
+// via flags, ENVIRONMENT variables, configuration files retrieved
+// from the file system, or a remote key/value store.
 
 // Each item takes precedence over the item below it:
 
 // flag
 // env
 // config
+// key/value store
 // default
 
 package viper
@@ -25,6 +27,7 @@
 	"os"
 	"path"
 	"path/filepath"
+	"reflect"
 	"runtime"
 	"strings"
 	"time"
@@ -38,14 +41,29 @@
 	"gopkg.in/yaml.v1"
 )
 
+// remoteProvider stores the configuration necessary
+// to connect to a remote key/value store.
+// Optional secretKeyring to unencrypt encrypted values
+// can be provided.
+type remoteProvider struct {
+	provider      string
+	endpoint      string
+	path          string
+	secretKeyring string
+}
+
 // A set of paths to look for the config file in
 var configPaths []string
 
+// A set of remote providers to search for the configuration
+var remoteProviders []*remoteProvider
+
 // Name of file to look for inside the path
 var configName string = "config"
 
 // extensions Supported
 var SupportedExts []string = []string{"json", "toml", "yaml", "yml"}
+var SupportedRemoteProviders []string = []string{"etcd", "consul"}
 var configFile string
 var configType string
 
@@ -53,6 +71,7 @@
 var override map[string]interface{} = make(map[string]interface{})
 var env map[string]string = make(map[string]string)
 var defaults map[string]interface{} = make(map[string]interface{})
+var kvstore map[string]interface{} = make(map[string]interface{})
 var pflags map[string]*pflag.Flag = make(map[string]*pflag.Flag)
 var aliases map[string]string = make(map[string]string)
 
@@ -81,6 +100,74 @@
 	}
 }
 
+// AddRemoteProvider adds a remote configuration source.
+// Remote Providers are searched in the order they are added.
+// provider is a string value, "etcd" or "consul" are currently supported.
+// endpoint is the url.  etcd requires http://ip:port  consul requires ip:port
+// path is the path in the k/v store to retrieve configuration
+// To retrieve a config file called myapp.json from /configs/myapp.json
+// you should set path to /configs and set config name (SetConfigName()) to
+// "myapp"
+func AddRemoteProvider(provider, endpoint, path string) error {
+	if !stringInSlice(provider, SupportedRemoteProviders) {
+		return UnsupportedRemoteProviderError(provider)
+	}
+	if provider != "" && endpoint != "" {
+		jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint)
+		rp := &remoteProvider{
+			endpoint: endpoint,
+			provider: provider,
+		}
+		if !providerPathExists(rp) {
+			remoteProviders = append(remoteProviders, rp)
+		}
+	}
+	return nil
+}
+
+// AddSecureRemoteProvider adds a remote configuration source.
+// Secure Remote Providers are searched in the order they are added.
+// provider is a string value, "etcd" or "consul" are currently supported.
+// endpoint is the url.  etcd requires http://ip:port  consul requires ip:port
+// secretkeyring is the filepath to your openpgp secret keyring.  e.g. /etc/secrets/myring.gpg
+// path is the path in the k/v store to retrieve configuration
+// To retrieve a config file called myapp.json from /configs/myapp.json
+// you should set path to /configs and set config name (SetConfigName()) to
+// "myapp"
+// Secure Remote Providers are implemented with github.com/xordataexchange/crypt
+func AddSecureRemoteProvider(provider, endpoint, secretkeyring string) error {
+	if !stringInSlice(provider, SupportedRemoteProviders) {
+		return UnsupportedRemoteProviderError(provider)
+	}
+	if provider != "" && endpoint != "" {
+		jww.INFO.Printf("adding %s:%s to remote provider list", provider, endpoint)
+		rp := &remoteProvider{
+			endpoint: endpoint,
+			provider: provider,
+		}
+		if !providerPathExists(rp) {
+			remoteProviders = append(remoteProviders, rp)
+		}
+	}
+	return nil
+}
+
+func providerPathExists(p *remoteProvider) bool {
+
+	for _, y := range remoteProviders {
+		if reflect.DeepEqual(y, p) {
+			return true
+		}
+	}
+	return false
+}
+
+type UnsupportedRemoteProviderError string
+
+func (str UnsupportedRemoteProviderError) Error() string {
+	return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str))
+}
+
 func GetString(key string) string {
 	return cast.ToString(Get(key))
 }
@@ -132,6 +219,10 @@
 	if err != nil {
 		return err
 	}
+	err = mapstructure.Decode(kvstore, rawVal)
+	if err != nil {
+		return err
+	}
 
 	insensativiseMaps()
 
@@ -221,6 +312,12 @@
 		return val
 	}
 
+	val, exists = kvstore[key]
+	if exists {
+		jww.TRACE.Println(key, "found in key/value store:", val)
+		return val
+	}
+
 	val, exists = defaults[key]
 	if exists {
 		jww.TRACE.Println(key, "found in defaults:", val)
@@ -289,6 +386,10 @@
 				delete(config, alias)
 				config[key] = val
 			}
+			if val, ok := kvstore[alias]; ok {
+				delete(kvstore, alias)
+				kvstore[key] = val
+			}
 			if val, ok := defaults[alias]; ok {
 				delete(defaults, alias)
 				defaults[key] = val
@@ -331,7 +432,8 @@
 }
 
 // The user provided value (via flag)
-// Will be used instead of values obtained via config file, ENV or default
+// Will be used instead of values obtained via
+// config file, ENV, default, or key/value store
 func Set(key string, value interface{}) {
 	// If alias passed in, then set the proper override
 	key = realKey(strings.ToLower(key))
@@ -345,7 +447,7 @@
 }
 
 // Viper will discover and load the configuration file from disk
-// searching in one of the defined paths.
+// and key/value stores, searching in one of the defined paths.
 func ReadInConfig() error {
 	jww.INFO.Println("Attempting to read in config file")
 	if !stringInSlice(getConfigType(), SupportedExts) {
@@ -357,6 +459,8 @@
 		return err
 	}
 
+	getKeyValueConfig()
+
 	MarshallReader(bytes.NewReader(file))
 	return nil
 }
@@ -389,6 +493,29 @@
 	insensativiseMap(config)
 	insensativiseMap(defaults)
 	insensativiseMap(override)
+	insensativiseMap(kvstore)
+}
+
+// retrieve the first found remote configuration
+func getKeyValueConfig() {
+	for _, rp := range remoteProviders {
+		val, err := getRemoteConfig(rp)
+		if err != nil {
+			kvstore = val
+			return
+		}
+	}
+}
+
+func getRemoteConfig(provider *remoteProvider) (map[string]interface{}, error) {
+	switch provider.provider {
+	case "etcd":
+		// do something
+	case "consul":
+		// do something
+
+	}
+	return config, nil
 }
 
 func insensativiseMap(m map[string]interface{}) {
@@ -412,6 +539,10 @@
 		m[key] = struct{}{}
 	}
 
+	for key, _ := range kvstore {
+		m[key] = struct{}{}
+	}
+
 	for key, _ := range override {
 		m[key] = struct{}{}
 	}
@@ -594,6 +725,8 @@
 func Debug() {
 	fmt.Println("Config:")
 	pretty.Println(config)
+	fmt.Println("Key/Value Store:")
+	pretty.Println(kvstore)
 	fmt.Println("Env:")
 	pretty.Println(env)
 	fmt.Println("Defaults:")
@@ -613,6 +746,7 @@
 	configFile = ""
 	configType = ""
 
+	kvstore = make(map[string]interface{})
 	config = make(map[string]interface{})
 	override = make(map[string]interface{})
 	env = make(map[string]string)