diff --git a/hosts.yml b/hosts.yml
index d2ad79fee6b9008ef0d11f211581c9aef3e209cd..dce8e8b97aa1d0be1290374e7b2392ae3577cab3 100644
--- a/hosts.yml
+++ b/hosts.yml
@@ -2,7 +2,7 @@ gateways:
   hosts:
     kaisertor:
     huextertor:
-    muehlentor:
+    # muehlentor:
   vars:
     ansible_python_interpreter: /usr/bin/env python2
     ansible_ssh_user: root
diff --git a/roles/base/files/bird/bird.conf b/roles/base/files/bird/bird.conf
new file mode 100644
index 0000000000000000000000000000000000000000..7c649e5fd0dd5914eb7faa44ddf7e169c81a3d3c
--- /dev/null
+++ b/roles/base/files/bird/bird.conf
@@ -0,0 +1,227 @@
+# debugging
+log syslog all;
+#debug protocols all;
+
+ipv6 table peering6;
+ipv6 table kernelcopy6;
+ipv6 table mesh6;
+ipv6 table transit6;
+
+roa6 table roa_icvpn6;
+
+protocol device {
+    scan time 10;
+}
+
+# host configuration
+#####################
+
+include "bird_host.conf";
+
+# constants
+############
+
+define OWNAS = 201173;
+define OWNMAGIC = 42;
+define KERNEL_TABLE = ipt_freifunk;
+
+# ROA table:
+#############
+# These tables are generated by a script in the icvpn-meta repository
+
+protocol static {
+    roa6 {table roa_icvpn6; };
+    include "roa6.con?";
+}
+
+
+# filter helpers
+#################
+
+function is_default()      { return net ~ [ ::/0 ]; }
+
+function is_freifunk()     { return net ~ [ 2001:bf7::/32+ ]; }
+function is_self()         { return net ~ [ fdef:ffc0:3dd7::/48+, 2001:67c:2d50::/48+, 2001:bf7:110::/44+ ]; }
+
+function is_self_mesh()    { return net ~ [ fdef:ffc0:3dd7::/64+, 2001:67c:2d50::/64+ ]; }
+function is_self_public()  { return net ~ [ 2001:67c:2d50::/48+ ]; }
+
+function is_global()       { return net ~ [ 2000::/3+ ]; }
+function is_ula()          { return net ~ [ fc00::/7{48,64} ]; }
+function is_self_mgmt()    { return net ~ [ 2001:67c:2d50:1::a82:7fe0/123+ ]; }
+
+
+
+# Filters:
+###########
+
+filter bgp_import_filter {
+    if is_self() then reject;
+    if is_ula() then accept;
+
+    if roa_check(roa_icvpn6) = ROA_VALID then {
+        accept;
+    } else {
+    #	print "ROA check failed for ", net, " ASN ", bgp_path.last;
+    }
+    accept;
+};
+
+
+
+# static routes
+################
+
+protocol static local_mesh6 {
+    ipv6 { table peering6; } ;
+    route fdef:ffc0:3dd7::/64 via "ffhl";
+    route 2001:67c:2d50::/64 via "ffhl";
+};
+
+protocol static local_freifunk {
+    ipv6 { table peering6; };
+    route fdef:ffc0:3dd7::/48 reject;
+    route 2001:67c:2d50::/48 reject;
+}
+
+
+# Kernel routing tables
+########################
+
+protocol kernel kernel_mesh6 {
+    scan time 20;
+    # device routes; # TODO: what is the equivalent in bird2?
+
+    kernel table KERNEL_TABLE;
+
+    ipv6 {
+        import none;
+        export filter {
+            if is_ula() then { krt_prefsrc = ULA_IP; accept; }
+            if is_self() then { krt_prefsrc = PUBLIC_IP; accept; }
+            if is_global() then accept;
+            reject;
+        };
+    };
+}
+
+protocol kernel {
+    kernel table KERNEL_TABLE;
+    scan time 20;
+    # device routes;
+
+    ipv6 {
+        table kernelcopy6;
+        import none;
+        export all;
+    };
+}
+
+
+# plumbing
+###########
+
+
+protocol pipe {
+    table master6;
+    peer table kernelcopy6;
+    import none;
+    export all;
+}
+
+protocol pipe {
+    table master6;
+    peer table peering6;
+    import all;
+    export none;
+}
+
+protocol pipe {
+    table master6;
+    peer table mesh6;
+    import where source != RTS_STATIC;
+    export where is_default() || is_self();
+}
+
+
+protocol pipe {
+    table master6;
+    peer table transit6;
+    import all;
+    export where is_self_public();
+}
+
+
+# static routes
+################
+
+protocol static unreachable_default {
+    ipv6 {
+        preference 0;
+    };
+
+    route ::/0 reject;
+}
+
+
+# IBGP
+#######
+
+template bgp bgp_ibgp {
+    local as OWNAS;
+    ipv6 {
+        table peering6;
+        import all;
+        export filter {
+            bgp_community.add((OWNMAGIC,1));
+            if source = RTS_BGP then accept;
+            accept;
+        };
+    };
+};
+
+
+# InterCity VPN peerings
+#########################
+# these templates are applied on the routes generated by the icvpn-meta script and included
+# From our icvpn peers, import everything that ist freifunk, dn42 or chaosvpn
+# but dont import our own routes. Announce all Freifunk and dn42 routes we have.
+# "but why don't we export ourself?". We do. is_freifunk() also covers 10.130.0.0/16
+
+
+template bgp bgp_icvpn {
+    ipv6 {
+        table peering6;
+        #import keep filtered;
+        import filter bgp_import_filter;
+        export all;
+    };
+
+    local as OWNAS;
+};
+
+
+# public IPv6
+##############
+
+template bgp bgp_public {
+    ipv6 {
+        table transit6;
+        import where !is_self() && is_global();
+        next hop self;
+        export where is_self_public();
+    };
+
+    local as OWNAS;
+}
+
+
+# Include local configuration
+# '?' instead of 'f' avoids failures when these
+# files do not exist
+################################################
+
+include "bird_local.con?";
+include "bird_ibgp.con?";
+include "bird6_icvpn.con?";
+include "bird_ffrhein.con?";
diff --git a/roles/base/files/etc/bird/password.conf b/roles/base/files/bird/password.conf
similarity index 100%
rename from roles/base/files/etc/bird/password.conf
rename to roles/base/files/bird/password.conf
diff --git a/roles/base/files/etc/bird/bird.conf b/roles/base/files/etc/bird/bird.conf
deleted file mode 100644
index 248d072a3cffe3faa33a3a9c99d2951256a7ec67..0000000000000000000000000000000000000000
--- a/roles/base/files/etc/bird/bird.conf
+++ /dev/null
@@ -1,436 +0,0 @@
-# debugging
-log stderr all;
-
-ipv4 table peering4;
-ipv4 table kernelcopy4;
-ipv4 table mesh4;
-
-ipv6 table peering6;
-ipv6 table kernelcopy6;
-ipv6 table mesh6;
-ipv6 table transit6;
-
-roa6 table roa_icvpn6;
-roa4 table roa_icvpn4;
-
-protocol device {
-	scan time 10;
-}
-
-# host configuration
-#####################
-
-include "bird_host.conf";
-
-# constants
-############
-
-define OWNAS = 201173;
-define OWNMAGIC = 42;
-define KERNEL_TABLE = ipt_freifunk;
-
-
-
-# ROA table:
-#############
-# These tables are generated by a script in the icvpn-meta repository
-
-protocol static {
-	roa4 {table roa_icvpn4; };
-	include "roa4.con?";
-}
-
-protocol static {
-	roa6 {table roa_icvpn6; };
-	include "roa6.con?";
-}
-
-
-# filter helpers
-#################
-
-function is_default()      { return net ~ [ 0.0.0.0/0, ::/0          ]; }
-
-function is_freifunk()     { return net ~ [ 10.0.0.0/8+, 2001:bf7::/32+ ]; }
-function is_dn42()         { return net ~ [ 172.22.0.0/15+, 172.20.0.0/16+ ]; }
-function is_chaosvpn()     { return net ~ [ 172.31.0.0/16+     ]; }
-function is_self()         { return net ~ [ 10.130.0.0/16+, fdef:ffc0:3dd7::/48+, 2001:67c:2d50::/48+, 2001:bf7:110::/44+ ]; }
-
-function is_self_mesh()    { return net ~ [ 10.130.16.0/20+, 10.130.32.0/20+, fdef:ffc0:3dd7::/64+, 2001:67c:2d50::/64+ ]; }
-function is_self_static()  { return net ~ [ 10.130.0.0/20+ ]; }
-function is_self_private() { return net ~ [ 10.130.64.0/18+, 10.130.128.0/17 ]; }
-function is_self_public()  { return net ~ [ 2001:67c:2d50::/48+ ]; }
-
-function is_global()       { return net ~ [ 2000::/3+           ]; }
-function is_ula()          { return net ~ [ fc00::/7{48,64}     ]; }
-function is_self_mgmt()    { return net ~ [ 10.130.127.224/27+, 2001:67c:2d50:1::a82:7fe0/123+ ]; }
-
-
-
-# Filters:
-###########
-
-filter bgp_import_filter {
-	if is_self() then reject;
-	if is_ula() then accept;
-
-	if roa_check(roa_icvpn4) = ROA_VALID || roa_check(roa_icvpn6) = ROA_VALID then {
-		accept;
-	} else {
-		print "ROA check failed for ", net, " ASN ", bgp_path.last;
-	}
-	accept;
-};
-
-
-
-# static routes
-################
-
-protocol static static_mesh4 {
-	ipv4 { table peering4; };
-	route 10.130.0.0/16 reject;
-};
-
-
-
-protocol static local_mesh4 {
-	ipv4;
-	route 10.130.0.0/16 via "ffhl";
-};
-
-
-protocol static local_mesh6 {
-	ipv6 { table peering6; } ;
-	route fdef:ffc0:3dd7::/64 via "ffhl";
-	route 2001:67c:2d50::/64 via "ffhl";
-};
-
-
-protocol static local_freifunk {
-	ipv6 { table peering6; };
-
-	route fdef:ffc0:3dd7::/48 reject;
-	route 2001:67c:2d50::/48 reject;
-}
-
-
-
-
-protocol static mesh_dn42 {
-	ipv4 { table mesh4; };
-	route 172.20.0.0/16 reject;
-	route 172.22.0.0/15 reject;
-};
-
-
-protocol static mesh_freifunk {
-	ipv4 { table mesh4; };
-	route 10.0.0.0/8 reject;
-};
-
-# Mesh-internal routing
-########################
-
-protocol rip rip_mesh4 {
-	ipv4 {
-		table mesh4;
-		import where is_self_private();
-		export where !((OWNMAGIC, 1) ~ bgp_community) && !is_self_mesh();
-	};
-
-	interface "ffhl";
-};
-
-protocol rip ng rip_mesh6 {
-	ipv6 {
-		table mesh6;
-		preference 10;
-		import where is_self() && !is_self_mgmt();
-		export where is_self() || is_default() || (!((OWNMAGIC, 1) ~ bgp_community) && is_ula()) || source = RTS_STATIC;
-	};
-
-	interface "ffhl";
-}
-
-
-
-
-
-
-
-# OSPF between gateways
-########################
-
-protocol ospf v3 ospf_mesh4 {
-	ipv4 {
-		preference 90;
-		export where !((OWNMAGIC, 1) ~ bgp_community) && proto != "rip_mesh";
-		import all;
-	};
-
-	area 0 {
-		interface "ffhl" {
-			authentication cryptographic;
-			include "password.conf";
-			type nonbroadcast;
-			neighbors {
-				10.130.0.252 eligible; # huextertor
-				10.130.0.253 eligible; # holstentor
-				10.130.0.254 eligible; # muehlentor
-				10.130.0.255 eligible; # kaisertor
-			};
-		};
-	};
-};
-
-
-protocol ospf v3 ospf_mesh6 {
-	ipv6 {
-		preference 90;
-		export where !((OWNMAGIC, 1) ~ bgp_community) && proto != "rip_mesh" && proto != "unreachable_default";
-		import all;
-	};
-
-	area 0 {
-		interface "ffhl" {
-			# OSPFv3 authentication not yet supported by bird
-			# authentication cryptographic;
-			# include "password.conf";
-			type nonbroadcast;
-			neighbors {
-				2001:67c:2d50::801 eligible; # huextertor
-				2001:67c:2d50::a01 eligible; # muehlentor
-				2001:67c:2d50::c01 eligible; # holstentor
-				2001:67c:2d50::e01 eligible; # burgtor
-			};
-		};
-	};
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-# Kernel routing tables
-########################
-
-protocol kernel kernel_mesh4 {
-	scan time 20;
-	# device routes; # TODO: what is the equivalent in bird2?
-	ipv4 {
-		import none;
-		export filter {
-			if is_dn42()     then { krt_prefsrc = OWNIP; accept ; }
-			if is_freifunk() then { krt_prefsrc = OWNIP; accept ; }
-			reject;
-		};
-	};
-};
-
-
-protocol kernel kernel_mesh6 {
-	scan time 20;
-	# device routes; # TODO: what is the equivalent in bird2?
-
-	ipv6 {
-		import none;
-		export filter {
-			if is_ula() then { krt_prefsrc = ULA_IP; accept; }
-			if is_self() then { krt_prefsrc = PUBLIC_IP; accept; }
-			reject;
-		};
-	};
-}
-
-
-
-protocol kernel {
-	kernel table KERNEL_TABLE;
-	scan time 20;
-	# device routes;
-	ipv4 {
-		table kernelcopy4;
-		import none;
-		export filter {
-			if is_default()  then reject;
-			if is_dn42()     then { krt_prefsrc = OWNIP; accept ; }
-			if is_freifunk() then { krt_prefsrc = OWNIP; accept ; }
-			reject;
-		};
-	};
-}
-
-
-protocol kernel {
-	kernel table KERNEL_TABLE;
-	scan time 20;
-	# device routes;
-
-	ipv6 {
-		table kernelcopy6;
-		import none;
-		export all;
-	};
-}
-
-
-
-
-
-
-
-# plumbing
-###########
-
-protocol pipe {
-	table master4;
-	peer table kernelcopy4;
-	import none;
-	export all;
-}
-
-protocol pipe {
-	table master6;
-	peer table kernelcopy6;
-	import none;
-	export all;
-}
-
-
-
-
-protocol pipe {
-	table master4;
-	peer table peering4;
-	import all;
-	export none;
-}
-
-protocol pipe {
-	table master6;
-	peer table peering6;
-	import all;
-	export none;
-}
-
-
-
-protocol pipe {
-	table master4;
-	peer table mesh4;
-	import where source != RTS_STATIC;
-	export where is_default() || is_self();
-}
-
-protocol pipe {
-	table master6;
-	peer table mesh6;
-	import where source != RTS_STATIC;
-	export where is_default() || is_self();
-}
-
-
-
-protocol pipe {
-	table master6;
-	peer table transit6;
-	import all;
-	export none;
-}
-
-
-
-
-
-# static routes
-################
-
-protocol static unreachable_default4 {
-	ipv4 {
-		preference 0;
-	};
-
-	route 0.0.0.0/0 reject;
-}
-
-protocol static unreachable_default {
-	ipv6 {
-		preference 0;
-	};
-
-	route ::/0 reject;
-}
-
-
-
-# InterCity VPN peerings
-#########################
-# these templates are applied on the routes generated by the icvpn-meta script and included
-# From our icvpn peers, import everything that ist freifunk, dn42 or chaosvpn
-# but dont import our own routes. Announce all Freifunk and dn42 routes we have.
-# "but why don't we export ourself?". We do. is_freifunk() also covers 10.130.0.0/16
-template bgp bgp_icvpn {
-	ipv4 {
-		table peering4;
-		import where (is_freifunk() || is_dn42() || is_chaosvpn()) && !is_self();
-		export where (is_freifunk() || is_dn42());
-	};
-	ipv6 {
-		table peering6;
-		import keep filtered;
-		import filter bgp_import_filter;
-		export all;
-	};
-
-	local as OWNAS;
-};
-
-
-# template bgp bgp_icvpn {
-# 	ipv6 {
-# 		table peering6;
-# 		import keep filtered;
-# 		import filter bgp_import_filter;
-# 		export all;
-# 	};
-
-# 	local as OWNAS;
-# }
-
-
-
-# public IPv6
-##############
-
-template bgp bgp_public {
-	ipv6 {
-		table transit6;
-		import where !is_self() && is_global();
-		export where is_self_public();
-		next hop self;
-	};
-
-	local as OWNAS;
-}
-
-
-# Include local configuration
-# '?' instead of 'f' avoids failures when these
-# files do not exist
-################################################
-
-include "bird_local.con?";
-include "bird_ibgp.conf";
-include "bird_icvpn.con?";
-include "bird_icvpn6.con?";
-include "bird_ffrhein.con?";
diff --git a/roles/base/files/etc/bird/bird.conf.bk2 b/roles/base/files/etc/bird/bird.conf.bk2
deleted file mode 100644
index 0f19ab0b12164c67eb1bcbb30707b27a16824438..0000000000000000000000000000000000000000
--- a/roles/base/files/etc/bird/bird.conf.bk2
+++ /dev/null
@@ -1,206 +0,0 @@
-table peering;
-table kernelcopy;
-table mesh;
-
-protocol device {
-	scan time 10;
-}
-
-# host configuration
-#####################
-
-include "bird_host.conf";
-
-# constants
-############
-
-define OWNAS = 201173;
-define OWNMAGIC = 42;
-define KERNEL_TABLE = ipt_freifunk;
-
-# filter helpers
-#################
-
-function is_default()       { return net ~ [ 0.0.0.0/0          ]; }
-function is_freifunk()      { return net ~ [ 10.0.0.0/8+        ]; }
-function is_dn42()          { return net ~ [ 172.22.0.0/15+, 172.20.0.0/16+ ]; }
-function is_chaosvpn()      { return net ~ [ 172.31.0.0/16+     ]; }
-function is_self()          { return net ~ [ 10.130.0.0/16+     ]; }
-function is_self_mesh()     { return net ~ [ 10.130.0.0/18+     ]; }
-function is_self_private()  { return net ~ [ 10.130.64.0/18+    ]; }
-function is_self_mgmt()     { return net ~ [ 10.130.127.224/27+ ]; }
-
-# static routes
-################
-
-protocol static static_mesh {
-	table peering;
-	route 10.130.0.0/16 reject;
-};
-
-protocol static local_mesh {
-	route 10.130.0.0/16 via "ffhl";
-};
-
-protocol static mesh_dn42 {
-	table mesh;
-	route 172.20.0.0/16 reject;
-	route 172.22.0.0/15 reject;
-};
-
-protocol static mesh_freifunk {
-  	table mesh;
-  	route 10.0.0.0/8 reject;
-};
-
-# Mesh-internal routing
-########################
-
-protocol rip rip_mesh {
-	table mesh;
-	interface "ffhl";
-	import where is_self_private() && !is_self_mgmt();
-	export where !((OWNMAGIC, 1) ~ bgp_community) && !is_self_mesh();
-};
-
-# OSPF between gateways
-########################
-
-protocol ospf ospf_mesh {
-	preference 90;
-	# export where !((OWNMAGIC, 1) ~ bgp_community) && proto != "rip_mesh";
-	export all;
-	import all;
-	area 0 {
-		interface "ffhl" {
-			authentication cryptographic;
-			include "password.conf";
-			type nonbroadcast;
-			neighbors {
-				10.130.0.252 eligible; # huextertor
-				10.130.0.253 eligible; # holstentor
-				10.130.0.254 eligible; # muehlentor
-				10.130.0.255 eligible; # kaisertor
-			};
-		};
-	};
-};
-
-# Kernel routing tables
-########################
-
-protocol static test {
-	route 10.80.0.0/16 via "enp1s0";
-};
-
-
-protocol kernel {
-	scan time 20;
-	device routes;
-	import all;
-	export all;
-	# export filter {
-	# 	if is_dn42()     then { krt_prefsrc = OWNIP; accept ; }
-	# 	if is_freifunk() then { krt_prefsrc = OWNIP; accept ; }
-	# 	reject;
-	# };
-};
-
-protocol kernel {
-	table kernelcopy;
-	kernel table KERNEL_TABLE;
-	scan time 20;
-	device routes;
-	import none;
-	export filter {
-		if is_default()  then accept;
-		if is_dn42()     then { krt_prefsrc = OWNIP; accept ; }
-		if is_freifunk() then { krt_prefsrc = OWNIP; accept ; }
-		reject;
-	};
-}
-
-# plumbing
-###########
-
-protocol pipe {
-	peer table kernelcopy;
-	import none;
-	export all;
-}
-
-protocol pipe {
-	peer table peering;
-	import all;
-	export none;
-}
-
-protocol pipe {
-  peer table mesh;
-  import where source != RTS_STATIC;
-  export where is_default() || is_self();
-}
-
-# static routes
-################
-
-protocol static unreachable_default {
-	preference 0;
-	route 0.0.0.0/0 reject;
-}
-
-# Mesh-internal BGP between all gateways
-#########################################
-
-template bgp bgp_ibgp {
-	table peering;
-	local as OWNAS;
-	direct;
-	import all;
-	export filter { bgp_community.add((OWNMAGIC, 1));
-	                if is_default() then reject;
-	                if source = RTS_BGP then accept;
-	                reject;
-	              };
-}
-
-# InterCity VPN peerings
-#########################
-
-template bgp bgp_icvpn {
-	table peering;
-	local as OWNAS;
-	import where (is_freifunk() || is_dn42() || is_chaosvpn()) && !is_self();
-	export where (is_freifunk() || is_dn42());
-};
-
-# ffrheinland ipv4
-###################
-
-template bgp bgp_ffrhein {
-	table peering;
-	local as 201173;
-	import all;
-	export where net ~ [185.66.193.32/29+];
-	next hop self;
-}
-
-# DN42 peerings
-################
-
-template bgp bgp_dn42 {
-	table peering;
-	local as OWNAS;
-	import where is_dn42() || is_chaosvpn();
-	export where !is_default();
-};
-
-# Include local configuration
-# '?' instead of 'f' avoids failures when these
-# files do not exist
-################################################
-
-include "bird_local.con?";
-# include "bird_ibgp.conf";
-include "bird_icvpn.con?";
-include "bird_ffrhein.con?";
diff --git a/roles/base/files/etc/bird/bird6.conf b/roles/base/files/etc/bird/bird6.conf
deleted file mode 100644
index 018a0e775271579af0f57e571dbf1408706076e5..0000000000000000000000000000000000000000
--- a/roles/base/files/etc/bird/bird6.conf
+++ /dev/null
@@ -1,238 +0,0 @@
-log syslog all;
-
-table peering;
-table transit;
-table kernelcopy;
-table mesh;
-
-protocol device {
-	scan time 10;
-}
-
-# host configuration
-#####################
-
-include "bird6_host.conf";
-
-# constants
-############
-
-define OWNAS        = 201173;
-define OWNMAGIC     = 42;
-define KERNEL_TABLE = ipt_freifunk;
-
-# ROA table
-############
-roa table roa_icvpn {
-  include "roa6.con?";
-}
-
-
-# filter helpers
-#################
-
-# function is_default()     { return net ~ [ ::/0                ]; }
-# function is_global()      { return net ~ [ 2000::/3+           ]; }
-# function is_ula()         { return net ~ [ fc00::/7{48,64}     ]; }
-# function is_freifunk()    { return net ~ [ 2001:bf7::/32+      ]; }
-# function is_self_public() { return net ~ [ 2001:67c:2d50::/48+ ]; }
-# function is_self_net()    { return net ~ [ fdef:ffc0:3dd7::/48+
-# 										 , 2001:67c:2d50::/48+
-# 										 ]; }
-# function is_self_mesh()   { return net ~ [ fdef:ffc0:3dd7::/64+
-# 										 , 2001:67c:2d50::/64+
-# 										 ]; }
-
-# function is_self_mgmt()   { return net ~ [ 2001:67c:2d50:1::a82:7fe0/123+ ]; }
-
-# filters
-##########
-
-# filter bgp_import_filter {
-# 	if is_self_net() then reject;
-# 	if is_ula() then accept;
-# 	# if roa_check(roa_icvpn) = ROA_VALID then {
-# 	#   accept;
-# 	# } else {
-# 	#   print "ROA check failed for ", net, " ASN ", bgp_path.last;
-# 	# }
-# 	accept;
-# }
-
-
-# static routes
-################
-
-
-protocol static local_freifunk_transit {
-	table transit;
-	route 2001:67c:2d50::/48 reject;
-}
-
-protocol static local_mesh {
-	route fdef:ffc0:3dd7::/64 via "ffhl";
-	route 2001:67c:2d50::/64 via "ffhl";
-}
-
-protocol static mesh_ula {
-	table mesh;
-	route fc00::/7 reject;
-}
-
-
-# Mesh-internal routing
-########################
-
-protocol rip rip_mesh {
-	table mesh;
-	interface "ffhl";
-	preference 10;
-	import where is_self_net() && !is_self_mgmt();
-	export where is_self_net() || is_default() || (!((OWNMAGIC, 1) ~ bgp_community) && is_ula()) || source = RTS_STATIC;
-}
-
-# OSPF between gateways
-########################
-
-protocol ospf ospf_mesh {
-	preference 90;
-	export where !((OWNMAGIC, 1) ~ bgp_community) && proto != "rip_mesh" && proto != "unreachable_default";
-	import all;
-	area 0 {
-		interface "ffhl" {
-			# OSPFv3 authentication not yet supported by bird
-			# authentication cryptographic;
-			# include "password.conf";
-			type nonbroadcast;
-			neighbors {
-				2001:67c:2d50::801 eligible; # huextertor
-				2001:67c:2d50::a01 eligible; # muehlentor
-				2001:67c:2d50::c01 eligible; # holstentor
-				2001:67c:2d50::e01 eligible; # burgtor
-			};
-		};
-	};
-};
-
-# Kernel routing tables
-########################
-
-protocol kernel {
-	scan time 20;
-	device routes;
-	import none;
-	export filter {
-		if is_ula() then { krt_prefsrc = ULA_IP;    accept; }
-		if is_self_net() then { krt_prefsrc = PUBLIC_IP; accept; }
-		reject;
-	};
-}
-
-protocol kernel {
-	table kernelcopy;
-	kernel table KERNEL_TABLE;
-	scan time 20;
-	device routes;
-	import none;
-	export all;
-}
-
-# plumbing
-###########
-
-protocol pipe {
-	peer table kernelcopy;
-	import none;
-	export all;
-}
-
-protocol pipe {
-	peer table peering;
-	import all;
-	export none;
-}
-
-protocol pipe {
-	peer table transit;
-	import all;
-	export none;
-}
-
-protocol pipe {
-	peer table mesh;
-	import where source != RTS_STATIC;
-	export where is_default() || is_self_net();
-}
-
-# static routes
-################
-
-protocol static unreachable_default {
-	preference 0;
-	route ::/0 reject;
-}
-
-# Mesh-internal BGP between all gateways
-#########################################
-
-template bgp bgp_ibgp {
-	table peering;
-	local as OWNAS;
-	direct;
-	import all;
-	export filter {
-		bgp_community.add((OWNMAGIC, 1));
-		if source = RTS_BGP then accept;
-		reject;
-	};
-}
-
-# InterCity VPN peerings
-#########################
-
-template bgp bgp_icvpn {
-	table peering;
-	local as OWNAS;
-	import keep filtered;
-	import filter bgp_import_filter;
-	export all;
-}
-
-# public IPv6
-##############
-
-template bgp bgp_public {
-	table transit;
-	local as OWNAS;
-	import where !is_self_net() && is_global();
-	export where is_self_public();
-	next hop self;
-}
-
-# DN42 peerings
-################
-
-template bgp bgp_dn42 {
-	table peering;
-	local as OWNAS;
-	import filter bgp_import_filter;
-	export all;
-}
-
-# anycast DNS
-##############
-
-protocol static anycast_dns {
-	route 2001:67c:2d50:1::10.130.127.224/128 via "anycast-dns";
-}
-
-# Include local configuration
-# '?' instead of 'f' avoids failures when these
-# files do not exist
-################################################
-
-
-
-include "bird6_local.con?";
-include "bird6_ibgp.con?";
-include "bird6_icvpn.con?";
diff --git a/roles/base/files/etc/bird/bird6_ibgp.conf b/roles/base/files/etc/bird/bird6_ibgp.conf
deleted file mode 100644
index 4d7e0f0bd568ea26bdcd7944f03170a0482a235c..0000000000000000000000000000000000000000
--- a/roles/base/files/etc/bird/bird6_ibgp.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-# protocol bgp bgp_ibgp_huextertor from bgp_ibgp {
-#   neighbor 2001:67c:2d50::801 as OWNAS;
-# }
-
-# protocol bgp bgp_ibgp_muehlentor from bgp_ibgp {
-#   neighbor 2001:67c:2d50::a01 as OWNAS;
-# }
-
-# protocol bgp bgp_ibgp_holstentor from bgp_ibgp {
-#   neighbor 2001:67c:2d50::c01 as OWNAS;
-# }
-
-# protocol bgp bgp_ibgp_burgtor from bgp_ibgp {
-#   neighbor 2001:67c:2d50::e01 as OWNAS;
-# }
diff --git a/roles/base/files/etc/bird/bird_ibgp.conf b/roles/base/files/etc/bird/bird_ibgp.conf
deleted file mode 100644
index 04a5272cf1ecf47a1343c35cb9b1c21d0ddccb17..0000000000000000000000000000000000000000
--- a/roles/base/files/etc/bird/bird_ibgp.conf
+++ /dev/null
@@ -1,15 +0,0 @@
-# protocol bgp bgp_ibgp_huextertor from bgp_ibgp {
-# 	neighbor 10.130.0.252 as OWNAS;
-# }
-
-# protocol bgp bgp_ibgp_holstentor from bgp_ibgp {
-# 	neighbor 10.130.0.253 as OWNAS;
-# }
-
-# protocol bgp bgp_ibgp_muehlentor from bgp_ibgp {
-# 	neighbor 10.130.0.254 as OWNAS;
-# }
-
-# protocol bgp bgp_ibgp_burgtor from bgp_ibgp {
-# 	neighbor 10.130.0.255 as OWNAS;
-# }
diff --git a/roles/base/files/host/huextertor/etc/bird/bird6_local.conf b/roles/base/files/host/huextertor/etc/bird/bird6_local.conf
deleted file mode 100644
index afd81a0330c1990a324e5bd32b0d874f78917b23..0000000000000000000000000000000000000000
--- a/roles/base/files/host/huextertor/etc/bird/bird6_local.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-# public BGP
-#############
-
-protocol bgp ffhh_wende0 from bgp_public {
-        neighbor 2a03:2267:ffff:b01::1 as 49009;
-}
diff --git a/roles/base/files/host/huextertor/etc/bird/bird_local.conf b/roles/base/files/host/huextertor/etc/bird/bird_local.conf
index b0be9229f004d6dd6bd5a0764dfb29abce5913f9..8fea37017d8bc9deedce74f8946a8d9e0c851d6c 100644
--- a/roles/base/files/host/huextertor/etc/bird/bird_local.conf
+++ b/roles/base/files/host/huextertor/etc/bird/bird_local.conf
@@ -1,2 +1,6 @@
-# default routes
-#################
+# public BGP
+#############
+
+protocol bgp ffhh_wende0 from bgp_public {
+    neighbor 2a03:2267:ffff:b01::1 as 49009;
+}
diff --git a/roles/base/files/host/huextertor/etc/iptables/iptables.rules b/roles/base/files/host/huextertor/etc/iptables/iptables.rules
deleted file mode 100644
index 1659fe8f58ae01b4f02cf23af987d5d86b9fb6d0..0000000000000000000000000000000000000000
--- a/roles/base/files/host/huextertor/etc/iptables/iptables.rules
+++ /dev/null
@@ -1,14 +0,0 @@
-*filter
--A OUTPUT -o internet -p icmp -m icmp --icmp-type 3/1 -j DROP
--A OUTPUT -o eth0 -p icmp -m icmp --icmp-type 3/1 -j DROP
--A OUTPUT -o eth2 -p icmp -m icmp --icmp-type 3/1 -j DROP
-COMMIT
-*nat
--A POSTROUTING -o hideio -j MASQUERADE
-COMMIT
-*mangle
--A FORWARD -o ffrhein-+ -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
--A PREROUTING -i freifunk-+ -j MARK --set-xmark 0x1/0xffffffff
--A PREROUTING -i nat64 -j MARK --set-xmark 0x1/0xffffffff
--A PREROUTING -i icvpn -j MARK --set-xmark 0x1/0xffffffff
-COMMIT
diff --git a/roles/base/files/host/kaisertor/etc/bird/bird6_local.conf b/roles/base/files/host/kaisertor/etc/bird/bird6_local.conf
deleted file mode 100644
index 0fe02eedd446b6a2cf1f0f8392ea3ac04674a900..0000000000000000000000000000000000000000
--- a/roles/base/files/host/kaisertor/etc/bird/bird6_local.conf
+++ /dev/null
@@ -1,27 +0,0 @@
-# public BGP
-#############
-
-# protocol bgp ffrhein_ber from bgp_public {
-# 	neighbor 2a03:2260:0:59::1 as 201701;
-# }
-
-# protocol bgp ffrhein_fra3 from bgp_public {
-# 	neighbor 2a03:2260:0:60::1 as 201701;
-# }
-
-# protocol bgp he from bgp_public {
-# 	neighbor 2001:470:12:35::1 as 6939;
-# }
-
-# dn42
-#######
-
-# protocol bgp bgp_dn42_chaos from bgp_dn42 {
-# 	source address fe80::ac16:fd92;
-# 	neighbor fe80::ac16:fd91%dn42_chaos as 64784;
-# }
-
-# protocol bgp bgp_nbsp_router from bgp_dn42 {
-# 	source address 2001:67c:2d50::c01;
-# 	neighbor 2001:67c:2d50::2b as 76129;
-# }
diff --git a/roles/base/files/host/kaisertor/etc/bird/bird_local.conf b/roles/base/files/host/kaisertor/etc/bird/bird_local.conf
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/roles/base/tasks/bird.yml b/roles/base/tasks/bird.yml
index 9bd841ed525f45b4c799669067f35f5e513d6ac7..e22cb3f0ab1eef8deba423a168f42c2c16994f53 100644
--- a/roles/base/tasks/bird.yml
+++ b/roles/base/tasks/bird.yml
@@ -1,12 +1,19 @@
 ---
-- template: src=bird/bird_host.conf.j2 dest=/etc/bird/bird_host.conf
+
+- name: copy static bird configs
+  copy: src=bird dest=/etc/
+  tags: [bird]
+
+- name: generate dynamic bird configs
+  template: src=bird/bird_host.conf.j2 dest=/etc/bird/bird_host.conf
   tags: ["bird"]
 
-  
-# - template: src=bird/bird6_host.conf.j2 dest=/etc/bird/bird6_host.conf
-#   tags: ["bird"]
-# - name: restart bird
-#   tags: ["bird"]
-#   systemd:
-#     state: restarted
-#     name: bird.service
+- name: generate ibgp configs
+  template: src=bird/bird_ibgp.conf.j2 dest=/etc/bird/bird_ibgp.conf
+  tags: ["bird"]
+
+- name: restart bird
+  tags: ["bird"]
+  systemd:
+    state: restarted
+    name: bird.service
diff --git a/roles/base/tasks/main.yml b/roles/base/tasks/main.yml
index a4a2a8f779f1c8dc735e83e056c89d667f76435b..9e313d766065841ea28285a8c4035d43d1b3bdbb 100644
--- a/roles/base/tasks/main.yml
+++ b/roles/base/tasks/main.yml
@@ -7,7 +7,7 @@
 
 - name: copy base configs
   copy: src=etc/ dest=/etc
-  tags: [bird, fastd]
+  tags: [fastd]
 
 - name: copy host specific configs
   copy: src=host/{{ inventory_hostname }}/etc/ dest=/etc
diff --git a/roles/base/templates/bird/bird_ibgp.conf.j2 b/roles/base/templates/bird/bird_ibgp.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..dc6ed772630d0e7820f460f8df20c0e1adf15e14
--- /dev/null
+++ b/roles/base/templates/bird/bird_ibgp.conf.j2
@@ -0,0 +1,9 @@
+# ibgp
+# This file is generated by an ansible template
+
+{% for host in groups["gateways"] %}
+protocol bgp bgp_ibgp_{{ host }} from bgp_ibgp {
+    neighbor {{ hostvars[host]['ip6'] }} as OWNAS;
+}
+
+{% endfor %}