diff --git a/localgw.yml b/localgw.yml
new file mode 100644
index 0000000000000000000000000000000000000000..5b333efcd32416a07c4413d3c5deb216b0d164ab
--- /dev/null
+++ b/localgw.yml
@@ -0,0 +1,4 @@
+---
+- hosts: localgw
+  roles:
+    - localgw
diff --git a/roles/localgw/defaults/main.yml b/roles/localgw/defaults/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..89434408721c369067f92c8adfdbc0075f21dbb2
--- /dev/null
+++ b/roles/localgw/defaults/main.yml
@@ -0,0 +1,9 @@
+---
+# name of the bridge where clients can be connected
+client_bridge_name: br-client
+# name of the mesh interface which is member of the client bridge
+# (i.e. the interface over which traffic from the mesh enters the 
+# client bridge)
+mesh_client_interface_name: bat0
+# Directory where ext-respondd will be installed
+ext_respondd_install_dir: /opt/ext-respondd
diff --git a/roles/localgw/handlers/main.yml b/roles/localgw/handlers/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3eb2f181beea2159b69d771af937a4b8f40725a5
--- /dev/null
+++ b/roles/localgw/handlers/main.yml
@@ -0,0 +1,3 @@
+---
+- name: restart ext-respondd
+  service: name=ext-respondd state=restarted
diff --git a/roles/localgw/tasks/batman.yml b/roles/localgw/tasks/batman.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0ad44148838b7ed1c5c1ecfde8bb85dbb768b267
--- /dev/null
+++ b/roles/localgw/tasks/batman.yml
@@ -0,0 +1,17 @@
+---
+- name: Install tools
+  apt:
+    name: 
+      - batctl
+      - bridge-utils
+    state: present
+
+- name: Ensure interfaces.d exsists
+  file:
+    path: /etc/network/interfaces.d
+    state: directory
+
+- name: Deploy BATMAN interface config
+  template:
+    src: interfaces-batman.j2
+    dest: /etc/network/interfaces.d/ffs-batman
diff --git a/roles/localgw/tasks/fastd.yml b/roles/localgw/tasks/fastd.yml
new file mode 100644
index 0000000000000000000000000000000000000000..84d75ad5383ee9e790c50937f034191aed07c3d6
--- /dev/null
+++ b/roles/localgw/tasks/fastd.yml
@@ -0,0 +1,22 @@
+---
+- name: Installing Dependencies
+  apt: 
+    name: fastd
+    state: present
+
+- name: Ensure fastd mesh_vpn folder exists
+  file:
+    state: directory
+    recurse: yes
+    path: /etc/fastd/mesh_vpn
+
+- name: Deploy fastd mesh_vpn config
+  template:
+    src: fastd.conf.j2
+    dest: /etc/fastd/mesh_vpn/fastd.conf
+
+- name: Enable fastd mesh_vpn service
+  service:
+    name: fastd@mesh_vpn
+    enabled: yes
+    state: started
diff --git a/roles/localgw/tasks/main.yml b/roles/localgw/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..50624735d54d700aa35cf4f990d0fc4fe3c3f9d5
--- /dev/null
+++ b/roles/localgw/tasks/main.yml
@@ -0,0 +1,14 @@
+---
+- name: Setup routing
+  include: routing.yml
+
+- name: Setup batman
+  include: batman.yml
+
+- name: Setup fastd
+  include: fastd.yml
+  when:
+    fastd["enable"] is defined and fastd["enable"]
+
+- name: Setup respondd
+  include: respondd.yml
diff --git a/roles/localgw/tasks/respondd.yml b/roles/localgw/tasks/respondd.yml
new file mode 100644
index 0000000000000000000000000000000000000000..fe82c5388cc8d2ae398f4aca805f5139c4d8b2f9
--- /dev/null
+++ b/roles/localgw/tasks/respondd.yml
@@ -0,0 +1,58 @@
+---
+- name: Install dependencies for ext-respondd
+  apt:
+    name:
+      - git
+      - python3-netifaces
+      - ethtool
+      - lsb-release
+
+- name: Checkout ext-respondd
+  git:
+    repo: 'https://github.com/freifunkMUC/ext-respondd.git'
+    dest: "{{ ext_respondd_install_dir }}"
+    update: yes
+  notify:
+    - restart ext-respondd
+
+- name: Deploy ext-respondd config.json
+  copy:
+    content: "{{ config_json|to_nice_json }}"
+    dest: "{{ ext_respondd_install_dir }}/config.json"
+  vars:
+    config_json:
+      batman: "{{ mesh_client_interface_name }}"
+      bridge: "{{ client_bridge_name }}"
+      mesh-vpn: 
+        - mesh-vpn
+      mesh-wlan: []
+      fastd_socket: "/var/run/fastd.mesh_vpn.socket"
+      rate_limit: 30
+      rate_limit_burst: 10
+  notify:
+    - restart ext-respondd
+
+- name: Deploy ext-respondd alias.json
+  copy:
+    content: "{{ alias_json|to_nice_json }}"
+    dest: "{{ ext_respondd_install_dir }}/alias.json"
+  vars:
+    alias_json:
+      nodeinfo:
+        owner:
+          contact: "{{ nodeinfo.owner_contact }}"
+        location:
+          zip: "{{ nodeinfo.location.zip }}"
+  notify:
+    - restart ext-respondd
+
+- name: Deploy ext-respondd systemd service
+  template:
+    src: ext-respondd.service
+    dest: /etc/systemd/system/ext-respondd.service
+
+- name: Enable ext-respondd systemd service
+  service:
+    enabled: yes
+    name: ext-respondd
+    state: started
diff --git a/roles/localgw/tasks/routing.yml b/roles/localgw/tasks/routing.yml
new file mode 100644
index 0000000000000000000000000000000000000000..825cce7d4a6965037a9439a06791520f43faa42a
--- /dev/null
+++ b/roles/localgw/tasks/routing.yml
@@ -0,0 +1,5 @@
+---
+- name: Setup routing table for mesh traffic
+  copy:
+    dest: /etc/iproute2/rt_tables.d/ffs-mesh-default.conf
+    content: "711001 ffs-mesh-default"
diff --git a/roles/localgw/templates/alias.json.j2 b/roles/localgw/templates/alias.json.j2
new file mode 100644
index 0000000000000000000000000000000000000000..31e69ac9004bb64a366114e2ddadefb95e71d6a8
--- /dev/null
+++ b/roles/localgw/templates/alias.json.j2
@@ -0,0 +1,18 @@
+{
+  "nodeinfo": {
+    "hostname": "{{ nodeinfo.nodename }}",
+    "owner": {
+      "contact": "{{ nodeinfo.owner_contact }}",
+    },
+    "location": {
+      "zip": "{{ nodeinfo.location.zip }}",
+      "longitude": 5.00932562351
+    },
+    "pages": [
+      "http://start.ffggrz/",
+      "http://start.ffggrz.de/"
+    ]
+  },
+  "firstseen": "2015-04-12T15:41:01"
+}
+
diff --git a/roles/localgw/templates/ext-respondd-config.json.j2 b/roles/localgw/templates/ext-respondd-config.json.j2
new file mode 100644
index 0000000000000000000000000000000000000000..92f76dd59d9845d6047240c95ed932a703cb68da
--- /dev/null
+++ b/roles/localgw/templates/ext-respondd-config.json.j2
@@ -0,0 +1,9 @@
+{
+  "batman": "{{ mesh_client_interface_name }}",
+  "bridge": "{{ client_bridge_name }}",
+  "mesh-vpn": [],
+  "mesh-wlan": [],
+  "fastd_socket": "/var/run/fastd.mesh_vpn.socket",
+  "rate_limit": 30,
+  "rate_limit_burst": 10
+}
diff --git a/roles/localgw/templates/ext-respondd.service b/roles/localgw/templates/ext-respondd.service
new file mode 100644
index 0000000000000000000000000000000000000000..ae475be2f459b4fe80a04c192e76256657643cbc
--- /dev/null
+++ b/roles/localgw/templates/ext-respondd.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=ext-respondd (respondd status for servers)
+After=syslog.target network-online.target
+
+[Service]
+Type=simple
+User=root
+Group=root
+WorkingDirectory={{ ext_respondd_install_dir }}
+ExecStart={{ ext_respondd_install_dir }}/ext-respondd.py
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/localgw/templates/fastd-onboarding.conf.j2 b/roles/localgw/templates/fastd-onboarding.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..c3e7eb1970271e2f28074ed09113532c7849c77d
--- /dev/null
+++ b/roles/localgw/templates/fastd-onboarding.conf.j2
@@ -0,0 +1,15 @@
+secret "{{ fastd["secret"] }}";
+log to syslog level info;
+method "salsa2012+umac";
+log to syslog level verbose;
+mode tap;
+interface "mesh-vpn";
+mtu 1340;
+group "gluon-mesh-vpn";
+status socket "/var/run/fastd.mesh_vpn_onboarding.socket";
+packet mark 1;
+peer group "mesh_vpn" {
+peer limit 1;
+include peers from "/etc/fastd/mesh_vpn_onboarding/peers";
+}
+
diff --git a/roles/localgw/templates/fastd.conf.j2 b/roles/localgw/templates/fastd.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..4b0f5cfd5b1e65864aad2cdb6f765335f3916a3d
--- /dev/null
+++ b/roles/localgw/templates/fastd.conf.j2
@@ -0,0 +1,54 @@
+secret "{{ fastd["secret"] }}";
+log to syslog level info;
+method "salsa2012+umac";
+log to syslog level verbose;
+mode tap;
+interface "mesh-vpn";
+mtu 1340;
+#group "gluon-mesh-vpn";
+status socket "/var/run/fastd.mesh_vpn.socket";
+packet mark 1;
+peer group "mesh_vpn" {
+  peer limit 1;
+  peer "gw01" {
+    remote "gw01s{{ fastd["segment"] }}.gw.freifunk-stuttgart.de":{{ fastd["port"] }};
+    key "d7b89d42b629bd5d419139b4c395e7b47ed7417112d3fcd232ba38137daa58e6";
+  }
+  peer "gw02" {
+    remote "gw02s{{ fastd["segment"] }}.gw.freifunk-stuttgart.de":{{ fastd["port"] }};
+    key "31eaff2ce1c19d0c9af693c4500defc4e1b4979ad75133d779532f0572955875";
+  }
+  peer "gw03" {
+    remote "gw03s{{ fastd["segment"] }}.gw.freifunk-stuttgart.de":{{ fastd["port"] }};
+    key "1e944f5f2dca02e1c1d2e006186417e76759c26f75da5e7850f6c1e5cddcb1c2";
+  }
+  peer "gw04" {
+    remote "gw04s{{ fastd["segment"] }}.gw.freifunk-stuttgart.de":{{ fastd["port"] }};
+    key "5689b2fd14bd313de1e95406c17e783b78b9d6f8aa86f896df4f2d843ab642bf";
+  }
+  peer "gw05" {
+    remote "gw05s{{ fastd["segment"] }}.gw.freifunk-stuttgart.de":{{ fastd["port"] }};
+    key "26cd067057e4fcf58fb68da66c75a360de56aa4c36094f1846f706824682a789";
+  }
+  peer "gw06" {
+    remote "gw06s{{ fastd["segment"] }}.gw.freifunk-stuttgart.de":{{ fastd["port"] }};
+    key "fdc1737906d7431763962f4daf6eb4d973c845aca7a96e40643d08a82159dff2";
+  }
+  peer "gw07" {
+    remote "gw07s{{ fastd["segment"] }}.gw.freifunk-stuttgart.de":{{ fastd["port"] }};
+    key "23f6d70be861effe9b1a7bc812fd8c9e2e575bf0ea63ca4ffdc0a3998afb59a1";
+  }
+  peer "gw08" {
+    remote "gw08s{{ fastd["segment"] }}.gw.freifunk-stuttgart.de":{{ fastd["port"] }};
+    key "1af6a5d41d866823e5712e8d9af42080397ad52bdd8664a11ca94225629398a3";
+  }
+  peer "gw09" {
+    remote "gw09s{{ fastd["segment"] }}.gw.freifunk-stuttgart.de":{{ fastd["port"] }};
+    key "bf7c1a62dbf61b8fda25be7e5e600c0ae745e6b6e90a419aeafaf85b6497e8f2";
+  }
+  peer "gw10" {
+    remote "gw10s{{ fastd["segment"] }}.gw.freifunk-stuttgart.de":{{ fastd["port"] }};
+    key "4b89e1a8882b4d7cf50eabc0360ff28138d78ca0b63fd63ec9e4c8260121da00";
+  }
+}
+
diff --git a/roles/localgw/templates/interfaces-batman.j2 b/roles/localgw/templates/interfaces-batman.j2
new file mode 100644
index 0000000000000000000000000000000000000000..d3e5c01cdf8ad6347f3d3878d24f312339fe3db1
--- /dev/null
+++ b/roles/localgw/templates/interfaces-batman.j2
@@ -0,0 +1,19 @@
+auto {{ client_bridge_name }}
+iface {{ client_bridge_name }} inet manual
+  #mtu 1500
+  bridge_ports {{ mesh_client_interface_name }}
+  bridge_fd 0
+  bridge_maxwait 0
+  # always route mesh-vpn traffic over wan
+  # post-up /sbin/ip rule add fwmark 1 table wan || true
+  # post-down /sbin/ip rule del fwmark 1 table wan || true
+
+auto {{ mesh_client_interface_name }}
+iface {{ mesh_client_interface_name }} inet manual
+  #mtu 1500
+  pre-up /sbin/modprobe batman-adv || true
+  up /usr/sbin/batctl -m $IFACE if create || true
+  # gateways set this for some reason? default in gluon is 5000
+  # post-up /usr/sbin/batctl -m $IFACE it 10000 || true
+  # post-up /usr/sbin/batctl -m $IFACE gw server 64mbit/64mbit || true
+