diff --git a/public_html/appmonitor/classes/appmonitor-client.class.php b/public_html/appmonitor/classes/appmonitor-client.class.php index bdf70db9f076e640763f452baccb98471a1ed0e1..66def5a5d02705512751a93982d325823d7a35f3 100755 --- a/public_html/appmonitor/classes/appmonitor-client.class.php +++ b/public_html/appmonitor/classes/appmonitor-client.class.php @@ -42,8 +42,10 @@ if (!class_exists('appmonitorcheck')) { * 2020-05-03 0.110 axel.hahn@iml.unibe.ch update renderHtmloutput<br> * 2023-07-06 0.128 axel.hahn@unibe.ch update httpcontent check<br> * 2024-07-19 0.137 axel.hahn@unibe.ch php 8 only: use typed variables + * 2024-11-22 0.141 axel.hahn@unibe.ch Set client version to server version after updating http, mysqli and app checks + * 2025-01-02 0.149 axel.hahn@unibe.ch add getChecks method * --------------------------------------------------------------------------------<br> - * @version 0.137 + * @version 0.149 * @author Axel Hahn * @link TODO * @license GPL @@ -57,7 +59,7 @@ class appmonitor * Name and Version number * @var string */ - protected string $_sVersion = 'php-client-v0.137'; + protected string $_sVersion = 'php-client-v0.149'; /** * config: default ttl for server before requesting the client check again @@ -402,6 +404,15 @@ class appmonitor die('<h1>503 Service Unavailable</h1>' . $sMessage); } + /** + * Get array with executed checks + * @return array + */ + public function getChecks(): array + { + return $this->_aChecks; + } + /** * Get full array for response with metadata and checks * @return array diff --git a/public_html/appmonitor/git_update_appmonitor.sh b/public_html/appmonitor/git_update_appmonitor.sh index 117d5084dc6473c2199cb3c23dcb070ba8e6462a..0426661154b1f446ce991eb2b4ad1a33894067d5 100755 --- a/public_html/appmonitor/git_update_appmonitor.sh +++ b/public_html/appmonitor/git_update_appmonitor.sh @@ -29,6 +29,9 @@ # 2022-05-03 0.3 <axel.hahn@iml.unibe.ch> create general_include.php # 2024-07-25 0.4 <axel.hahn@iml.unibe.ch> update quoting and comments # 2024-07-31 0.5 <axel.hahn@iml.unibe.ch> Show more helpful information; wait on 1st install; added param -n +# 2024-12-23 0.6 <axel.hahn@iml.unibe.ch> remove which command. Maybe it is not installed on a shared hoster. +# 2024-12-26 0.7 <axel.hahn@iml.unibe.ch> rsync test with --version instead of -V (for compatibility with older versions) +# 2025-01-06 0.8 <axel.hahn@iml.unibe.ch> git test with --version instead of -v (for compatibility with older versions) # ====================================================================== # ---------------------------------------------------------------------- @@ -38,7 +41,7 @@ readonly git_repo_url="https://github.com/iml-it/appmonitor.git" readonly docs_url="https://os-docs.iml.unibe.ch/appmonitor/PHP_client/index.html" readonly line="______________________________________________________________________________" -readonly version="0.5" +readonly version="0.8" git_target=/tmp/git_data__appmonitor client_from="${git_target}/public_html/client" @@ -168,8 +171,11 @@ ENDOFHELP fi esac -which rsync >/dev/null || exit 1 -which git >/dev/null || exit 1 +# which rsync >/dev/null || exit 1 +# which git >/dev/null || exit 1 + +rsync --version >/dev/null || exit 1 +git --version >/dev/null || exit 1 test -f general_include.php && isUpdate=1 @@ -221,6 +227,7 @@ rsync -rav \ --exclude "example.json" \ --exclude "check-appmonitor-server.php" \ --exclude "local.php" \ + --exclude "git_update_appmonitor.sh" \ $client_from/* "$client_to" echo @@ -260,5 +267,6 @@ echo "Documentation: $docs_url" echo echo $line echo done. +cp -rp "$client_from/git_update_appmonitor.sh" "$client_to" # ---------------------------------------------------------------------- diff --git a/public_html/appmonitor/plugins/apps/concrete5.php b/public_html/appmonitor/plugins/apps/concrete5.php new file mode 100644 index 0000000000000000000000000000000000000000..fa846205e0702f73170f7b9a0281071bb2578141 --- /dev/null +++ b/public_html/appmonitor/plugins/apps/concrete5.php @@ -0,0 +1,165 @@ +<?php +/* ______________________________________________________________________ + * + * A P P M O N I T O R :: CLIENT - CHECK + * ______________________________________________________________________ + * + * Check for a Concrete5 instance. + * CMS https://www.concrete5.org/ + * + * It checks + * - the write access to the config file + * - the write access to the file storage + * - connect to mysql database (which is read from config) + * - ssl certificate (on https request only) + * + * @author: Axel Hahn - https://www.axel-hahn.de/ + * ---------------------------------------------------------------------- + * 2018-06-30 v1.0 ah + * 2019-05-24 v1.01 ah detect include or standalone mode + * 2024-11-18 v1.02 <axel.hahn@unibe.ch> integrate in appmonitor repository + * 2024-11-22 v1.03 <axel.hahn@unibe.ch> send 400 instead of 503 on error + * 2024-12-21 v1.04 ah short array syntax; add php-modules and parent + * 2025-01-06 v1.05 ah add df + */ + +// ---------------------------------------------------------------------- +// Init +// ---------------------------------------------------------------------- + +$aAppDefaults = [ + "name" => "Concrete5 CMS", + "tags" => ["concrete5", "cms"], + "df" => [ + "warning" => "100MB", + "critical" => "10MB" + ] +]; + +require 'inc_appcheck_start.php'; + +// ---------------------------------------------------------------------- +// Read Concrete5 specific config items +// ---------------------------------------------------------------------- + + +$sConfigfile = $sApproot . '/application/config/database.php'; +if (!file_exists($sConfigfile)) { + header('HTTP/1.0 400 Bad request'); + die('ERROR: Config file was not found. Use ?rel=[subdir] to set the correct subdir to find /application/config/database.php.'); +} + +$aConfig = include($sConfigfile); +$sActive = $aConfig['default-connection']; + +if (!isset($aConfig['connections'][$sActive])) { + header('HTTP/1.0 400 Bad request'); + die('ERROR: Config file application/config/database.php was read - but database connection could not be detected from it in connections -> ' . $sActive . '.'); +} +// print_r($aConfig['connections'][$sActive]); die(); +$aDb = $aConfig['connections'][$sActive]; + +// ---------------------------------------------------------------------- +// checks +// ---------------------------------------------------------------------- + +// required php modules +// see https://documentation.concretecms.org/developers/introduction/system-requirements +$oMonitor->addCheck( + [ + "name" => "PHP modules", + "description" => "Check needed PHP modules", + // "group" => "folder", + "check" => [ + "function" => "Phpmodules", + "params" => [ + "required" => [ + "PDO", + "curl", + "dom", + "fileinfo", + "gd", + "iconv", + "mbstring", + "pdo_mysql", + "xml", + "zip" + ], + "optional" => [], + ], + ], + ] +); + +$oMonitor->addCheck( + [ + "name" => "config file", + "description" => "The config file must be readable and writable", + "check" => [ + "function" => "File", + "params" => [ + "filename" => $sConfigfile, + "file" => true, + "readable" => true, + "writable" => true, + ], + ], + ] +); +$oMonitor->addCheck( + [ + "name" => "check file storage", + "description" => "The file storage must be writable", + "check" => [ + "function" => "File", + "params" => [ + "filename" => "$sApproot/application/files", + "dir" => true, + "writable" => true, + ], + ], + ] +); + +$sPdoConnectString = "mysql:host=$aDb[server];port=3306;dbname=$aDb[database];"; + +$oMonitor->addCheck( + [ + "name" => "Mysql Master", + "description" => "Connect mysql server " . $aDb['server'] . " as user " . $aDb['username'] . " to scheme " . $aDb['database'], + "parent" => "config file", + "check" => [ + "function" => "PdoConnect", + "params" => [ + "connect" => $sPdoConnectString, + "user" => $aDb['username'], + "password" => $aDb['password'], + ], + ], + ] +); + +if (isset($aAppDefaults['df'])) { + + $oMonitor->addCheck( + [ + "name" => "check disk space", + "description" => "The file storage must have some space left - warn: " . $aAppDefaults["df"]['warning'] . "/ critical: " . $aAppDefaults["df"]['critical'], + "parent" => "check file storage", + "check" => [ + "function" => "Diskfree", + "params" => [ + "directory" => "$sApproot/application", + "warning" => $aAppDefaults["df"]['warning'], + "critical" => $aAppDefaults["df"]['critical'], + ], + ], + ] + ); +} + +// ---------------------------------------------------------------------- + +require 'inc_appcheck_end.php'; + +// ---------------------------------------------------------------------- diff --git a/public_html/appmonitor/plugins/apps/dokuwiki.php b/public_html/appmonitor/plugins/apps/dokuwiki.php new file mode 100644 index 0000000000000000000000000000000000000000..c03f3a122b354f9a5f54cb8f563f94eeda27e2ed --- /dev/null +++ b/public_html/appmonitor/plugins/apps/dokuwiki.php @@ -0,0 +1,150 @@ +<?php +/* ______________________________________________________________________ + * + * A P P M O N I T O R :: CLIENT - CHECK + * ______________________________________________________________________ + * + * Check for a Dokuwiki instance. + * https://www.dokuwiki.org/ + * + * @author: Axel Hahn - https://www.axel-hahn.de/ + * ---------------------------------------------------------------------- + * 2024-12-23 v1.00 ah initial version + * 2024-12-26 v1.01 ah fix directory checks + * 2025-01-06 v1.02 ah add df + */ + +// ---------------------------------------------------------------------- +// Init +// ---------------------------------------------------------------------- + +$aAppDefaults = [ + "name" => "Dokuwiki", + "tags" => ["dokuwiki", "wiki"], + "df" => [ + "warning" => "100MB", + "critical" => "10MB" + ] +]; + +require 'inc_appcheck_start.php'; + +// ---------------------------------------------------------------------- +// Read Concrete5 specific config items +// ---------------------------------------------------------------------- + +$sConfigfile = "$sApproot/conf/local.php"; +if (!file_exists($sConfigfile)) { + header('HTTP/1.0 400 Bad request'); + die('ERROR: Config file was not found. Use ?rel=[subdir] to set the correct subdir to find /conf/local.php.'); +} + +// ---------------------------------------------------------------------- +// checks +// ---------------------------------------------------------------------- + +// required php modules +// see https://www.dokuwiki.org/install:php +$oMonitor->addCheck( + [ + "name" => "PHP modules", + "description" => "Check needed PHP modules", + // "group" => "folder", + "check" => [ + "function" => "Phpmodules", + "params" => [ + "required" => [ + "json", + "pcre", + "session", + ], + "optional" => [ + "bz2", + "gd", + "intl", + "mbstring", + "openssl", + "zlib" + ], + ], + ], + ] +); + +$oMonitor->addCheck( + [ + "name" => "config file", + "description" => "The config file must be readable and writable", + "check" => [ + "function" => "File", + "params" => [ + "filename" => $sConfigfile, + "file" => true, + "readable" => true, + "writable" => true, + ], + ], + ] +); + +foreach (['lib/tpl/', 'lib/plugins/',] as $sDir) { + $oMonitor->addCheck( + [ + "name" => "check read dir $sDir", + "description" => "The directory $sDir must be readable", + "group" => "folder", + "check" => [ + "function" => "File", + "params" => [ + "filename" => "$sApproot/$sDir", + "dir" => true, + "readable" => true, + ], + ], + ] + ); +} + + +foreach (['data/attic', 'data/cache', 'data/index', 'data/locks', 'data/log', 'data/media', 'data/meta', 'data/pages', 'data/tmp',] as $sDir) { + $oMonitor->addCheck( + [ + "name" => "check writable dir $sDir", + "description" => "The directory $sDir must be readable and writable", + "group" => "folder", + "check" => [ + "function" => "File", + "params" => [ + "filename" => "$sApproot/$sDir", + "dir" => true, + "readable" => true, + "writable" => true, + ], + ], + ] + ); +} + +if (isset($aAppDefaults['df'])) { + + $oMonitor->addCheck( + [ + "name" => "check disk space", + "description" => "The file storage must have some space left - warn: " . $aAppDefaults["df"]['warning'] . "/ critical: " . $aAppDefaults["df"]['critical'], + "check" => [ + "function" => "Diskfree", + "params" => [ + "directory" => "$sApproot/data", + "warning" => $aAppDefaults["df"]['warning'], + "critical" => $aAppDefaults["df"]['critical'], + ], + ], + ] + ); +} + +// ---------------------------------------------------------------------- + +require 'inc_appcheck_end.php'; + +// ---------------------------------------------------------------------- diff --git a/public_html/appmonitor/plugins/apps/iml-appmonitor-server.php b/public_html/appmonitor/plugins/apps/iml-appmonitor-server.php index 01797f877e280adcc54f4d99812c930f8c18c112..87473021d5cbe8b47d9ac9de7b512f732e593636 100755 --- a/public_html/appmonitor/plugins/apps/iml-appmonitor-server.php +++ b/public_html/appmonitor/plugins/apps/iml-appmonitor-server.php @@ -13,12 +13,28 @@ * 2021-11-nn removed all checks ... created as single files * 2022-03-28 move checks into plugins/apps/ * 2024-07-23 php 8: short array syntax + * 2024-12-28 added check for custom config and url file (if they exist) */ // ---------------------------------------------------------------------- // files and dirs // ---------------------------------------------------------------------- +$oMonitor->addCheck( + [ + "name" => "PHP modules", + "description" => "Check needed PHP modules", + // "group" => "folder", + "check" => [ + "function" => "Phpmodules", + "params" => [ + "required" => ["curl"], + "optional" => [], + ], + ], + ] +); + $oMonitor->addCheck( [ "name" => "write to ./tmp/", @@ -49,48 +65,74 @@ $oMonitor->addCheck( ], ] ); + $oMonitor->addCheck( [ "name" => "check config file", - "description" => "The config file must be writable", + "description" => "The default config file must be readable", "parent" => "write to ./config/", // "group" => "file", "check" => [ "function" => "File", "params" => [ - "filename" => "$sApproot/server/config/appmonitor-server-config.json", + "filename" => "$sApproot/server/config/appmonitor-server-config-defaults.json", "file" => true, - "writable" => true, + "readable" => true, ], ], ] ); -$oMonitor->addCheck( - [ - "name" => "PHP modules", - "description" => "Check needed PHP modules", - // "group" => "folder", - "check" => [ - "function" => "Phpmodules", - "params" => [ - "required" => ["curl"], - "optional" => [], +if (is_file("$sApproot/server/config/appmonitor-server-config.json")) { + $oMonitor->addCheck( + [ + "name" => "check custom config file", + "description" => "The custom config file must be readable and writable", + "parent" => "write to ./config/", + // "group" => "file", + "check" => [ + "function" => "File", + "params" => [ + "filename" => "$sApproot/server/config/appmonitor-server-config.json", + "file" => true, + "readable" => true, + "writable" => true, + ], ], - ], - ] -); + ] + ); +} + +if (is_file("$sApproot/server/config/appmonitor-server-urls.json")) { + $oMonitor->addCheck( + [ + "name" => "check url file", + "description" => "The url config file must be readable and writable", + "parent" => "write to ./config/", + // "group" => "file", + "check" => [ + "function" => "File", + "params" => [ + "filename" => "$sApproot/server/config/appmonitor-server-urls.json", + "file" => true, + "readable" => 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'])); +$sBaseUrl = 'http' . (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] ? 's' : '') + . '://' . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'] + . dirname(dirname($_SERVER['REQUEST_URI'])); -foreach(['server/config', 'server/tmp'] as $sMyDir){ +foreach (['server/config', 'server/tmp'] as $sMyDir) { $oMonitor->addCheck( [ "name" => "http to $sMyDir", @@ -111,15 +153,15 @@ foreach(['server/config', 'server/tmp'] as $sMyDir){ // ---------------------------------------------------------------------- // count of current projects // ---------------------------------------------------------------------- -require_once($sApproot.'/server/classes/appmonitor-server.class.php'); -$oServer=new appmonitorserver(); -$iCount=count($oServer->getAppIds()); +require_once($sApproot . '/server/classes/appmonitor-server.class.php'); +$oServer = new appmonitorserver(); +$iCount = count($oServer->getAppIds()); $oMonitor->addCheck( [ "name" => "appcounter", "description" => "Monitored apps", "group" => "monitor", - "parent" => "check config file", + "parent" => false, "check" => [ "function" => "Simple", "params" => [ @@ -134,11 +176,11 @@ $oMonitor->addCheck( // ---------------------------------------------------------------------- // check running service // ---------------------------------------------------------------------- -require_once($sApproot.'/server/classes/tinyservice.class.php'); +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(); +$sIsStopped = $oService->canStart(); +$out = ob_get_contents(); ob_clean(); $oMonitor->addCheck( [ @@ -149,13 +191,13 @@ $oMonitor->addCheck( "function" => "Simple", "params" => [ "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" + "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 + "worstresult" => RESULT_OK ] ); // ---------------------------------------------------------------------- diff --git a/public_html/appmonitor/plugins/apps/inc_appcheck_end.php b/public_html/appmonitor/plugins/apps/inc_appcheck_end.php index 5f958628cffe7fb80936cf50bc333c5e032b39e6..e939ed6d5c31046af8b140082395c6aec270ad85 100644 --- a/public_html/appmonitor/plugins/apps/inc_appcheck_end.php +++ b/public_html/appmonitor/plugins/apps/inc_appcheck_end.php @@ -5,9 +5,29 @@ * ______________________________________________________________________ */ +include 'shared_check_ssl.php'; + // $bStandalone was set in inc_appcheck_start.php // send response if client was not initialized there -if($bStandalone){ +if ($bStandalone) { + + if(count($oMonitor->getChecks())==0){ + + $oMonitor->addCheck( + [ + "name" => "Simple", + "description" => "Welcome to a simple app check. This is just a quick winner.", + "check" => [ + "function" => "Simple", + "params" => [ + "result" => RESULT_OK, + "value" => "Create a custom check and add all checks you need to test the ability to run the application", + ], + ], + ] + ); + } + $oMonitor->setResult(); $oMonitor->render(); } diff --git a/public_html/appmonitor/plugins/apps/inc_appcheck_start.php b/public_html/appmonitor/plugins/apps/inc_appcheck_start.php index 93e17e635c07e66aa8b2680cfb39e8d5738e3472..3218fc99bd70bff01a289fbf65af2b793cdf1a45 100644 --- a/public_html/appmonitor/plugins/apps/inc_appcheck_start.php +++ b/public_html/appmonitor/plugins/apps/inc_appcheck_start.php @@ -9,32 +9,54 @@ // CHECK IF THE APPROOT IS SET // ---------------------------------------------------------------------- -if (!$sApproot) { - header('HTTP/1.0 503 Service Unavailable'); - echo "<h1>503 Service Unavailable</h1>"; - echo 'ERROR:'.PHP_EOL; - echo '$sApproot was not set. Define it before including the application check.'.PHP_EOL; - echo 'Set the base folder of your application installation.'.PHP_EOL; - echo PHP_EOL; - echo 'Example:'.PHP_EOL; - echo '$sApproot = $_SERVER[\'DOCUMENT_ROOT\'];'.PHP_EOL; - echo '$sApproot = $_SERVER[\'DOCUMENT_ROOT\'].\'/myapp\';'.PHP_EOL; - die(); -} - // initialize client and set very basic metadata ... if needed -$bStandalone=!(class_exists('appmonitor') && isset($oMonitor)); -if($bStandalone){ - require_once(__DIR__.'/../../classes/appmonitor-client.class.php'); +$bStandalone = !(class_exists('appmonitor') && isset($oMonitor)); +if ($bStandalone) { + require_once __DIR__ . '/../../classes/appmonitor-client.class.php'; $oMonitor = new appmonitor(); - $oMonitor->setWebsite('Wordpress Instance'); - @include __DIR__.'/../../general_include.php'; -} + if (!isset($sApproot) || empty($sApproot)) { + $sApproot = $_SERVER['DOCUMENT_ROOT']; + if (isset($_GET['rel'])) { + $sApproot .= str_replace('..', '__', $_GET['rel']); + if (!is_dir($sApproot)) { + header('HTTP/1.0 400 Bad request'); + die('ERROR: The given rel dir does not exist below webroot.'); + } + } + } -// ---------------------------------------------------------------------- -// FUNCTIONS -// ---------------------------------------------------------------------- + // --- set values coming from app plugins defaults & GET params + // "name" + // "host" + // "tags" + // "dfw", "dfc" + $aAppDefaults['name'] = (isset($_GET['name']) && $_GET['name']) ? $_GET['name'] : $aAppDefaults['name']; + $aAppDefaults['host'] = $_GET['host'] + ? explode(',', $_GET['host']) + : ($_SERVER['HTTP_HOST'] ?? ''); + $aAppDefaults['tags'] = $_GET['tags'] ? explode(',', $_GET['tags']) : $aAppDefaults['tags']; + + $aAppDefaults['df']['warning'] = (isset($_GET['dfw']) && $_GET['dfw']) ? $_GET['dfw'] : $aAppDefaults['df']['warning'] ?? false; + $aAppDefaults['df']['critical'] = (isset($_GET['dfc']) && $_GET['dfc']) ? $_GET['dfc'] : $aAppDefaults['df']['critical'] ?? false; + if($aAppDefaults['df']['warning'] == false && $aAppDefaults['df']['critical'] == false) { + unset($aAppDefaults['df']); + } + if ($aAppDefaults['name']) { + $oMonitor->setWebsite($aAppDefaults['name']); + } + if ($aAppDefaults['host']) { + $oMonitor->setHost($aAppDefaults['host']); + } + ; + if (isset($aAppDefaults['tags']) && is_array($aAppDefaults['tags']) && count($aAppDefaults['tags']) > 0) { + foreach ($aAppDefaults['tags'] as $sTag) { + $oMonitor->addTag($sTag); + } + } + + @include __DIR__ . '/../../general_include.php'; +} // ---------------------------------------------------------------------- diff --git a/public_html/appmonitor/plugins/apps/matomo.php b/public_html/appmonitor/plugins/apps/matomo.php new file mode 100644 index 0000000000000000000000000000000000000000..3be9f6e55adf6b9da63800a8ced5977ec5f98c69 --- /dev/null +++ b/public_html/appmonitor/plugins/apps/matomo.php @@ -0,0 +1,156 @@ +<?php +/* ______________________________________________________________________ + * + * A P P M O N I T O R :: CLIENT - CHECK + * ______________________________________________________________________ + * + * Check for a Matomo instance. + * Open Analytics platform - https://matomo.org/ + * + * It checks + * - the write access to the config file + * - connect to matomo database (which is read from config) + * - ssl certificate (on https request only) + * + * @author: Axel Hahn - https://www.axel-hahn.de/ + * ---------------------------------------------------------------------- + * 2018-06-30 v1.0 + * 2019-05-24 v1.01 detect include or standalone mode + * 2019-05-24 v1.02 detect include or standalone mode + * 2024-12-20 v1.03 <axel.hahn@unibe.ch> integrate in appmonitor repository + * 2024-12-21 v1.04 ah add php-modules and parent + * 2025-01-06 v1.05 ah add checks for writable dirs; add df + */ + +// ---------------------------------------------------------------------- +// Init +// ---------------------------------------------------------------------- + +$aAppDefaults = [ + "name" => "Matomo web statistics", + "tags" => ["matomo", "statistics"], + "df" => [ + "warning" => "100MB", + "critical" => "10MB" + ] +]; + +require 'inc_appcheck_start.php'; + +// ---------------------------------------------------------------------- +// Read Matomo specific config items +// ---------------------------------------------------------------------- + +$sConfigfile = $sApproot . '/config/config.ini.php'; +if (!file_exists($sConfigfile)) { + header('HTTP/1.0 400 Bad request'); + die('ERROR: Config file was not found. Set a correct $sApproot pointing to Matomo install dir.'); +} +$aConfig = parse_ini_file($sConfigfile, true); + + +// ---------------------------------------------------------------------- +// checks +// ---------------------------------------------------------------------- + +// required php modules +// see https://matomo.org/faq/on-premise/matomo-requirements/ +$oMonitor->addCheck( + [ + "name" => "PHP modules", + "description" => "Check needed PHP modules", + // "group" => "folder", + "check" => [ + "function" => "Phpmodules", + "params" => [ + "required" => [ + "PDO", + "curl", + "gd", + "mbstring", + "pdo_mysql", + "xml", + ], + "optional" => [], + ], + ], + ] +); + +$oMonitor->addCheck( + [ + "name" => "config file", + "description" => "The config file must be readable and writable", + "check" => [ + "function" => "File", + "params" => [ + "filename" => $sConfigfile, + "file" => true, + "writable" => true, + ], + ], + ] +); + +$oMonitor->addCheck( + [ + "name" => "Mysql Connect", + "description" => "Connect mysql server " . $aConfig['database']['host'] . " as user " . $aConfig['database']['username'] . " to scheme " . $aConfig['database']['dbname'], + "parent" => "config file", + "check" => [ + "function" => "MysqlConnect", + "params" => [ + "server" => $aConfig['database']['host'], + "user" => $aConfig['database']['username'], + "password" => $aConfig['database']['password'], + "db" => $aConfig['database']['dbname'], + ], + ], + ] +); + + +// directory list from system check +foreach (['/tmp', '/tmp/assets', '/tmp/cache', '/tmp/climulti', '/tmp/latest', '/tmp/logs', '/tmp/sessions', '/tmp/tcpdf', '/tmp/templates_c'] as $sDir) { + $oMonitor->addCheck( + [ + "name" => "check writable dir $sDir", + "description" => "The directory $sDir must be readable and writable", + "group" => "folder", + "check" => [ + "function" => "File", + "params" => [ + "filename" => "$sApproot/$sDir", + "dir" => true, + "readable" => true, + "writable" => true, + ], + ], + ] + ); +} + + +if (isset($aAppDefaults['df'])) { + + $oMonitor->addCheck( + [ + "name" => "check disk space", + "description" => "The file storage must have some space left - warn: " . $aAppDefaults["df"]['warning'] . "/ critical: " . $aAppDefaults["df"]['critical'], + "check" => [ + "function" => "Diskfree", + "params" => [ + "directory" => $sApproot, + "warning" => $aAppDefaults["df"]['warning'], + "critical" => $aAppDefaults["df"]['critical'], + ], + ], + ] + ); +} + +// ---------------------------------------------------------------------- + +require 'inc_appcheck_end.php'; + +// ---------------------------------------------------------------------- \ No newline at end of file diff --git a/public_html/appmonitor/plugins/apps/nextcloud.php b/public_html/appmonitor/plugins/apps/nextcloud.php new file mode 100644 index 0000000000000000000000000000000000000000..231fbb0ad95a459a0001c96c8d730e8e6b79bc99 --- /dev/null +++ b/public_html/appmonitor/plugins/apps/nextcloud.php @@ -0,0 +1,235 @@ +<?php +/* ______________________________________________________________________ + * + * A P P M O N I T O R :: CLIENT - CHECK + * ______________________________________________________________________ + * + * Check for a Nextcloud instance. + * + * It checks + * - the read + write access to the config file + * - connect to database (which is read from config) + * - the read + write access to data dir + * - free disk space on data dir + * - ssl certificate (on https request only) + * + * @author: Axel Hahn - https://www.axel-hahn.de/ + * ---------------------------------------------------------------------- + * 2025-01-02 v1.0 + */ + +// ---------------------------------------------------------------------- +// Init +// ---------------------------------------------------------------------- + +$aAppDefaults = [ + "name" => "Nextcloud", + "tags" => ["nextcloud", "share"], + "df" => [ + "warning" => "1GB", + "critical" => "100MB" + ] +]; + +require 'inc_appcheck_start.php'; + +// ---------------------------------------------------------------------- +// Read Nextcloud specific config items +// ---------------------------------------------------------------------- + +$sConfigfile = "$sApproot/config/config.php"; +if (!file_exists($sConfigfile)) { + header('HTTP/1.0 400 Bad request'); + die('ERROR: Config file was not found. Use ?rel=/NAME or similiar to set a relative install dir.'); +} + +if (!include "$sConfigfile") { + header('HTTP/1.0 400 Bad request'); + die('ERROR: Unable to read config file.'); +} + +// now $CONFIG is available ... +/* +Array +( + [instanceid] => ocw... + [passwordsalt] => cNs... + [secret] => kFdQXw2w... + [trusted_domains] => Array + ( + [0] => https://www.example.com + ) + + [datadirectory] => /home/httpd/cloud/data + [dbtype] => mysql + [version] => 30.0.4.1 + [overwrite.cli.url] => https://www.example.com/cloud + [dbname] => nextcloud + [dbhost] => 127.0.0.1 + [dbport] => + [dbtableprefix] => oc_ + [mysql.utf8mb4] => 1 + [dbuser] => mydbuser + [dbpassword] => 516px9kcc... + [installed] => 1 + [maintenance] => + [theme] => + [loglevel] => 2 + [mail_smtpmode] => smtp + [mail_sendmailmode] => smtp +) +*/ + +if (!isset($CONFIG) || !is_array($CONFIG)) { + header('HTTP/1.0 400 Bad request'); + die('ERROR: Config file was found but has unexpected format.'); +} + + +// ---------------------------------------------------------------------- +// checks +// ---------------------------------------------------------------------- + +// required php modules +// see https://docs.nextcloud.com/server/latest/admin_manual/installation/system_requirements.html +// doesn't show needed modules +/* +$oMonitor->addCheck( + [ + "name" => "PHP modules", + "description" => "Check needed PHP modules", + // "group" => "folder", + "check" => [ + "function" => "Phpmodules", + "params" => [ + "required" => [ + "PDO", + "curl", + "gd", + "mbstring", + "pdo_mysql", + "xml", + ], + "optional" => [], + ], + ], + ] +); +*/ + +$oMonitor->addCheck( + [ + "name" => "config file", + "description" => "The config file must be readable and writable", + "check" => [ + "function" => "File", + "params" => [ + "filename" => $sConfigfile, + "file" => true, + "readable" => true, + "writable" => true, + ], + ], + ] +); +$oMonitor->addCheck( + [ + "name" => "Version", + "description" => "Nextcloud version", + "parent" => "config file", + "check" => [ + "function" => "Simple", + "params" => [ + "result" => RESULT_OK, + "value" => $CONFIG['version'] ?? "??", + "count" => $CONFIG['version'] ?? "??", + "visual" => "simple" + ], + ], + ] +); +$oMonitor->addCheck( + [ + "name" => "maintenance", + "description" => "Is maintenance mode enabled?", + "parent" => "config file", + "check" => [ + "function" => "Simple", + "params" => [ + "result" => $CONFIG['maintenance'] ? RESULT_ERROR : RESULT_OK, + "value" => $CONFIG['maintenance'] ? "enabled - public access is denied" : "disabled (OK)", + ], + ], + ] +); + +// ---------------------------------------------------------------------- +// database +// ---------------------------------------------------------------------- + +if($CONFIG['dbtype'] == "mysql"){ + $oMonitor->addCheck( + [ + "name" => "Mysql Connect", + // "description" => "Connect mysql server " . $aConfig['database']['host'] . " as user " . $aConfig['database']['username'] . " to scheme " . $aConfig['database']['dbname'], + "description" => "Connect mysql server", + "parent" => "config file", + "check" => [ + "function" => "MysqlConnect", + "params" => [ + "server" => $CONFIG['dbhost'], + "user" => $CONFIG['dbuser'], + "password" => $CONFIG['dbpassword'], + "db" => $CONFIG['dbname'], + "port" => $CONFIG['dbport'], + ], + ], + ] + ); +} + +// ---------------------------------------------------------------------- +// data directory +// ---------------------------------------------------------------------- + +$oMonitor->addCheck( + [ + "name" => "data dir", + "description" => "Data directory must be readable and writable", + "parent" => "config file", + "check" => [ + "function" => "File", + "params" => [ + "filename" => $CONFIG['datadirectory'], + "dir" => true, + "readable" => true, + "writable" => true, + ], + ], + ] +); + +if (isset($aAppDefaults['df'])) { + + $oMonitor->addCheck( + [ + "name" => "check disk space", + "description" => "The file storage must have some space left - warn: " . $aAppDefaults["df"]['warning'] . "/ critical: " . $aAppDefaults["df"]['critical'], + "parent" => "data dir", + "check" => [ + "function" => "Diskfree", + "params" => [ + "directory" => $CONFIG['datadirectory'], + "warning" => $aAppDefaults["df"]['warning'], + "critical" => $aAppDefaults["df"]['critical'], + ], + ], + ] + ); +} + +// ---------------------------------------------------------------------- + +require 'inc_appcheck_end.php'; + +// ---------------------------------------------------------------------- diff --git a/public_html/appmonitor/plugins/apps/shared_check_ssl.php b/public_html/appmonitor/plugins/apps/shared_check_ssl.php index c2f45b778e14194367197b336351205646034ce9..c80a3b8da347af8e1d5eefe20dc2d6017c30e91a 100644 --- a/public_html/appmonitor/plugins/apps/shared_check_ssl.php +++ b/public_html/appmonitor/plugins/apps/shared_check_ssl.php @@ -18,7 +18,7 @@ // ---------------------------------------------------------------------- // check certificate - only if https is used // ---------------------------------------------------------------------- -if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']){ +if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']) { $oMonitor->addCheck( [ "name" => "Certificate check", diff --git a/public_html/appmonitor/plugins/apps/wordpress.php b/public_html/appmonitor/plugins/apps/wordpress.php index 711a15fcc7bbc64f564f95cd07c6e7e9cba9a643..1ac052034d32a09d01b14fc6dae2e730f79c2160 100644 --- a/public_html/appmonitor/plugins/apps/wordpress.php +++ b/public_html/appmonitor/plugins/apps/wordpress.php @@ -20,8 +20,24 @@ * 2019-05-24 v0.02 detect include or standalone mode * 2019-05-24 v0.03 detect include or standalone mode * 2024-07-31 v0.04 first version for wordpress check in plugins/apps/ + * 2024-11-21 v0.05 use shared_check_sl + * 2024-11-22 v0.07 <axel.hahn@unibe.ch> send 400 instead of 503 on error + * 2024-12-21 v0.08 ah add php-modules and parent + * 2025-01-06 v1.05 ah add df */ +// ---------------------------------------------------------------------- +// Init +// ---------------------------------------------------------------------- + +$aAppDefaults = [ + "name" => "Wordpress", + "tags" => ["wordpress", "blog"], + "df" => [ + "warning" => "100MB", + "critical" => "10MB" + ] +]; require 'inc_appcheck_start.php'; @@ -31,23 +47,62 @@ require 'inc_appcheck_start.php'; $sConfigfile = $sApproot . '/wp-config.php'; if (!file_exists($sConfigfile)) { - header('HTTP/1.0 503 Service Unavailable'); - die('ERROR: Config file [wp-config.php] was not found. Set a correct $sApproot pointing to wordpress install dir.'); + header('HTTP/1.0 400 Bad request'); + die('ERROR: Config file [wp-config.php] was not found. Set a correct app root pointing to wordpress install dir.'); } require($sConfigfile); -$aDb=[ - 'server' => DB_HOST, - 'username' => DB_USER, - 'password' => DB_PASSWORD, - 'database' => DB_NAME, - // 'port' => ??, -]; +$aDb = [ + 'server' => DB_HOST, + 'username' => DB_USER, + 'password' => DB_PASSWORD, + 'database' => DB_NAME, + // 'port' => ??, +]; // ---------------------------------------------------------------------- // checks // ---------------------------------------------------------------------- +// required php modules +// see https://ertano.com/required-php-modules-for-wordpress/ +$oMonitor->addCheck( + [ + "name" => "PHP modules", + "description" => "Check needed PHP modules", + // "group" => "folder", + "check" => [ + "function" => "Phpmodules", + "params" => [ + "required" => [ + // "cmath", + "cli", + "curl", + "date", + "dom", + "fileinfo", + "filter", + "gd", + "gettext", + "hash", + "iconv", + "imagick", + "json", + // "libsodium", + "mysql", + "openssl", + "pcre", + // "opcache", + // "readline", + "xml", + "zip" + ], + "optional" => [], + ], + ], + ] +); + $oMonitor->addCheck( [ "name" => "config file", @@ -72,30 +127,34 @@ $oMonitor->addCheck( "check" => [ "function" => "MysqlConnect", "params" => [ - "server" => $aDb['server'], - "user" => $aDb['username'], + "server" => $aDb['server'], + "user" => $aDb['username'], "password" => $aDb['password'], - "db" => $aDb['database'], + "db" => $aDb['database'], // "port" => $aDb['port'], ], ], ] ); -if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']){ +if (isset($aAppDefaults['df'])) { + $oMonitor->addCheck( [ - "name" => "Certificate check", - "description" => "Check if SSL cert is valid and does not expire soon", + "name" => "check disk space", + "description" => "The file storage must have some space left - warn: " . $aAppDefaults["df"]['warning'] . "/ critical: " . $aAppDefaults["df"]['critical'], "check" => [ - "function" => "Cert", + "function" => "Diskfree", + "params" => [ + "directory" => "$sApproot", + "warning" => $aAppDefaults["df"]['warning'], + "critical" => $aAppDefaults["df"]['critical'], + ], ], ] ); } -// ---------------------------------------------------------------------- - require 'inc_appcheck_end.php'; // ---------------------------------------------------------------------- diff --git a/public_html/appmonitor/plugins/checks/diskfree.php b/public_html/appmonitor/plugins/checks/diskfree.php index f1d942849f73698c98493c5131451baf5891516b..86e8efc8d4f74547b9e1647074167e59cb3af206 100755 --- a/public_html/appmonitor/plugins/checks/diskfree.php +++ b/public_html/appmonitor/plugins/checks/diskfree.php @@ -19,7 +19,7 @@ * * 2021-10-26 <axel.hahn@iml.unibe.ch> * 2024-07-23 <axel.hahn@unibe.ch> php 8 only: use typed variables - * + * 2025-01-02 <www.axel-hahn.de> update output */ class checkDiskfree extends appmonitorcheck { @@ -58,7 +58,7 @@ class checkDiskfree extends appmonitorcheck $iCritical = $this->_getSize($aParams["critical"]); $iSpaceLeft = disk_free_space($sDirectory); - $sMessage = '[' . $sDirectory . '] has ' . $this->_getHrSize($iSpaceLeft) . ' left.'; + $sMessage = $this->_getHrSize($iSpaceLeft) . ' left in [' . $sDirectory . '].'; if ($iWarn) { if ($iWarn <= $iCritical) { @@ -68,7 +68,7 @@ class checkDiskfree extends appmonitorcheck if ($iWarn < $iSpaceLeft) { return [ RESULT_OK, - "$sMessage Warning level is not reached yet (still " . $this->_getHrSize($iSpaceLeft - $iWarn) . "over warning limit)." + "$sMessage Warning level is not reached yet (still " . $this->_getHrSize($iSpaceLeft - $iWarn) . " over warning limit)." ]; } if ($iWarn > $iSpaceLeft && $iCritical < $iSpaceLeft) { diff --git a/public_html/appmonitor/plugins/checks/httpcontent.php b/public_html/appmonitor/plugins/checks/httpcontent.php index 8655a067077af819ffd52480a65d5c725d608de8..3d981c54e7a34dcf29f9473681d7e2a2be8e950c 100755 --- a/public_html/appmonitor/plugins/checks/httpcontent.php +++ b/public_html/appmonitor/plugins/checks/httpcontent.php @@ -21,7 +21,7 @@ * 2022-12-21 <axel.hahn@unibe.ch> add flag sslverify * 2023-07-06 <axel.hahn@unibe.ch> add flag userpwd * 2024-07-23 <axel.hahn@unibe.ch> php 8 only: use typed variables - * + * 2024-11-22 <axel.hahn@unibe.ch> Return unknown if curl module is not active */ class checkHttpContent extends appmonitorcheck { @@ -67,8 +67,7 @@ class checkHttpContent extends appmonitorcheck { $this->_checkArrayKeys($aParams, "url"); if (!function_exists("curl_init")) { - header('HTTP/1.0 503 Service Unavailable'); - die("ERROR: PHP CURL module is not installed."); + return [RESULT_UNKNOWN, "UNKNOWN: Unable to perform mysqli test. The php-curl module is not active."]; } $bShowContent = (isset($aParams["content"]) && $aParams["content"]) ? true : false; $ch = curl_init($aParams["url"]); diff --git a/public_html/appmonitor/plugins/checks/mysqlconnect.php b/public_html/appmonitor/plugins/checks/mysqlconnect.php index d259ec001b3e4c7bb6723352e78ba08ae8c96fb0..5fe8a611cccb570bdd57475a915b11a9f16c96eb 100755 --- a/public_html/appmonitor/plugins/checks/mysqlconnect.php +++ b/public_html/appmonitor/plugins/checks/mysqlconnect.php @@ -19,7 +19,7 @@ * * 2021-10-27 <axel.hahn@iml.unibe.ch> * 2024-07-23 <axel.hahn@unibe.ch> php 8 only: use typed variables - * + * 2024-11-22 <axel.hahn@unibe.ch> detect installed mysqli function */ class checkMysqlConnect extends appmonitorcheck { @@ -48,6 +48,9 @@ class checkMysqlConnect extends appmonitorcheck public function run(array $aParams): array { $this->_checkArrayKeys($aParams, "server,user,password,db"); + if (!function_exists("mysqli_init")) { + return [RESULT_UNKNOWN, "UNKNOWN: Unable to perform mysqli test. The php-mysqli module is not active."]; + } $mysqli = mysqli_init(); if (!$mysqli) { return [RESULT_ERROR, 'ERROR: mysqli_init failed.'];