diff --git a/lib/context.c b/lib/context.c
index 17615fb5a72d1045b0f6996e09019600f0921e0b..88e7fe4557c35b8632791a81cbf5a806c9442a6e 100644
--- a/lib/context.c
+++ b/lib/context.c
@@ -122,6 +122,10 @@ lws_vhost_protocol_options(struct lws_vhost *vh, const char *name)
 	return NULL;
 }
 
+/*
+ * inform every vhost that hasn't already done it, that
+ * his protocols are initializing
+ */
 int
 lws_protocol_init(struct lws_context *context)
 {
@@ -138,6 +142,10 @@ lws_protocol_init(struct lws_context *context)
 	while (vh) {
 		wsi.vhost = vh;
 
+		/* only do the protocol init once for a given vhost */
+		if (vh->created_vhost_protocols)
+			goto next;
+
 		/* initialize supported protocols on this vhost */
 
 		for (n = 0; n < vh->count_protocols; n++) {
@@ -185,11 +193,15 @@ lws_protocol_init(struct lws_context *context)
 				return 1;
 		}
 
+		vh->created_vhost_protocols = 1;
+next:
 		vh = vh->vhost_next;
 	}
 
+	if (!context->protocol_init_done)
+		lws_finalize_startup(context);
+
 	context->protocol_init_done = 1;
-	lws_finalize_startup(context);
 
 	return 0;
 }
@@ -520,6 +532,11 @@ lws_create_vhost(struct lws_context *context,
 		vh1 = &(*vh1)->vhost_next;
 	};
 
+	/* for the case we are adding a vhost much later, after server init */
+
+	if (context->protocol_init_done)
+		lws_protocol_init(context);
+
 	return vh;
 
 bail:
diff --git a/lib/libuv.c b/lib/libuv.c
index 742ca87a0904a279b2770f49b794a1c5b19d4815..4e80936b2d3d6f35c288230a4c93ffda3d52582a 100644
--- a/lib/libuv.c
+++ b/lib/libuv.c
@@ -143,47 +143,91 @@ lws_uv_timeout_cb(uv_timer_t *timer
 
 static const int sigs[] = { SIGINT, SIGTERM, SIGSEGV, SIGFPE };
 
+int
+lws_uv_initvhost(struct lws_vhost* vh, struct lws* wsi)
+{
+	struct lws_context_per_thread *pt;
+	int n;
+
+	if (!LWS_LIBUV_ENABLED(vh->context))
+		return 0;
+	if (!wsi)
+		wsi = vh->lserv_wsi;
+	if (!wsi)
+		return 0;
+	if (wsi->w_read.context)
+		return 0;
+
+	pt = &vh->context->pt[(int)wsi->tsi];
+	if (!pt->io_loop_uv)
+		return 0;
+
+	wsi->w_read.context = vh->context;
+	n = uv_poll_init_socket(pt->io_loop_uv,
+				&wsi->w_read.uv_watcher, wsi->sock);
+	if (n) {
+		lwsl_err("uv_poll_init failed %d, sockfd=%p\n",
+				 n, (void *)(long)wsi->sock);
+
+		return -1;
+	}
+	lws_libuv_io(wsi, LWS_EV_START | LWS_EV_READ);
+
+	return 0;
+}
+
+/*
+ * This needs to be called after vhosts have been defined.
+ *
+ * If later, after server start, another vhost is added, this must be
+ * called again to bind the vhost
+ */
+
 LWS_VISIBLE int
 lws_uv_initloop(struct lws_context *context, uv_loop_t *loop, int tsi)
 {
 	struct lws_context_per_thread *pt = &context->pt[tsi];
 	struct lws_vhost *vh = context->vhost_list;
-	int status = 0, n, ns;
+	int status = 0, n, ns, first = 1;
 
-	if (!loop) {
-		loop = lws_malloc(sizeof(*loop));
+	if (!pt->io_loop_uv) {
 		if (!loop) {
-			lwsl_err("OOM\n");
-			return -1;
+			loop = lws_malloc(sizeof(*loop));
+			if (!loop) {
+				lwsl_err("OOM\n");
+				return -1;
+			}
+	#if UV_VERSION_MAJOR > 0
+			uv_loop_init(loop);
+	#else
+			lwsl_err("This libuv is too old to work...\n");
+			return 1;
+	#endif
+			pt->ev_loop_foreign = 0;
+		} else {
+			lwsl_notice(" Using foreign event loop...\n");
+			pt->ev_loop_foreign = 1;
 		}
-#if UV_VERSION_MAJOR > 0
-		uv_loop_init(loop);
-#else
-		lwsl_err("This libuv is too old to work...\n");
-		return 1;
-#endif
-		pt->ev_loop_foreign = 0;
-	} else {
-		lwsl_notice(" Using foreign event loop...\n");
-		pt->ev_loop_foreign = 1;
-	}
 
-	pt->io_loop_uv = loop;
-	uv_idle_init(loop, &pt->uv_idle);
+		pt->io_loop_uv = loop;
+		uv_idle_init(loop, &pt->uv_idle);
 
-	ns = ARRAY_SIZE(sigs);
-	if (lws_check_opt(context->options, LWS_SERVER_OPTION_UV_NO_SIGSEGV_SIGFPE_SPIN))
-		ns = 2;
+		ns = ARRAY_SIZE(sigs);
+		if (lws_check_opt(context->options,
+				  LWS_SERVER_OPTION_UV_NO_SIGSEGV_SIGFPE_SPIN))
+			ns = 2;
 
-	if (pt->context->use_ev_sigint) {
-		assert(ns <= ARRAY_SIZE(pt->signals));
-		for (n = 0; n < ns; n++) {
-			uv_signal_init(loop, &pt->signals[n]);
-			pt->signals[n].data = pt->context;
-			uv_signal_start(&pt->signals[n],
-					context->lws_uv_sigint_cb, sigs[n]);
+		if (pt->context->use_ev_sigint) {
+			assert(ns <= ARRAY_SIZE(pt->signals));
+			for (n = 0; n < ns; n++) {
+				uv_signal_init(loop, &pt->signals[n]);
+				pt->signals[n].data = pt->context;
+				uv_signal_start(&pt->signals[n],
+						context->lws_uv_sigint_cb, sigs[n]);
+			}
 		}
-	}
+	} else
+		first = 0;
 
 	/*
 	 * Initialize the accept wsi read watcher with all the listening sockets
@@ -193,24 +237,16 @@ lws_uv_initloop(struct lws_context *context, uv_loop_t *loop, int tsi)
 	 * initialized until after context creation.
 	 */
 	while (vh) {
-		if (vh->lserv_wsi) {
-			vh->lserv_wsi->w_read.context = context;
-			n = uv_poll_init_socket(pt->io_loop_uv,
-						&vh->lserv_wsi->w_read.uv_watcher,
-						vh->lserv_wsi->sock);
-			if (n) {
-				lwsl_err("uv_poll_init failed %d, sockfd=%p\n",
-					n, (void *)(long)vh->lserv_wsi->sock);
-
-				return -1;
-			}
-			lws_libuv_io(vh->lserv_wsi, LWS_EV_START | LWS_EV_READ);
-		}
+		if (lws_uv_initvhost(vh, vh->lserv_wsi) == -1)
+			return -1;
 		vh = vh->vhost_next;
 	}
 
-	uv_timer_init(pt->io_loop_uv, &pt->uv_timeout_watcher);
-	uv_timer_start(&pt->uv_timeout_watcher, lws_uv_timeout_cb, 10, 1000);
+	if (first) {
+		uv_timer_init(pt->io_loop_uv, &pt->uv_timeout_watcher);
+		uv_timer_start(&pt->uv_timeout_watcher, lws_uv_timeout_cb,
+			       10, 1000);
+	}
 
 	return status;
 }
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index 6162d55e2ec27d3957a3fd778aadf8b4b8458e06..6a3ad8cb697993e5648556785e27126df31173da 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -800,6 +800,8 @@ struct lws_vhost {
 	unsigned int user_supplied_ssl_ctx:1;
 #endif
 
+	unsigned int created_vhost_protocols:1;
+
 	unsigned char default_protocol_index;
 };
 
@@ -965,6 +967,8 @@ LWS_EXTERN void
 lws_libuv_run(const struct lws_context *context, int tsi);
 LWS_EXTERN void
 lws_libuv_destroyloop(struct lws_context *context, int tsi);
+LWS_EXTERN int
+lws_uv_initvhost(struct lws_vhost* vh, struct lws*);
 #define LWS_LIBUV_ENABLED(context) lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV)
 LWS_EXTERN void lws_feature_status_libuv(struct lws_context_creation_info *info);
 #else
diff --git a/lib/server.c b/lib/server.c
index f7e6fb42325adf06820627b92b655196ac52ef6e..d4a9d16ea5c7b834cc0a68a8ce5de7c23eb55672 100644
--- a/lib/server.c
+++ b/lib/server.c
@@ -153,6 +153,12 @@ lws_context_init_server(struct lws_context_creation_info *info,
 	wsi->listener = 1;
 
 	vhost->context->pt[m].wsi_listening = wsi;
+
+#ifdef LWS_USE_LIBUV
+	if (LWS_LIBUV_ENABLED(vhost->context))
+		lws_uv_initvhost(vhost, wsi);
+#endif
+
 	if (insert_wsi_socket_into_fds(vhost->context, wsi))
 		goto bail;