diff --git a/inc/lektor/reg.h b/inc/lektor/reg.h
index 50049e703f5da7e27fd324c65586af08b08a0ff3..e64b641479d9e1d948794bb5af50a44872bd9e0c 100644
--- a/inc/lektor/reg.h
+++ b/inc/lektor/reg.h
@@ -1,4 +1,4 @@
-#pragma once
+#if ! defined(__REG_H__)
 
 struct lkt_state;
 
@@ -9,18 +9,28 @@ struct module_reg {
     void (*func)(void);
 };
 
-extern struct module_reg *reg;
-
 #define REG_BEGIN(reg)          struct module_reg reg[] = {
 #define REG_ADD(__f)            { .name = #__f,  .func = (void(*)(void)) __f    },
 #define REG_ADD_NAMED(__n, __f) { .name = __n,   .func = (void(*)(void)) __f    },
 #define REG_END()               { .name = NULL,  .func = NULL                   } };
 
+#if ! defined(_STATIC_MODULES)
+#define REG_EXPORT(__reg)       struct module_reg *__reg__ = __reg;
+#else
+#define REG_EXPORT(__reg)
+#endif
+
 /* If handle is NULL, file is unused and the reg is red. Otherwise,
    we use dlfcn to search for the symbol which is returned. If *handle
    is NULL, it will be created by opening the file. */
 void *reg_pick(const char *file, void **handle, const char *symbol);
 
+/* Get the reg from a .so file. This reg must be exported by the
+   shared library with REG_EXPORT. Note that this reg is named `__reg__`,
+   thus no symbol must be named `__reg__` in the .so file.
+   Returns 0 on success, something else on error. */
+int reg_from_file(const char *file, struct module_reg *ret);
+
 /* Set the ref for this .a / .so file */
 void reg_set(struct module_reg *);
 
@@ -28,3 +38,5 @@ void reg_set(struct module_reg *);
    type is done, it is up to the user to check if the structure passed as a
    `void*` is the right structure. */
 int load_module_by_name(struct lkt_state *srv, const char *name, void *mod);
+
+#endif
diff --git a/src/module/module_sdl2.c b/src/module/module_sdl2.c
index 45b04f2333ec3fa3469e4eb512819f27670a029c..81292ef28a209cb417b98a0bf4a00a0ad17bd004 100644
--- a/src/module/module_sdl2.c
+++ b/src/module/module_sdl2.c
@@ -423,3 +423,4 @@ REG_ADD(module_sdl2_set_volume)
 REG_ADD(module_sdl2_get_duration)
 REG_ADD(module_sdl2_get_elapsed)
 REG_END()
+REG_EXPORT(sdl2_reg)
diff --git a/src/module/module_x11.c b/src/module/module_x11.c
index fcce96a6ab83517961665f2531a3386f4f1c96e9..061440ab2ad8e0dee9cac3634dc08ffaf9cfd32c 100644
--- a/src/module/module_x11.c
+++ b/src/module/module_x11.c
@@ -275,3 +275,4 @@ REG_ADD(module_x11_set_volume)
 REG_ADD(module_x11_get_duration)
 REG_ADD(module_x11_get_elapsed)
 REG_END()
+REG_EXPORT(x11_reg)
diff --git a/src/module/repo.c b/src/module/repo.c
index 7e9f6ceeab77907ac54fc84289fa7afda7a0c121..6d71daa95875d5094308fa96b6262a52c67a167e 100644
--- a/src/module/repo.c
+++ b/src/module/repo.c
@@ -17,6 +17,7 @@
 #include <mthread/mthread.h>
 #include <lektor/database.h>
 #include <lektor/net.h>
+#include <lektor/reg.h>
 
 static volatile unsigned int curl_init = false;
 
@@ -491,3 +492,8 @@ repo_update(struct lkt_repo *const repo)
 {
     return mthread_create(NULL, ATTR_DETACHED, __repo_get_all_id_async, repo);
 }
+
+REG_BEGIN(repo_reg)
+REG_ADD_NAMED("new", load_repo_https)
+REG_END()
+REG_EXPORT(repo_reg)