diff --git a/software/slapos-master/buildout.hash.cfg b/software/slapos-master/buildout.hash.cfg
index 506acf6f638417b7ba178507af23924b9a6997ab..11ce266378c0e79f7d01de730fdb6964130717ca 100644
--- a/software/slapos-master/buildout.hash.cfg
+++ b/software/slapos-master/buildout.hash.cfg
@@ -15,11 +15,11 @@
 # not need these here).
 [template-erp5]
 filename = instance-erp5.cfg.in
-md5sum = 1489091851f27c41243eeaa4967cc91c
+md5sum = be397f283e5a21f9d986252072f42835
 
 [template-balancer]
 filename = instance-balancer.cfg.in
-md5sum = a410f10fe9766c9321ffd7b18ace5a4f
+md5sum = 5562e6738470b0fc96211f46bf8d41bc
 
 [template-apache-backend-conf]
 filename = apache-backend.conf.in
diff --git a/software/slapos-master/instance-balancer.cfg.in b/software/slapos-master/instance-balancer.cfg.in
index 8d5fdac8528f129d5d24e47406ca91a33b4b3ecd..3064ad3d3ec087d09cdb7043dd719b276603f3d1 100644
--- a/software/slapos-master/instance-balancer.cfg.in
+++ b/software/slapos-master/instance-balancer.cfg.in
@@ -170,6 +170,7 @@ recipe = slapos.cookbook:publish.serialised
 {{   family_name ~ '-v6' }} = {% if ipv6_set %}{{ scheme ~ '://[' ~ ipv6 ~ ']:' ~ apache_port }}{% endif %}
 {{   family_name }} = {{ scheme ~ '://' ~ ipv4 ~ ':' ~ apache_port }}
 {% endfor -%}
+monitor-base-url = ${monitor-publish-parameters:monitor-base-url}
 
 [apache-ssl]
 {% if ssl_parameter_dict.get('key') -%}
@@ -232,11 +233,34 @@ private = ${:ca-dir}/private
 certs = ${:ca-dir}/certs
 newcerts = ${:ca-dir}/newcerts
 crl = ${:ca-dir}/crl
+apachedex = ${monitor-directory:private}/apachedex
+
+[monitor-generate-apachedex-report]
+recipe = slapos.cookbook:wrapper
+wrapper-path = ${monitor-directory:reports}/${:command}
+command-line = "{{ parameter_dict['run-apachedex-location'] }}" "{{ parameter_dict['apachedex-location'] }}" "${directory:apachedex}" --default "${apachedex-parameters:default}" --apache-log-list "${apachedex-parameters:apache-log-list}" --base-list "${apachedex-parameters:base-list}" --skip-base-list "${apachedex-parameters:skip-base-list}" --erp5-base-list "${apachedex-parameters:erp5-base-list}"
+command = apachedex_every_3_hour
+
+[apachedex-parameters]
+default_parameter = 
+# XXX - Sample log file with curent date: apache_access.log-%(date)s.gz
+# which will be equivalent to apache_access.log-20150112.gz if the date is 2015-01-12
+apache-log-list = ${apache-conf-parameter-dict:access-log}
+default = ${monitor-directory:etc}/apdex_default
+base-list = ${monitor-directory:etc}/apdex_base_list
+skip-base-list = ${monitor-directory:etc}/apdex_skip_base_list
+erp5-base-list = ${monitor-directory:etc}/apdex_erp5_base_list
 
 [monitor-instance-parameter]
 monitor-httpd-ipv6 = {{ (ipv6_set | list)[0] }}
 monitor-httpd-port = {{ next_port() }}
 monitor-title = Balancer monitor
+password = {{ slapparameter_dict['monitor-passwd'] }}
+instance-configuration = 
+  file apachedex-default ${apachedex-parameters:default}
+  file apachedex-base-list ${apachedex-parameters:base-list}
+  file apachedex-skip-base-list ${apachedex-parameters:skip-base-list}
+  file apachedex-erp5-base-list ${apachedex-parameters:erp5-base-list}
 
 [buildout]
 extends =
@@ -245,4 +269,5 @@ extends =
 parts +=
   publish
   logrotate-apache
+  monitor-generate-apachedex-report
   {{ part_list | join('\n  ') }}
diff --git a/software/slapos-master/instance-erp5.cfg.in b/software/slapos-master/instance-erp5.cfg.in
index 0c19d5993fecc6b1de55e7c59f607dadf8ae847c..1b5aec4913a70a6934a70c0e93de9dac1ba0007c 100644
--- a/software/slapos-master/instance-erp5.cfg.in
+++ b/software/slapos-master/instance-erp5.cfg.in
@@ -8,6 +8,7 @@
 {% set jupyter_dict = slapparameter_dict.get('jupyter', {}) -%}
 {% set has_jupyter = jupyter_dict.get('enable', jupyter_enable_default.lower() in ('true', 'yes')) -%}
 {% set jupyter_zope_family = jupyter_dict.get('zope-family', '') -%}
+{% set monitor_base_url_dict = {} -%}
 [request-common]
 <= request-common-base
 config-use-ipv6 = {{ dumps(slapparameter_dict.get('use-ipv6', False)) }}
@@ -22,7 +23,10 @@ software-type = {{ software_type }}
 return = {{ ' '.join(ret) }}
 {% for ret, publish in ret.iteritems() -%}
 {%   if publish -%}
-{%     do publish_dict.__setitem__(name ~ '-' ~ ret, '${' ~ section ~ ':connection-' ~ ret ~ '}')%}
+{%     do publish_dict.__setitem__(name ~ '-' ~ ret, '${' ~ section ~ ':connection-' ~ ret ~ '}') %}
+{%   endif -%}
+{%   if ret == "monitor-base-url" -%}
+{%     do monitor_base_url_dict.__setitem__(section, '${' ~ section ~ ':connection-' ~ ret ~ '}') -%}
 {%   endif -%}
 {% endfor -%}
 {{ root_common.sla(name) }}
@@ -34,10 +38,10 @@ config-{{ k }} = {{ '${' ~ v ~ '}' }}
 {% endfor -%}
 {% endmacro -%}
 
-{{ request('memcached-persistent', 'kumofs', 'kumofs', {'tcpv4-port': 2000}) }}
-{{ request('memcached-volatile', 'kumofs', 'memcached', {'tcpv4-port': 2010, 'ram-storage-size': 64}) }}
-{{ request('cloudooo', 'cloudooo', 'cloudooo', {'tcpv4-port': 2020}) }}
-{{ request('mariadb', 'mariadb', 'mariadb', {'tcpv4-port': 2099}, {'database-list': True, 'test-database-list': True}) }}
+{{ request('memcached-persistent', 'kumofs', 'kumofs', {'tcpv4-port': 2000}, {'url': True, 'monitor-base-url': False}, key_config={'monitor-passwd': 'monitor-htpasswd:passwd'}) }}
+{{ request('memcached-volatile', 'kumofs', 'memcached', {'tcpv4-port': 2010, 'ram-storage-size': 64}, {'url': True, 'monitor-base-url': False}, key_config={'monitor-passwd': 'monitor-htpasswd:passwd'}) }}
+{{ request('cloudooo', 'cloudooo', 'cloudooo', {'tcpv4-port': 2020}, {'url': True, 'monitor-base-url': False}, key_config={'monitor-passwd': 'monitor-htpasswd:passwd'}) }}
+{{ request('mariadb', 'mariadb', 'mariadb', {'tcpv4-port': 2099}, {'database-list': True, 'test-database-list': True, 'monitor-base-url': False}, key_config={'monitor-passwd': 'monitor-htpasswd:passwd'}) }}
 {% if has_posftix -%}
 {{   request('smtp', 'postfix', 'smtp', {'tcpv4-port': 2025, 'smtpd-sasl-user': 'erp5@nowhere'}, key_config={'smtpd-sasl-password': 'publish-early:smtpd-sasl-password'}) }}
 {%- else %}
@@ -74,7 +78,7 @@ connection-url = smtp://127.0.0.2:0/
 {%   else -%}
 {{     assert(server_type == 'zeo', server_type) -}}
 {# BBB: for compatibility, keep 'zodb' as partition_reference for ZEO -#}
-{{     request('zodb', 'zodb-' ~ server_type, 'zodb-' ~ server_type, {'tcpv4-port': 2100, 'zodb-dict': server_dict}, dict.fromkeys(('storage-dict', 'tidstorage-ip', 'tidstorage-port'))) }}
+{{     request('zodb', 'zodb-' ~ server_type, 'zodb-' ~ server_type, {'tcpv4-port': 2100, 'zodb-dict': server_dict}, dict.fromkeys(('storage-dict', 'tidstorage-ip', 'tidstorage-port', 'monitor-base-url')), key_config={'monitor-passwd': 'monitor-htpasswd:passwd'}) }}
 {%   endif -%}
 {% endfor -%}
 
@@ -126,6 +130,7 @@ name = neo-${gen-neo-cluster-base:passwd}
 return =
   zope-address-list
   hosts-dict
+  monitor-base-url
 {% set bt5_default_list = 'erp5_full_text_myisam_catalog erp5_configurator_standard erp5_configurator_maxma_demo erp5_configurator_ung erp5_configurator_run_my_doc slapos_configurator' -%}
 {% if has_jupyter -%}
 {%   set bt5_default_list = bt5_default_list + ' erp5_data_notebook' -%}
@@ -141,6 +146,7 @@ config-inituser-login = {{ dumps(inituser_login) }}
 config-inituser-password = ${publish-early:inituser-password}
 config-kumofs-url = ${request-memcached-persistent:connection-url}
 config-memcached-url = ${request-memcached-volatile:connection-url}
+config-monitor-passwd = ${monitor-htpasswd:passwd}
 config-mysql-test-url-list = ${request-mariadb:connection-test-database-list}
 config-mysql-url-list = ${request-mariadb:connection-database-list}
 config-site-id = {{ dumps(site_id) }}
@@ -183,6 +189,7 @@ software-type = zope
 [{{ section_name }}]
 <= request-zope-base
 name = {{ partition_name }}
+{% do monitor_base_url_dict.__setitem__(section_name, '${' ~ section_name ~ ':connection-monitor-base-url}') -%}
 {{ root_common.sla(partition_name) }}
 config-name = {{ dumps(custom_name) }}
 config-instance-count = {{ dumps(zope_parameter_dict.get('instance-count', 1)) }}
@@ -288,6 +295,7 @@ return =
   {{ family }}
   {{ family }}-v6
 {% endfor -%}
+{% do monitor_base_url_dict.__setitem__('request-balancer', '${' ~ 'request-balancer' ~ ':connection-monitor-base-url}') -%}
 config-zope-family-dict = {{ dumps(zope_family_parameter_dict) }}
 config-tcpv4-port = {{ dumps(balancer_dict.get('tcpv4-port', 2150)) }}
 {% for zope_section_id, name in zope_address_list_id_dict.items() -%}
@@ -300,6 +308,8 @@ config-ssl = {{ dumps(balancer_dict.get('ssl', {})) }}
 config-backend-path-dict = {{ dumps(zope_backend_path_dict) }}
 config-ssl-authentication-dict = {{ dumps(ssl_authentication_dict) }}
 config-shared-certificate-authority-path = ${directory:ca-dir} 
+config-monitor-passwd = ${monitor-htpasswd:passwd}
+
 
 [request-frontend-base]
 {% if has_frontend -%}
@@ -323,6 +333,7 @@ return = site_url
 {% endif -%}{# if zope_partition_dict -#}
 
 [publish]
+<= monitor-publish
 recipe = slapos.cookbook:publish.serialised
 -extends = publish-early
 {% if 'neo' in storage_dict -%}
@@ -340,11 +351,25 @@ hosts-dict = {{ '${' ~ zope_address_list_id_dict.keys()[0] ~ ':connection-hosts-
 {{   name }} = {{ value }}
 {% endfor -%}
 
-{{ root_common.common_section() }}
+[monitor-instance-parameter]
+ monitor-httpd-port = 8386
 
+{{ root_common.common_section() }}
 
 [buildout]
+extends = {{ template_monitor }}
 parts += 
   apache-certificate-authority
   fix-ca-folder
   publish
+  monitor-base
+
+[monitor-conf-parameters]
+  monitor-title = ERP5 monitor
+  password = ${monitor-htpasswd:passwd}
+
+[monitor-base-url-dict]
+  {% for key, value in monitor_base_url_dict.items() -%}
+  {{ key }} = {{ value }}
+  {% endfor %}
+