diff --git a/README.lwsws.md b/README.lwsws.md
index 28cf5c14..63b02668 100644
--- a/README.lwsws.md
+++ b/README.lwsws.md
@@ -284,6 +284,19 @@ To help that happen conveniently, there are some new apis
 dumb increment, mirror and status protocol plugins are provided as examples.
 
 
+Additional plugin search paths
+------------------------------
+
+Packages that have their own lws plugins can install them in their own
+preferred dir and ask lwsws to scan there by using a config fragment
+like this, in its own conf.d/ file managed by the other package
+
+{
+  "global": {
+   "plugin-dir": "/usr/local/share/coherent-timeline/plugins"
+  }
+}
+
 
 lws-server-status plugin
 ------------------------
diff --git a/lib/libuv.c b/lib/libuv.c
index b00d2a87..a230b57f 100644
--- a/lib/libuv.c
+++ b/lib/libuv.c
@@ -416,7 +416,7 @@ lws_libuv_closehandle(struct lws *wsi)
 #if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
 
 LWS_VISIBLE int
-lws_plat_plugins_init(struct lws_context * context, const char *d)
+lws_plat_plugins_init(struct lws_context * context, const char * const *d)
 {
 	struct lws_plugin_capability lcaps;
 	struct lws_plugin *plugin;
@@ -434,65 +434,71 @@ lws_plat_plugins_init(struct lws_context * context, const char *d)
 
 	uv_loop_init(&loop);
 
-	if (!uv_fs_scandir(&loop, &req, d, 0, NULL)) {
-		lwsl_err("Scandir on %s failed\n", d);
-		return 1;
-	}
-
 	lwsl_notice("  Plugins:\n");
 
-	while (uv_fs_scandir_next(&req, &dent) != UV_EOF) {
-		if (strlen(dent.name) < 7)
+	while (d && *d) {
+
+		lwsl_notice("  Scanning %s\n", *d);
+		m =uv_fs_scandir(&loop, &req, *d, 0, NULL);
+		if (m < 1) {
+			lwsl_err("Scandir on %s failed\n", *d);
+			return 1;
+		}
+
+		while (uv_fs_scandir_next(&req, &dent) != UV_EOF) {
+			if (strlen(dent.name) < 7)
+				continue;
+
+			lwsl_notice("   %s\n", dent.name);
+
+			snprintf(path, sizeof(path) - 1, "%s/%s", *d, dent.name);
+			if (uv_dlopen(path, &lib)) {
+				uv_dlerror(&lib);
+				lwsl_err("Error loading DSO: %s\n", lib.errmsg);
+				goto bail;
+			}
+			/* we could open it, can we get his init function? */
+			m = snprintf(path, sizeof(path) - 1, "init_%s",
+				     dent.name + 3 /* snip lib... */);
+			path[m - 3] = '\0'; /* snip the .so */
+			if (uv_dlsym(&lib, path, &v)) {
+				uv_dlerror(&lib);
+				lwsl_err("Failed to get init on %s: %s",
+						dent.name, lib.errmsg);
+				goto bail;
+			}
+			initfunc = (lws_plugin_init_func)v;
+			lcaps.api_magic = LWS_PLUGIN_API_MAGIC;
+			m = initfunc(context, &lcaps);
+			if (m) {
+				lwsl_err("Initializing %s failed %d\n", dent.name, m);
+				goto skip;
+			}
+
+			plugin = lws_malloc(sizeof(*plugin));
+			if (!plugin) {
+				lwsl_err("OOM\n");
+				goto bail;
+			}
+			plugin->list = context->plugin_list;
+			context->plugin_list = plugin;
+			strncpy(plugin->name, dent.name, sizeof(plugin->name) - 1);
+			plugin->name[sizeof(plugin->name) - 1] = '\0';
+			plugin->lib = lib;
+			plugin->caps = lcaps;
+			context->plugin_protocol_count += lcaps.count_protocols;
+			context->plugin_extension_count += lcaps.count_extensions;
+
 			continue;
 
-		lwsl_notice("   %s\n", dent.name);
-
-		snprintf(path, sizeof(path) - 1, "%s/%s", d, dent.name);
-		if (uv_dlopen(path, &lib)) {
-			uv_dlerror(&lib);
-			lwsl_err("Error loading DSO: %s\n", lib.errmsg);
-			goto bail;
-		}
-		/* we could open it, can we get his init function? */
-		m = snprintf(path, sizeof(path) - 1, "init_%s",
-			     dent.name + 3 /* snip lib... */);
-		path[m - 3] = '\0'; /* snip the .so */
-		if (uv_dlsym(&lib, path, &v)) {
-			uv_dlerror(&lib);
-			lwsl_err("Failed to get init on %s: %s",
-					dent.name, lib.errmsg);
-			goto bail;
-		}
-		initfunc = (lws_plugin_init_func)v;
-		lcaps.api_magic = LWS_PLUGIN_API_MAGIC;
-		m = initfunc(context, &lcaps);
-		if (m) {
-			lwsl_err("Initializing %s failed %d\n", dent.name, m);
-			goto skip;
-		}
-
-		plugin = lws_malloc(sizeof(*plugin));
-		if (!plugin) {
-			lwsl_err("OOM\n");
-			goto bail;
-		}
-		plugin->list = context->plugin_list;
-		context->plugin_list = plugin;
-		strncpy(plugin->name, dent.name, sizeof(plugin->name) - 1);
-		plugin->name[sizeof(plugin->name) - 1] = '\0';
-		plugin->lib = lib;
-		plugin->caps = lcaps;
-		context->plugin_protocol_count += lcaps.count_protocols;
-		context->plugin_extension_count += lcaps.count_extensions;
-
-		continue;
-
 skip:
-		uv_dlclose(&lib);
+			uv_dlclose(&lib);
+		}
+bail:
+		uv_fs_req_cleanup(&req);
+		d++;
 	}
 
-bail:
-	uv_fs_req_cleanup(&req);
 	uv_loop_close(&loop);
 
 	return ret;
diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h
index 1f693461..82ed98d9 100644
--- a/lib/libwebsockets.h
+++ b/lib/libwebsockets.h
@@ -1478,8 +1478,8 @@ struct lws_http_mount {
  * @vhost_name: VHOST: name of vhost, must match external DNS name used to
  *		access the site, like "warmcat.com" as it's used to match
  *		Host: header and / or SNI name for SSL.
- * @plugins_dir: CONTEXT: directory to scan for lws protocol plugins at
- *		context creation time
+ * @plugin_dirs: CONTEXT: NULL, or NULL-terminated array of directories to
+ *		scan for lws protocol plugins at context creation time
  * @pvo:	VHOST: pointer to optional linked list of per-vhost
  *		options made accessible to protocols
  * @keepalive_timeout: VHOST: (default = 0 = 60s) seconds to allow remote
@@ -1525,7 +1525,7 @@ struct lws_context_creation_info {
 	unsigned int timeout_secs;			/* VH */
 	const char *ecdh_curve;				/* VH */
 	const char *vhost_name;				/* VH */
-	const char *plugins_dir;			/* context */
+	const char * const *plugin_dirs;		/* context */
 	const struct lws_protocol_vhost_options *pvo;	/* VH */
 	int keepalive_timeout;				/* VH */
 	const char *log_filepath;			/* VH */
diff --git a/lib/lws-plat-unix.c b/lib/lws-plat-unix.c
index e4894fa0..98b6c588 100644
--- a/lib/lws-plat-unix.c
+++ b/lib/lws-plat-unix.c
@@ -306,7 +306,7 @@ static int filter(const struct dirent *ent)
 }
 
 LWS_VISIBLE int
-lws_plat_plugins_init(struct lws_context * context, const char *d)
+lws_plat_plugins_init(struct lws_context * context, const char * const *d)
 {
 	struct lws_plugin_capability lcaps;
 	struct lws_plugin *plugin;
@@ -316,70 +316,73 @@ lws_plat_plugins_init(struct lws_context * context, const char *d)
 	char path[256];
 	void *l;
 
-
-	n = scandir(d, &namelist, filter, alphasort);
-	if (n < 0) {
-		lwsl_err("Scandir on %s failed\n", d);
-		return 1;
-	}
-
 	lwsl_notice("  Plugins:\n");
 
-	for (i = 0; i < n; i++) {
-		if (strlen(namelist[i]->d_name) < 7)
-			goto inval;
-
-		lwsl_notice("   %s\n", namelist[i]->d_name);
-
-		snprintf(path, sizeof(path) - 1, "%s/%s", d,
-			 namelist[i]->d_name);
-		l = dlopen(path, RTLD_NOW);
-		if (!l) {
-			lwsl_err("Error loading DSO: %s\n", dlerror());
-			while (i++ < n)
-				free(namelist[i]);
-			goto bail;
+	while (d && *d) {
+		n = scandir(*d, &namelist, filter, alphasort);
+		if (n < 0) {
+			lwsl_err("Scandir on %s failed\n", *d);
+			return 1;
 		}
-		/* we could open it, can we get his init function? */
-		m = snprintf(path, sizeof(path) - 1, "init_%s",
-			     namelist[i]->d_name + 3 /* snip lib... */);
-		path[m - 3] = '\0'; /* snip the .so */
-		initfunc = dlsym(l, path);
-		if (!initfunc) {
-			lwsl_err("Failed to get init on %s: %s",
-					namelist[i]->d_name, dlerror());
+
+		for (i = 0; i < n; i++) {
+			if (strlen(namelist[i]->d_name) < 7)
+				goto inval;
+
+			lwsl_notice("   %s\n", namelist[i]->d_name);
+
+			snprintf(path, sizeof(path) - 1, "%s/%s", *d,
+				 namelist[i]->d_name);
+			l = dlopen(path, RTLD_NOW);
+			if (!l) {
+				lwsl_err("Error loading DSO: %s\n", dlerror());
+				while (i++ < n)
+					free(namelist[i]);
+				goto bail;
+			}
+			/* we could open it, can we get his init function? */
+			m = snprintf(path, sizeof(path) - 1, "init_%s",
+				     namelist[i]->d_name + 3 /* snip lib... */);
+			path[m - 3] = '\0'; /* snip the .so */
+			initfunc = dlsym(l, path);
+			if (!initfunc) {
+				lwsl_err("Failed to get init on %s: %s",
+						namelist[i]->d_name, dlerror());
+				dlclose(l);
+			}
+			lcaps.api_magic = LWS_PLUGIN_API_MAGIC;
+			m = initfunc(context, &lcaps);
+			if (m) {
+				lwsl_err("Initializing %s failed %d\n",
+					namelist[i]->d_name, m);
+				dlclose(l);
+				goto skip;
+			}
+
+			plugin = lws_malloc(sizeof(*plugin));
+			if (!plugin) {
+				lwsl_err("OOM\n");
+				goto bail;
+			}
+			plugin->list = context->plugin_list;
+			context->plugin_list = plugin;
+			strncpy(plugin->name, namelist[i]->d_name, sizeof(plugin->name) - 1);
+			plugin->name[sizeof(plugin->name) - 1] = '\0';
+			plugin->l = l;
+			plugin->caps = lcaps;
+			context->plugin_protocol_count += lcaps.count_protocols;
+			context->plugin_extension_count += lcaps.count_extensions;
+
+			free(namelist[i]);
+			continue;
+
+	skip:
 			dlclose(l);
+	inval:
+			free(namelist[i]);
 		}
-		lcaps.api_magic = LWS_PLUGIN_API_MAGIC;
-		m = initfunc(context, &lcaps);
-		if (m) {
-			lwsl_err("Initializing %s failed %d\n",
-				namelist[i]->d_name, m);
-			dlclose(l);
-			goto skip;
-		}
-
-		plugin = lws_malloc(sizeof(*plugin));
-		if (!plugin) {
-			lwsl_err("OOM\n");
-			goto bail;
-		}
-		plugin->list = context->plugin_list;
-		context->plugin_list = plugin;
-		strncpy(plugin->name, namelist[i]->d_name, sizeof(plugin->name) - 1);
-		plugin->name[sizeof(plugin->name) - 1] = '\0';
-		plugin->l = l;
-		plugin->caps = lcaps;
-		context->plugin_protocol_count += lcaps.count_protocols;
-		context->plugin_extension_count += lcaps.count_extensions;
-
-		free(namelist[i]);
-		continue;
-
-skip:
-		dlclose(l);
-inval:
-		free(namelist[i]);
+		free(namelist);
+		d++;
 	}
 
 bail:
@@ -707,8 +710,8 @@ lws_plat_init(struct lws_context *context,
 	context->fops.write	= _lws_plat_file_write;
 
 #ifdef LWS_WITH_PLUGINS
-	if (info->plugins_dir)
-		lws_plat_plugins_init(context, info->plugins_dir);
+	if (info->plugin_dirs)
+		lws_plat_plugins_init(context, info->plugin_dirs);
 #endif
 
 	return 0;
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index 91f4d757..df2bbf64 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -770,7 +770,7 @@ LWS_EXTERN void
 lws_libuv_closehandle(struct lws *wsi);
 
 LWS_VISIBLE LWS_EXTERN int
-lws_plat_plugins_init(struct lws_context * context, const char *d);
+lws_plat_plugins_init(struct lws_context * context, const char * const *d);
 
 LWS_VISIBLE LWS_EXTERN int
 lws_plat_plugins_destroy(struct lws_context * context);
diff --git a/lwsws/conf.c b/lwsws/conf.c
index 31d38f85..f222ed64 100644
--- a/lwsws/conf.c
+++ b/lwsws/conf.c
@@ -27,6 +27,7 @@ static const char * const paths_global[] = {
 	"global.count-threads",
 	"global.init-ssl",
 	"global.server-string",
+	"global.plugin-dir"
 };
 
 enum lejp_global_paths {
@@ -35,6 +36,7 @@ enum lejp_global_paths {
 	LEJPGP_COUNT_THREADS,
 	LWJPGP_INIT_SSL,
 	LEJPGP_SERVER_STRING,
+	LEJPGP_PLUGIN_DIR
 };
 
 static const char * const paths_vhosts[] = {
@@ -91,6 +93,8 @@ enum lejp_vhost_paths {
 	LEJPVP_KEEPALIVE_TIMEOUT,
 };
 
+#define MAX_PLUGIN_DIRS 10
+
 struct jpargs {
 	struct lws_context_creation_info *info;
 	struct lws_context *context;
@@ -101,6 +105,8 @@ struct jpargs {
 
 	struct lws_protocol_vhost_options *pvo;
 	struct lws_http_mount m;
+	const char **plugin_dirs;
+	int count_plugin_dirs;
 };
 
 static void *
@@ -154,6 +160,13 @@ lejp_globals_cb(struct lejp_ctx *ctx, char reason)
 	case LEJPGP_SERVER_STRING:
 		a->info->server_string = a->p;
 		break;
+	case LEJPGP_PLUGIN_DIR:
+		if (a->count_plugin_dirs == MAX_PLUGIN_DIRS - 1) {
+			lwsl_err("Too many plugin dirs\n");
+			return -1;
+		}
+		a->plugin_dirs[a->count_plugin_dirs++] = a->p;
+		break;
 
 	default:
 		return 0;
@@ -537,12 +550,27 @@ lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d,
 			 char **cs, int *len)
 {
 	struct jpargs a;
+	const char * const *old = info->plugin_dirs;
+
+	memset(&a, 0, sizeof(a));
 
 	a.info = info;
 	a.p = *cs;
 	a.end = (a.p + *len) - 1;
 	a.valid = 0;
 
+	lwsws_align(&a);
+	info->plugin_dirs = (void *)a.p;
+	a.plugin_dirs = (void *)a.p; /* writeable version */
+	a.p += MAX_PLUGIN_DIRS * sizeof(void *);
+
+	/* copy any default paths */
+
+	while (old && *old) {
+		a.plugin_dirs[a.count_plugin_dirs++] = *old;
+		old++;
+	}
+
 	if (lwsws_get_config(&a, "/etc/lwsws/conf", paths_global,
 			     ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
 		return 1;
@@ -550,6 +578,8 @@ lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d,
 			       ARRAY_SIZE(paths_global), lejp_globals_cb) > 1)
 		return 1;
 
+	a.plugin_dirs[a.count_plugin_dirs] = NULL;
+
 	*cs = a.p;
 	*len = a.end - a.p;
 
@@ -563,6 +593,8 @@ lwsws_get_config_vhosts(struct lws_context *context,
 {
 	struct jpargs a;
 
+	memset(&a, 0, sizeof(a));
+
 	a.info = info;
 	a.p = *cs;
 	a.end = a.p + *len;
diff --git a/lwsws/main.c b/lwsws/main.c
index 8d84552b..2a7579fc 100644
--- a/lwsws/main.c
+++ b/lwsws/main.c
@@ -80,6 +80,11 @@ static const struct lws_extension exts[] = {
 	{ NULL, NULL, NULL /* terminator */ }
 };
 
+static const char * const plugin_dirs[] = {
+		INSTALL_DATADIR"/libwebsockets-test-server/plugins/",
+		NULL
+};
+
 static struct option options[] = {
 	{ "help",	no_argument,		NULL, 'h' },
 	{ "debug",	required_argument,	NULL, 'd' },
@@ -107,6 +112,8 @@ void signal_cb(uv_signal_t *watcher, int signum)
 }
 #endif
 
+
+
 int main(int argc, char **argv)
 {
 	struct lws_context_creation_info info;
@@ -184,8 +191,7 @@ int main(int argc, char **argv)
 			      LWS_SERVER_OPTION_EXPLICIT_VHOSTS |
 			      LWS_SERVER_OPTION_LIBUV;
 
-	info.plugins_dir = INSTALL_DATADIR"/libwebsockets-test-server/plugins/";
-
+	info.plugin_dirs = plugin_dirs;
 	lwsl_notice("Using config dir: \"%s\"\n", config_dir);
 
 	/*
diff --git a/test-server/test-server-v2.0.c b/test-server/test-server-v2.0.c
index 28a9264a..8702049b 100644
--- a/test-server/test-server-v2.0.c
+++ b/test-server/test-server-v2.0.c
@@ -155,6 +155,11 @@ static const struct option options[] = {
 	{ NULL, 0, 0, 0 }
 };
 
+static const char * const plugin_dirs[] = {
+		INSTALL_DATADIR"/libwebsockets-test-server/plugins/",
+		NULL
+};
+
 int main(int argc, char **argv)
 {
 	struct lws_context_creation_info info;
@@ -344,7 +349,7 @@ int main(int argc, char **argv)
 			       "!AES256-SHA256";
 
 	/* tell lws to look for protocol plugins here */
-	info.plugins_dir = INSTALL_DATADIR"/libwebsockets-test-server/plugins/";
+	info.plugin_dirs = plugin_dirs;
 
 	/* tell lws about our mount we want */
 	info.mounts = &mount;