diff --git a/Makefile b/Makefile
index 20b28d131437534798a0640d0381d05af6ca71b7..b78ce7d2706ceb2b140f090b9a359820e8e69f51 100644
--- a/Makefile
+++ b/Makefile
@@ -75,6 +75,21 @@ endif
 	$(ANSIBLE_BIN) -i $(i) -l $(l) -m ping all
 	$(ANSIBLE_PLAYBOOK_BIN) -i $(i) site.yml -e conf_update=true -l $(l) -t $(t)
 
+.PHONY: deploy-ha
+## deploy-ha: Run deployment playbooks : i=<inventory-path>, l=<host-or-group>, t=<tag>
+deploy-ha:
+ifndef i
+	$(error i is undefined)
+endif
+ifndef l
+	$(eval l=all)
+endif
+ifndef t
+	$(eval t=all)
+endif
+	$(ANSIBLE_BIN) -i $(i) -l $(l) -m ping all
+	$(ANSIBLE_PLAYBOOK_BIN) -i $(i) site-ha.yml -e conf_update=true -l $(l) -t $(t)
+
 .PHONY: image-validate
 ## image-validate: Check that Packer image is valid : build=<path-to-packer-file>
 image-validate:
diff --git a/doc/deploy-ha.md b/doc/deploy-ha.md
new file mode 100644
index 0000000000000000000000000000000000000000..ed9bcd4b3a1c2e6a09e324438e8d784967479ff0
--- /dev/null
+++ b/doc/deploy-ha.md
@@ -0,0 +1,84 @@
+# HA deployment
+
+## Prerequisites
+
+* root access on the computer used for the deployment, with the following :
+  * SSH access to every computers of the deployment scope
+  * `git` package
+* An account on [mirismanager](https://mirismanager.ubicast.eu)
+
+## Configuration on miris manager
+
+Go to the [miris manager](https://mirismanager.ubicast.eu/) web page corresponding to the mediaserver.
+Go to the ERP webpage of the server.
+
+In the `Mot de passe` tab clic on `Nouvel identifiant` and fill the fields as following (keep default value if the field is not mentionned) :
+```sh
+Type d'identifiant : Database
+Mot de passe : <Générer un mot de passe complexe avec le bouton associé>
+Avancé : <Cocher>
+Lien : localhost:54321
+```
+
+Clic on `Envoyer`
+
+You can check in `Exporter tous les identifiants > envsetup` that the `DB_PORT='54321'` line is showing.
+
+## Installation scripts preparation
+
+On the computer used for the deployment, go to the `/root` folder.
+
+Get the latest deployment scripts :
+```sh
+cd /root
+git clone https://git.ubicast.net/mediaserver/envsetup
+cd envsetup
+```
+
+Configure the environment as described [here](./install.md)
+
+## HA inventory configuration
+
+Make a copy of the example inventory :
+```sh
+cp -r inventories/exemple-ha inventories/<client-ha>
+```
+Configure the following :
+* `inventories/<client-ha>/hosts` : change the IP addresses according to the real deployment environment
+* `inventories/<client-ha>/group_vars/all.yml` : adapt the IP addresses following the `server pgX` and `server msX` statements
+* `inventories/<client-ha>/host_vars/*.yml` : in every file put the skyreach API key in place of the `changeme` statement
+
+## Verification
+
+Before deploying, check that every computer is accessible from ansible with the following command :
+```sh
+ansible -i inventories/<client-ha> -m ping all
+```
+If a computer response is `UNREACHABLE`, check if he is powered on and accessible through SSH
+
+## Deployment
+
+You can deploy the environment with the following command :
+```sh
+make deploy-ha i=inventories/<client-ha>
+```
+
+# Known error (patched in the next skyreach release)
+
+If the following error is encountered during the deployment :
+```sh
+[...]
+Action "init" failed:
+Database creation failed. The following command exited with code 2:
+PGPASSWORD='*****' psql -w -q -A -h localhost -p 5432 -U postgres -c "CREATE USER skyreach WITH PASSWORD '******';"
+psql: FATAL:  password authentication failed for user "postgres"
+FATAL:  password authentication failed for user "postgres"
+[...]
+```
+It may be linked to a current skyreach bug (a patch is waiting to be deployed at the time of writing) causing it not to take the DB_PORT from mirismanager configuration in account (5432 instead of 54321 for HA).
+
+You can edit the skyreach configuration manual with the following command :
+```sh
+ansible -i inventories/<client-ha> -m shell -a "sed -i \"s/'PORT': .*/'PORT': '54321'/g\" /home/skyreach/htdocs/skyreach_site/settings_override.py" ms1
+```
+and then deploy again as described in the previous section
diff --git a/roles/ferm-configure/handlers/main.yml b/roles/ferm-configure/handlers/main.yml
index 920efd0e606e42d3ad642e2cc27a7f93fa5d29f6..1df71e19ab322054f7a1de2cf01b075a5a4749a8 100644
--- a/roles/ferm-configure/handlers/main.yml
+++ b/roles/ferm-configure/handlers/main.yml
@@ -1,9 +1,9 @@
 ---
 
-- name: restart ferm
+- name: reload ferm
   when: ansible_facts.services['ferm.service'] is defined
   systemd:
     name: ferm
-    state: restarted
+    state: reloaded
 
 ...
diff --git a/roles/ferm-configure/tasks/main.yml b/roles/ferm-configure/tasks/main.yml
index a10cf787ca6f978c32ac4842bac4eedcd031ab2c..98f3ace9ce43b4a80a5b1b0358c1c56cd167f6d8 100644
--- a/roles/ferm-configure/tasks/main.yml
+++ b/roles/ferm-configure/tasks/main.yml
@@ -1,5 +1,8 @@
 ---
 
+- name: populate service facts
+  service_facts:
+
 - name: directories
   loop:
     - /etc/ferm/ferm.d
@@ -12,14 +15,14 @@
 
 - name: global
   when: ferm_global_settings | d(false)
-  notify: restart ferm
+  notify: reload ferm
   copy:
     dest: /etc/ferm/ferm.d/{{ ferm_rules_filename }}.conf
     content: "{{ ferm_global_settings }}"
 
 - name: input
   when: ferm_input_rules | length > 0
-  notify: restart ferm
+  notify: reload ferm
   copy:
     dest: /etc/ferm/input.d/{{ ferm_rules_filename }}.conf
     content: |
@@ -36,7 +39,7 @@
 
 - name: output
   when: ferm_output_rules | length > 0
-  notify: restart ferm
+  notify: reload ferm
   copy:
     dest: /etc/ferm/output.d/{{ ferm_rules_filename }}.conf
     content: |
@@ -53,7 +56,7 @@
 
 - name: forward
   when: ferm_forward_rules | length > 0
-  notify: restart ferm
+  notify: reload ferm
   copy:
     dest: /etc/ferm/forward.d/{{ ferm_rules_filename }}.conf
     content: |
diff --git a/site-ha.yml b/site-ha.yml
new file mode 100755
index 0000000000000000000000000000000000000000..a05ec42539e90364fb5c383107a9a5aa940b32b8
--- /dev/null
+++ b/site-ha.yml
@@ -0,0 +1,34 @@
+#!/usr/bin/env ansible-playbook
+---
+
+- name: PYTHON
+  hosts: all
+  gather_facts: false
+  tasks:
+    - name: ensure python3 is installed
+      register: python_install
+      changed_when: "'es_pyinstall' in python_install.stdout_lines"
+      raw: command -v python3 || echo es_pyinstall && apt update && apt install -y python3-minimal python3-apt
+
+- import_playbook: playbooks/postgres-ha.yml
+  tags: postgres
+- import_playbook: playbooks/msmonitor.yml
+  tags: monitor
+- import_playbook: playbooks/mirismanager.yml
+  tags: manager
+- import_playbook: playbooks/wowza.yml
+  tags: wowza
+- import_playbook: playbooks/celerity.yml
+  tags: celerity
+- import_playbook: playbooks/mediaworker.yml
+  tags: worker
+- import_playbook: playbooks/mediaserver.yml
+  tags: server
+- import_playbook: playbooks/mediavault.yml
+  tags: vault
+- import_playbook: playbooks/mediaimport.yml
+  tags: import
+- import_playbook: playbooks/netcapture.yml
+  tags: netcapture
+
+...