diff --git a/host_vars/romanesco.adm.crans.org.yml b/host_vars/romanesco.adm.crans.org.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4bbdaaa4b98bbf536d1107ccde890cd06f4780c3
--- /dev/null
+++ b/host_vars/romanesco.adm.crans.org.yml
@@ -0,0 +1,43 @@
+---
+interfaces:
+  name: ens18
+  name: ens19
+  name: ens20
+
+unbound:
+  verbosity: 1
+  interfaces:
+    - 0.0.0.0
+    - ::0
+  access-control:
+    - name: "srv"
+      addr:
+        - 185.230.79.0/26
+        - 2a0c:700:2::/48
+      policy: allow
+    - name: "srv-nat"
+      addr:
+        - 172.16.3.0/24
+        - 2a0c:700:3::/48
+      policy: allow
+    - name: "adm"
+      addr:
+        - 172.16.10.0/24
+        - fd00:0:0:10::/64
+      policy: allow
+    - name: "infra"
+      addr:
+        - 172.16.32.0/22
+        - fd00:0:0:11::/64
+      policy: allow
+    - name: "adh"
+      addr:
+        - 185.230.78.0/24
+        - 2a0c:700:12::/48
+      policy: allow
+    - name: "adh-nat"
+      addr:
+        - 100.64.0.0/16
+        - 2a0c:700:13::/48
+      policy: allow
+  val-log-level: 2
diff --git a/hosts b/hosts
index ae3f2c44c800db5e6c601512ad23cbe4c7267e47..8228d2d699bf88311870ca3b67e21e743dfcbb95 100644
--- a/hosts
+++ b/hosts
@@ -70,6 +70,9 @@ ovh_physical
 [dns_recursive:children]
 routeurs_vm
 
+[dns_recursive_unbound]
+romanesco.adm.crans.org
+
 [dovecot]
 owl.adm.crans.org
 
diff --git a/plays/unbound.yml b/plays/unbound.yml
new file mode 100755
index 0000000000000000000000000000000000000000..8e93d886eeb85bb0fd9167d9ff0bdede3632b19a
--- /dev/null
+++ b/plays/unbound.yml
@@ -0,0 +1,5 @@
+#!/usr/bin/env ansible-playbook
+---
+- hosts: dns_recursive_unbound
+  roles:
+    - unbound
diff --git a/roles/nftables/tasks/main.yml b/roles/nftables/tasks/main.yml
index 8a5506a52c6be1867eaaedfda6634c38d16a9d46..4abb52336d0a0de89c6eb680130f57b0068fa235 100644
--- a/roles/nftables/tasks/main.yml
+++ b/roles/nftables/tasks/main.yml
@@ -8,6 +8,16 @@
   retries: 3
   until: apt_result is succeeded
 
+- name: Deploy the configuration files
+  template:
+    src: "{{ item }}"
+    dest: "/etc/unbound/{{ item }}"
+    owner: "unbound"
+    group: "unbound"
+    mode: 0600
+  loop:
+    - unbound.conf
+
 - name: Enable and start nftables
   systemd:
     name: nftables
diff --git a/roles/unbound/handlers/main.yml b/roles/unbound/handlers/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b433c429bd00add22816e9823127013f3fa586a8
--- /dev/null
+++ b/roles/unbound/handlers/main.yml
@@ -0,0 +1,6 @@
+---
+- name: Restart unbound
+  systemd:
+    name: unbound
+    enabled: true
+    state: restart
diff --git a/roles/unbound/tasks/main.yml b/roles/unbound/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..de4c69f72ee7f5c4884b5f7c79207388e48cb81b
--- /dev/null
+++ b/roles/unbound/tasks/main.yml
@@ -0,0 +1,36 @@
+---
+- name: Install unbound
+  apt:
+    name: unbound
+    state: present
+    update_cache: true
+  register: apt_result
+  retries: 3
+  until: apt_result is succeeded
+
+
+- name: Download the root file
+  get_url:
+    url: https://www.internic.net/domain/named.root
+    dest: /var/unbound/etc/root.hints
+    mode: '0444'
+  notify: Reload unbound
+
+- name: Fetch the initial keys
+  command: unbound-anchor
+
+- name: Deploy the configuration
+  template:
+    src: unbound.conf.j2
+    dest: /etc/unbound/unbound.conf
+    owner: root
+    group: root
+    mode: 0644
+  notify: Reload unbound
+
+- name: Enable and start unbound
+  systemd:
+    name: unbound
+    enabled: true
+    state: started
+
diff --git a/roles/unbound/templates/unbound.conf.j2 b/roles/unbound/templates/unbound.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..036dcf47b6e6f6e88a9541a1dce7f2f738dc4d3a
--- /dev/null
+++ b/roles/unbound/templates/unbound.conf.j2
@@ -0,0 +1,54 @@
+server:
+    verbosity: {{ unbound['verbosity'] | default(1) }}
+
+{% for adr in unbound['interfaces'] %}
+    interface: {{ adr }}
+{% endfor %}
+
+{% for ac in unbound['access-control'] %}
+    # {{ ac['name'] }}
+{% for addr in ac['addr'] %}
+    access-control: {{ addr }} {{ ac['policy'] }}
+{% endfor %}
+{% endfor %}
+
+    # chroot: "/etc/unbound"
+    # username: "unbound"
+    # directory: "/etc/unbound"
+    
+    num-threads: 8
+
+    # the log file, "" means log to stderr.
+    # Use of this option sets use-syslog to "no".
+    # logfile: ""
+
+    use-syslog: yes
+
+    # Log identity to report. if empty, defaults to the name of argv[0]
+    # (usually "unbound").
+    # log-identity: ""
+
+    # print UTC timestamp in ascii to logfile, default is epoch in seconds.
+    # log-time-ascii: no
+
+    #log-queries: yes
+    #log-replies: yes
+
+    root-hints: "root.hints"
+
+    module-config: "validator iterator"
+    auto-trust-anchor-file: "/etc/unbound/root.key"
+    val-log-level: {{ unbound['val-log-level'] | default(2) }}
+
+
+
+
+python:
+    # ...
+
+dynlib:
+    # ...
+
+# Remote control config section.
+remote-control:
+    # ...