diff --git a/group_vars/all/vault.yml b/group_vars/all/vault.yml
new file mode 100644
index 0000000000000000000000000000000000000000..865eacadd32a4c2a3bcad2cc5ee26d997c225c7e
--- /dev/null
+++ b/group_vars/all/vault.yml
@@ -0,0 +1,28 @@
+$ANSIBLE_VAULT;1.1;AES256
+39306562623331663735646339313933373165343362386465376564653434313263336661316130
+3365653666303038613330666534313737653539393362660a396535643361643065386561636338
+63326336643465653061376135653031373664613139306338326236373963353433313334633737
+6464346433316634370a616637343637386233623736653331616131393732633861323638623931
+34353337636131643531343537373132666338663138633832613034343733643630373532306438
+33336638643966343738363333346236393937643165346133376561333663383766303462306338
+39356634376435313531356465663266383766373863646265303435303661393462663461306461
+30666335343731356633366230393631623237313363333066663062346537333362653334336466
+63343264366566346235376630326261396461643462376231373165393864666563656430383063
+32303737353930333962316230653961343961643165613837343565313636363833313830333435
+34643664616662326334323836346232633131663361613831353563303761313064303133623637
+64353865373638396161623861323063306333353735356634646437646636303565623261343634
+65636463613064663732663366616130333632333961373835656534633930356637643834313739
+37626362313763356635336134393038616235333736626632343863383033356464333462306430
+35393861333364666232356263396364386165613730353162356362333064303762353464346430
+62623635373634646330393364636139363962313666346232363734326334393362326661353765
+65373166656465313262373636353235306666323234343866383065326335633261643363346433
+63633839663538663536656239356336313732316461393461326337366134303933623538643163
+63393031613061306539393261386636633430353661336666626530306365333763366232353663
+38666632323663646135316361376665336165343364393937346636343165633065346462343163
+64633164623366633837393737363937336537666664646530393363393537653838636634666439
+39306232383237613238353961343561666362363763393436393536336634376637353534393632
+30623132646435303331313130633765316133323538613737353362663334343239346566663537
+33656562616165633262383037306537356536316439646533623033663433363464383163376431
+38376233396166353862306461363036353561336664346230396239323439366163653232643432
+64643634333635363838343764613063363166303763303036333066386332643333363237626366
+623363313165323038643166313535616233
diff --git a/ldap.yml b/ldap.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3f613fff99924f8df9b6697af0b83542c6e9b6f3
--- /dev/null
+++ b/ldap.yml
@@ -0,0 +1,22 @@
+---
+# Plug LDAP on all servers
+- hosts: all
+  vars:
+    # LDAP binding
+    ldap_base: 'dc=crans,dc=org'
+    ldap_master_ipv4: '10.231.136.19'
+    ldap_local_replica_uri:
+      - "ldpa://10.231.136.38"
+      - "ldpa://10.231.136.4"
+    ldap_master_uri: "ldap://{{ ldap_master_ipv4 }}"
+    ldap_user_tree: "cn=Utilisateurs,{{ ldap_base }}"
+    ldap_nslcd_bind_dn: "cn=nslcd,ou=service-users,{{ ldap_base }}"
+    ldap_nslcd_passwd: "{{ vault_ldap_nslcd_passwd }}"
+
+    # Scripts will tell users to go there to manage their account
+    intranet_url: 'https://intranet.crans.org/'
+
+    # SSH keys for root account to use when LDAP is broken
+    ssh_pub_keys: "{{ vault_ssh_pub_keys }}"
+  roles:
+    - ldap-client
diff --git a/roles/ldap-client/handlers/main.yml b/roles/ldap-client/handlers/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f0f3111bbe5253acd2e1ceb94275097042abd017
--- /dev/null
+++ b/roles/ldap-client/handlers/main.yml
@@ -0,0 +1,16 @@
+---
+- name: Reconfigure libnss-ldapd package
+  command: dpkg-reconfigure libnss-ldapd -f noninteractive
+
+- name: Restart nslcd service
+  service:
+    name: nslcd
+    state: restarted
+
+# Empty cache when nslcd is restarted
+- name: Restart nscd service
+  service:
+    name: nscd
+    state: restarted
+  ignore_errors: true  # Sometimes service do not exist
+  listen: Restart nslcd service
diff --git a/roles/ldap-client/tasks/group_security.yml b/roles/ldap-client/tasks/group_security.yml
new file mode 100644
index 0000000000000000000000000000000000000000..08fb426c01cc2d0efda0413b04916abc6253fad5
--- /dev/null
+++ b/roles/ldap-client/tasks/group_security.yml
@@ -0,0 +1,24 @@
+---
+# Filter SSH on groups
+- name: Filter SSH on groups
+  lineinfile:
+    dest: /etc/ssh/sshd_config
+    regexp: ^AllowGroups
+    line: AllowGroups ssh nounou apprenti cableur root
+    state: present
+
+# To gain root access with ldap rights
+- name: Install SUDO package
+  package:
+    name: sudo
+    state: present
+  register: package_result
+  retries: 3
+  until: package_result is succeeded
+
+# Set sudo group
+- name: Configure sudoers sudo group
+  template:
+    src: sudoers.j2
+    dest: /etc/sudoers
+    mode: 0440
diff --git a/roles/ldap-client/tasks/install_ldap.yml b/roles/ldap-client/tasks/install_ldap.yml
new file mode 100644
index 0000000000000000000000000000000000000000..cb9959c2ceecea83d45e0c2f41e54276701b51cd
--- /dev/null
+++ b/roles/ldap-client/tasks/install_ldap.yml
@@ -0,0 +1,35 @@
+---
+# Install LDAP client packages
+- name: Install LDAP client packages
+  apt:
+    update_cache: true
+    name:
+      - nslcd
+      - libnss-ldapd
+      - libpam-ldapd
+      - nscd  # local cache
+    state: present
+  register: apt_result
+  retries: 3
+  until: apt_result is succeeded
+
+# Configure /etc/nslcd.conf
+- name: Configure nslcd LDAP credentials
+  template:
+    src: nslcd.conf.j2
+    dest: /etc/nslcd.conf
+    mode: 0600
+  notify: Restart nslcd service
+
+# Configure /etc/nsswitch.conf
+- name: Configure NSS to use LDAP
+  lineinfile:
+    dest: /etc/nsswitch.conf
+    regexp: "^{{ item }}:"
+    line: "{{ item }}: files ldap"
+  loop:
+    - passwd
+    - group
+    - shadow
+    - sudoers
+  notify: Restart nslcd service
diff --git a/roles/ldap-client/tasks/main.yml b/roles/ldap-client/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..7b79d34d18bf079a6eb40ee48b4dff018bec5786
--- /dev/null
+++ b/roles/ldap-client/tasks/main.yml
@@ -0,0 +1,24 @@
+---
+# Install and configure main LDAP tools
+- include_tasks: install_ldap.yml
+
+# Filter who can access server and sudo on groups
+- include_tasks: group_security.yml
+
+# Some userland scripts specific to LDAP install
+- include_tasks: userland_scripts.yml
+
+# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=568577
+- name: Ensure home directories are created upon login
+  lineinfile:
+    dest: /etc/pam.d/common-account
+    regexp: 'pam_mkhomedir\.so'
+    line: "session required pam_mkhomedir.so skel=/etc/skel/ umask=0077"
+
+# If LDAP crashes
+- name: Install SSH keys for root account
+  authorized_key:
+    user: root
+    key: "{{ ssh_pub_keys }}"
+    state: present
+    exclusive: true
diff --git a/roles/ldap-client/tasks/userland_scripts.yml b/roles/ldap-client/tasks/userland_scripts.yml
new file mode 100644
index 0000000000000000000000000000000000000000..fa41780bb95eb7c7164e1e6355fb354ac5ec2da0
--- /dev/null
+++ b/roles/ldap-client/tasks/userland_scripts.yml
@@ -0,0 +1,17 @@
+---
+# Disable passwd and chsh
+- name: Copy passwd and chsh scripts
+  template:
+    src: "{{ item }}.j2"
+    dest: /usr/local/bin/{{ item }}
+    mode: 0755
+  loop:
+    - chsh
+    - passwd
+
+# We do not want password change this way
+- name: Symlink chsh.ldap to chsh
+  file:
+    src: /usr/local/bin/chsh
+    dest: /usr/local/bin/chsh.ldap
+    state: link
diff --git a/roles/ldap-client/templates/chsh.j2 b/roles/ldap-client/templates/chsh.j2
new file mode 100644
index 0000000000000000000000000000000000000000..9e6f30f3595dad181fe9ff4c5b6fca60512026b9
--- /dev/null
+++ b/roles/ldap-client/templates/chsh.j2
@@ -0,0 +1,3 @@
+#!/bin/sh
+# {{ ansible_managed }}
+echo "Pour changer votre shell,\nAllez sur l'intranet : {{intranet_url}}"
diff --git a/roles/ldap-client/templates/nslcd.conf.j2 b/roles/ldap-client/templates/nslcd.conf.j2
new file mode 100644
index 0000000000000000000000000000000000000000..0a8c813caf66903de55b159d4db96f5c310bf3db
--- /dev/null
+++ b/roles/ldap-client/templates/nslcd.conf.j2
@@ -0,0 +1,44 @@
+# {{ ansible_managed }}
+
+# The user and group nslcd should run as.
+uid nslcd
+gid nslcd
+
+# The location at which the LDAP server(s) should be reachable.
+{% if ldap_local_replica_uri is defined %}
+{% for uri in ldap_local_replica_uri %}
+uri {{ uri }}
+{% endfor %}
+{% endif %}
+uri {{ ldap_master_uri }}
+
+# The search base that will be used for all queries.
+base {{ ldap_base }}
+base passwd cn=Utilisateurs,{{ ldap_base }}
+base shadow cn=Utilisateurs,{{ ldap_base }}
+base group ou=posix,ou=groups,{{ ldap_base }}
+
+# The LDAP protocol version to use.
+ldap_version 3
+
+# Time limit to wait for an answer
+timelimit 5
+
+# Time limit to wait for a bind
+bind_timelimit 5
+
+# The DN to bind with for normal lookups.
+binddn {{ ldap_nslcd_bind_dn }}
+bindpw {{ ldap_nslcd_passwd }}
+
+# The DN used for password modifications by root.
+#rootpwmoddn cn=admin,dc=example,dc=com
+
+# SSL options
+#ssl off
+tls_reqcert allow
+tls_cacertfile /etc/ssl/certs/ca-certificates.crt
+
+# The search scope.
+#scope sub
+
diff --git a/roles/ldap-client/templates/passwd.j2 b/roles/ldap-client/templates/passwd.j2
new file mode 100644
index 0000000000000000000000000000000000000000..d7ce14d7e4f7f491b1313eefdc4a99e4c1b38f0e
--- /dev/null
+++ b/roles/ldap-client/templates/passwd.j2
@@ -0,0 +1,3 @@
+#!/bin/sh
+# {{ ansible_managed }}
+echo "Pour changer votre mot de passe,\nAllez sur l'intranet : {{intranet_url}}"
diff --git a/roles/ldap-client/templates/sudoers.j2 b/roles/ldap-client/templates/sudoers.j2
new file mode 100644
index 0000000000000000000000000000000000000000..8eb1b8f2327075883c6296f3935531be8f10944b
--- /dev/null
+++ b/roles/ldap-client/templates/sudoers.j2
@@ -0,0 +1,34 @@
+# {{ ansible_managed }}
+#
+# This file MUST be edited with the 'visudo' command as root.
+#
+# Please consider adding local content in /etc/sudoers.d/ instead of
+# directly modifying this file.
+#
+# See the man page for details on how to write a sudoers file.
+#
+Defaults        env_keep += "DARCS_EMAIL EDITOR PYTHONIOENCODING GIT_*"
+Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+Defaults        passprompt_override
+Defaults        passprompt="[sudo] password for %p on %h: "
+
+# Host alias specification
+
+# User alias specification
+User_Alias      NOUNOUS= %nounou
+User_Alias      CABLEUR= %cableur
+User_Alias      ANCIEN= %ancien
+User_Alias      IMPRIMEURS= %imprimeurs
+User_Alias      BUREAU= %bureau
+
+Runas_Alias     USERS= %users
+
+# Cmnd alias specification
+
+# User privilege specification
+root    ALL=(ALL:ALL) ALL
+NOUNOUS    ALL=(ALL:ALL) ALL
+
+# See sudoers(5) for more information on "#include" directives:
+
+#includedir /etc/sudoers.d