diff --git a/public_html/appmonitor/appmonitor-checks.class.php b/public_html/appmonitor/appmonitor-checks.class.php
new file mode 100644
index 0000000000000000000000000000000000000000..f5f8b84f40fbc279196c2afbc89b6620fd7edda8
--- /dev/null
+++ b/public_html/appmonitor/appmonitor-checks.class.php
@@ -0,0 +1,306 @@
+<?php
+
+define("RESULT_OK", 0);
+define("RESULT_WARNING", 1);
+define("RESULT_ERROR", 2);
+define("RESULT_UNKNOWN", 255);
+/** 
+ * APPMONITOR CLIENT CHECKS<br>
+ * <br>
+ * THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE <br>
+ * LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR <br>
+ * OTHER PARTIES PROVIDE THE PROGRAM ?AS IS? WITHOUT WARRANTY OF ANY KIND, <br>
+ * EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED <br>
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE <br>
+ * ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. <br>
+ * SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY <br>
+ * SERVICING, REPAIR OR CORRECTION.<br>
+ * <br>
+ * --------------------------------------------------------------------------------<br>
+ * <br>
+ * --- HISTORY:<br>
+ * 2014-10-24  0.5  axel.hahn@iml.unibe.ch<br>
+ * --------------------------------------------------------------------------------<br>
+ * @version 0.5
+ * @author Axel Hahn
+ * @link TODO
+ * @license GPL
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL 3.0
+ * @package IML-Appmonitor
+ */
+class appmonitorcheck {
+    
+    // ----------------------------------------------------------------------
+    // CONFIG
+    // ----------------------------------------------------------------------
+
+    /**
+     * config container
+     * @var array
+     */
+    private $_aConfig = array();
+
+    /**
+     * data of all checks
+     * @var array
+     */
+    private $_aData = array();
+
+    // ----------------------------------------------------------------------
+    // CONSTRUCTOR
+    // ----------------------------------------------------------------------
+
+    /**
+     * constructor (nothing)
+     */
+    public function __construct() {
+        
+    }
+
+    // ----------------------------------------------------------------------
+    // PRIVATE FUNCTIONS
+    // ----------------------------------------------------------------------
+
+    /**
+     * create basic array values for metadata
+     * @return boolean
+     */
+    private function _createDefaultMetadata() {
+
+        $this->_aData = array(
+            "name" => $this->_aConfig["name"],
+            "description" => $this->_aConfig["description"],
+            "result" => RESULT_UNKNOWN,
+            "value" => false,
+        );
+        return true;
+    }
+
+    /**
+     * set a result value of a check
+     * @param type $iResult
+     * @return type
+     */
+    private function _setResult($iResult) {
+        return $this->_aData["result"] = (int) $iResult;
+    }
+
+    /**
+     * set a result value of a check
+     * @param type $iResult
+     * @return type
+     */
+    private function _setOutput($s) {
+        return $this->_aData["value"] = (string) $s;
+    }
+
+    /**
+     * set result and output
+     * @param type $iResult
+     * @param type $s
+     * @return boolean
+     */
+    private function _setReturn($iResult, $s) {
+        $this->_setResult($iResult);
+        $this->_setOutput($s);
+        return true;
+    }
+
+    private function _checkArrayKeys($aConfig, $sKeyList) {
+        foreach (explode(",", $sKeyList) as $sKey) {
+            if (!array_key_exists($sKey, $aConfig)) {
+                die('ERROR in ' . __CLASS__ . "<br>array requires the keys [$sKeyList] - but key '$sKey' was not found in config array <pre>" . print_r($aConfig, true));
+            }
+            if (is_null($aConfig[$sKey])) {
+                die('ERROR in ' . __CLASS__ . "<br> key '$sKey' is empty in config array <pre>" . print_r($aConfig, true));
+            }
+        }
+        return true;
+    }
+
+    // ----------------------------------------------------------------------
+    // PUBLIC FUNCTIONS
+    // ----------------------------------------------------------------------
+
+    /**
+     * perform a check
+     * @param type $aConfig
+     * Array
+     * (
+     *     [name] => Dummy
+     *     [description] => Dummy Test
+     *     [check] => array(
+     *         [function] => [check function] // i.e. Simple
+     *         [params] => [array]            // optional; arguments for Check function
+     *                                        // its keys depend on the function  
+     *     )
+     * )
+     * 
+     * @return array
+     */
+    public function makeCheck($aConfig) {
+        $this->_checkArrayKeys($aConfig, "name,description,check");
+        $this->_checkArrayKeys($aConfig["check"], "function");
+
+        $this->_aConfig = $aConfig;
+        $this->_createDefaultMetadata();
+
+        $sCheck = "check" . $this->_aConfig["check"]["function"];
+        if (!method_exists($this, $sCheck)) {
+            die(__CLASS__ . " check not found: $sCheck <pre>" . print_r($aConfig, true));
+        }
+        $aParams = array_key_exists("params", $this->_aConfig["check"]) ? $this->_aConfig["check"]["params"] : array();
+
+        // call the check ...
+        call_user_func(array($this, $sCheck), $aParams);
+
+        // echo "<pre>"; print_r($this->listChecks()); die();
+        // ... and send response 
+        return $this->respond();
+    }
+
+    /**
+     * list all available check functions. This is a helper class you cann call
+     * to get an overview overbuilt in functions. You get a flat array with
+     * all function names.
+     * @return array
+     */
+    public function listChecks() {
+        $aReturn = array();
+        $class = new ReflectionClass($this);
+        foreach ($class->getMethods(ReflectionMethod::IS_PRIVATE) as $oReflectionMethod) {
+            if (strpos($oReflectionMethod->name, "check") === 0) {
+                $aReturn[] = (string) $oReflectionMethod->name;
+            }
+        }
+        return $aReturn;
+    }
+
+    /**
+     * final call of class: send response (data array)
+     * @return type
+     */
+    public function respond() {
+        return $this->_aData;
+    }
+
+    // ----------------------------------------------------------------------
+    // CHECK FUNCTIONS (private)
+    // ----------------------------------------------------------------------
+
+    /**
+     * most simple check: set values
+     * @return type
+     */
+    private function checkSimple($aParams) {
+        $aHelp = array(
+            "result" => "(integer) result value",
+            "value" => "(string) explaination"
+        );
+        $this->_checkArrayKeys($aParams, "result,value");
+        return $this->_setReturn((int) $aParams["result"], $aParams["value"]);
+    }
+
+    /**
+     * make http request and test response body
+     * @param array $aParams
+     * array(
+     *     "url"       url to fetch
+     *     "contains"  string that must exist in response body
+     * )
+     */
+    private function checkHttpContent($aParams, $iTimeout = 5) {
+        $this->_checkArrayKeys($aParams, "url,contains");
+        if (!function_exists("curl_init")) {
+            die("ERROR: PHP CURL module is not installed.");
+        }
+        $ch = curl_init($aParams["url"]);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
+        curl_setopt($ch, CURLOPT_TIMEOUT, $iTimeout);
+        $res = curl_exec($ch);
+        curl_close($ch);
+
+        if (!$res) {
+            $this->_setReturn(RESULT_ERROR, 'ERROR: failed to fetch ' . $aParams["url"] . '.');
+        } else {
+            if (!strpos($res, $aParams["contains"]) === false) {
+                $this->_setReturn(RESULT_OK, 'OK: The text "' . $aParams["contains"] . '" was found in response of ' . $aParams["url"] . '.');
+            } else {
+                $this->_setReturn(RESULT_ERROR, 'ERROR: The text ' . $aParams["contains"] . ' was NOT found in response of ' . $aParams["url"] . '.');
+            }
+        }
+        return $res;
+    }
+
+    /**
+     * check mysql connection to a database
+     * @param array $aParams
+     * array(
+     *     "server" 
+     *     "user" 
+     *     "password" 
+     *     "db" 
+     * )
+     */
+    private function checkMysqlConnect($aParams) {
+        $this->_checkArrayKeys($aParams, "server,user,password,db");
+        $db = mysqli_connect(
+                $aParams["server"], $aParams["user"], $aParams["password"], $aParams["db"]
+        );
+        if ($db) {
+            $this->_setReturn(RESULT_OK, "OK: Mysql database " . $aParams["db"] . " was connected");
+            return true;
+        } else {
+            $this->_setReturn(RESULT_ERROR, "ERROR: Mysql database " . $aParams["db"] . " was not connected. " . mysqli_connect_error());
+            return false;
+        }
+    }
+
+    /**
+     * check sqlite connection
+     * @param array $aParams
+     * array(
+     *     "db" 
+     * )
+     * @return boolean
+     */
+    private function checkSqliteConnect($aParams) {
+        $this->_checkArrayKeys($aParams, "db");
+        if (!file_exists($aParams["db"])) {
+            $this->_setReturn(RESULT_ERROR, "ERROR: Sqlite database file " . $aParams["db"] . " does not exist.");
+            return false;
+        }
+        try {
+            // $db = new SQLite3($sqliteDB);
+            // $db = new PDO("sqlite:".$sqliteDB);
+            $o = new PDO("sqlite:" . $aParams["db"]);
+            $this->_setReturn(RESULT_OK, "OK: Sqlite database " . $aParams["db"] . " was connected");
+            return true;
+        } catch (Exception $exc) {
+            $this->_setReturn(RESULT_ERROR, "ERROR: Sqlite database " . $aParams["db"] . " was not connected. " . mysqli_connect_error());
+            return false;
+        }
+    }
+
+    /**
+     * check if system is listening to a given port
+     * @param array $aParams
+     * array(
+     *     "port" 
+     * )
+     * @return boolean
+     */
+    private function checkListeningIp($aParams) {
+        $this->_checkArrayKeys($aParams, "port");
+        $sResult = exec('netstat -tulen | grep ":' . $aParams["port"] . ' "');
+        if ($sResult) {
+            $this->_setReturn(RESULT_OK, "OK: Port " . $aParams["port"] . " was found: " . $sResult);
+            return true;
+        } else {
+            $this->_setReturn(RESULT_ERROR, "ERROR: Port " . $aParams["port"] . " is not in use.");
+            return false;
+        }
+    }
+
+}
diff --git a/public_html/appmonitor/appmonitor-client.class.php b/public_html/appmonitor/appmonitor-client.class.php
new file mode 100644
index 0000000000000000000000000000000000000000..a468e240963accd75c6efde22e52419b5a6355b4
--- /dev/null
+++ b/public_html/appmonitor/appmonitor-client.class.php
@@ -0,0 +1,287 @@
+<?php
+/** 
+ * APPMONITOR CLIENT<br>
+ * <br>
+ * THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE <br>
+ * LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR <br>
+ * OTHER PARTIES PROVIDE THE PROGRAM ?AS IS? WITHOUT WARRANTY OF ANY KIND, <br>
+ * EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED <br>
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE <br>
+ * ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. <br>
+ * SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY <br>
+ * SERVICING, REPAIR OR CORRECTION.<br>
+ * <br>
+ * --------------------------------------------------------------------------------<br>
+ * <br>
+ * --- HISTORY:<br>
+ * 2014-10-24  0.5  axel.hahn@iml.unibe.ch<br>
+ * --------------------------------------------------------------------------------<br>
+ * @version 0.5
+ * @author Axel Hahn
+ * @link TODO
+ * @license GPL
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL 3.0
+ * @package IML-Appmonitor
+ */
+class appmonitor {
+
+    /**
+     * config: default ttl for server before requesting the client check again
+     * value is in seconds
+     * @var int
+     */
+    private $_iDefaultTtl = 300;
+    
+    /**
+     * internal counter: greatest return value of all checks
+     * @var type 
+     */
+    private $_iMaxResult = false;
+    
+    /**
+     * responded metadata of a website
+     * @see _createDefaultMetadata()
+     * @var array
+     */
+    private $_aMeta = array();
+    
+    /**
+     * repended array of all checks
+     * @see addCheck()
+     * @var array
+     */
+    private $_aChecks = array();
+    
+    /**
+     * @var array
+     */
+    private $_aMustKeysChecks = array("name", "description", "result", "value");
+
+    /**
+     * constructor: init data
+     */
+    public function __construct() {
+        $this->_createDefaultMetadata();
+    }
+
+    // ----------------------------------------------------------------------
+    // private function
+    // ----------------------------------------------------------------------
+
+    /**
+     * create basic array values for metadata
+     * @return boolean
+     */
+    private function _createDefaultMetadata() {
+        $this->_aMeta = array(
+            "host" => false,
+            "website" => false,
+            "ttl" => false,
+            "ts" => (int) date("U"),
+            "result" => false
+        );
+
+        // fill with default values
+        $this->setHost();
+        $this->setWebsite();
+        $this->setTTL();
+
+        return true;
+    }
+
+    // ----------------------------------------------------------------------
+    // setter
+    // ----------------------------------------------------------------------
+
+    /**
+     * set a host for metadata
+     * @param string $s  hostname
+     * @return bool
+     */
+    public function setHost($s = false) {
+        if (!$s) {
+            $s = php_uname("n");
+        }
+        return $this->_aMeta["host"] = $s;
+    }
+
+    /**
+     * set a vhost for metadata
+     * @param string $sNewHost  hostname
+     * @return bool
+     */
+    public function setWebsite($s = false) {
+        if (!$s) {
+            $s = $_SERVER["HTTP_HOST"];
+        }
+        return $this->_aMeta["website"] = $s;
+    }
+
+    /**
+     * set a ttl value for 
+     * @param int $iTTl TTL value in sec
+     * @return boolean
+     */
+    public function setTTL($iTTl = false) {
+        if (!$iTTl) {
+            $iTTl = $this->_iDefaultTtl;
+        }
+        return $this->_aMeta["ttl"] = $iTTl;
+    }
+
+    /**
+     * set final result in meta data; if no value was given then it
+     * sets the biggest value of any check.
+     * @param integer  $iResult  set resultcode
+     * @return boolean
+     */
+    public function setResult($iResult = false) {
+        if ($iResult === false) {
+            $iResult = $this->_iMaxResult; // see addCheck()
+        }
+        return $this->_aMeta["result"] = $iResult;
+    }
+
+    /**
+     * add a check array;
+     * @param type $aJob
+     * @return type
+     */
+    public function addCheck($aJob = array()) {
+
+        require_once 'appmonitor-checks.class.php';
+        $oCheck = new appmonitorcheck();
+        // print_r($aJob); die();
+        $aCheck = $oCheck->makecheck($aJob);
+
+        if (!$this->_iMaxResult || $aCheck["result"] > $this->_iMaxResult) {
+            $this->_iMaxResult = $aCheck["result"];
+        }
+        return $this->_aChecks[] = $aCheck;
+    }
+
+    // ----------------------------------------------------------------------
+    // getter
+    // ----------------------------------------------------------------------
+
+    /**
+     * list all available check functions. This is a helper class you cann call
+     * to get an overview overbuilt in functions. You get a flat array with
+     * all function names.
+     * @return array
+     */
+    public function listChecks() {
+        require_once 'appmonitor-checks.class.php';
+        $oCheck = new appmonitorcheck();
+        return $oCheck->listChecks();
+    }
+
+    // ----------------------------------------------------------------------
+    // checks
+    // ----------------------------------------------------------------------
+
+    /**
+     * verify array values and abort with all found errors
+     */
+    private function _checkData() {
+        $aErrors = array();
+
+        if (!count($this->_aChecks)) {
+            $aErrors[] = "No checks have been defined.";
+        }
+
+        if ($this->_aMeta["result"] === false) {
+            $aErrors[] = "method setResult was not used to set a final result for all checks.";
+        }
+
+
+        if (count($aErrors)) {
+            echo "<h1>Errors detected</h1><ol><li>" . implode("<li>", $aErrors) . "</ol><hr>";
+            echo "<pre>" . print_r($this->_generateOutputArray(), true) . "</pre><hr>";
+            die("ABORT");
+        }
+    }
+
+    // ----------------------------------------------------------------------
+    // output
+    // ----------------------------------------------------------------------
+
+    /**
+     * get full array for response with metadata and Checks
+     * @return type
+     */
+    private function _generateOutputArray() {
+        return array(
+            "meta" => $this->_aMeta,
+            "checks" => $this->_aChecks,
+        );
+    }
+
+    /**
+     * output appmonitor values as JSON
+     * @param bool  $bPretty     turn on pretty print; default is false
+     * @param bool  $bHighlight  print syntax highlighted html code; $bPretty must be true to enable
+     */
+    public function render($bPretty = false, $bHighlight = false) {
+        $this->_checkData();
+	
+	// JSON_PRETTY_PRINT reqires PHP 5.4
+	if (!defined('JSON_PRETTY_PRINT')) {
+		$bPretty=false;
+	}
+        if (!$bPretty) {
+            $bHighlight=false;
+            $sOut = json_encode($this->_generateOutputArray());
+        } else {
+            $sOut = json_encode($this->_generateOutputArray(), JSON_PRETTY_PRINT);
+            if ($bHighlight) {
+                $aMsg=array(
+                    0=>"OK",
+                    1=>"WARNING",
+                    2=>"ERROR",
+                    255=>"UNKNOWN"
+                );
+                foreach(array_keys($aMsg) as $iCode){
+                    $sOut = preg_replace('/(\"result\":\ '.$iCode.')/', '$1 <span class="result'.$iCode.'"> &lt;--- '.$aMsg[$iCode].' </span>', $sOut);
+                }
+                
+                $sOut = preg_replace('/:\ \"(.*)\"/U', ': "<span style="color:#66e;">$1</span>"', $sOut);
+                $sOut = preg_replace('/:\ ([0-9]*)/', ': <span style="color:#3a3; font-weight: bold;">$1</span>', $sOut);
+                $sOut = preg_replace('/\"(.*)\":/U', '"<span style="color:#e90;">$1</span>":', $sOut);
+
+                $sOut = preg_replace('/([{\[])/', '$1<blockquote>', $sOut);
+                $sOut = preg_replace('/([}\]])/', '</blockquote>$1', $sOut);
+                $sOut = str_replace('    ', '', $sOut);
+                // $sOut = preg_replace('/([{}])/', '<span style="color:#a00; ">$1</span>', $sOut);
+                // $sOut = preg_replace('/([\[\]])/', '<span style="color:#088; ">$1</span>', $sOut);
+                
+                $sOut = '<!DOCTYPE html><html><head>'
+                . '<style>'
+                . 'body{background:#282830; color:#9ac; font-family: verdana,arial;}'
+                . 'blockquote{background:rgba(215,180,255,0.03); border-left: 5px solid #222; margin-top: 0; padding: 0; ;}'
+                . 'blockquote blockquote:hover{border-color: #345; }'
+                . 'blockquote blockquote blockquote:hover{border-color: #808;}'
+                . 'pre{background:#222; padding: 1em; border-radius: 1em;}'
+                . '.result0{background:#080; border-right: 1em solid #0f0;}'
+                . '.result1{background:#860; border-right: 1em solid #fc0;}'
+                . '.result2{background:#800; border-right: 1em solid #f00;}'
+                . '.result255{background:#666; border-right: 1em solid #ccc;}'
+                . '</style>'
+                . '<title>'.__CLASS__.'</title>'
+                . '</head><body>'
+                . '<h1>'.__CLASS__.' :: debug</h1>'
+                . '<pre>'
+                . $sOut 
+                . '</pre></body></html>';
+            }
+        }
+        if (!$bHighlight) {
+            header('Content-type: application/json');
+            header('Cache-Control: cache');
+            header('max-age: ' . $this->_aMeta["ttl"]);
+        }
+        echo $sOut;
+        return $sOut;
+    }
+
+}
diff --git a/public_html/appmonitor/index.php b/public_html/appmonitor/index.php
new file mode 100644
index 0000000000000000000000000000000000000000..303c2c67b7dae7cd8aa51e05a7fab0394e989734
--- /dev/null
+++ b/public_html/appmonitor/index.php
@@ -0,0 +1,41 @@
+<?php
+
+require_once('appmonitor-client.class.php');
+$oMonitor = new appmonitor();
+
+$oMonitor->addCheck(
+        array(
+            "name" => "simple",
+            "description" => "Very simple test",
+            "check" => array(
+                "function" => "Simple",
+                "params" => array(
+                    "result" => 0,
+                    "value" => "The appmonitor client is reachable.",
+                ),
+            ),
+        )
+);
+
+
+require_once '../../config/inc_projects_config.php';
+$sSqlitefile=$aConfig['dataDir'].'/database/logs.db';
+$oMonitor->addCheck(
+    array(
+        "name" => "Sqlite DB for action logs",
+        "description" => "Connect sqlite db ". basename($sSqlitefile),
+        "check" => array(
+            "function" => "SqliteConnect",
+            "params" => array(
+                "db"=>$sSqlitefile
+            ),
+        ),
+    )
+);
+
+
+// Gesamt-Ergebnis - ohne Param=aut. max. Wert nehmen
+$oMonitor->setResult();
+
+// Ausgabe
+$oMonitor->render();