diff --git a/package/libgluonutil/Makefile b/package/libgluonutil/Makefile
index 489a9ba9916771923491b1afea4c24419b401e2d..2536727c2dc0a3d949a465b61a324a92d458d4e0 100644
--- a/package/libgluonutil/Makefile
+++ b/package/libgluonutil/Makefile
@@ -16,7 +16,7 @@ define Package/libgluonutil
   SECTION:=libs
   CATEGORY:=Libraries
   TITLE:=Gluon utility library
-  DEPENDS:=+libjson-c
+  DEPENDS:=+libjson-c +libuci
 endef
 
 CMAKE_OPTIONS += \
diff --git a/package/libgluonutil/src/CMakeLists.txt b/package/libgluonutil/src/CMakeLists.txt
index 7df17b1a3c651b9249e0258cf0251431d4101985..41dd038a41dac66699a5e3632628554596bef693 100644
--- a/package/libgluonutil/src/CMakeLists.txt
+++ b/package/libgluonutil/src/CMakeLists.txt
@@ -6,7 +6,7 @@ set_property(DIRECTORY PROPERTY COMPILE_DEFINITIONS _GNU_SOURCE)
 
 add_library(gluonutil SHARED libgluonutil.c)
 set_property(TARGET gluonutil PROPERTY COMPILE_FLAGS "-Wall -std=c99")
-target_link_libraries(gluonutil json-c)
+target_link_libraries(gluonutil json-c uci)
 install(TARGETS gluonutil
   ARCHIVE DESTINATION lib
   LIBRARY DESTINATION lib
diff --git a/package/libgluonutil/src/libgluonutil.c b/package/libgluonutil/src/libgluonutil.c
index db46b9c90a2a32d4709f1efcf85e714a3261a89e..0f4bfe4a05d00d4015be5dcd15c169a45fdd1798 100644
--- a/package/libgluonutil/src/libgluonutil.c
+++ b/package/libgluonutil/src/libgluonutil.c
@@ -27,11 +27,44 @@
 #include "libgluonutil.h"
 
 #include <json-c/json.h>
+#include <uci.h>
 #include <arpa/inet.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <unistd.h>
+
+/**
+ * Merges two JSON objects
+ *
+ * Both objects are consumed. On conflicts, object b will be preferred.
+ */
+static struct json_object * merge_json(struct json_object *a, struct json_object *b) {
+	if (!json_object_is_type(a, json_type_object) || !json_object_is_type(b, json_type_object)) {
+		json_object_put(a);
+		return b;
+	}
+
+	json_object *m = json_object_new_object();
+
+	json_object_object_foreach(a, key_a, val_a)
+		json_object_object_add(m, key_a, json_object_get(val_a));
+	json_object_put(a);
 
+	json_object_object_foreach(b, key_b, val_b) {
+		struct json_object *val_m;
+
+		if (json_object_object_get_ex(m, key_b, &val_m))
+			val_m = merge_json(json_object_get(val_m), json_object_get(val_b));
+		else
+			val_m = json_object_get(val_b);
+
+		json_object_object_add(m, key_b, val_m);
+	}
+	json_object_put(b);
+
+	return m;
+}
 
 char * gluonutil_read_line(const char *filename) {
 	FILE *f = fopen(filename, "r");
@@ -141,6 +174,75 @@ bool gluonutil_get_node_prefix6(struct in6_addr *prefix) {
 }
 
 
+
+bool gluonutil_has_domains(void) {
+	return (access("/lib/gluon/domains/", F_OK) == 0);
+}
+
+char * gluonutil_get_domain(void) {
+	if (!gluonutil_has_domains())
+		return NULL;
+
+	char *ret = NULL;
+
+	struct uci_context *ctx = uci_alloc_context();
+	if (!ctx)
+		goto uci_fail;
+
+	ctx->flags &= ~UCI_FLAG_STRICT;
+
+	struct uci_package *p;
+	if (uci_load(ctx, "gluon", &p))
+		goto uci_fail;
+
+	struct uci_section *s = uci_lookup_section(ctx, p, "core");
+	if (!s)
+		goto uci_fail;
+
+	const char *domain_code = uci_lookup_option_string(ctx, s, "domain");
+	if (!domain_code)
+		goto uci_fail;
+
+	ret = strdup(domain_code);
+
+uci_fail:
+	if (ctx)
+		uci_free_context(ctx);
+
+	return ret;
+}
+
+
 struct json_object * gluonutil_load_site_config(void) {
-	return json_object_from_file("/lib/gluon/site.json");
+	char *domain_code = NULL;
+	struct json_object *site = NULL, *domain = NULL;
+
+	site = json_object_from_file("/lib/gluon/site.json");
+	if (!site)
+		return NULL;
+
+	if (!gluonutil_has_domains())
+		return site;
+
+	domain_code = gluonutil_get_domain();
+	if (!domain_code)
+		goto err;
+
+	{
+		const char *domain_path_fmt = "/lib/gluon/domains/%s.json";
+		char domain_path[strlen(domain_path_fmt) + strlen(domain_code)];
+		snprintf(domain_path, sizeof(domain_path), domain_path_fmt, domain_code);
+		free(domain_code);
+
+		domain = json_object_from_file(domain_path);
+	}
+	if (!domain)
+		goto err;
+
+	return merge_json(site, domain);
+
+err:
+	json_object_put(site);
+	free(domain_code);
+	return NULL;
 }
diff --git a/package/libgluonutil/src/libgluonutil.h b/package/libgluonutil/src/libgluonutil.h
index b2f90d699da759b58e1adfed59f94891f954fe7c..39b253baa4348b8d73a284dac098895a670c9b7e 100644
--- a/package/libgluonutil/src/libgluonutil.h
+++ b/package/libgluonutil/src/libgluonutil.h
@@ -40,6 +40,8 @@ bool gluonutil_get_node_prefix6(struct in6_addr *prefix);
 struct json_object * gluonutil_wrap_string(const char *str);
 struct json_object * gluonutil_wrap_and_free_string(char *str);
 
+bool gluonutil_has_domains(void);
+char * gluonutil_get_domain(void);
 struct json_object * gluonutil_load_site_config(void);
 
 #endif /* _LIBGLUON_LIBGLUON_H_ */