diff --git a/README.md b/README.md
index 3edfbf7..e7c4bae 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,151 @@
-# role_modele
+# role_keepalived
-Modèle
\ No newline at end of file
+Rôle de déploiement de keepalived.
+
+## Dépendance
+
+Le rôle *users* est requis afin que l'utilisateur dédié exécutant les scripts définis via `keepalived_track_scripts` soit créé.
+
+## Variables
+
+### keepalived_uid
+
+Identifiant unique permettant d'identifer les membres.
+
+*Valeur par défaut: aucune*
+
+### keepalived_priority
+
+Priorité de la machine pour prendre l'IP de failover.
+Ce chiffre doit être différent sur chaque machine portant le même identifiant unique.
+
+*Valeur par défaut: aucune*
+
+### keepalived_interface
+
+Interface sur laquelle l'IP de failover sera montée.
+
+*Valeur par défaut: aucune*
+
+### keepalived_mail_to
+
+Adresse mail sur laquelle envoyer les alertes.
+
+*Valeur par défaut: aucune*
+
+### keepalived_mail_from
+
+Adresse mail source depuis laquelle partent les alertes.
+Le serveur d'envoi (smtp) est défini par défaut sur localhost.
+
+*Valeur par défaut: aucune*
+
+### keepalived_ipv4
+
+Adresse IPv4 de failover.
+
+*Valeur par défaut: aucune*
+
+### keepalived_ipv6: ""
+
+Adresse IPv6 de failover.
+
+*Valeur par défaut: aucune*
+
+### keepalived_track_scripts
+
+Liste de script dont le code retour doit être à zéro pour que le membre conserve ou puisse prendre l'IP de failover.
+
+*Valeur par défaut: aucune*
+
+### keepalived_track_processes
+
+Liste de processus devant fonctionner pour que le membre conserve ou puisse prendre l'IP de failover.
+
+*Valeur par défaut: aucune*
+
+## Exemples
+
+Dans les exemples ci-dessous, j'utilise aussi le rôle *nftables* afin d'installer et configurer le pare-feu logiciel éponyme.
+
+### host_vars/infra-gw-2315a.nyx.ykn.local.yml
+
+```yaml
+---
+
+# BEGIN role_ifupdown
+ifupdown_interfaces:
+ - interface: eth0
+ ipv4:
+ inet: static
+ address: 192.168.50.250
+ mask: 24
+ dns: 192.168.50.11 192.168.50.16
+ ipv6:
+ inet: static
+ address: fd00:ff50::d250
+ mask: 64
+ dns: fd00:ff50::d011 fd00:ff50::d016
+ - interface: eth1
+ ipv4:
+ inet: static
+ address: 192.168.1.51
+ mask: 24
+ dns: 192.168.1.254
+ ipv6:
+ inet: auto
+# END role_ifupdown
+```
+
+### group_vars/gw.yml
+
+```yaml
+---
+
+# BEGIN role_users
+users:
+ - name: keepalived_script
+ comment: "Dedicated user for keepalived script"
+ update_password: on_create
+ password_lock: true
+ shell: /bin/bash
+# END role_users
+
+# BEGIN role_nftables
+nftables_rules:
+ - filename: keepalived
+ rules:
+ - ip saddr 192.168.50.250 accept
+ - ip saddr 192.168.50.251 accept
+ - ip saddr 192.168.50.252 accept
+# END role_nftables
+
+# BEGIN role_keepalived
+keepalived_ipv4: 192.168.50.254/24
+keepalived_ipv6: fd00:ff50::d254/64
+
+keepalived_uid: "{{ keepalived_ipv4 | split('.') | last | split('/') | first }}"
+
+keepalived_track_scripts:
+ - name: check_nftables_service
+ interval: 5
+ command: /usr/bin/systemctl is-active nftables.service
+# END role_keepalived
+```
+
+### playbook.yml
+
+```yaml
+---
+
+- name: Déployer les passerelles réseau
+ hosts: gateways
+ vars:
+ primary_interface: "{{ ifupdown_interfaces | first }}"
+ keepalived_priority: "{{ 255 - (primary_interface.ipv4.address | split('.') | last | int) }}"
+ keepalived_interface: "{{ primary_interface.interface }}"
+ roles:
+ - name: users
+ - name: nftables
+ - name: keepalived
+```
diff --git a/defaults/main.yml b/defaults/main.yml
new file mode 100644
index 0000000..ca24d30
--- /dev/null
+++ b/defaults/main.yml
@@ -0,0 +1,25 @@
+---
+# defaults file for role_keepalived
+
+keepalived_uid: ""
+keepalived_priority: ""
+keepalived_interface: ""
+
+keepalived_mail_to: ""
+keepalived_mail_from: ""
+
+keepalived_ipv4: ""
+keepalived_ipv6: ""
+
+keepalived_track_scripts: []
+# Exemple:
+# - name: check_haproxy_8080
+# command: /usr/bin/nc -zv 127.0.0.1 8080
+# - name: check_haproxy_8081
+# command: /usr/bin/nc -zv 127.0.0.1 8081
+
+keepalived_track_processes: []
+# Exemple:
+# - name: check_haproxy
+# search: /usr/sbin/haproxy
+# quorum: 2
diff --git a/handlers/main.yml b/handlers/main.yml
new file mode 100644
index 0000000..952280a
--- /dev/null
+++ b/handlers/main.yml
@@ -0,0 +1,8 @@
+---
+# handlers file for network
+
+- name: Redémarrer keepalived.service
+ become: true
+ ansible.builtin.systemd:
+ state: restarted
+ name: keepalived.service
diff --git a/meta/main.yml b/meta/main.yml
index c58bebf..5f58a50 100644
--- a/meta/main.yml
+++ b/meta/main.yml
@@ -1,7 +1,7 @@
galaxy_info:
namespace: ykn
author: pulsar89.5
- description: Rôle modèle
+ description: Rôle de déploiement de keepalived
license: GPL-3.0-or-later
@@ -12,4 +12,5 @@ galaxy_info:
versions:
- all
-dependencies: []
+dependencies:
+ - role: users
diff --git a/tasks/main.yml b/tasks/main.yml
new file mode 100644
index 0000000..d0a1d7a
--- /dev/null
+++ b/tasks/main.yml
@@ -0,0 +1,17 @@
+---
+# tasks file for keepalived
+
+- name: Installer keepalived
+ ansible.builtin.apt:
+ name: keepalived
+ become: true
+
+- name: Déployer la configuration
+ ansible.builtin.template:
+ owner: root
+ group: root
+ mode: u=rw,g=r,o=r
+ src: keepalived.j2
+ dest: /etc/keepalived/keepalived.conf
+ become: true
+ notify: Redémarrer keepalived.service
diff --git a/templates/keepalived.j2 b/templates/keepalived.j2
new file mode 100644
index 0000000..4acb3bb
--- /dev/null
+++ b/templates/keepalived.j2
@@ -0,0 +1,70 @@
+# {{ ansible_managed }}
+
+global_defs {
+{% if keepalived_mail_to | length > 0 %}
+ notification_email {
+ {{ keepalived_mail_to }}
+ }
+{% endif %}
+
+{% if keepalived_mail_from | length > 0 %}
+ notification_email_from {{ keepalived_mail_from }}
+ smtp_server 127.0.0.1
+ smtp_connect_timeout 30
+{% endif %}
+
+ enable_script_security
+ max_auto_priority 50
+}
+
+{% for script in keepalived_track_scripts %}
+vrrp_script {{ script.name }} {
+ script {{ script.command }}
+ interval {{ script.interval }}
+}
+{% endfor %}
+
+{% for process in keepalived_track_processes %}
+vrrp_track_process {{ process.name }} {
+ process "{{ process.search }}"
+ quorum {{ process.quorum }}
+}
+{% endfor %}
+
+vrrp_instance VIP_{{ keepalived_uid }} {
+ state BACKUP
+ priority {{ keepalived_priority }}
+ nopreempt
+
+ interface {{ keepalived_interface }}
+ virtual_router_id {{ keepalived_uid }}
+ advert_int 1
+
+{% if keepalived_ipv4 | length > 0 %}
+ virtual_ipaddress {
+ {{ keepalived_ipv4 }} dev {{ keepalived_interface }} scope global
+ }
+{% endif %}
+
+{% if keepalived_ipv6 | length > 0 %}
+ virtual_ipaddress_excluded {
+ {{ keepalived_ipv6 }} dev {{ keepalived_interface }} scope global
+ }
+{% endif %}
+
+{% if keepalived_track_scripts | length > 0 %}
+ track_script {
+{% for script in keepalived_track_scripts %}
+ {{ script.name }}
+{% endfor%}
+ }
+{% endif %}
+
+{% if keepalived_track_processes | length > 0 %}
+ track_process {
+{% for process in keepalived_track_processes %}
+ {{ process.name }}
+{% endfor %}
+ }
+{% endif %}
+}