diff --git a/Blammo.cabal b/Blammo.cabal
--- a/Blammo.cabal
+++ b/Blammo.cabal
@@ -1,6 +1,6 @@
 cabal-version:   1.18
 name:            Blammo
-version:         1.0.2.2
+version:         1.0.2.3
 license:         MIT
 license-file:    LICENSE
 maintainer:      Freckle Education
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,8 @@
-## [_Unreleased_](https://github.com/freckle/blammo/compare/v1.0.2.2...main)
+## [_Unreleased_](https://github.com/freckle/blammo/compare/v1.0.2.3...main)
+
+## [v1.0.2.3](https://github.com/freckle/blammo/compare/v1.0.2.2...v1.0.2.3)
+
+- Fix for localhost `clientIp` value in `requestLogger` ([#18](https://github.com/freckle/blammo/issues/18))
 
 ## [v1.0.2.2](https://github.com/freckle/blammo/compare/v1.0.2.1...v1.0.2.2)
 
diff --git a/src/Network/Wai/Middleware/Logging.hs b/src/Network/Wai/Middleware/Logging.hs
--- a/src/Network/Wai/Middleware/Logging.hs
+++ b/src/Network/Wai/Middleware/Logging.hs
@@ -8,12 +8,14 @@
   , Config
   , defaultConfig
   , setConfigLogSource
+  , setConfigGetClientIp
   , setConfigGetDestinationIp
   ) where
 
 import Prelude
 
 import Blammo.Logging
+import Control.Applicative ((<|>))
 import Control.Arrow ((***))
 import Control.Monad.IO.Unlift (withRunInIO)
 import Data.Aeson
@@ -21,7 +23,10 @@
 import qualified Data.Aeson.Compat as KeyMap
 import Data.ByteString (ByteString)
 import qualified Data.CaseInsensitive as CI
+import Data.List (find)
+import Data.Maybe (fromMaybe)
 import Data.Text (Text, pack)
+import qualified Data.Text as T
 import Data.Text.Encoding (decodeUtf8With)
 import Data.Text.Encoding.Error (lenientDecode)
 import Network.HTTP.Types.Header (Header, HeaderName)
@@ -87,17 +92,23 @@
 
 data Config = Config
   { cLogSource :: LogSource
+  , cGetClientIp :: Request -> Text
   , cGetDestinationIp :: Request -> Maybe Text
   }
 
 defaultConfig :: Config
 defaultConfig = Config
   { cLogSource = "requestLogger"
-  , cGetDestinationIp = fmap decodeUtf8 . lookupRequestHeader "x-real-ip"
+  , cGetClientIp = \req ->
+    fromMaybe (pack $ show $ remoteHost req)
+      $ (firstValue =<< lookupRequestHeader "x-forwarded-for" req)
+      <|> lookupRequestHeader "x-real-ip" req
+  , cGetDestinationIp = lookupRequestHeader "x-real-ip"
   }
+  where firstValue = find (not . T.null) . map T.strip . T.splitOn ","
 
-lookupRequestHeader :: HeaderName -> Request -> Maybe ByteString
-lookupRequestHeader h = lookup h . requestHeaders
+lookupRequestHeader :: HeaderName -> Request -> Maybe Text
+lookupRequestHeader h = fmap decodeUtf8 . lookup h . requestHeaders
 
 -- | Change the source used for log messages
 --
@@ -106,10 +117,25 @@
 setConfigLogSource :: LogSource -> Config -> Config
 setConfigLogSource x c = c { cLogSource = x }
 
+-- | Change how the @clientIp@ field is determined
+--
+-- Default is looking up the first value in @x-forwarded-for@, then the
+-- @x-real-ip@ header, then finally falling back to 'Network.Wai.remoteHost'.
+--
+setConfigGetClientIp :: (Request -> Text) -> Config -> Config
+setConfigGetClientIp x c = c { cGetClientIp = x }
+
 -- | Change how the @destinationIp@ field is determined
 --
 -- Default is looking up the @x-real-ip@ header.
 --
+-- __NOTE__: Our default uses a somewhat loose definition of /destination/. It
+-- would be more accurate to report the resolved IP address of the @Host@
+-- header, but we don't have that available. Our default of @x-real-ip@ favors
+-- containerized Warp on AWS/ECS, where this value holds the ECS target
+-- container's IP address. This is valuable debugging information and could, if
+-- you squint, be considered a /destination/.
+--
 setConfigGetDestinationIp :: (Request -> Maybe Text) -> Config -> Config
 setConfigGetDestinationIp x c = c { cGetDestinationIp = x }
 
@@ -150,7 +176,7 @@
       [ "code" .= statusCode status
       , "message" .= decodeUtf8 (statusMessage status)
       ]
-    , "clientIp" .= show (remoteHost req)
+    , "clientIp" .= cGetClientIp req
     , "destinationIp" .= cGetDestinationIp req
     , "durationMs" .= duration
     , "requestHeaders"
