diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
 # Revision history for network-run
 
+## 0.2.7
+
+* Introduce `runTCPServerWithSocket`
+  [#3](https://github.com/kazu-yamamoto/network-run/pull/3)
+
+## 0.2.6
+
+* Adding the Network.Run.TCP.Timeout module.
+
 ## 0.2.5
 
 * Making accept breakable on windows
diff --git a/Network/Run/Core.hs b/Network/Run/Core.hs
--- a/Network/Run/Core.hs
+++ b/Network/Run/Core.hs
@@ -26,6 +26,13 @@
 openSocket addr = socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
 #endif
 
+-- | Open socket for server use
+--
+-- The socket is configured to
+--
+-- * allow reuse of local addresses (SO_REUSEADDR)
+-- * automatically be closed during a successful @execve@ (FD_CLOEXEC)
+-- * bind to the address specified
 openServerSocket :: AddrInfo -> IO Socket
 openServerSocket addr = E.bracketOnError (openSocket addr) close $ \sock -> do
     setSocketOption sock ReuseAddr 1
diff --git a/Network/Run/TCP.hs b/Network/Run/TCP.hs
--- a/Network/Run/TCP.hs
+++ b/Network/Run/TCP.hs
@@ -4,6 +4,10 @@
 module Network.Run.TCP (
     runTCPClient,
     runTCPServer,
+
+    -- * Generalized API
+    runTCPServerWithSocket,
+    openServerSocket,
 ) where
 
 import Control.Concurrent (forkFinally)
@@ -25,11 +29,29 @@
 
 -- | Running a TCP server with an accepted socket and its peer name.
 runTCPServer :: Maybe HostName -> ServiceName -> (Socket -> IO a) -> IO a
-runTCPServer mhost port server = withSocketsDo $ do
+runTCPServer = runTCPServerWithSocket openServerSocket
+
+----------------------------------------------------------------
+-- Generalized API
+
+-- | Generalization of 'runTCPServer'
+runTCPServerWithSocket
+    :: (AddrInfo -> IO Socket)
+    -- ^ Initialize socket.
+    --
+    -- This function is called while exceptions are masked.
+    --
+    -- The default (used by 'runTCPServer') is 'openServerSocket'.
+    -> Maybe HostName
+    -> ServiceName
+    -> (Socket -> IO a)
+    -- ^ Called for each incoming connection, in a new thread
+    -> IO a
+runTCPServerWithSocket initSocket mhost port server = withSocketsDo $ do
     addr <- resolve Stream mhost port True
     E.bracket (open addr) close loop
   where
-    open addr = E.bracketOnError (openServerSocket addr) close $ \sock -> do
+    open addr = E.bracketOnError (initSocket addr) close $ \sock -> do
         listen sock 1024
         return sock
     loop sock = forever $
diff --git a/Network/Run/TCP/Timeout.hs b/Network/Run/TCP/Timeout.hs
--- a/Network/Run/TCP/Timeout.hs
+++ b/Network/Run/TCP/Timeout.hs
@@ -4,6 +4,9 @@
 module Network.Run.TCP.Timeout (
     runTCPServer,
     TimeoutServer,
+    -- * Generalized API
+    runTCPServerWithSocket,
+    openServerSocket,
 ) where
 
 import Control.Concurrent (forkFinally)
@@ -32,12 +35,28 @@
     -> ServiceName
     -> TimeoutServer a
     -> IO a
-runTCPServer tm mhost port server = withSocketsDo $ do
+runTCPServer = runTCPServerWithSocket openServerSocket
+
+----------------------------------------------------------------
+-- Generalized API
+
+-- | Generalization of 'runTCPServer'
+--
+-- See 'Network.Run.TCP.runTCPServerWithSocket' for additional discussion.
+runTCPServerWithSocket
+    :: (AddrInfo -> IO Socket)
+    -> Int
+    -- ^ Timeout in second.
+    -> Maybe HostName
+    -> ServiceName
+    -> TimeoutServer a
+    -> IO a
+runTCPServerWithSocket initSocket tm mhost port server = withSocketsDo $ do
     T.withManager (tm * 1000000) $ \mgr -> do
         addr <- resolve Stream mhost port True
         E.bracket (open addr) close $ loop mgr
   where
-    open addr = E.bracketOnError (openServerSocket addr) close $ \sock -> do
+    open addr = E.bracketOnError (initSocket addr) close $ \sock -> do
         listen sock 1024
         return sock
     loop mgr sock = forever $
diff --git a/network-run.cabal b/network-run.cabal
--- a/network-run.cabal
+++ b/network-run.cabal
@@ -1,5 +1,5 @@
 name:                network-run
-version:             0.2.6
+version:             0.2.7
 synopsis:            Simple network runner library
 description:         Simple functions to run network clients and servers.
 -- bug-reports:
