diff --git a/check_eol-data/program-languages.cfg b/check_eol-data/program-languages.cfg
index f4376365ee7d0ef6401a2b739cdeae0472245648..60165fae749c2da98cded9b4a95044205836a7bc 100644
--- a/check_eol-data/program-languages.cfg
+++ b/check_eol-data/program-languages.cfg
@@ -30,6 +30,7 @@ php:7.1:2019-12-01:Security support
 php:7.2:2020-11-30:Security support
 php:7.3:2021-12-06:Security support
 php:7.4:2022-11-28:Security support
+php:8.0:2023-11-26:Security support
 
 # ----------------------------------------------------------------------
 node:Node.js is a JavaScript runtime built on a V8 Javascript engine.
diff --git a/check_haproxy_health b/check_haproxy_health
index b37977a817f4ccc8b917da8131a2aa73346cbead..4d4372d86c21c013700dc145084b778d831da8b7 100755
--- a/check_haproxy_health
+++ b/check_haproxy_health
@@ -4,10 +4,11 @@
 # NAGIOS CLIENT CHECK :: haproxy healthcheck
 #
 # ----------------------------------------------------------------------
-# 
+#
 # ----------------------------------------------------------------------
 # 2020-04-27  v1.0  <axel.hahn@iml.unibe.ch>
 # 2020-05-04  v1.1  <axel.hahn@iml.unibe.ch>  show message if monitor-uri was not set
+# 2020-12-03  v1.2  <axel.hahn@iml.unibe.ch>  loop over multiple frontend status urls
 # ======================================================================
 
 . `dirname $0`/inc_pluginfunctions
@@ -50,31 +51,37 @@ if [ -z "$uri" ]; then
 fi
 
 cat $cfgfile | grep "bind\ .*\ ssl\ " >/dev/null && proto=https
-port=`cat $cfgfile | grep "\ bind\ "        | awk '{ print $2 }' | cut -f 2 -d ':'`
 
-url="$proto://${host}:${port}${uri}"
+# fix #4176 - take first found frontend ip only
+# port=`cat $cfgfile | grep "\ bind\ "        | awk '{ print $2 }' | head -1 | cut -f 2 -d ':'`
 
 
 # ----------------------------------------------------------------------
-# check output
+# loop over found bind ports
 # ----------------------------------------------------------------------
 
-# --- get status page
-wget --no-check-certificate -O $tmpfile $url 2>/dev/null
-if [ $? -ne 0 ]; then
-  rm -f $tmpfile
-  ph.abort "UNKNOWN: url $url did not respond. `wget --no-check-certificate -O - -S $url`"
-fi
+for myport in `cat $cfgfile | grep "\ bind\ "        | awk '{ print $2 }' | cut -f 2 -d ':'`
+do
+  url="$proto://${host}:${myport}${uri}"
+
+  # --- get status page
+  wget --no-check-certificate -O $tmpfile $url 2>/dev/null
+  if [ $? -ne 0 ]; then
+    rm -f $tmpfile
+    ph.abort "UNKNOWN: url $url did not respond. `wget --no-check-certificate -O - -S $url`"
+  fi
+
+  grep "200 OK" $tmpfile >/dev/null
+  if [ $? -ne 0 ]; then
+    ph.setStatus "error"
+    ph.status "url $url did not contain 200 OK. `wget --no-check-certificate -O - -S $url`"
+  else
+    ph.status "HA Proxy $url is up and running."
+  fi
 
-grep "200 OK" $tmpfile >/dev/null
-if [ $? -ne 0 ]; then
-  ph.setStatus "error"
-  ph.status "url did not contain 200 OK. `wget --no-check-certificate -O - -S $url`"
-else
-  ph.status "HA Proxy is up and running."
-fi
+  rm -f $tmpfile
 
-rm -f $tmpfile
+done
 
 ph.exit
 
diff --git a/check_haproxy_status b/check_haproxy_status
index 8841b3361bdbd36da3a4dc39a3d6862b342b7677..e06bbaf36c335f77ec13f62c3add2fbe5ff3df51 100755
--- a/check_haproxy_status
+++ b/check_haproxy_status
@@ -13,6 +13,7 @@
 # 2020-04-28  v1.1  <axel.hahn@iml.unibe.ch>  added status and max connections for frontend and backend
 # 2020-04-29  v1.2  <axel.hahn@iml.unibe.ch>  parse ini section by given section
 # 2020-06-03  v1.3  <axel.hahn@iml.unibe.ch>  added ping to each backend server
+# 2020-12-03  v1.4  <axel.hahn@iml.unibe.ch>  added support of multiple front- and backends
 # ======================================================================
 
 . `dirname $0`/inc_pluginfunctions
@@ -101,7 +102,7 @@ function getColnumber(){
   cat $tmpfile | head -1 | sed 's#,#\n#g' | grep -n "^$1$" | cut -f 1 -d ':'
 }
 
-# get column #N 
+# get stats data from column [name]
 function getColumn(){
   typeset -i local _iNumber=$1
   local _filter=$2
@@ -109,6 +110,24 @@ function getColumn(){
   grep "$_filter" $tmpfile | grep -v "stats_frontend" | cut -f 2,$_iNumber -d ','
 }
 
+# get sum of all stats data from column [name]
+function getColSum(){
+  getColumn $1 $2 | rev | cut -f 1 -d "," | rev | while read myvalue
+  do
+    echo +$myvalue
+  done
+}
+
+function checkStatus(){
+  local _value=$1
+  local _must=$2
+  echo $_value | grep "$_must" >/dev/null
+  if [ $? -eq 0 ]; then
+    echo $_value | grep -v "$_must" | grep "." >/dev/null && echo ERROR
+  else
+    echo ERROR
+  fi
+}
 # ----------------------------------------------------------------------
 # build url
 # ----------------------------------------------------------------------
@@ -157,30 +176,32 @@ colLimit=`getColnumber "slim"`
 colCurrentConnections=`getColnumber "scur"`
 colStatus=`getColnumber "status"`
 
-statusFront=`getColumn $colStatus ",FRONTEND," | cut -f 2 -d ","`
-statusBack=` getColumn $colStatus ",BACKEND,"  | cut -f 2 -d ","`
+statusFront=`getColumn $colStatus ",FRONTEND," | cut -f 2 -d "," | tr "\n" " "`
+statusBack=` getColumn $colStatus ",BACKEND,"  | cut -f 2 -d "," | tr "\n" " "`
 
-typeset -i iMaxConnFront=`getColumn $colLimit ",FRONTEND,"`
-typeset -i iMaxConnBack=` getColumn $colLimit ",BACKEND,"`
+typeset -i iMaxConnFront=`getColSum $colLimit ",FRONTEND,"`
+typeset -i iMaxConnBack=` getColSum $colLimit ",BACKEND,"`
 
-typeset -i iFrontend=`getColumn $colCurrentConnections ",FRONTEND,"`
+typeset -i iFrontend=`getColSum $colCurrentConnections ",FRONTEND,"`
 typeset -i iFrontendFree=$iMaxConnFront-$iFrontend
 
 
-typeset -i iBackend=` getColumn $colCurrentConnections ",BACKEND," `
+typeset -i iBackend=` getColSum $colCurrentConnections ",BACKEND," `
 typeset -i iBackendFree=$iMaxConnBack-$iBackend
 
 statusExt=
-if [ ! "$statusFront" = "OPEN" ]; then
+
+if [ "$( checkStatus ""$statusFront"" 'OPEN' )" = "ERROR" ]; then
   ph.setStatus "critical"
-  statusExt="${statusExt}ERROR: frontend status is not OPEN - it is ${statusFront}\n"
+  statusExt="${statusExt}ERROR: a frontend status is not OPEN\n"
 fi
 
-if [ ! "$statusBack" = "UP" ]; then
+if [ "$( checkStatus ""$statusBack"" 'UP' )" = "ERROR" ]; then
   ph.setStatus "critical"
-  statusExt="${statusExt}ERROR: backend status is not UP - it is ${statusBack}\n"
+  statusExt="${statusExt}ERROR: a backend status is not UP\n"
 fi
 
+
 ph.status "FRONT: $statusFront - ${iFrontend} (max: ${iMaxConnFront}) .. BACK: $statusBack - $iBackend (max: ${iMaxConnBack})"
 test -z "$statusExt" || echo "${statusExt}"
 # echo; echo DEBUG: ; cat $tmpfile
@@ -202,11 +223,11 @@ ph.perfadd "backend-free"  "${iBackendFree}"
 getColumn $colCurrentConnections | sed -n "2,$ p" >$tmpfile2
 while read line
 do
-	srv=`echo $line  | cut -f 1 -d ","`
-	val=`echo $line  | cut -f 2 -d ","`
-	label=`echo $srv | tr [:upper:] [:lower:]`
+        srv=`echo $line  | cut -f 1 -d ","`
+        val=`echo $line  | cut -f 2 -d ","`
+        label=`echo $srv | tr [:upper:] [:lower:]`
 
-	# echo "${srv} - ${val}"
+        # echo "${srv} - ${val}"
   echo -n "${srv} - ${val} "
 
   # v1.3: if it is a servername then ping to it
@@ -234,4 +255,4 @@ done < $tmpfile2
 rm -f $cfgfile2 $tmpfile $tmpfile2 2>/dev/null
 ph.exit
 
-# ----------------------------------------------------------------------
\ No newline at end of file
+# ----------------------------------------------------------------------
diff --git a/check_mysqlserver b/check_mysqlserver
index 45e7d651bb7c00a1fbb1cc66e04fcc751c9bb381..f10c6cd51a7ddeb05a06ffd90c761b530983b252 100755
--- a/check_mysqlserver
+++ b/check_mysqlserver
@@ -35,7 +35,8 @@ datafile=/tmp/mysqlvars.out
 NL="
 "
 
-out=
+lastvalue=
+out=" "
 
 # ----------------------------------------------------------------------
 # FUNCTIONS
@@ -115,9 +116,12 @@ OPTIONS:
 
 PARAMETERS:
   -m  method; valid methods are:
-      connections  current/ max connections
-      connects     connects per min and aborted connections/ clients
-      commands     current running statements insert, select, ...
+      connections     current/ max connections
+      connects        connects per min and aborted connections/ clients
+      commands        current running statements insert, select, ...
+      qcache-blocks   query cache blocks total vs free
+      qcache-queries  cached / non cached queries; low memeory prunes 
+      qcache-hits     query cache efficiency: cached vs non cached and inserted
 
 EXAMPLES:
   `basename $0` -i
@@ -133,7 +137,8 @@ function _mysqlreadvars(){
 
 function _mysqlgetvar() {
     local sVarname=$1
-    grep "^$sVarname[^_a-z]" ${datafile} | awk '{ print $2 }'
+    lastvalue=`grep "^$sVarname[^_a-z]" ${datafile} | awk '{ print $2 }'`
+    echo $lastvalue
 }
 # get a value from mysql status output
 # param  string  variable name
@@ -153,14 +158,15 @@ function _mysqlrendervar() {
 
     # get label for perfdata
     local sLabel=`echo ${sVarname} | sed "s#^${sRemove}##g"`
-    
     if [ ! -z $sDeltaUnit ]; then
         local iSpeed=` ph.perfdeltaspeed "mysql-${sVarname}" ${iValue} $sDeltaUnit $sFloat`
-        out="${out}${sLabel}: ${iValue} ... delta = ${iSpeed} per $sDeltaUnit${NL}"
+        out=$out`printf "%25s: %10s %s \n" "${sLabel}" "${iValue}" "... delta = ${iSpeed} per $sDeltaUnit${NL}"`
         ph.perfadd "${sLabel}"   "${iSpeed}"
+        lastvalue=$iSpeed
     else
-        out="${out}${sLabel}: ${iValue}${NL}"
+        out=${out}`printf "%25s: %10s \n" "${sLabel}" "${iValue}${NL}"`
         ph.perfadd "${sLabel}" "${iValue}"
+        lastvalue=$iValue
     fi
 
 }
@@ -230,8 +236,8 @@ if [ $? -ne 0 ]; then
 fi
 
 # --- set optional limits
-# typeset -i iWarnLimit=`     ph.getValueWithParam 0 w "$@"`
-# typeset -i iCriticalLimit=` ph.getValueWithParam 0 c "$@"`
+typeset -i iWarnLimit=`     ph.getValueWithParam 0 w "$@"`
+typeset -i iCriticalLimit=` ph.getValueWithParam 0 c "$@"`
 
 sMode=`ph.getValueWithParam '' m "$@"`
 
@@ -241,8 +247,23 @@ case "${sMode}" in
         descr="current/ max connections"
 
         _mysqlrendervar    max_connections
+        typeset -i iMaxConn=$lastvalue
+
         _mysqlrendervar    Max_used_connections
+        typeset -i iMaxUsed=$lastvalue
+
+        typeset -i iMaxPercent=$iMaxUsed*100/$iMaxConn
+        out=$out"                                 --> $iMaxPercent % ${NL}${NL}"
+
         _mysqlrendervar    Threads_connected
+        typeset -i iThreads=$lastvalue
+        typeset -i iUsage=$iThreads*100/$iMaxConn
+        out=$out"                                 --> $iUsage % ${NL}${NL}"
+        if [ $iWarnLimit -gt 0 -a $iCriticalLimit -gt 0 ]; then
+            ph.setStatusByLimit $iUsage $iWarnLimit $iCriticalLimit
+        fi
+        _mysqlrendervar    Questions
+
         ;;
 
     "connects")
@@ -254,18 +275,18 @@ case "${sMode}" in
 
     "commands")
         descr="currently executed commands"
-        _mysqlrendervar Com_delete  "Com_"
-        _mysqlrendervar Com_insert  "Com_"
-        _mysqlrendervar Com_replace "Com_"
-        _mysqlrendervar Com_select  "Com_"
-        _mysqlrendervar Com_update  "Com_"
+        _mysqlrendervar    Com_delete  "Com_"
+        _mysqlrendervar    Com_insert  "Com_"
+        _mysqlrendervar    Com_replace "Com_"
+        _mysqlrendervar    Com_select  "Com_"
+        _mysqlrendervar    Com_update  "Com_"
         ;;
 
     "qcache-blocks")
         descr="query cache blocks"
         _mysqlgetvar "have_query_cache" | grep "YES" >/dev/null || ph.abort "Query cache is not active"
-        _mysqlrendervar Qcache_total_blocks "Qcache_"
-        _mysqlrendervar Qcache_free_blocks  "Qcache_"
+        _mysqlrendervar    Qcache_total_blocks "Qcache_"
+        _mysqlrendervar    Qcache_free_blocks  "Qcache_"
         ;;
 
     "qcache-queries")
@@ -275,13 +296,13 @@ case "${sMode}" in
         _mysqlrenderdelta  Qcache_not_cached        "Qcache_"  min  float
         _mysqlrenderdelta  Qcache_lowmem_prunes     "Qcache_"  min  float
         ;;
+
     "qcache-hits")
         descr="query cache hits"
         _mysqlgetvar "have_query_cache" | grep "YES" >/dev/null || ph.abort "Query cache is not active"
-        _mysqlrendervar    Qcache_hits        "Qcache_"
-        _mysqlrendervar    Qcache_inserts     "Qcache_"
-        _mysqlrendervar    Qcache_not_cached  "Qcache_"
-
+        _mysqlrenderdelta  Qcache_hits        "Qcache_"  min
+        _mysqlrenderdelta  Qcache_inserts     "Qcache_"  min
+        _mysqlrenderdelta  Qcache_not_cached  "Qcache_"  min
         ;;
 
     *)
diff --git a/zz_template_check_.md b/zz_template_check_.md
new file mode 100644
index 0000000000000000000000000000000000000000..63d8e5fcb142dfb372bc551a46e98d88b855f0d3
--- /dev/null
+++ b/zz_template_check_.md
@@ -0,0 +1,26 @@
+# IML Checks for Icinga / Nagios
+
+[Home](readme.md)
+
+---
+
+## check NAME
+
+### Introduction
+
+**check_NAME** is a plugin for ...
+
+### Syntax
+
+``$ check_NAME [-c CRITICAL] [-w WARING] PRODUCT VERSION``
+
+#### Parameters
+
+...
+
+### Examples
+
+...
+
+``check_NAME blubb``
+    Show blubber bubbles