diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt
index bff4ebf..f2697b3 100644
--- a/server/CMakeLists.txt
+++ b/server/CMakeLists.txt
@@ -1,13 +1,13 @@
 add_executable(dragonfly dfly_main.cc)
 cxx_link(dragonfly base dragonfly_lib)
 
-add_library(dragonfly_lib command_registry.cc db_slice.cc dragonfly_listener.cc
+add_library(dragonfly_lib command_registry.cc config_flags.cc db_slice.cc dragonfly_listener.cc
             dragonfly_connection.cc 
             main_service.cc engine_shard_set.cc 
             redis_parser.cc resp_expr.cc reply_builder.cc)
 
 cxx_link(dragonfly_lib uring_fiber_lib
-         fibers_ext strings_lib http_server_lib)
+         fibers_ext strings_lib http_server_lib tls_lib)
 
 add_library(dfly_test_lib test_utils.cc)
 cxx_link(dfly_test_lib dragonfly_lib gtest_main_ext)
diff --git a/server/config_flags.cc b/server/config_flags.cc
new file mode 100644
index 0000000..1b6d46a
--- /dev/null
+++ b/server/config_flags.cc
@@ -0,0 +1,19 @@
+// Copyright 2021, Beeri 15.  All rights reserved.
+// Author: Roman Gershman (romange@gmail.com)
+//
+#include "server/config_flags.h"
+
+namespace dfly {
+
+bool ValidateConfigEnum(const char* nm, const std::string& val, const ConfigEnum* ptr, unsigned len,
+                     int* dest) {
+  for (unsigned i = 0; i < len; ++i) {
+    if (val == ptr[i].first) {
+      *dest = ptr[i].second;
+      return true;
+    }
+  }
+  return false;
+}
+
+}  // namespace dfly
diff --git a/server/config_flags.h b/server/config_flags.h
new file mode 100644
index 0000000..02061a7
--- /dev/null
+++ b/server/config_flags.h
@@ -0,0 +1,92 @@
+// Copyright 2021, Beeri 15.  All rights reserved.
+// Author: Roman Gershman (romange@gmail.com)
+//
+
+#pragma once
+
+#include <string.h>
+#include <absl/base/macros.h>
+
+#include "base/flags.h"
+
+namespace dfly {
+
+// DashStr - replaces all underscores to dash characters and keeps the rest as is.
+template <unsigned N> class DashStr {
+ public:
+  DashStr(const char* s) {
+    memcpy(str_, s, N);
+    for (unsigned i = 0; i < N; ++i) {
+      if (str_[i] == '_')
+        str_[i] = '-';
+    }
+  }
+
+  const char* str() const {
+    return str_;
+  }
+
+ private:
+  char str_[N];
+};
+
+using ConfigEnum = std::pair<const char*, int>;
+
+bool ValidateConfigEnum(const char* nm, const std::string& val, const ConfigEnum* ptr, unsigned len,
+                        int* dest);
+
+}  // namespace dfly
+
+inline bool TrueValidator(const char* nm, const std::string& val) {
+  return true;
+}
+
+#define DEFINE_CONFIG_VAR(type, shorttype, name, value, help, validator)                          \
+  namespace fL##shorttype {                                                                       \
+    type FLAGS_##name = value;                                                                    \
+    static type FLAGS_no##name = value;                                                           \
+    static ::dfly::DashStr<sizeof(#name)> _dash_##name(#name);                                   \
+    static GFLAGS_NAMESPACE::FlagRegisterer o_##name(                                             \
+        _dash_##name.str(), MAYBE_STRIPPED_HELP(help), __FILE__, &FLAGS_##name, &FLAGS_no##name); \
+    static const bool name##_val_reg =                                                            \
+                         GFLAGS_NAMESPACE::RegisterFlagValidator(&FLAGS_##name, validator);       \
+  }                                                                                               \
+  using fL##shorttype::FLAGS_##name
+
+#define BIND_CONFIG(var) [](const char* nm, auto val) { \
+          var = val;                                    \
+          return true;}
+
+
+#define BIND_ENUM_CONFIG(enum_arr, dest_var) [](const char* nm, const std::string& val) { \
+         return ::dfly::ValidateConfigEnum(nm, val, enum_arr, ABSL_ARRAYSIZE(enum_arr),  \
+                         &(dest_var));}
+
+#define CONFIG_uint64(name,val, txt, validator) \
+   DEFINE_CONFIG_VAR(GFLAGS_NAMESPACE::uint64, U64, name, val, txt, validator)
+
+
+#define CONFIG_string(name, val, txt, validator)                                       \
+  namespace fLS {                                                           \
+    using ::fLS::clstring;                                                  \
+    using ::fLS::StringFlagDestructor;                                      \
+    static union { void* align; char s[sizeof(clstring)]; } s_##name[2];    \
+    clstring* const FLAGS_no##name = ::fLS::                                \
+                                   dont_pass0toDEFINE_string(s_##name[0].s, \
+                                                             val);          \
+    static ::dfly::DashStr<sizeof(#name)> _dash_##name(#name);             \
+    static GFLAGS_NAMESPACE::FlagRegisterer o_##name(                       \
+        _dash_##name.str(), MAYBE_STRIPPED_HELP(txt), __FILE__,             \
+        FLAGS_no##name, new (s_##name[1].s) clstring(*FLAGS_no##name));     \
+    static StringFlagDestructor d_##name(s_##name[0].s, s_##name[1].s);     \
+    extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name;                   \
+    using fLS::FLAGS_##name;                                                \
+    clstring& FLAGS_##name = *FLAGS_no##name;                               \
+    static const bool name##_val_reg =                                      \
+      GFLAGS_NAMESPACE::RegisterFlagValidator(&FLAGS_##name, validator);    \
+  }                                                                         \
+  using fLS::FLAGS_##name
+
+#define CONFIG_enum(name, val, txt, enum_arr, dest_var)    \
+    CONFIG_string(name, val, txt, BIND_ENUM_CONFIG(enum_arr, dest_var))
+
diff --git a/server/dragonfly_connection.cc b/server/dragonfly_connection.cc
index 5ebc922..93cd3d8 100644
--- a/server/dragonfly_connection.cc
+++ b/server/dragonfly_connection.cc
@@ -8,11 +8,12 @@
 
 #include "base/io_buf.h"
 #include "base/logging.h"
+#include "server/command_registry.h"
+#include "server/conn_context.h"
 #include "server/main_service.h"
 #include "server/redis_parser.h"
-#include "server/conn_context.h"
-#include "server/command_registry.h"
 #include "util/fiber_sched_algo.h"
+#include "util/tls/tls_socket.h"
 
 using namespace util;
 using namespace std;
@@ -68,8 +69,7 @@ struct Connection::Shutdown {
   }
 };
 
-Connection::Connection(Service* service)
-    : service_(service) {
+Connection::Connection(Service* service, SSL_CTX* ctx) : service_(service), ctx_(ctx) {
   redis_parser_.reset(new RedisParser);
 }
 
@@ -106,7 +106,19 @@ void Connection::HandleRequests() {
   int val = 1;
   CHECK_EQ(0, setsockopt(socket_->native_handle(), SOL_TCP, TCP_NODELAY, &val, sizeof(val)));
 
-  FiberSocketBase* peer = socket_.get();
+  std::unique_ptr<tls::TlsSocket> tls_sock;
+  if (ctx_) {
+    tls_sock.reset(new tls::TlsSocket(socket_.get()));
+    tls_sock->InitSSL(ctx_);
+
+    FiberSocketBase::accept_result aresult = tls_sock->Accept();
+    if (!aresult) {
+      LOG(WARNING) << "Error handshaking " << aresult.error().message();
+      return;
+    }
+    VLOG(1) << "TLS handshake succeeded";
+  }
+  FiberSocketBase* peer = tls_sock ? (FiberSocketBase*)tls_sock.get() : socket_.get();
   cc_.reset(new ConnectionContext(peer, this));
   cc_->shard_set = &service_->shard_set();
 
@@ -132,7 +144,7 @@ void Connection::InputLoop(FiberSocketBase* peer) {
 
     io_buf.CommitWrite(*recv_sz);
     status = ParseRedis(&io_buf);
-     if (status == NEED_MORE) {
+    if (status == NEED_MORE) {
       status = OK;
     } else if (status != OK) {
       break;
diff --git a/server/dragonfly_connection.h b/server/dragonfly_connection.h
index 7fff4af..b4b9b8d 100644
--- a/server/dragonfly_connection.h
+++ b/server/dragonfly_connection.h
@@ -8,15 +8,17 @@
 
 #include "base/io_buf.h"
 
+typedef struct ssl_ctx_st SSL_CTX;
+
 namespace dfly {
 
-class Service;
-class RedisParser;
 class ConnectionContext;
+class RedisParser;
+class Service;
 
 class Connection : public util::Connection {
  public:
-  Connection(Service* service);
+  Connection(Service* service, SSL_CTX* ctx);
   ~Connection();
 
   using error_code = std::error_code;
@@ -39,9 +41,10 @@ class Connection : public util::Connection {
   ParserStatus ParseRedis(base::IoBuf* buf);
 
   std::unique_ptr<RedisParser> redis_parser_;
+  Service* service_;
+  SSL_CTX* ctx_;
   std::unique_ptr<ConnectionContext> cc_;
 
-  Service* service_;
   unsigned parser_error_ = 0;
 
   struct Shutdown;
diff --git a/server/dragonfly_listener.cc b/server/dragonfly_listener.cc
index 449c825..01f7568 100644
--- a/server/dragonfly_listener.cc
+++ b/server/dragonfly_listener.cc
@@ -4,25 +4,96 @@
 
 #include "server/dragonfly_listener.h"
 
+#include <openssl/ssl.h>
+
 #include "base/logging.h"
+#include "server/config_flags.h"
 #include "server/dragonfly_connection.h"
 #include "util/proactor_pool.h"
 
 using namespace util;
 
 DEFINE_uint32(conn_threads, 0, "Number of threads used for handing server connections");
+DEFINE_bool(tls, false, "");
 
+CONFIG_string(tls_client_cert_file, "", "", TrueValidator);
+CONFIG_string(tls_client_key_file, "", "", TrueValidator);
+
+enum TlsClientAuth {
+  CL_AUTH_NO = 0,
+  CL_AUTH_YES = 1,
+  CL_AUTH_OPTIONAL = 2,
+};
+
+dfly::ConfigEnum tls_auth_clients_enum[] = {
+    {"no", CL_AUTH_NO},
+    {"yes", CL_AUTH_YES},
+    {"optional", CL_AUTH_OPTIONAL},
+};
+
+static int tls_auth_clients_opt = CL_AUTH_YES;
+
+CONFIG_enum(tls_auth_clients, "yes", "", tls_auth_clients_enum, tls_auth_clients_opt);
 
 namespace dfly {
 
+// To connect: openssl s_client  -cipher "ADH:@SECLEVEL=0" -state -crlf  -connect 127.0.0.1:6380
+static SSL_CTX* CreateSslCntx() {
+  SSL_CTX* ctx = SSL_CTX_new(TLS_server_method());
+
+  if (FLAGS_tls_client_key_file.empty()) {
+    // To connect - use openssl s_client -cipher with either:
+    // "AECDH:@SECLEVEL=0" or "ADH:@SECLEVEL=0" setting.
+    CHECK_EQ(1, SSL_CTX_set_cipher_list(ctx, "aNULL"));
+
+    // To allow anonymous ciphers.
+    SSL_CTX_set_security_level(ctx, 0);
+
+    // you can still connect with redis-cli with :
+    // redis-cli --tls --insecure --tls-ciphers "ADH:@SECLEVEL=0"
+    LOG(WARNING)
+        << "tls-client-key-file not set, no keys are loaded and anonymous ciphers are enabled. "
+        << "Do not use in production!";
+  } else { // tls_client_key_file is set.
+    CHECK_EQ(1,
+             SSL_CTX_use_PrivateKey_file(ctx, FLAGS_tls_client_key_file.c_str(), SSL_FILETYPE_PEM));
+
+    if (!FLAGS_tls_client_cert_file.empty()) {
+      // TO connect with redis-cli you need both tls-client-key-file and tls-client-cert-file
+      // loaded. Use `redis-cli --tls -p 6380 --insecure  PING` to test
+
+      CHECK_EQ(1, SSL_CTX_use_certificate_chain_file(ctx, FLAGS_tls_client_cert_file.c_str()));
+    }
+    CHECK_EQ(1, SSL_CTX_set_cipher_list(ctx, "DEFAULT"));
+  }
+  SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
+
+  SSL_CTX_set_options(ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
+
+  unsigned mask = SSL_VERIFY_NONE;
+
+  // if (tls_auth_clients_opt)
+  // mask |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+  SSL_CTX_set_verify(ctx, mask, NULL);
+
+  CHECK_EQ(1, SSL_CTX_set_dh_auto(ctx, 1));
+
+  return ctx;
+}
+
 Listener::Listener(Service* e) : engine_(e) {
+  if (FLAGS_tls) {
+    OPENSSL_init_ssl(OPENSSL_INIT_SSL_DEFAULT, NULL);
+    ctx_ = CreateSslCntx();
+  }
 }
 
 Listener::~Listener() {
+  SSL_CTX_free(ctx_);
 }
 
 util::Connection* Listener::NewConnection(ProactorBase* proactor) {
-  return new Connection{engine_};
+  return new Connection{engine_, ctx_};
 }
 
 void Listener::PreShutdown() {
diff --git a/server/dragonfly_listener.h b/server/dragonfly_listener.h
index f1e9098..15aa5d5 100644
--- a/server/dragonfly_listener.h
+++ b/server/dragonfly_listener.h
@@ -6,6 +6,8 @@
 
 #include "util/listener_interface.h"
 
+typedef struct ssl_ctx_st SSL_CTX;
+
 namespace dfly {
 
 class Service;
@@ -26,6 +28,7 @@ class Listener : public util::ListenerInterface {
   Service* engine_;
 
   std::atomic_uint32_t next_id_{0};
+  SSL_CTX* ctx_ = nullptr;
 };
 
 }  // namespace dfly