diff --git a/group_vars/dns_authoritative.yml b/group_vars/dns_authoritative.yml
new file mode 100644
index 0000000000000000000000000000000000000000..42248b65e918f5ee6b672f8585064fc7c079a251
--- /dev/null
+++ b/group_vars/dns_authoritative.yml
@@ -0,0 +1,24 @@
+---
+glob_bind:
+  default:
+    format: 'bak.%s'
+  zones:
+    '_acme-challenge.crans.org':
+    '_acme-challenge.adm.crans.org':
+    'adh.crans.org': {}
+    'adm.crans.org': {}
+    'cachan-adm.crans.org': {}
+    'crans.eu': {}
+    'crans.fr': {}
+    'crans.org': {}
+    'lists.crans.org': {}
+    'san.crans.org': {}
+    'renater.crans.org': {}
+    'ens.crans.org': {}
+    'lp.crans.org': {}
+    'admissibles.crans.org': {}
+    '76.230.185.in-addr.arpa': {}
+    '77.230.185.in-addr.arpa': {}
+    '78.230.185.in-addr.arpa': {}
+    '79.230.185.in-addr.arpa': {}
+    '0.0.7.0.c.0.a.2.ip6.arpa': {}
diff --git a/host_vars/silice.adm.crans.org.yml b/host_vars/silice.adm.crans.org.yml
index 736408c89ab9eb9a903aef26c5f21fd45b40befa..deb491cfd296b29cfaae8f011766df6c2de57993 100644
--- a/host_vars/silice.adm.crans.org.yml
+++ b/host_vars/silice.adm.crans.org.yml
@@ -2,3 +2,29 @@
 interfaces:
   adm: eth1
   srv: eth0
+
+loc_bind:
+  options:
+    secondaries: "{{ query('ldap', 'ip', 'sputnik', 'adm') }}"
+    key_directory: "/var/cache/bind/keys"
+  default:
+    format: 'generated/%s.db'
+    type: primary
+    notify: 'yes'
+    dnssec: true
+  zones:
+    '_acme-challenge.crans.org':
+      update_policy:
+        - 'grant certbot_challenge. name _acme-challenge.crans.org. txt'
+      format: 'bak.%s'
+    '_acme-challenge.adm.crans.org':
+      update_policy:
+        - 'grant certbot_adm_challenge. name _acme-challenge.adm.crans.org. txt'
+      format: 'bak.%s'
+  rfc2136_keys:
+    'certbot_challenge.':
+      algorithm: hmac-sha512
+      secret: "{{ vault.bind.rfc2136_keys['certbot_challenge.'].secret }}"
+    'certbot_adm_challenge.':
+      algorithm: hmac-sha512
+      secret: "{{ vault.bind.rfc2136_keys['certbot_adm_challenge.'].secret }}"
diff --git a/host_vars/sputnik.adm.crans.org.yml b/host_vars/sputnik.adm.crans.org.yml
index 0214a0f97f8e8400bfcbe8edc566ba4cd4768c92..f9bd86664101ee188c81183f993e0c23366bf812 100644
--- a/host_vars/sputnik.adm.crans.org.yml
+++ b/host_vars/sputnik.adm.crans.org.yml
@@ -111,3 +111,8 @@ loc_reverseproxy:
   redirect_sites: []
 
   static_sites: []
+
+loc_bind:
+  default:
+    type: slave
+    primaries: "{{ query('ldap', 'ip', 'silice', 'adm') }}"
diff --git a/hosts b/hosts
index e5d3aa92199085a17e5ef021496fd9b449c49464..6e630f601c39652e7d40b7e4a78b69299278c910 100644
--- a/hosts
+++ b/hosts
@@ -55,12 +55,9 @@ gitlab_runner
 [django_cas]
 cas.adm.crans.org
 
-[dns_auth_master]
+[dns_authoritative]
 silice.adm.crans.org
-
-[dns_authoritative:children]
-dns_auth_master
-ovh_physical
+sputnik.adm.crans.org
 
 [dns_recursive:children]
 routeurs_vm
diff --git a/plays/dns-authoritative.yml b/plays/dns-authoritative.yml
index 928a751e3444c1e8ea403960816c910c57ebc85f..8996f396b4ce2d5fc9179d6b237331e6d9e0eb95 100755
--- a/plays/dns-authoritative.yml
+++ b/plays/dns-authoritative.yml
@@ -3,21 +3,6 @@
 # Deploy authoritative DNS server
 - hosts: dns_authoritative
   vars:
-    certbot_dns_secret: "{{ vault.certbot_dns_secret }}"
-    certbot_adm_dns_secret: "{{ vault.certbot_adm_dns_secret }}"
-    bind:
-      masters: "{{ query('ldap', 'role', 'dns-primary') }}"
-      slaves: "{{ query('ldap', 'role', 'dns-secondary') }}"
-      zones: "{{ (lookup('re2oapi', 'dnszones') + query('ldap', 'zones')) | unique }}"
-      reverse: "{{ lookup('re2oapi', 'dnsreverse') }}"
+    bind: '{{ glob_bind | default({}) | combine(loc_bind | default({}), recursive=True) }}'
   roles:
     - bind-authoritative
-
-- hosts: dns_auth_master
-  vars:
-    re2o:
-      server: re2o.adm.crans.org
-      service_user: "{{ vault.re2o_service_user }}"
-      service_password: "{{ vault.re2o_service_password }}"
-  roles:
-    - dns
diff --git a/roles/bind-authoritative/handlers/main.yml b/roles/bind-authoritative/handlers/main.yml
index 0f5025c5534af5d7dbfebca5b3e8be1a98afebaf..ce76692886d3838ca2dcb1bba900586a8f227a04 100644
--- a/roles/bind-authoritative/handlers/main.yml
+++ b/roles/bind-authoritative/handlers/main.yml
@@ -1,5 +1,5 @@
 ---
-- name: Reload Bind9
+- name: systemctl reload bind9.service
   systemd:
     name: bind9
     state: reloaded
diff --git a/roles/bind-authoritative/tasks/dnssec.yml b/roles/bind-authoritative/tasks/dnssec.yml
deleted file mode 100644
index f01f4353df85dc711f6a92159e1bc7abd4a2d5a3..0000000000000000000000000000000000000000
--- a/roles/bind-authoritative/tasks/dnssec.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-- name: TODO
-  debug:
-    msg: "Hey some work is being done here!"
diff --git a/roles/bind-authoritative/tasks/main.yml b/roles/bind-authoritative/tasks/main.yml
index 1c6daf7fe5b04b4e6aa95178841aea81888ae9ce..649d8415989ae21b8e96cc4f5ffdeac254fb1e9b 100644
--- a/roles/bind-authoritative/tasks/main.yml
+++ b/roles/bind-authoritative/tasks/main.yml
@@ -7,11 +7,6 @@
   retries: 3
   until: apt_result is succeeded
 
-- name: Is this the master?
-  set_fact:
-    is_master: "{{ ansible_hostname in query('ldap', 'role', 'dns-primary') }}"
-    cacheable: true
-
 - name: Deploy Bind9 configuration
   template:
     src: bind/{{ item }}.j2
@@ -22,11 +17,10 @@
   loop:
     - named.conf
     - named.conf.local
+    - named.conf.key
     - named.conf.options
-  notify: Reload Bind9
-
-- include_tasks: dnssec.yml
-  when: is_master
+  when: item != "named.conf.key" or bind.rfc2136_keys is defined
+  notify: systemctl reload bind9.service
 
 - name: Indicate role in motd
   template:
diff --git a/roles/bind-authoritative/templates/bind/named.conf.key.j2 b/roles/bind-authoritative/templates/bind/named.conf.key.j2
new file mode 100644
index 0000000000000000000000000000000000000000..6d16ebeb482a518378fbf8b99188b84d4865791b
--- /dev/null
+++ b/roles/bind-authoritative/templates/bind/named.conf.key.j2
@@ -0,0 +1,9 @@
+{{ ansible_header | comment(decoration='// ') }}
+
+// Let's Encrypt Challenge DNS-01 key
+{% for keyname,key in bind.rfc2136_keys.items() %}
+key "{{ keyname }}" {
+	algorithm {{ key.algorithm }};
+	secret "{{ key.secret }}";
+};
+{% endfor %}
diff --git a/roles/bind-authoritative/templates/bind/named.conf.local.j2 b/roles/bind-authoritative/templates/bind/named.conf.local.j2
index a91863c714c6330ecc3683421509db9ba70e6ac7..ccb3e1fd976c524bd2c38f10becd886ff3c7ca2e 100644
--- a/roles/bind-authoritative/templates/bind/named.conf.local.j2
+++ b/roles/bind-authoritative/templates/bind/named.conf.local.j2
@@ -3,148 +3,35 @@
 // Consider adding the 1918 zones here, if they are not used in your
 // organization
 //include "/etc/bind/zones.rfc1918";
+{% if bind.rfc2136_keys is defined %}
 
-{% if is_master -%}
-// Let's Encrypt Challenge DNS-01 key
-key "certbot_challenge." {
-	algorithm hmac-sha512;
-	secret "{{ certbot_dns_secret }}";
-};
-key "certbot_adm_challenge." {
-	algorithm hmac-sha512;
-	secret "{{ certbot_adm_dns_secret }}";
-};
+include "/etc/bind/named.conf.key";
 {% endif %}
 
-// Let's Encrypt Challenge DNS-01 zone
-zone "_acme-challenge.crans.org" {
-{% if is_master %}
-	type master;
-	notify yes;
+{% for zonename,zone in bind.zones.items() %}
+zone "{{ zonename }}" {
+{% set zone = bind.default | combine(zone) %}
+	type {{ zone.type | default('primary') }};
+{% if zone.update_policy is defined %}
 	update-policy {
-		grant certbot_challenge. name _acme-challenge.crans.org. txt;
-	};
-{% else %}
-	type slave;
-	masters {
-{% for host in bind.masters %}
-{% for ip in query('ldap', 'ip', host, 'adm') %}
-		{{ ip }};
-{% endfor -%}
+{% for policy in zone.update_policy %}
+		{{ policy }};
 {% endfor %}
 	};
-	notify no;
 {% endif %}
-	file "bak._acme-challenge.crans.org";
-};
-
-// Let's Encrypt Challenge DNS-01 zone
-zone "_acme-challenge.adm.crans.org" {
-{% if is_master %}
-	type master;
-	notify yes;
-	update-policy {
-		grant certbot_adm_challenge. name _acme-challenge.adm.crans.org. txt;
-	};
-{% else %}
-	type slave;
+	file "{{ zone.format | default('') | format(zonename) }}";
+{% if zone.primaries is defined and zone.primaries != False %}
 	masters {
-{% for host in bind.masters %}
-{% for ip in query('ldap', 'ip', host, 'adm') %}
-		{{ ip }};
-{% endfor -%}
+{% for primary in zone.primaries %}
+		{{ primary }};
 {% endfor %}
 	};
-	notify no;
 {% endif %}
-	file "bak._acme-challenge.adm.crans.org";
-};
-
-zone "_acme-challenge.crans.fr" {
-{% if is_master %}
-	type master;
-	notify yes;
-	update-policy {
-		grant certbot_challenge. name _acme-challenge.crans.fr. txt;
-	};
-{% else %}
-	type slave;
-	masters {
-{% for host in bind.masters %}
-{% for ip in query('ldap', 'ip', host, 'adm') %}
-		{{ ip }};
-{% endfor -%}
-{% endfor %}
-	};
-	notify no;
-{% endif %}
-	file "bak._acme-challenge.crans.fr";
-};
-
-zone "_acme-challenge.crans.eu" {
-{% if is_master %}
-	type master;
-	notify yes;
-	update-policy {
-		grant certbot_challenge. name _acme-challenge.crans.eu. txt;
-	};
-{% else %}
-	type slave;
-	masters {
-{% for host in bind.masters %}
-{% for ip in query('ldap', 'ip', host, 'adm') %}
-		{{ ip }};
-{% endfor -%}
-{% endfor %}
-	};
-	notify no;
-{% endif %}
-	file "bak._acme-challenge.crans.eu";
-};
-
-// Crans zones
-{% for zone in bind.zones|sort %}
-zone "{{ zone }}" {
-{% if is_master %}
-	type master;
-	// Apparmor: Need to ln -s /var/cache/bind/generated /var/local/re2o-services/dns/generated
-	file "generated/{{ zone }}.db";
-	notify yes;
-{% else %}
-	type slave;
-	file "bak.{{ zone }}";
-	masters {
-{% for host in bind.masters %}
-{% for ip in query('ldap', 'ip', host, 'adm') %}
-		{{ ip }};
-{% endfor -%}
-{% endfor %}
-	};
-	notify no;
-{% endif %}
-};
-
-{% endfor %}
-
-// Crans reverse zones
-{% for zone in bind.reverse %}
-zone "{{ zone }}" {
-{% if is_master %}
-	type master;
-	// Apparmor: Need to ln -s /var/cache/bind/generated /var/local/re2o-services/dns/generated
-	file "generated/{{ zone }}.db";
-	notify yes;
-{% else %}
-	type slave;
-	file "bak.{{ zone }}";
-	masters {
-{% for host in bind.masters %}
-{% for ip in query('ldap', 'ip', host, 'adm') %}
-		{{ ip }};
-{% endfor -%}
-{% endfor %}
-	};
-	notify no;
+	notify {{ zone.notify | default('no') }};
+{% if zone.dnssec is defined and zone.dnssec %}
+	inline-signing yes;
+	auto-dnssec maintain;
+	serial-update-method increment;
 {% endif %}
 };
 
diff --git a/roles/bind-authoritative/templates/bind/named.conf.options.j2 b/roles/bind-authoritative/templates/bind/named.conf.options.j2
index f76d7e20e9382f54ff002fea5f523b26292b4952..f972196bf9c98f4e091b81a038509593c845367a 100644
--- a/roles/bind-authoritative/templates/bind/named.conf.options.j2
+++ b/roles/bind-authoritative/templates/bind/named.conf.options.j2
@@ -2,6 +2,10 @@
 
 options {
 	directory "/var/cache/bind";
+{% if bind.options.key_directory is defined %}
+
+	key-directory "{{ bind.options.key_directory }}";
+{% endif %}
 
 	// If there is a firewall between you and nameservers you want
 	// to talk to, you may need to fix the firewall to allow multiple
@@ -30,20 +34,16 @@ options {
 	// Hide version from clients
 	version "not currently available";
 
-{% if is_master %}
+{% if bind.options.secondaries is defined %}
 	allow-transfer {
-{% for host in bind.slaves %}
-{% for ip in query('ldap', 'ip', host, 'adm') %}
-		{{ ip }};
-{% endfor %}
+{% for host in bind.options.secondaries %}
+		{{ host }};
 {% endfor %}
 	};
 
 	also-notify {
-{% for host in bind.slaves %}
-{% for ip in query('ldap', 'ip', host, 'adm') %}
-		{{ ip }};
-{% endfor %}
+{% for host in bind.options.secondaries %}
+		{{ host }};
 {% endfor %}
 	};
 {% else %}
diff --git a/roles/bind-authoritative/templates/update-motd.d/05-service.j2 b/roles/bind-authoritative/templates/update-motd.d/05-service.j2
index 39aab8509f2eeecb2b92e438aee2d950b6dba164..e36d04f598c3d4c7778cc7e511e58e910b1469d8 100755
--- a/roles/bind-authoritative/templates/update-motd.d/05-service.j2
+++ b/roles/bind-authoritative/templates/update-motd.d/05-service.j2
@@ -1,7 +1,3 @@
 #!/usr/bin/tail +14
 {{ ansible_header | comment }}
-{% if is_master %}
-> Bind9 (autoritaire, maître) a été déployé sur cette machine. Voir /etc/bind/.
-{% else %}
-> Bind9 (autoritaire, esclave) a été déployé sur cette machine. Voir /etc/bind/.
-{% endif %}
+> Bind9 (authoritative) a été déployé sur cette machine. Voir /etc/bind/.