diff --git a/networkd/defaults/main.yml b/networkd/defaults/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a9d2b38fc002cb7f3eec93d52a6e37c640daac1f
--- /dev/null
+++ b/networkd/defaults/main.yml
@@ -0,0 +1,24 @@
+---
+
+networkd_type: 'dhcp' # or: 'static', 'bond'
+
+# for static type only
+networkd_address: 10.10.10.10/24
+networkd_gateway: 10.10.10.1
+
+# for bond type only
+networkd_bond: bond0
+networkd_bond_devices: [ eth0, eth1 ]
+networkd_bond_vlans:
+  - id: 23
+    name: storage
+    bridge: no
+    address: 10.10.10.10/24
+  - id: 42
+    name: public
+    bridge: yes
+    address: 10.10.12.22/24
+    gateway: 10.10.12.1
+  - id: 69
+    name: transport
+    bridge: yes
diff --git a/networkd/handlers/main.yml b/networkd/handlers/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1c3361f9a70161cdaef3af3294eb18e421aec178
--- /dev/null
+++ b/networkd/handlers/main.yml
@@ -0,0 +1,8 @@
+---
+
+- name: reload systemd service files
+  systemd: daemon_reload=yes
+
+- name: restart networkd
+  service: name=systemd-networkd state=restarted
+
diff --git a/networkd/tasks/main.yml b/networkd/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f7885307a3cbbff1f4bd385c4f4022ff3f782128
--- /dev/null
+++ b/networkd/tasks/main.yml
@@ -0,0 +1,101 @@
+---
+
+- name: ensure networkd has a valid configuration
+  template:
+    src: "20-wired-{{ networkd_type }}.network.j2"
+    dest: /etc/systemd/network/20-wired.network
+    owner: root
+    group: root
+    mode: 0644
+  notify:
+    - reload systemd service files
+    - restart networkd
+
+- name: ensure bonding works correctly
+  block:
+    - name: ensure the network packages are installed
+      apt:
+        name: "{{ item }}"
+        state: present
+      with_items:
+        - vlan
+        - bridge-utils
+    - name: ensure bond module is loaded
+      modprobe:
+        name: 8021q
+        state: present
+    - name: ensure bond module is loaded after a reboot
+      copy:
+        content: "8021q"
+        dest: /etc/modules-load.d/bond.conf
+    - name: ensure bond netdev is configured
+      template:
+        src: bond.netdev.j2
+        dest: /etc/systemd/network/{{ networkd_bond }}.netdev
+        owner: root
+        group: root
+        mode: 0644
+    - name: ensure bond network is configured   
+      template:
+        src: bond.network.j2
+        dest: /etc/systemd/network/{{ networkd_bond }}.network
+        owner: root
+        group: root
+        mode: 0644
+    - name: ensure vlan netdevs are configured
+      template:
+        src: vlan.netdev.j2
+        dest: /etc/systemd/network/vl-{{ item.name }}.netdev
+        owner: root
+        group: root
+        mode: 0644
+      with_items: networkd_bond_vlans
+    - name: ensure vlan networks are configured
+      template:
+        src: vlan.network.j2
+        dest: /etc/systemd/network/vl-{{ item.name }}.network
+        owner: root
+        group: root
+        mode: 0644
+      with_items: networkd_bond_vlans
+    - name: ensure bridge netdevs are configured
+      template:
+        src: bridge.netdev.j2
+        dest: /etc/systemd/network/vmbr-{{ item.name }}.netdev
+        owner: root
+        group: root
+        mode: 0644
+      with_items: networkd_bond_vlans
+      when: item.bridge == yes
+    - name: ensure bridge networks are configured
+      template:
+        src: bridge.network.j2
+        dest: /etc/systemd/network/vmbr-{{ item.name }}.network
+        owner: root
+        group: root
+        mode: 0644
+      with_items: networkd_bond_vlans
+      when: item.bridge == yes and 'address' in item
+  when: networkd_type == 'bond'
+  notify:
+    - reload systemd service files
+    - restart networkd
+
+- meta: flush_handlers
+
+- name: ensure networkd is enabled and running
+  service:
+    name: systemd-networkd
+    state: started
+    enabled: yes
+
+- name: ensure legacy methods are disabled
+  systemd:
+    name: networking
+    enabled: no
+
+- name: ensure we wait for network to be online
+  service:
+    name: systemd-networkd-wait-online
+    enabled: yes
+
diff --git a/networkd/templates/20-wired-bond.network.j2 b/networkd/templates/20-wired-bond.network.j2
new file mode 100644
index 0000000000000000000000000000000000000000..7ff16874453cf639d8a4bdc647910d9f432bb17a
--- /dev/null
+++ b/networkd/templates/20-wired-bond.network.j2
@@ -0,0 +1,5 @@
+[Match]
+Name={{ networkd_bond_devices|join(' ') }}
+
+[Network]
+Bond={{ networkd_bond }}
diff --git a/networkd/templates/20-wired-dhcp.network.j2 b/networkd/templates/20-wired-dhcp.network.j2
new file mode 100644
index 0000000000000000000000000000000000000000..020f88170fac52615c749786f8683c6f2a61fdb2
--- /dev/null
+++ b/networkd/templates/20-wired-dhcp.network.j2
@@ -0,0 +1,5 @@
+[Match]
+Name={{ ansible_default_ipv4.interface }}
+
+[Network]
+DHCP=ipv4
diff --git a/networkd/templates/20-wired-static.network.j2 b/networkd/templates/20-wired-static.network.j2
new file mode 100644
index 0000000000000000000000000000000000000000..ba04d8bb5ba3e212894f44d2a8f0dfc5a13e548d
--- /dev/null
+++ b/networkd/templates/20-wired-static.network.j2
@@ -0,0 +1,10 @@
+[Match]
+Name={{ ansible_default_ipv4.interface }}
+
+[Network]
+Address={{ networkd_address }}
+Gateway={{ networkd_gateway }}
+{%- for server in nameservers %}
+DNS={{ server }}
+{% endfor -%}
+
diff --git a/networkd/templates/bond.netdev.j2 b/networkd/templates/bond.netdev.j2
new file mode 100644
index 0000000000000000000000000000000000000000..44c8fddd96893c69ec01c50ebe10945a81310a32
--- /dev/null
+++ b/networkd/templates/bond.netdev.j2
@@ -0,0 +1,9 @@
+[NetDev]
+Name={{ networkd_bond }}
+Kind=bond
+
+[Bond]
+Mode=802.3ad
+TransmitHashPolicy=layer3+4
+MIIMonitorSec=100ms
+LACPTransmitRate=fast
diff --git a/networkd/templates/bond.network.j2 b/networkd/templates/bond.network.j2
new file mode 100644
index 0000000000000000000000000000000000000000..aa8627d2142395bb0c2d483e9a0a1234a4988f7f
--- /dev/null
+++ b/networkd/templates/bond.network.j2
@@ -0,0 +1,8 @@
+[Match]
+Name={{ networkd_bond }}
+
+[Network]
+{%- for vlan in networkd_bond_vlans %}
+VLAN=vl-{{ vlan.name }}
+{% endfor -%}
+BindCarrier={{ networkd_bond_devices|join(' ') }}
diff --git a/networkd/templates/bridge.netdev.j2 b/networkd/templates/bridge.netdev.j2
new file mode 100644
index 0000000000000000000000000000000000000000..e2106865f127b8f95784529f7b478061ac6b947d
--- /dev/null
+++ b/networkd/templates/bridge.netdev.j2
@@ -0,0 +1,8 @@
+[NetDev]
+Name=vmbr-{{ item.name }}
+Kind=bridge
+
+[Bridge]
+STP=false
+ForwardDelaySec=0
+#VLANFiltering=true
diff --git a/networkd/templates/bridge.network.j2 b/networkd/templates/bridge.network.j2
new file mode 100644
index 0000000000000000000000000000000000000000..1149208fb2eb9a81dee50ecb83bdd678c6f34b17
--- /dev/null
+++ b/networkd/templates/bridge.network.j2
@@ -0,0 +1,8 @@
+[Match]
+Name=vmbr-{{ item.name }}
+
+[Network]
+Address={{ item.address }}
+{%- if item.gateway %}
+Gateway={{ item.gateway }}
+{% endif -%}
diff --git a/networkd/templates/vlan.netdev.j2 b/networkd/templates/vlan.netdev.j2
new file mode 100644
index 0000000000000000000000000000000000000000..a531d862b4dd783a351dba89ca56c643f5e1c40d
--- /dev/null
+++ b/networkd/templates/vlan.netdev.j2
@@ -0,0 +1,6 @@
+[NetDev]
+Name=vl-{{ item.name }}
+Kind=vlan
+
+[VLAN]
+Id={{ item.id }}
diff --git a/networkd/templates/vlan.network.j2 b/networkd/templates/vlan.network.j2
new file mode 100644
index 0000000000000000000000000000000000000000..959fbc75c592cad839d44fbf84e52bb98b729d76
--- /dev/null
+++ b/networkd/templates/vlan.network.j2
@@ -0,0 +1,14 @@
+[Match]
+Name=vl-{{ item.name }}
+
+[Network]
+{%- if item.bridge %}
+Bridge=vmbr-{{ item.name }}
+{% else %}
+{%- if item.address %}
+Address={{ item.address }}
+{%- if item.gateway %}
+Gateway={{ item.gateway }}
+{% endif -%}
+{% endif -%}
+{% endif -%}