diff --git a/conf/nebula-graphd.conf.default b/conf/nebula-graphd.conf.default
index 9edf937d70421e0691ec6924f4f94a563db99478..06f6826d836de70750add9766e7e69f9bcbcd676 100644
--- a/conf/nebula-graphd.conf.default
+++ b/conf/nebula-graphd.conf.default
@@ -13,6 +13,9 @@
 --stderr_log_file=stderr.log
 
 ########## networking ##########
+# Network device to listen on
+--listen_netdev=any
+# Port to listen on
 --port=3699
 # seconds before we close the idle connections, 0 for infinite
 --client_idle_timeout_secs=0
diff --git a/src/daemons/CMakeLists.txt b/src/daemons/CMakeLists.txt
index 835f99322aea19d81bf2518e94118fd23d6b6ddd..bf2b71c9ea141e8304aed4290ffe785611189d84 100644
--- a/src/daemons/CMakeLists.txt
+++ b/src/daemons/CMakeLists.txt
@@ -9,6 +9,8 @@ add_executable(
     $<TARGET_OBJECTS:fs_obj>
     $<TARGET_OBJECTS:thread_obj>
     $<TARGET_OBJECTS:parser_obj>
+    $<TARGET_OBJECTS:network_obj>
+    $<TARGET_OBJECTS:proc_obj>
 )
 
 target_link_libraries(
diff --git a/src/daemons/GraphDaemon.cpp b/src/daemons/GraphDaemon.cpp
index 1846ce38db3a768c8906b89eb15a125b4665e5fd..bb3acca2a90bd219eb0fbd906ce67d7ca0defe95 100644
--- a/src/daemons/GraphDaemon.cpp
+++ b/src/daemons/GraphDaemon.cpp
@@ -4,8 +4,9 @@
  *  (found in the LICENSE.Apache file in the root directory)
  */
 
-#include <signal.h>
 #include "base/Base.h"
+#include "network/NetworkUtils.h"
+#include <signal.h>
 #include "base/Status.h"
 #include "fs/FileUtils.h"
 #include <thrift/lib/cpp2/server/ThriftServer.h>
@@ -15,6 +16,7 @@
 using namespace nebula;
 using namespace nebula::graph;
 using namespace nebula::fs;
+using namespace nebula::network;
 
 static std::unique_ptr<apache::thrift::ThriftServer> gServer;
 
@@ -37,11 +39,21 @@ int main(int argc, char *argv[]) {
         return EXIT_FAILURE;
     }
 
+    std::string localIP;
+    {
+        auto result = NetworkUtils::getIPv4FromDevice(FLAGS_listen_netdev);
+        if (!result.ok()) {
+            LOG(ERROR) << result.status();
+            return EXIT_FAILURE;
+        }
+        localIP = std::move(result).value();
+    }
+
     auto interface = std::make_shared<GraphService>();
     gServer = std::make_unique<apache::thrift::ThriftServer>();
 
     gServer->setInterface(interface);
-    gServer->setPort(FLAGS_port);
+    gServer->setAddress(localIP, FLAGS_port);
     gServer->setReusePort(FLAGS_reuse_port);
     gServer->setIdleTimeout(std::chrono::seconds(FLAGS_client_idle_timeout_secs));
 
diff --git a/src/executor/GraphFlags.cpp b/src/executor/GraphFlags.cpp
index c4ca13e6eb9feff90bb506922bf4014f473a9926..5c4cd447fcf9722f011941e60f71391fa1030296 100644
--- a/src/executor/GraphFlags.cpp
+++ b/src/executor/GraphFlags.cpp
@@ -15,6 +15,7 @@ DEFINE_int32(num_netio_threads, 0, "Number of networking threads, 0 for number o
 DEFINE_int32(num_accept_threads, 1, "Number of threads to accept incoming connections");
 DEFINE_bool(reuse_port, true, "Whether to turn on the SO_REUSEPORT option");
 DEFINE_int32(listen_backlog, 1024, "Backlog of the listen socket");
+DEFINE_string(listen_netdev, "any", "The network device to listen on");
 
 DEFINE_bool(redirect_stdout, true, "Whether to redirect stdout and stderr to separate files");
 DEFINE_string(stdout_log_file, "graphd-stdout.log", "Destination filename of stdout");
diff --git a/src/executor/GraphFlags.h b/src/executor/GraphFlags.h
index 445a1a97a0dd8f39f22db43413415f9d7600bf39..9a0430e74eef8deefbe670f9601a413350839dad 100644
--- a/src/executor/GraphFlags.h
+++ b/src/executor/GraphFlags.h
@@ -17,6 +17,7 @@ DECLARE_int32(num_netio_threads);
 DECLARE_int32(num_accept_threads);
 DECLARE_bool(reuse_port);
 DECLARE_int32(listen_backlog);
+DECLARE_string(listen_netdev);
 
 DECLARE_bool(redirect_stdout);
 DECLARE_string(stdout_log_file);