diff --git a/src/shrpx.cc b/src/shrpx.cc
index 617d997f562d4dd40326627ae6ad5e3d7166182b..202da17ccec1b11afc1c7a13c2f5c1ae9ce8d0c8 100644
--- a/src/shrpx.cc
+++ b/src/shrpx.cc
@@ -312,6 +312,7 @@ void fill_default_config()
   set_config_str(&mod_config()->host, "0.0.0.0");
   mod_config()->port = 3000;
   mod_config()->private_key_file = 0;
+  mod_config()->private_key_passwd = 0;
   mod_config()->cert_file = 0;
 
   // Read timeout for SPDY upstream connection
@@ -465,6 +466,11 @@ void print_help(std::ostream& out)
       << "                       linked OpenSSL is configured to load system\n"
       << "                       wide certificates, they are loaded\n"
       << "                       at startup regardless of this option.\n"
+      << "    --private-key-passwd-file=<FILEPATH>\n"
+      << "                       Path to file that contains password for the\n"
+      << "                       server's private key. If none is given and\n"
+      << "                       the private key is password protected it'll\n"
+      << "                       be requested interactively."
       << "\n"
       << "  SPDY:\n"
       << "    -c, --spdy-max-concurrent-streams=<NUM>\n"
@@ -566,6 +572,7 @@ int main(int argc, char **argv)
       {"cacert", required_argument, &flag, 19 },
       {"backend-ipv4", no_argument, &flag, 20 },
       {"backend-ipv6", no_argument, &flag, 21 },
+      {"private-key-passwd-file", required_argument, &flag, 22},
       {0, 0, 0, 0 }
     };
     int option_index = 0;
@@ -703,6 +710,11 @@ int main(int argc, char **argv)
         // --backend-ipv6
         cmdcfgs.push_back(std::make_pair(SHRPX_OPT_BACKEND_IPV6, "yes"));
         break;
+      case 22:
+        // --private-key-passwd-file
+        cmdcfgs.push_back(std::make_pair(SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE,
+                                         optarg));
+        break;
       default:
         break;
       }
diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc
index 05520b9ddd0c9e6f1fdd7387f5a6be6ebc6e12e5..4cb207807f420edcd146f37f27313f35d5cf463e 100644
--- a/src/shrpx_config.cc
+++ b/src/shrpx_config.cc
@@ -27,6 +27,9 @@
 #include <pwd.h>
 #include <netdb.h>
 #include <syslog.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include <cstring>
 #include <cerrno>
@@ -41,6 +44,7 @@ using namespace spdylay;
 namespace shrpx {
 
 const char SHRPX_OPT_PRIVATE_KEY_FILE[] = "private-key-file";
+const char SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE[] = "private-key-passwd-file";
 const char SHRPX_OPT_CERTIFICATE_FILE[] = "certificate-file";
 
 const char SHRPX_OPT_BACKEND[] = "backend";
@@ -125,6 +129,41 @@ int split_host_port(char *host, size_t hostlen, uint16_t *port_ptr,
 }
 } // namespace
 
+bool is_secure(const char *filename)
+{
+  struct stat buf;
+  int rv = stat(filename, &buf);
+  if (rv == 0) {
+    if ((buf.st_mode & S_IRWXU) &&
+        !(buf.st_mode & S_IRWXG) &&
+        !(buf.st_mode & S_IRWXO)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+std::string read_passwd_from_file(const char *filename)
+{
+  std::string line;
+
+  if (!is_secure(filename)) {
+    LOG(ERROR) << "Private key passwd file " << filename
+               << " has insecure mode.";
+    return line;
+  }
+
+  std::ifstream in(filename, std::ios::binary);
+  if(!in) {
+    LOG(ERROR) << "Could not open key passwd file " << filename;
+    return line;
+  }
+
+  std::getline(in, line);
+  return line;
+}
+
 void set_config_str(char **destp, const char *val)
 {
   if(*destp) {
@@ -221,6 +260,13 @@ int parse_config(const char *opt, const char *optarg)
     mod_config()->gid = pwd->pw_gid;
   } else if(util::strieq(opt, SHRPX_OPT_PRIVATE_KEY_FILE)) {
     set_config_str(&mod_config()->private_key_file, optarg);
+  } else if(util::strieq(opt, SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE)) {
+    std::string passwd = read_passwd_from_file(optarg);
+    if (passwd.empty()) {
+      LOG(ERROR) << "Couldn't read key file's passwd from " << optarg;
+      return -1;
+    }
+    set_config_str(&mod_config()->private_key_passwd, passwd.c_str());
   } else if(util::strieq(opt, SHRPX_OPT_CERTIFICATE_FILE)) {
     set_config_str(&mod_config()->cert_file, optarg);
   } else if(util::strieq(opt, SHRPX_OPT_SYSLOG)) {
diff --git a/src/shrpx_config.h b/src/shrpx_config.h
index 275afe2ef29d95242c98dbdf0f78be95afe96765..4301d25a1b1d4b17fede5f1409472bc4267cbb07 100644
--- a/src/shrpx_config.h
+++ b/src/shrpx_config.h
@@ -36,6 +36,7 @@
 namespace shrpx {
 
 extern const char SHRPX_OPT_PRIVATE_KEY_FILE[];
+extern const char SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE[];
 extern const char SHRPX_OPT_CERTIFICATE_FILE[];
 
 extern const char SHRPX_OPT_BACKEND[];
@@ -81,6 +82,7 @@ struct Config {
   char *host;
   uint16_t port;
   char *private_key_file;
+  char *private_key_passwd;
   char *cert_file;
   bool verify_client;
   const char *server_name;
@@ -136,6 +138,9 @@ int parse_config(const char *opt, const char *optarg);
 // -1.
 int load_config(const char *filename);
 
+// Read passwd from |filename|
+std::string read_passwd_from_file(const char *filename);
+
 // Copies NULL-terminated string |val| to |*destp|. If |*destp| is not
 // NULL, it is freed before copying.
 void set_config_str(char **destp, const char *val);
diff --git a/src/shrpx_ssl.cc b/src/shrpx_ssl.cc
index d556d6d11098923f49085732063b76e16c2e342b..3bdae05ecbb11d3162070b5623d08379cf11f6b9 100644
--- a/src/shrpx_ssl.cc
+++ b/src/shrpx_ssl.cc
@@ -91,6 +91,22 @@ void set_npn_prefs(unsigned char *out, const char **protos, size_t len)
 }
 } // namespace
 
+
+static int ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *user_data)
+{
+  Config *config = (Config *)user_data;
+  int len = (int)strlen(config->private_key_passwd);
+  if (size < len + 1) {
+    LOG(ERROR) << "ssl_pem_passwd_cb: buf is too small " << size;
+    return 0;
+  }
+
+  strncpy(buf, config->private_key_passwd, len);
+  buf[len] = '\0';
+  return len;
+}
+
+
 SSL_CTX* create_ssl_context()
 {
   SSL_CTX *ssl_ctx;
@@ -118,6 +134,10 @@ SSL_CTX* create_ssl_context()
   SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
   SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
   SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
+  if (get_config()->private_key_passwd) {
+    SSL_CTX_set_default_passwd_cb(ssl_ctx, ssl_pem_passwd_cb);
+    SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)get_config());
+  }
   if(SSL_CTX_use_PrivateKey_file(ssl_ctx,
                                  get_config()->private_key_file,
                                  SSL_FILETYPE_PEM) != 1) {