diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,10 @@
+## 0.8.16
+
+Add env variable parsing. `loadYamlSettings` can read config values from the environment with Yaml that specifies an env var.
+The syntax is
+
+`var: _env:ENV_VAR:default`
+
 ## 0.8.15.3
 
 * Give a warning when compiling with GHCJS
diff --git a/Data/Yaml/Config.hs b/Data/Yaml/Config.hs
new file mode 100644
--- /dev/null
+++ b/Data/Yaml/Config.hs
@@ -0,0 +1,143 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+-- | Functionality for using YAML as configuration files
+--
+-- In particular, merging environment variables with yaml values
+--
+-- 'loadYamlSettings' is a high-level API for loading YAML and merging environment variables.
+-- A yaml value of @_env:ENV_VAR:default@ will lookup the environment variable @ENV_VAR@.
+--
+-- On a historical note, this code was taken directly from the yesod web framework's configuration module.
+module Data.Yaml.Config
+    ( applyCurrentEnv
+    , getCurrentEnv
+    , applyEnvValue
+    , loadYamlSettings
+    , EnvUsage
+    , ignoreEnv
+    , useEnv
+    , requireEnv
+    , useCustomEnv
+    , requireCustomEnv
+    ) where
+
+
+#if __GLASGOW_HASKELL__ < 710
+import Control.Applicative ((<$>))
+import Data.Monoid
+#endif
+import Data.Semigroup
+import Data.List.NonEmpty (nonEmpty)
+import Data.Aeson
+import qualified Data.HashMap.Strict as H
+import Data.Text (Text, pack)
+import System.Environment (getEnvironment)
+import Control.Arrow ((***))
+import Control.Monad (forM)
+import Control.Exception (throwIO)
+import Data.Text.Encoding (encodeUtf8)
+import qualified Data.Yaml as Y
+import Data.Maybe (fromMaybe)
+import qualified Data.Text as T
+
+newtype MergedValue = MergedValue { getMergedValue :: Value }
+
+instance Semigroup MergedValue where
+    MergedValue x <> MergedValue y = MergedValue $ mergeValues x y
+
+-- | Left biased
+mergeValues :: Value -> Value -> Value
+mergeValues (Object x) (Object y) = Object $ H.unionWith mergeValues x y
+mergeValues x _ = x
+
+applyEnvValue :: Bool -- ^ require an environment variable to be present?
+              -> H.HashMap Text Text -> Value -> Value
+applyEnvValue requireEnv' env =
+    goV
+  where
+    goV (Object o) = Object $ goV <$> o
+    goV (Array a) = Array (goV <$> a)
+    goV (String t1) = fromMaybe (String t1) $ do
+        t2 <- T.stripPrefix "_env:" t1
+        let (name, t3) = T.break (== ':') t2
+            mdef = fmap parseValue $ T.stripPrefix ":" t3
+        Just $ case H.lookup name env of
+            Just val ->
+                -- If the default value parses as a String, we treat the
+                -- environment variable as a raw value and do not parse it.
+                -- This means that things like numeric passwords just work.
+                -- However, for originally numerical or boolean values (e.g.,
+                -- port numbers), we still perform a normal YAML parse.
+                --
+                -- For details, see:
+                -- https://github.com/yesodweb/yesod/issues/1061
+                case mdef of
+                    Just (String _) -> String val
+                    _ -> parseValue val
+            Nothing ->
+                case mdef of
+                    Just val | not requireEnv' -> val
+                    _ -> Null
+    goV v = v
+
+    parseValue val = fromMaybe (String val) $ Y.decode $ encodeUtf8 val
+
+getCurrentEnv :: IO (H.HashMap Text Text)
+getCurrentEnv = fmap (H.fromList . map (pack *** pack)) getEnvironment
+
+applyCurrentEnv :: Bool -- ^ require an environment variable to be present?
+                -> Value -> IO Value
+applyCurrentEnv requireEnv' orig = flip (applyEnvValue requireEnv') orig <$> getCurrentEnv
+
+data EnvUsage = IgnoreEnv
+              | UseEnv
+              | RequireEnv
+              | UseCustomEnv (H.HashMap Text Text)
+              | RequireCustomEnv (H.HashMap Text Text)
+
+ignoreEnv, useEnv, requireEnv :: EnvUsage
+ignoreEnv = IgnoreEnv
+useEnv = UseEnv
+requireEnv = RequireEnv
+
+useCustomEnv, requireCustomEnv :: H.HashMap Text Text -> EnvUsage
+useCustomEnv = UseCustomEnv
+requireCustomEnv = RequireCustomEnv
+
+-- | Load the settings from the following three sources:
+--
+-- * Run time config files
+--
+-- * Run time environment variables
+--
+-- * The default compile time config file
+loadYamlSettings
+    :: FromJSON settings
+    => [FilePath] -- ^ run time config files to use, earlier files have precedence
+    -> [Value] -- ^ any other values to use, usually from compile time config. overridden by files
+    -> EnvUsage
+    -> IO settings
+loadYamlSettings runTimeFiles compileValues envUsage = do
+    runValues <- forM runTimeFiles $ \fp -> do
+        eres <- Y.decodeFileEither fp
+        case eres of
+            Left e -> do
+                putStrLn $ "loadYamlSettings: Could not parse file as YAML: " ++ fp
+                throwIO e
+            Right value -> return value
+
+    value' <-
+        case nonEmpty $ map MergedValue $ runValues ++ compileValues of
+            Nothing -> error "loadYamlSettings: No configuration provided"
+            Just ne -> return $ getMergedValue $ sconcat ne
+    value <-
+        case envUsage of
+            IgnoreEnv            -> return $ applyEnvValue   False mempty value'
+            UseEnv               ->          applyCurrentEnv False        value'
+            RequireEnv           ->          applyCurrentEnv True         value'
+            UseCustomEnv env     -> return $ applyEnvValue   False env    value'
+            RequireCustomEnv env -> return $ applyEnvValue   True  env    value'
+
+    case fromJSON value of
+        Error s -> error $ "Could not convert to AppSettings: " ++ s
+        Success settings -> return settings
diff --git a/yaml.cabal b/yaml.cabal
--- a/yaml.cabal
+++ b/yaml.cabal
@@ -1,5 +1,5 @@
 name:            yaml
-version:         0.8.15.3
+version:         0.8.16
 license:         BSD3
 license-file:    LICENSE
 author:          Michael Snoyman <michael@snoyman.com>, Anton Ageev <antage@gmail.com>,Kirill Simonov 
@@ -53,10 +53,12 @@
                    , filepath
                    , directory
                    , enclosed-exceptions
+                   , semigroups
     exposed-modules: Text.Libyaml
                      Data.Yaml
                      Data.Yaml.Aeson
                      Data.Yaml.Builder
+                     Data.Yaml.Config
                      Data.Yaml.Pretty
                      Data.Yaml.Parser
                      Data.Yaml.Include
