diff --git a/contrib/ci/olsr-site/i18n b/contrib/ci/olsr-site/i18n
new file mode 120000
index 0000000000000000000000000000000000000000..57a3c3977ac165a8c413fcebee2a9840e564e26f
--- /dev/null
+++ b/contrib/ci/olsr-site/i18n
@@ -0,0 +1 @@
+../minimal-site/i18n
\ No newline at end of file
diff --git a/contrib/ci/olsr-site/modules b/contrib/ci/olsr-site/modules
new file mode 120000
index 0000000000000000000000000000000000000000..72d21398d0d4711668d34d5f58668993a6eaec99
--- /dev/null
+++ b/contrib/ci/olsr-site/modules
@@ -0,0 +1 @@
+../minimal-site/modules
\ No newline at end of file
diff --git a/contrib/ci/olsr-site/site.conf b/contrib/ci/olsr-site/site.conf
new file mode 100644
index 0000000000000000000000000000000000000000..868d3d569d665f6d99335dde4f9a9c4115ade727
--- /dev/null
+++ b/contrib/ci/olsr-site/site.conf
@@ -0,0 +1,176 @@
+-- This is an example site configuration for Gluon v2022.1
+--
+-- Take a look at the documentation located at
+-- https://gluon.readthedocs.io/ for details.
+--
+-- This configuration will not work as is. You're required to make
+-- community specific changes to it!
+{
+  -- Used for generated hostnames, e.g. freifunk-abcdef123456. (optional)
+  -- hostname_prefix = 'freifunk-',
+
+  -- Name of the community.
+  site_name = 'Continuous Integration',
+
+  -- Shorthand of the community.
+  site_code = 'ci',
+
+  -- 32 bytes of random data, encoded in hexadecimal
+  -- This data must be unique among all sites and domains!
+  -- Can be generated using: echo $(hexdump -v -n 32 -e '1/1 "%02x"' </dev/urandom)
+  domain_seed = 'e9608c4ff338b920992d629190e9ff11049de1dfc3f299eac07792dfbcda341c',
+
+  -- Prefixes used by clients within the mesh.
+  -- prefix6 is required, prefix4 can be omitted if next_node.ip4
+  -- is not set.
+  prefix6 = 'fdff:cafe:cafe:cafe::/64',
+
+  -- Prefixes used by nodes within the mesh
+  node_prefix6 = 'fdff:cafe:cafe:cafe::/64',
+
+  -- Timezone of your community.
+  -- See https://openwrt.org/docs/guide-user/base-system/system_configuration#time_zones
+  timezone = 'CET-1CEST,M3.5.0,M10.5.0/3',
+
+  -- List of NTP servers in your community.
+  -- Must be reachable using IPv6!
+  --  ntp_servers = {'1.ntp.services.ffxx'},
+
+  -- Wireless regulatory domain of your community.
+  regdom = 'DE',
+
+  -- Wireless configuration for 2.4 GHz interfaces.
+  wifi24 = {
+    -- Wireless channel.
+    channel = 1,
+
+    -- ESSIDs used for client network.
+    ap = {
+      ssid = 'gluon-ci-ssid',
+      -- disabled = true, -- (optional)
+
+      -- Configuration for a backward compatible OWE network below.
+      owe_ssid = 'owe.gluon-ci-ssid', -- (optional - SSID for OWE client network)
+      owe_transition_mode = true, -- (optional - enables transition-mode - requires ssid as well as owe_ssid)
+    },
+
+    mesh = {
+      -- Adjust these values!
+      id = 'ueH3uXjdp', -- usually you don't want users to connect to this mesh-SSID, so use a cryptic id that no one will accidentally mistake for the client WiFi
+      mcast_rate = 12000,
+      -- disabled = true, -- (optional)
+    },
+  },
+
+  -- Wireless configuration for 5 GHz interfaces.
+  -- This should be equal to the 2.4 GHz variant, except
+  -- for channel.
+  wifi5 = {
+    channel = 44,
+    outdoor_chanlist = '100-140',
+    ap = {
+      ssid = 'gluon-ci-ssid',
+      -- disabled = true, -- (optional)
+
+      -- Configuration for a backward compatible OWE network below.
+      owe_ssid = 'owe.gluon-ci-ssid', -- (optional - SSID for OWE client network)
+      owe_transition_mode = true, -- (optional - enables transition-mode - requires ssid as well as owe_ssid)
+    },
+    mesh = {
+      -- Adjust these values!
+      id = 'ueH3uXjdp',
+      mcast_rate = 12000,
+    },
+  },
+
+
+  -- The next node feature allows clients to always reach the node it is
+  -- connected to using a known IP address.
+  next_node = {
+    -- anycast IPs of all nodes
+    name = { 'nextnode.location.community.example.org', 'nextnode', 'nn' },
+    ip4 = '10.0.0.1',
+    ip6 = 'fd::1',
+  },
+
+  -- Options specific to routing protocols (optional)
+  mesh = {
+    vxlan = true,
+    olsrd = {},
+  },
+
+  mesh_vpn = {
+    -- enabled = true,
+
+    fastd = {
+      -- Refer to https://fastd.readthedocs.io/en/latest/ to better understand
+      -- what these options do.
+
+      -- List of crypto-methods to use.
+      methods = {'salsa2012+umac'},
+      mtu = 1312,
+      -- configurable = true,
+      -- syslog_level = 'warn',
+
+      groups = {
+        backbone = {
+          -- Limit number of connected peers to reduce bandwidth.
+          limit = 1,
+
+          -- List of peers.
+          peers = {
+          },
+
+          -- Optional: nested peer groups
+          -- groups = {
+            -- backbone_sub = {
+              -- ...
+            -- },
+          -- ...
+          -- },
+        },
+        -- Optional: additional peer groups, possibly with other limits
+        -- backbone2 = {
+          -- ...
+        -- },
+      },
+    },
+
+    bandwidth_limit = {
+      -- The bandwidth limit can be enabled by default here.
+      enabled = false,
+
+      -- Default upload limit (kbit/s).
+      egress = 200,
+
+      -- Default download limit (kbit/s).
+      ingress = 3000,
+    },
+  },
+
+  autoupdater = {
+    -- Default branch (optional), can be overridden by setting GLUON_AUTOUPDATER_BRANCH when building.
+    -- Set GLUON_AUTOUPDATER_ENABLED to enable the autoupdater by default for newly installed nodes.
+    branch = 'stable',
+
+    -- List of branches. You may define multiple branches.
+    branches = {
+      stable = {
+        name = 'stable',
+
+        -- List of mirrors to fetch images from. IPv6 required!
+        mirrors = {'http://1.updates.services.ffhl/stable/sysupgrade'},
+
+        -- Number of good signatures required.
+        -- Have multiple maintainers sign your build and only
+        -- accept it when a sufficient number of them have
+        -- signed it.
+        good_signatures = 0,
+
+        -- List of public keys of maintainers.
+        pubkeys = {
+        },
+      },
+    },
+  },
+}
diff --git a/contrib/ci/olsr-site/site.mk b/contrib/ci/olsr-site/site.mk
new file mode 100644
index 0000000000000000000000000000000000000000..8b4a5a434a5f8415c03dfaef8239d03f3686f103
--- /dev/null
+++ b/contrib/ci/olsr-site/site.mk
@@ -0,0 +1,57 @@
+##	gluon site.mk makefile example
+
+##	GLUON_FEATURES
+#		Specify Gluon features/packages to enable;
+#		Gluon will automatically enable a set of packages
+#		depending on the combination of features listed
+
+GLUON_FEATURES := \
+	autoupdater \
+	ebtables-filter-multicast \
+	ebtables-filter-ra-dhcp \
+	ebtables-limit-arp \
+	mesh-olsrd \
+	mesh-vpn-fastd \
+	respondd \
+	status-page \
+	web-advanced \
+	web-wizard
+
+GLUON_FEATURES_standard := \
+  wireless-encryption-wpa3
+
+##	GLUON_SITE_PACKAGES
+#		Specify additional Gluon/OpenWrt packages to include here;
+#		A minus sign may be prepended to remove a packages from the
+#		selection that would be enabled by default or due to the
+#		chosen feature flags
+
+GLUON_SITE_PACKAGES := iwinfo
+
+##	DEFAULT_GLUON_RELEASE
+#		version string to use for images
+#		gluon relies on
+#			opkg compare-versions "$1" '>>' "$2"
+#		to decide if a version is newer or not.
+
+DEFAULT_GLUON_RELEASE := 0.6+exp$(shell date '+%Y%m%d')
+
+# Variables set with ?= can be overwritten from the command line
+
+##	GLUON_RELEASE
+#		call make with custom GLUON_RELEASE flag, to use your own release version scheme.
+#		e.g.:
+#			$ make images GLUON_RELEASE=23.42+5
+#		would generate images named like this:
+#			gluon-ff%site_code%-23.42+5-%router_model%.bin
+
+GLUON_RELEASE ?= $(DEFAULT_GLUON_RELEASE)
+
+# Default priority for updates.
+GLUON_PRIORITY ?= 0
+
+# Region code required for some images; supported values: us eu
+GLUON_REGION ?= eu
+
+# Languages to include
+GLUON_LANGS ?= en de