diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,7 @@
+Copyright Robert Fischer (c) 2018
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+RFC Environment Variable Support
+===================================
+
+This provides the environment variable support for the Robert Fischer Commons, currently
+based on [envy](https://hackage.haskell.org/package/envy).
diff --git a/package.common.yaml b/package.common.yaml
new file mode 100644
--- /dev/null
+++ b/package.common.yaml
@@ -0,0 +1,103 @@
+- &defaults
+  author: Robert Fischer
+  maintainer: smokejumperit+rfc@gmail.com
+  license: MIT
+  license-file: LICENSE
+
+  flags:
+    production:
+      description: If true, disables failing on warnings and enables aggressive optimizations.
+      manual: true
+      default: false
+
+  library:
+    source-dirs:
+      - './src'
+
+  extra-source-files:
+    - LICENSE
+    - README.md
+    - package.yaml
+    - package.common.yaml
+
+  default-extensions:
+    - ApplicativeDo
+    - BangPatterns
+    - ConstraintKinds
+    - DataKinds
+    - DefaultSignatures
+    - DeriveFoldable
+    - DeriveFunctor
+    - DeriveGeneric
+    - DeriveLift
+    - DeriveTraversable
+    - ExistentialQuantification
+    - FlexibleContexts
+    - FlexibleInstances
+    - FunctionalDependencies
+    - GADTs
+    - GeneralizedNewtypeDeriving
+    - InstanceSigs
+    - KindSignatures
+    - LambdaCase
+    - MultiParamTypeClasses
+    - MultiWayIf
+    - NamedFieldPuns
+    - PatternSynonyms
+    - RankNTypes
+    - ScopedTypeVariables
+    - StandaloneDeriving
+    - TupleSections
+    - TypeApplications
+    - TypeFamilies
+    - TypeFamilyDependencies
+    - TypeOperators  
+    - RebindableSyntax
+    - MonadFailDesugaring
+    - DisambiguateRecordFields
+
+  ghc-options: 
+    - -Wall
+    - -Wcompat 
+    - -Wincomplete-record-updates 
+    - -Wincomplete-uni-patterns 
+    - -Wredundant-constraints 
+    - -fno-max-relevant-binds 
+    - -fprint-potential-instances 
+    - -fprint-explicit-foralls
+    - -Wno-missing-monadfail-instances
+    - -fno-warn-name-shadowing 
+    - -fno-warn-tabs 
+    - -fno-warn-orphans
+    - -Wnoncanonical-monad-instances 
+    - -Wall-missed-specialisations
+    - -Wnoncanonical-monadfail-instances 
+    - -Wimplicit-prelude 
+    - -Wmissing-exported-signatures 
+    - -Widentities
+    - -j
+
+  when:
+  - condition: flag(production)
+    then:
+      ghc-options:
+        - -feager-blackholing 
+        - -funbox-strict-fields 
+        - -fstatic-argument-transformation
+        - -flate-dmd-anal 
+        - -fexpose-all-unfoldings 
+        - -fspecialise-aggressively 
+        - -fexcess-precision 
+        - -fmax-simplifier-iterations=15
+        - -fsimplifier-phases=4
+        - -fstrictness-before=3
+        - -funfolding-keeness-factor=1.5
+        - -funfolding-use-threshold=150
+    else:
+      cpp-options:
+        - -DDEVELOPMENT
+      ghc-options:
+        - -freverse-errors
+        - -Werror 
+        - -dcore-lint 
+        - -dcmm-lint
diff --git a/package.yaml b/package.yaml
new file mode 100644
--- /dev/null
+++ b/package.yaml
@@ -0,0 +1,23 @@
+name: rfc-env
+version: 0.0.0.1
+synopsis: Environment variable support from the Robert Fischer Commons.
+description: >
+  Provides an opinionated and simple way to interface with environment variables, 
+  current based on @envy@.
+
+  This is part of the Robert Fischer commons, which are the @rfc-@ family of packages.
+category: envars
+github: RobertFischer/rfc/rfc-env
+author: Robert Fischer
+license: MIT
+
+_common: !include package.common.yaml
+
+<<: *defaults
+
+dependencies:
+  - rfc-prelude 
+  - base >= 4.10 && < 5
+  - envy >= 1.5
+  - network >= 2.6
+  - time >= 1.8
diff --git a/rfc-env.cabal b/rfc-env.cabal
new file mode 100644
--- /dev/null
+++ b/rfc-env.cabal
@@ -0,0 +1,57 @@
+-- This file has been generated from package.yaml by hpack version 0.28.2.
+--
+-- see: https://github.com/sol/hpack
+--
+-- hash: fcb57a1afbc97ad75c0a2a7fbb71488233197865dd78ab6778aa2f01244344a7
+
+name:           rfc-env
+version:        0.0.0.1
+synopsis:       Environment variable support from the Robert Fischer Commons.
+description:    Provides an opinionated and simple way to interface with environment variables,  current based on @envy@.
+                This is part of the Robert Fischer commons, which are the @rfc-@ family of packages.
+category:       envars
+homepage:       https://github.com/RobertFischer/rfc#readme
+bug-reports:    https://github.com/RobertFischer/rfc/issues
+author:         Robert Fischer
+maintainer:     smokejumperit+rfc@gmail.com
+license:        MIT
+license-file:   LICENSE
+build-type:     Simple
+cabal-version:  >= 1.10
+extra-source-files:
+    LICENSE
+    package.common.yaml
+    package.yaml
+    README.md
+
+source-repository head
+  type: git
+  location: https://github.com/RobertFischer/rfc
+  subdir: rfc-env
+
+flag production
+  description: If true, disables failing on warnings and enables aggressive optimizations.
+  manual: True
+  default: False
+
+library
+  exposed-modules:
+      RFC.Env
+  other-modules:
+      Paths_rfc_env
+  hs-source-dirs:
+      ./src
+  default-extensions: ApplicativeDo BangPatterns ConstraintKinds DataKinds DefaultSignatures DeriveFoldable DeriveFunctor DeriveGeneric DeriveLift DeriveTraversable ExistentialQuantification FlexibleContexts FlexibleInstances FunctionalDependencies GADTs GeneralizedNewtypeDeriving InstanceSigs KindSignatures LambdaCase MultiParamTypeClasses MultiWayIf NamedFieldPuns PatternSynonyms RankNTypes ScopedTypeVariables StandaloneDeriving TupleSections TypeApplications TypeFamilies TypeFamilyDependencies TypeOperators RebindableSyntax MonadFailDesugaring DisambiguateRecordFields
+  ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -fno-max-relevant-binds -fprint-potential-instances -fprint-explicit-foralls -Wno-missing-monadfail-instances -fno-warn-name-shadowing -fno-warn-tabs -fno-warn-orphans -Wnoncanonical-monad-instances -Wall-missed-specialisations -Wnoncanonical-monadfail-instances -Wimplicit-prelude -Wmissing-exported-signatures -Widentities -j
+  build-depends:
+      base >=4.10 && <5
+    , envy >=1.5
+    , network >=2.6
+    , rfc-prelude
+    , time >=1.8
+  if flag(production)
+    ghc-options: -feager-blackholing -funbox-strict-fields -fstatic-argument-transformation -flate-dmd-anal -fexpose-all-unfoldings -fspecialise-aggressively -fexcess-precision -fmax-simplifier-iterations=15 -fsimplifier-phases=4 -fstrictness-before=3 -funfolding-keeness-factor=1.5 -funfolding-use-threshold=150
+  else
+    ghc-options: -freverse-errors -Werror -dcore-lint -dcmm-lint
+    cpp-options: -DDEVELOPMENT
+  default-language: Haskell2010
diff --git a/src/RFC/Env.hs b/src/RFC/Env.hs
new file mode 100644
--- /dev/null
+++ b/src/RFC/Env.hs
@@ -0,0 +1,138 @@
+{-# LANGUAGE CPP                 #-}
+{-# LANGUAGE InstanceSigs        #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module RFC.Env
+  ( isDevelopment
+  , readHost
+  , readPort
+  , readAppSlug
+  , forDevOnly
+  , envWithDefault
+  , envWithDevDefault
+  , module System.Envy
+  ) where
+
+import           Control.Applicative
+import           Data.Time.Clock
+import           Data.Word
+import           Network             ( PortID (..) )
+import           RFC.Prelude
+import           System.Environment
+import           System.Envy
+import           Text.Read           ( readEither, readMaybe )
+
+envWithDefault :: Var a => String -> a -> Parser a
+envWithDefault name defaultValue = fromMaybe defaultValue <$> envMaybe name
+{-# INLINE envWithDefault #-}
+
+envWithDevDefault :: Var a => String -> a -> Parser a
+envWithDevDefault name defaultValue =
+  if isDevelopment then
+    envWithDefault name defaultValue
+  else
+    env name
+{-# INLINE envWithDevDefault #-}
+
+isDevelopment :: Bool
+isDevelopment =
+#ifdef DEVELOPMENT
+  True
+#else
+  False
+#endif
+{-# INLINE isDevelopment #-}
+
+forDevOnly :: a -> Maybe a
+forDevOnly defaultValue =
+  if isDevelopment then
+    Just defaultValue
+  else
+    Nothing
+{-# INLINE forDevOnly #-}
+
+readAppSlug :: (MonadIO m, MonadFail m) => m String
+readAppSlug = readEnvStringWithDevDefault "APP_SLUG" "dev"
+{-# INLINE readAppSlug #-}
+
+readHost :: (MonadIO m, MonadFail m) => m String
+readHost =
+  readEnvStringWithDevDefault "HOST" "localhost"
+{-# INLINE readHost #-}
+
+readPort :: (MonadIO m, MonadFail m) => Word16 -> m Word16
+readPort = readEnvWithDevDefault "PORT"
+{-# INLINE readPort #-}
+
+readEnvStringWithDefault :: (MonadIO m) => String -> String -> m String
+readEnvStringWithDefault name defaultValue =
+  fromMaybe defaultValue <$> readEnvString name
+{-# INLINE readEnvStringWithDefault #-}
+
+readEnvStringWithDevDefault :: (MonadIO m, MonadFail m) => String -> String -> m String
+readEnvStringWithDevDefault =
+  if isDevelopment then
+    readEnvStringWithDefault
+  else
+    (\name _ -> do -- Need to join the MonadFail instances
+      result <- readEnvString name
+      case result of
+        Left err -> fail err
+        Right x  -> return x
+    )
+{-# INLINE readEnvStringWithDevDefault #-}
+
+readEnvWithDefault :: (MonadIO m, Read a) => String -> a -> m a
+readEnvWithDefault name defaultValue = do
+  maybeVal <- readEnvString name
+  return . fromMaybe defaultValue $ maybeVal >>= readMaybe
+{-# INLINE readEnvWithDefault #-}
+
+readEnvWithDevDefault :: (MonadIO m, MonadFail m, Read a) => String -> a -> m a
+readEnvWithDevDefault =
+  if isDevelopment then
+    readEnvWithDefault
+  else
+    (\name _ -> do
+      errOrResult <- readEnv name
+      case errOrResult of
+        Left err -> fail err
+        Right x  -> return x
+    )
+{-# INLINE readEnvWithDevDefault #-}
+
+readEnvString :: (MonadIO m1, MonadFail m2) => String -> m1 (m2 String)
+readEnvString name = do
+  result <- liftIO $ lookupEnv name
+  return $ case result of
+    Nothing -> fail $ "No value set for environment variable: " <> name
+    Just x  -> return x
+{-# INLINE readEnvString #-}
+
+readEnv :: (MonadIO m1, MonadFail m2, Read a) => String -> m1 (m2 a)
+readEnv name = do
+  eitherOrVal <- readEnvString name
+  return $ case eitherOrVal :: ((Either String) String) of
+    Left err -> fail err
+    Right val ->
+      case readEither val of
+        Left err -> fail $ "Error parsing value from environment variable. " <> name <> " = " <> (show val) <> " => " <> err
+        Right result -> return result
+{-# INLINE readEnv #-}
+
+instance Var NominalDiffTime where
+  toVar :: NominalDiffTime -> String
+  toVar = show
+  {-# INLINE toVar #-}
+
+  fromVar :: String -> Maybe NominalDiffTime
+  fromVar var = fromInteger <$> readMaybe var
+  {-# INLINE fromVar #-}
+
+instance Var PortID where
+  toVar (PortNumber portNum) = toVar $ toInteger portNum
+  toVar _                    = error "Can only write port numbers to var"
+  {-# INLINE toVar #-}
+
+  fromVar = fmap (PortNumber . fromInteger) . fromVar
+  {-# INLINE fromVar #-}
