diff --git a/viper.go b/viper.go
index a475e95..6014bf7 100644
--- a/viper.go
+++ b/viper.go
@@ -47,6 +47,7 @@ import (
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/pflag"
 	"github.com/subosito/gotenv"
+	"gopkg.in/ini.v1"
 )
 
 // ConfigMarshalError happens when failing to marshal the configuration.
@@ -240,7 +241,7 @@ func New() *Viper {
 // can use it in their testing as well.
 func Reset() {
 	v = New()
-	SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env"}
+	SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"}
 	SupportedRemoteProviders = []string{"etcd", "consul"}
 }
 
@@ -279,7 +280,7 @@ type RemoteProvider interface {
 }
 
 // SupportedExts are universally supported extensions.
-var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env"}
+var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"}
 
 // SupportedRemoteProviders are universally supported remote providers.
 var SupportedRemoteProviders = []string{"etcd", "consul"}
@@ -1462,6 +1463,23 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error {
 			// set innermost value
 			deepestMap[lastKey] = value
 		}
+
+	case "ini":
+		cfg := ini.Empty()
+		err := cfg.Append(buf.Bytes())
+		if err != nil {
+			return ConfigParseError{err}
+		}
+		sections := cfg.Sections()
+		for i := 0; i < len(sections); i++ {
+			section := sections[i]
+			keys := section.Keys()
+			for j := 0; j < len(keys); j++ {
+				key := keys[j]
+				value := cfg.Section(section.Name()).Key(key.Name()).String()
+				c[section.Name()+"."+key.Name()] = value
+			}
+		}
 	}
 
 	insensitiviseMap(c)
@@ -1545,6 +1563,22 @@ func (v *Viper) marshalWriter(f afero.File, configType string) error {
 		if _, err = f.WriteString(string(b)); err != nil {
 			return ConfigMarshalError{err}
 		}
+
+	case "ini":
+		keys := v.AllKeys()
+		cfg := ini.Empty()
+		ini.PrettyFormat = false
+		for i := 0; i < len(keys); i++ {
+			key := keys[i]
+			lastSep := strings.LastIndex(key, ".")
+			sectionName := key[:(lastSep)]
+			keyName := key[(lastSep + 1):]
+			if sectionName == "default" {
+				sectionName = ""
+			}
+			cfg.Section(sectionName).Key(keyName).SetValue(Get(key).(string))
+		}
+		cfg.WriteTo(f)
 	}
 	return nil
 }
diff --git a/viper_test.go b/viper_test.go
index 85c2d02..f8349ac 100644
--- a/viper_test.go
+++ b/viper_test.go
@@ -118,6 +118,24 @@ var remoteExample = []byte(`{
 "newkey":"remote"
 }`)
 
+var iniExample = []byte(`; Package name
+NAME        = ini
+; Package version
+VERSION     = v1
+; Package import path
+IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
+
+# Information about package author
+# Bio can be written in multiple lines.
+[author]
+NAME   = Unknwon  ; Succeeding comment
+E-MAIL = fake@localhost
+GITHUB = https://github.com/%(NAME)s
+BIO    = """Gopher.
+Coding addict.
+Good man.
+"""  # Succeeding comment`)
+
 func initConfigs() {
 	Reset()
 	var r io.Reader
@@ -148,6 +166,10 @@ func initConfigs() {
 	SetConfigType("json")
 	remote := bytes.NewReader(remoteExample)
 	unmarshalReader(remote, v.kvstore)
+
+	SetConfigType("ini")
+	r = bytes.NewReader(iniExample)
+	unmarshalReader(r, v.config)
 }
 
 func initConfig(typ, config string) {
@@ -204,6 +226,14 @@ func initHcl() {
 	unmarshalReader(r, v.config)
 }
 
+func initIni() {
+	Reset()
+	SetConfigType("ini")
+	r := bytes.NewReader(iniExample)
+
+	unmarshalReader(r, v.config)
+}
+
 // make directories for testing
 func initDirs(t *testing.T) (string, string, func()) {
 
@@ -396,6 +426,11 @@ func TestHCL(t *testing.T) {
 	assert.NotEqual(t, "cronut", Get("type"))
 }
 
+func TestIni(t *testing.T) {
+	initIni()
+	assert.Equal(t, "ini", Get("default.name"))
+}
+
 func TestRemotePrecedence(t *testing.T) {
 	initJSON()
 
@@ -521,6 +556,10 @@ func TestAllKeys(t *testing.T) {
 
 	ks := sort.StringSlice{
 		"title",
+		"author.bio",
+		"author.e-mail",
+		"author.github",
+		"author.name",
 		"newkey",
 		"owner.organization",
 		"owner.dob",
@@ -532,6 +571,9 @@ func TestAllKeys(t *testing.T) {
 		"hobbies",
 		"clothing.jacket",
 		"clothing.trousers",
+		"default.import_path",
+		"default.name",
+		"default.version",
 		"clothing.pants.size",
 		"age",
 		"hacker",
@@ -556,13 +598,24 @@ func TestAllKeys(t *testing.T) {
 			"dob":          dob,
 		},
 		"title": "TOML Example",
-		"ppu":   0.55,
-		"eyes":  "brown",
+		"author": map[string]interface{}{
+			"e-mail": "fake@localhost",
+			"github": "https://github.com/Unknwon",
+			"name":   "Unknwon",
+			"bio":    "Gopher.\nCoding addict.\nGood man.\n",
+		},
+		"ppu":  0.55,
+		"eyes": "brown",
 		"clothing": map[string]interface{}{
 			"trousers": "denim",
 			"jacket":   "leather",
 			"pants":    map[string]interface{}{"size": "large"},
 		},
+		"default": map[string]interface{}{
+			"import_path": "gopkg.in/ini.v1",
+			"name":        "ini",
+			"version":     "v1",
+		},
 		"id": "0001",
 		"batters": map[string]interface{}{
 			"batter": []interface{}{