diff --git a/public_html/appmonitor/classes/appmonitor-checks.class.php b/public_html/appmonitor/classes/appmonitor-checks.class.php
index b571cfaa3c4d64641bdf224342ce438a9700f8e2..525aed631b57ab5c127226b72e45dda8e9dde1a7 100644
--- a/public_html/appmonitor/classes/appmonitor-checks.class.php
+++ b/public_html/appmonitor/classes/appmonitor-checks.class.php
@@ -119,6 +119,7 @@ class appmonitorcheck {
             "name" => $this->_aConfig["name"],
             "description" => $this->_aConfig["description"],
             "group" => isset($this->_aConfig["group"]) ? $this->_aConfig["group"] : false,
+            "parent" => isset($this->_aConfig["parent"]) ? $this->_aConfig["parent"] : false,
             "result" => RESULT_UNKNOWN,
             "value" => false,
             "type" => false,
diff --git a/public_html/appmonitor/classes/appmonitor-client.class.php b/public_html/appmonitor/classes/appmonitor-client.class.php
index fc98da629296b5ad0365d98669a5068aa18aca5d..ec21adcff914a8cfe77327899dff1edfab3c4311 100644
--- a/public_html/appmonitor/classes/appmonitor-client.class.php
+++ b/public_html/appmonitor/classes/appmonitor-client.class.php
@@ -54,7 +54,7 @@ class appmonitor {
      * value is in seconds
      * @var int
      */
-    protected $_sVersion = 'php-client-v0.99';
+    protected $_sVersion = 'php-client-v0.109';
 
     /**
      * config: default ttl for server before requesting the client check again
diff --git a/public_html/appmonitor/example.json b/public_html/appmonitor/example.json
new file mode 100644
index 0000000000000000000000000000000000000000..b856bf639168b05d9db88cbf7d02e2183a19ae4c
--- /dev/null
+++ b/public_html/appmonitor/example.json
@@ -0,0 +1,34 @@
+{
+    "meta": {
+        "host": "my-computer", 
+        "website": "localhost", 
+        "ttl": 300, 
+        "result": 1
+    },
+    "checks": [
+        {
+            "name": "simple ok", 
+            "description": "Very simple test", 
+            "result": 0, 
+            "value": "The appmonitor client is reachable."
+        },
+        {
+            "name": "simple unknown", 
+            "description": "a dummy test with unknown status", 
+            "result": 1, 
+            "value": "any message"
+        },
+        {
+            "name": "simple warning", 
+            "description": "a dummy warning", 
+            "result": 2, 
+            "value": "warning message"
+        },
+        {
+            "name": "dummy error", 
+            "description": "a dummy error test", 
+            "result": 3, 
+            "value": "ERROR: the error message was not found"
+        } 
+    ] 
+}
\ No newline at end of file
diff --git a/public_html/appmonitor/general_include.sample.php b/public_html/appmonitor/general_include.sample.php
new file mode 100644
index 0000000000000000000000000000000000000000..f5ebae3bc79239323bd852a7089391aca87c881f
--- /dev/null
+++ b/public_html/appmonitor/general_include.sample.php
@@ -0,0 +1,46 @@
+<?php
+/* ______________________________________________________________________
+ * 
+ * A P P M O N I T O R  ::  CLIENT - CHECK  ::  GENERAL INCLUDE
+ * ______________________________________________________________________
+ * 
+ * The idea behind  is to a file with the same actions on all your 
+ * installations and hosts that can be deployed by a software delivery service 
+ * (Puppet, Ansible, ...)
+ * 
+ * Instruction:
+ * (1) copy sample file to general_include.php and enable wished features below
+ * (2) in your checks enable it by
+ *     @include 'general_include.php';
+ *     see index.sample.php too
+ * 
+ * @author: Axel Hahn
+ * ----------------------------------------------------------------------
+ * 2018-06-30  v0.1
+ */
+
+// ----------------------------------------------------------------------
+// SECURITY STUFF ... protect access to monitoring data
+// ----------------------------------------------------------------------
+
+// --- check an IP range of allowed clients
+/*
+$oMonitor->checkIp(array(
+    '127.0.0.1',
+    '::1',
+    '192.168.',
+));
+ */
+
+// --- check a token
+// an incoming request must have the param ?token=123
+// $oMonitor->checkToken('token', '123');
+
+
+// ----------------------------------------------------------------------
+// NOTIFICATION
+// ----------------------------------------------------------------------
+
+// $oMonitor->addEmail('sysadmin@example.com');
+// $oMonitor->addSlackWebhook(array("mywebhook"=> "https://hooks.slack.com/services/(...)"));
+
diff --git a/public_html/appmonitor/index.php b/public_html/appmonitor/index.php
index b978327cd2e28029d7e891b6b730b847ea434b82..1e075077871e65c1853e198475601f604d2e023e 100644
--- a/public_html/appmonitor/index.php
+++ b/public_html/appmonitor/index.php
@@ -27,7 +27,7 @@ $sCfgfile='../../config/inc_projects_config.php';
 
 $oMonitor->addCheck(
     array(
-        "name" => "read Cfg file",
+        "name" => "read config file",
         "description" => "Check if config file is readable",
         "check" => array(
             "function" => "File",
@@ -66,6 +66,7 @@ foreach (array(
         array(
             "name" => "dir $sKey",
             "description" => $aItem['descr'],
+            "parent" => "read config file",
             "check" => array(
                 "function" => "File",
                 "params" => array(
@@ -83,6 +84,7 @@ $oMonitor->addCheck(
 		"description" => "The file storage must have some space left",
 		"check" => array(
 			"function" => "Diskfree",
+            "parent" => "read config file",
 			"params" => array(
 				"directory" => $aConfig['archiveDir'],
 				"warning"   => "2GB",
@@ -115,6 +117,7 @@ $oMonitor->addCheck(
         "name" => "ci projects",
         "description" => "Count of Projects in CI Webgui",
         "group" => "monitor",
+        "parent" => "read config file",
         "check" => array(
             "function" => "Simple",
             "params" => array(
@@ -131,6 +134,7 @@ $oMonitor->addCheck(
         "name" => "ci inProgress",
         "description" => "Projects in progress",
         "group" => "monitor",
+        "parent" => "read config file",
         "check" => array(
             "function" => "Simple",
             "params" => array(
@@ -147,6 +151,7 @@ $oMonitor->addCheck(
         "name" => "ci hasqueue",
         "description" => "Waiting for install",
         "group" => "monitor",
+        "parent" => "read config file",
         "check" => array(
             "function" => "Simple",
             "params" => array(
@@ -159,17 +164,7 @@ $oMonitor->addCheck(
     )
 );
 
-if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']){
-    $oMonitor->addCheck(
-        array(
-            "name" => "Certificate check",
-            "description" => "Check if SSL cert is valid and does not expire soon",
-            "check" => array(
-                "function" => "Cert",
-            ),
-        )
-    );
-}
+include 'plugins/apps/shared_check_ssl.php';
 
 
 // ----------------------------------------------------------------------
@@ -196,6 +191,7 @@ if(isset($aConfig['foreman']['api'])){
                 "name" => "Foreman $sForemanKey",
                 "description" => "Count of Foreman $sForemanKey",
                 "group" => "monitor",
+                "parent" => "read config file",
                 "check" => array(
                     "function" => "Simple",
                     "params" => array(
@@ -233,6 +229,7 @@ if(count($aConfig['mirrorPackages'])){
                 "name" => "mirror target $sHostKey",
                 "description" => "Sync target of generated packages",
                 "group" => "network",
+                "parent" => "read config file",
                 "check" => array(
                     "function" => "Simple",
                     "params" => array(
@@ -269,6 +266,7 @@ foreach(array(
                     "name" => 'port check '.$aDescr['host'].':'.$aDescr['port'],
                     "description" => $aDescr['descr'],
                     "group" => "cloud",
+                    "parent" => "read config file",
                     "check" => array(
                             "function" => "PortTcp",
                             "params" => array(
@@ -290,6 +288,7 @@ $oMonitor->addCheck(
     array(
         "name" => "Sqlite DB for action logs",
         "description" => "Connect sqlite db ". basename($sSqlitefile),
+        "parent" => "read config file",
         "check" => array(
             "function" => "SqliteConnect",
             "params" => array(
@@ -306,6 +305,7 @@ $oMonitor->addCheck(
     array(
         "name" => "plugin Load",
         "description" => "current load",
+        "parent" => false,
         "check" => array(
             "function" => "Loadmeter",
             "params" => array(
@@ -320,6 +320,7 @@ $oMonitor->addCheck(
     array(
         "name" => "plugin ApacheProcesses",
         "description" => "Apache processes",
+        "parent" => false,
         "check" => array(
             "function" => "ApacheProcesses",
             "params" => array(
diff --git a/public_html/appmonitor/index.sample.php b/public_html/appmonitor/index.sample.php
new file mode 100644
index 0000000000000000000000000000000000000000..e3894bb4a0714724714b574d0236845557e1c977
--- /dev/null
+++ b/public_html/appmonitor/index.sample.php
@@ -0,0 +1,55 @@
+<?php
+/* ______________________________________________________________________
+ * 
+ * A P P M O N I T O R  ::  CLIENT - CHECK  ::  SAMPLE
+ * ______________________________________________________________________
+ * 
+ * this is a sample file for the appmonitor client
+ * copy the sample file to index.php and modify it as needed (see ../readme.md).
+ * 
+ */
+
+require_once('classes/appmonitor-client.class.php');
+$oMonitor = new appmonitor();
+
+// set a name with application name and environment or hostname
+$oMonitor->setWebsite('[My CMS on host XY]');
+
+// how often the server should ask for updates
+$oMonitor->setTTL(300);
+
+// a general include ... the idea is to a file with the same actions on all
+// installations and hosts that can be deployed by a software delivery service 
+// (Puppet, Ansible, ...)
+@include 'general_include.php';
+
+// add any tag to add it in the filter list in the server web gui
+// $oMonitor->addTag('cms');
+// $oMonitor->addTag('production');
+
+// ----------------------------------------------------------------------
+
+// include default checks for an application
+// @require 'plugins/apps/[name-of-app].php';
+
+// add a few custom checks
+// $oMonitor->addCheck(...)
+$oMonitor->addCheck(
+    array(
+        "name" => "hello plugin",
+        "description" => "Test a plugin ... plugins/checks/hello.php",
+        "check" => array(
+            "function" => "Hello",
+            "params" => array(
+                "message" => "Here I am",
+            ),
+        ),
+    )
+);
+
+// ----------------------------------------------------------------------
+
+$oMonitor->setResult();
+$oMonitor->render();
+
+// ----------------------------------------------------------------------
diff --git a/public_html/appmonitor/plugins/apps/iml-appmonitor-server.php b/public_html/appmonitor/plugins/apps/iml-appmonitor-server.php
new file mode 100644
index 0000000000000000000000000000000000000000..603be84aa5f1c778173c701f4501a238c1a50bac
--- /dev/null
+++ b/public_html/appmonitor/plugins/apps/iml-appmonitor-server.php
@@ -0,0 +1,196 @@
+<?php
+/* ______________________________________________________________________
+ * 
+ * A P P M O N I T O R  ::  CLIENT - CHECKS for server instance
+ * ______________________________________________________________________
+ * 
+ * requires variable $sApproot
+ * 
+ * @author: Axel Hahn
+ * ----------------------------------------------------------------------
+ * 2019-04-29  aded check for ssl cert; removed a check
+ * 2019-05-17  aded check http to config- and tmp dir
+ * 2021-11-nn  removed all checks ... created as single files
+ * 2022-03-28  move checks into plugins/apps/
+ */
+
+// ----------------------------------------------------------------------
+// files and dirs
+// ----------------------------------------------------------------------
+
+$oMonitor->addCheck(
+    array(
+        "name" => "write to ./tmp/",
+        "description" => "Check cache storage",
+        // "group" => "folder",
+        "check" => array(
+            "function" => "File",
+            "params" => array(
+                "filename" => $sApproot . "/server/tmp",
+                "dir" => true,
+                "writable" => true,
+            ),
+        ),
+    )
+);
+$oMonitor->addCheck(
+    array(
+        "name" => "write to ./config/",
+        "description" => "Check config target directory",
+        // "group" => "folder",
+        "check" => array(
+            "function" => "File",
+            "params" => array(
+                "filename" => $sApproot . "/server/config",
+                "dir" => true,
+                "writable" => true,
+            ),
+        ),
+    )
+);
+$oMonitor->addCheck(
+    array(
+        "name" => "check config file",
+        "description" => "The config file must be writable",
+        "parent" => "write to ./config/",
+        // "group" => "file",
+        "check" => array(
+            "function" => "File",
+            "params" => array(
+                "filename" => $sApproot . "/server/config/appmonitor-server-config.json",
+                "file" => true,
+                "writable" => true,
+            ),
+        ),
+    )
+);
+// ----------------------------------------------------------------------
+// protect dirs against web access
+// specialty: if the test results in an error, the total result switches
+// to WARNING -> see worstresult value
+// ----------------------------------------------------------------------
+$sBaseUrl = 'http'.(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] ? 's' : '')
+        .'://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT']
+        .dirname(dirname($_SERVER['REQUEST_URI']));
+
+foreach(array('server/config', 'server/tmp') as $sMyDir){
+    $oMonitor->addCheck(
+        array(
+            "name" => "http to $sMyDir",
+            "description" => "Check if the $sMyDir directory is not accessible (counts as warning on fail)",
+            "group" => "deny",
+            "check" => array(
+                "function" => "HttpContent",
+                "params" => array(
+                    "url" => $sBaseUrl . "/$sMyDir/readme.md",
+                    "status" => 403,
+                ),
+            ),
+            "worstresult" => RESULT_WARNING
+        )
+    );
+}
+
+// ----------------------------------------------------------------------
+// count of current projects
+// ----------------------------------------------------------------------
+require_once($sApproot.'/server/classes/appmonitor-server.class.php');
+$oServer=new appmonitorserver();
+$iCount=count($oServer->apiGetAppIds());
+$oMonitor->addCheck(
+    array(
+        "name" => "appcounter",
+        "description" => "Monitored apps",
+        "group" => "monitor",
+        "parent" => "check config file",
+        "check" => array(
+            "function" => "Simple",
+            "params" => array(
+                "result" => RESULT_OK,
+                "value" => "Found monitored web apps: $iCount",
+                "count" => $iCount,
+                "visual" => "simple",
+            ),
+        ),
+    )
+);
+// ----------------------------------------------------------------------
+// check running service
+// ----------------------------------------------------------------------
+require_once($sApproot.'/server/classes/tinyservice.class.php');
+ob_start();
+$oService = new tinyservice($sApproot.'/server/service.php', 15, $sApproot.'/server/tmp');
+$sIsStopped=$oService->canStart();
+$out=ob_get_contents();
+ob_clean();
+$oMonitor->addCheck(
+    array(
+        "name" => "running service",
+        "description" => "Check if the service is running",
+        "group" => "service",
+        "check" => array(
+            "function" => "Simple",
+            "params" => array(
+                "result" => ($sIsStopped ? RESULT_WARNING : RESULT_OK),
+                "value" => ($sIsStopped 
+                    ? "Info: Service is NOT running. Apps are checked interactively only (if the appmonitor web ui is running). | Output: $out" 
+                    : "OK, service is running. | Output: $out"
+                ),
+            ),
+        ),
+        "worstresult" => RESULT_OK        
+    )
+);
+// ----------------------------------------------------------------------
+// check certificate if https is used
+// ----------------------------------------------------------------------
+include 'shared_check_ssl.php';
+
+// ----------------------------------------------------------------------
+// plugin test
+// ----------------------------------------------------------------------
+/*
+ * 
+ * AS A DEMO: using a custom plugin:
+ * 
+$oMonitor->addCheck(
+    array(
+        "name" => "plugin test",
+        "description" => "minimal test of the plugin plugins/checkHello.php",
+        "check" => array(
+            "function" => "Hello",
+            "params" => array(
+                "message" => "Here I am",
+            ),
+        ),
+    )
+);
+$oMonitor->addCheck(
+    array(
+        "name" => "plugin Load",
+        "description" => "check current load",
+        "check" => array(
+            "function" => "Loadmeter",
+            "params" => array(
+                "warning" => 1.0,
+                "error" => 3,
+            ),
+        ),
+        "worstresult" => RESULT_OK
+    )
+);
+$oMonitor->addCheck(
+    array(
+        "name" => "plugin ApacheProcesses",
+        "description" => "check count running Apache processes",
+        "check" => array(
+            "function" => "ApacheProcesses",
+            "params" => array(
+            ),
+        ),
+        "worstresult" => RESULT_OK
+    )
+);
+*/
+
+// ----------------------------------------------------------------------
diff --git a/public_html/appmonitor/plugins/apps/shared_check_ssl.php b/public_html/appmonitor/plugins/apps/shared_check_ssl.php
new file mode 100644
index 0000000000000000000000000000000000000000..bdf8e68db39a774d3b64c9f2af386cf636600ece
--- /dev/null
+++ b/public_html/appmonitor/plugins/apps/shared_check_ssl.php
@@ -0,0 +1,33 @@
+<?php
+/* ______________________________________________________________________
+ * 
+ * A P P M O N I T O R  ::  GENERIC CHECK SSL CERT
+ * 
+ * If https is enabled on standard port 443 the validity of the
+ * certificate.
+ * If the current appplication uses http only this check does nothing.
+ * 
+ * ______________________________________________________________________
+ * 
+ * @author: Axel Hahn
+ * ----------------------------------------------------------------------
+ * 2022-03-28  created
+ */
+
+
+// ----------------------------------------------------------------------
+// check certificate - only if https is used
+// ----------------------------------------------------------------------
+if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']){
+    $oMonitor->addCheck(
+        array(
+            "name" => "Certificate check",
+            "description" => "Check if SSL cert is valid and does not expire soon",
+            "check" => array(
+                "function" => "Cert",
+            ),
+        )
+    );
+}
+
+// ----------------------------------------------------------------------