Can't access web interface

Discussions related to the 1.36.x series of ZoneMinder
Post Reply
anndrew
Posts: 12
Joined: Tue Nov 26, 2024 11:02 am

Can't access web interface

Post by anndrew »

Hi all!

I'm trying to run ZoneMinder in my PC since I want to manage my IP camera through ZoneMinder. My operating system is Debian bookworm. I followed the instalation steps at https://wiki.zoneminder.com/Debian_12_B ... and_1.37.x, basically the suggested script in that website. So I now have ZoneMinder version 1.36.35~20241022.27-bookworm installed.

But I can't access the web interface via http://hostname_or_ip/zm. What I get is a text result in the browser, either in firefox or in chromium.

Here are some outputs in case it would help to narrow down my issue:

Code: Select all

dpkg -s zoneminder
Package: zoneminder
Status: install ok installed
Priority: optional
Section: net
Installed-Size: 33559
Maintainer: Isaac Connor <isaac@zoneminder.com>
Architecture: amd64
Version: 1.36.35~20241022.27-bookworm
Depends: libavcodec59 (>= 7:5.0), libavformat59 (>= 7:5.0), libavutil57 (>= 7:5.1), libc6 (>= 2.34), libgcc-s1 (>= 3.0), libgcrypt20 (>= 1.10.0), libgnutls30 (>= 3.7.0), libjpeg62-turbo (>= 1.3.1), libjwt-gnutls0 (>= 1.9.0), libmariadb3 (>= 3.0.0), libpcre3, libstdc++6 (>= 12), libswresample4 (>= 7:5.1), libswscale6 (>= 7:5.0), zlib1g (>= 1:1.1.4), perl:any, javascript-common, ffmpeg, libdate-manip-perl, libmime-lite-perl, libmime-tools-perl, libdbd-mysql-perl, libphp-serialization-perl, libmodule-load-conditional-perl, libnet-sftp-foreign-perl, libarchive-zip-perl, libdevice-serialport-perl, libimage-info-perl, libio-interface-perl, libjson-maybexs-perl, libsys-mmap-perl, liburi-encode-perl, libwww-perl, liburi-perl, libdata-dump-perl, libdatetime-perl, libclass-std-fast-perl, libsoap-wsdl-perl, libio-socket-multicast-perl, libdigest-sha-perl, libsys-cpu-perl, libsys-meminfo-perl, libdata-uuid-perl, libnumber-bytes-human-perl, libfile-slurp-perl, default-mysql-client | mariadb-client | virtual-mysql-client, php-mysql, php-gd, php-apcu, php-json, php-intl, policykit-1, rsyslog | system-log-daemon, zip, libcrypt-eksblowfish-perl, libdata-entropy-perl, libvncclient1 | libvncclient0
Recommends: apache2 (>= 2.4.6-4~) | nginx | httpd, libapache2-mod-php | php-fpm, default-mysql-server | mariadb-server | virtual-mysql-server, zoneminder-doc (>= 1.36.35~20241022.27-bookworm)
Suggests: fcgiwrap, logrotate
Conffiles:
 /etc/apache2/conf-available/zoneminder.conf 845925cd0e008e93c0850b9f5236db82
 /etc/init.d/zoneminder bb12d862700881828f722c477ef271c1
 /etc/logrotate.d/zoneminder 94a48a435af9434bea71b00802e7a5d9
 /etc/zm/conf.d/01-system-paths.conf 934bbdf926fdc4c9b5167028e134f70a
 /etc/zm/conf.d/02-multiserver.conf af136258d51fdb551b50d39f4f563cd9
 /etc/zm/conf.d/README 15fa271f6d59fd553c7e282ddd502898
 /etc/zm/zm.conf 21d5c0e3b2c2337aae600ffa4429152a
Description: video camera security and surveillance solution
 ZoneMinder is intended for use in single or multi-camera video security
 applications, including commercial or home CCTV, theft prevention and child
 or family member or home monitoring and other care scenarios. It
 supports capture, analysis, recording, and monitoring of video data coming
 from one or more video or network cameras attached to a Linux system.
 ZoneMinder also support web and semi-automatic control of Pan/Tilt/Zoom
 cameras using a variety of protocols. It is suitable for use as a home
 video security system and for commercial or professional video security
 and surveillance. It can also be integrated into a home automation system
 via X.10 or other protocols.
Homepage: https://www.zoneminder.com/
All the following commands yield correct outputs:

Code: Select all

sudo systemctl enable zoneminder
sudo service zoneminder start
sudo adduser www-data video
sudo a2enconf zoneminder
sudo a2enmod rewrite
sudo a2enmod headers
sudo a2enmod expires
sudo service apache2 reload
The text outputs when I try to access the web interface, in firefox, seems to correspond to the php file at: /usr/share/zoneminder/www/index.php. Here I attach a screenshot:

Image

Here is the same in text format. It is shown as a long and continuos text:

Code: Select all

setPatter(ZM_DATE_FORMAT_PATTERN); } if (ZM_DATETIME_FORMAT_PATTERN) { $dateTimeFormatter->setPattern(ZM_DATETIME_FORMAT_PATTERN); } if (ZM_TIME_FORMAT_PATTERN) { $timeFormatter->setPattern(ZM_TIME_FORMAT_PATTERN); } require_once('includes/session.php'); require_once('includes/logger.php'); require_once('includes/Server.php'); // Useful debugging lines for mobile devices if ( 0 and ZM\Logger::fetch()->debugOn() ) { ob_start(); phpinfo(INFO_VARIABLES); ZM\Debug(ob_get_contents()); ob_end_clean(); } global $Servers; $Servers = ZM\Server::find(); if ( (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') or (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ) { $protocol = 'https'; } else { $protocol = 'http'; } define('ZM_BASE_PROTOCOL', $protocol); // Absolute URL's are unnecessary and break compatibility with reverse proxies // define( "ZM_BASE_URL", $protocol.'://'.$_SERVER['HTTP_HOST'] ); // Use relative URL's instead define('ZM_BASE_URL', ''); require_once('includes/functions.php'); if ( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ) { ZM\Debug('OPTIONS Method, only doing CORS'); # Add Cross domain access headers CORSHeaders(); return; } if ( isset($_GET['skin']) ) { $skin = $_GET['skin']; } else if ( isset($_COOKIE['zmSkin']) ) { $skin = $_COOKIE['zmSkin']; } else if ( defined('ZM_SKIN_DEFAULT') ) { $skin = ZM_SKIN_DEFAULT; } else { $skin = 'classic'; } if (!is_dir('skins/'.$skin) ) { $skins = array_map('basename', glob('skins/*', GLOB_ONLYDIR)); if ( !in_array($skin, $skins) ) { ZM\Error("Invalid skin '$skin' setting to ".$skins[0]); $skin = $skins[0]; } } global $css; if ( isset($_GET['css']) ) { $css = $_GET['css']; } else if ( isset($_COOKIE['zmCSS']) ) { $css = $_COOKIE['zmCSS']; } else if ( defined('ZM_CSS_DEFAULT') ) { $css = ZM_CSS_DEFAULT; } else { $css = 'classic'; } if (!is_dir("skins/$skin/css/$css")) { $css_skins = array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR)); if (count($css_skins)) { if (!in_array($css, $css_skins)) { ZM\Error("Invalid skin css '$css' setting to " . $css_skins[0]); $css = $css_skins[0]; if (isset($_COOKIE['zmCSS'])) { unset($_COOKIE['zmCSS']); setcookie('zmCSS', '', time() - 3600); } } else { $css = ''; } } else { ZM\Error("No css options found at skins/$skin/css"); $css = ''; } } define('ZM_BASE_PATH', dirname($_SERVER['REQUEST_URI'])); define('ZM_SKIN_PATH', "skins/$skin"); define('ZM_SKIN_NAME', $skin); $skinBase = array(); // To allow for inheritance of skins if (!file_exists(ZM_SKIN_PATH)) ZM\Fatal("Invalid skin '$skin'"); $skinBase[] = $skin; zm_session_start(); if ( !isset($_SESSION['skin']) || isset($_REQUEST['skin']) || !isset($_COOKIE['zmSkin']) || ($_COOKIE['zmSkin'] != $skin) ) { $_SESSION['skin'] = $skin; zm_setcookie('zmSkin', $skin); } if ( !isset($_SESSION['css']) || isset($_REQUEST['css']) || !isset($_COOKIE['zmCSS']) || ($_COOKIE['zmCSS'] != $css) ) { $_SESSION['css'] = $css; zm_setcookie('zmCSS', $css); } # Add Cross domain access headers CORSHeaders(); // Check for valid content dirs if ( !is_writable(ZM_DIR_EVENTS) ) { ZM\Warning("Cannot write to event folder ".ZM_DIR_EVENTS.". Check that it exists and is owned by the web account user."); } # Globals # Running is global but only do the daemonCheck if it is actually needed $running = null; $action = null; $error_message = null; $redirect = null; $view = isset($_REQUEST['view']) ? detaintPath($_REQUEST['view']) : null; $user = null; $request = isset($_REQUEST['request']) ? detaintPath($_REQUEST['request']) : null; require_once('includes/auth.php'); # Only one request can open the session file at a time, so let's close the session here to improve concurrency. # Any file/page that sets session variables must re-open it. session_write_close(); require_once('includes/Storage.php'); require_once('includes/Event.php'); require_once('includes/Group.php'); require_once('includes/Monitor.php'); // lang references $user[Language] so must come after auth require_once('includes/lang.php'); foreach ( getSkinIncludes('skin.php') as $includeFile ) { require_once $includeFile; } if (isset($_POST['action'])) { # Actions can only be performed on POST because we don't check csrf on GETs. $action = detaintPath($_POST['action']); } else if (isset($_REQUEST['action']) and $_REQUEST['action'] and empty($_REQUEST['request'])) { ZM\Error('actions can no longer be performed without POST. Requested: '.$_REQUEST['action']. ' for ' .$view); } # The only variable we really need to set is action. The others are informal. isset($view) || $view = NULL; isset($request) || $request = NULL; isset($action) || $action = NULL; if ( (!$view and !$request) or ($view == 'console') ) { check_timezone(); } ZM\Debug("View: $view Request: $request Action: $action User: " . ( isset($user) ? $user['Username'] : 'none' )); if ( ZM_ENABLE_CSRF_MAGIC && ( $action != 'login' ) && ( $view != 'view_video' ) && // only video no html ( $view != 'image' ) && // view=image doesn't return html, just image data. ( $request != 'control' ) && //( $view != 'frames' ) && // big html can overflow ob ( $view != 'archive' ) // returns data && ( (!isset($_SERVER['CONTENT_TYPE']) or ($_SERVER['CONTENT_TYPE'] != 'application/csp-report')) ) ) { require_once('includes/csrf/csrf-magic.php'); #ZM\Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\""); csrf_check(); } # If I put this here, it protects all views and popups, but it has to go after actions.php because actions.php does the actual logging in. if ( ZM_OPT_USE_AUTH and (!isset($user)) and ($view != 'login') and ($view != 'none') ) { if ($request) { # requests only return json header('HTTP/1.1 401 Unauthorized'); exit; } $view = 'none'; $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=login'; zm_session_start(); $_SESSION['postLoginQuery'] = $_SERVER['QUERY_STRING']; session_write_close(); } else if ( ZM_SHOW_PRIVACY && ($view != 'privacy') && ($view != 'options') && (!$request) && canEdit('System') ) { $view = 'none'; $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=privacy'; $request = null; } # Need to include actions because it does auth if ( $action and $view and !$request ) { if ( file_exists('includes/actions/'.$view.'.php') ) { require_once('includes/actions/'.$view.'.php'); } else { ZM\Debug("No includes/actions/$view.php for action $action"); } } if ( isset($_REQUEST['redirect']) ) { $redirect = '?view='.detaintPath($_REQUEST['redirect']); } if ($redirect) { ZM\Debug("Redirecting to $redirect"); header('Location: '.$redirect); return; } if ( $request ) { foreach ( getSkinIncludes('ajax/'.$request.'.php', true, true) as $includeFile ) { if ( !file_exists($includeFile) ) ZM\Fatal("Request '$request' does not exist"); require_once $includeFile; } return; } # Add CSP Headers $cspNonce = bin2hex(zm_random_bytes(16)); if ( $includeFiles = getSkinIncludes('views/'.$view.'.php', true, true) ) { ob_start(); CSPHeaders($view, $cspNonce); foreach ( $includeFiles as $includeFile ) { if (!file_exists($includeFile)) { ZM\Error("View '$view' does not exist, redirecting to console"); header('Location: ?view=console'); return; } require_once $includeFile; } // If the view overrides $view to 'error', and the user is not logged in, then the // issue is probably resolvable by logging in, so provide the opportunity to do so. // The login view should handle redirecting to the correct location afterward. if ( $view == 'error' && !isset($user) ) { $view = 'login'; foreach ( getSkinIncludes('views/login.php', true, true) as $includeFile ) require_once $includeFile; } while (ob_get_level() > 0) ob_end_flush(); } # end if include files for view // If the view is missing or the view still returned error with the user logged in, // then it is not recoverable. if ( !$includeFiles || $view == 'error' ) { foreach ( getSkinIncludes('views/error.php', true, true) as $includeFile ) require_once $includeFile; } ?> 
...so for easier reading I've inserted new lines after the characters ; { }. Here it is:

Code: Select all

setPatter(ZM_DATE_FORMAT_PATTERN);
 }
 if (ZM_DATETIME_FORMAT_PATTERN) {
 $dateTimeFormatter->setPattern(ZM_DATETIME_FORMAT_PATTERN);
 }
 if (ZM_TIME_FORMAT_PATTERN) {
 $timeFormatter->setPattern(ZM_TIME_FORMAT_PATTERN);
 }
 require_once('includes/session.php');
 require_once('includes/logger.php');
 require_once('includes/Server.php');
 // Useful debugging lines for mobile devices if ( 0 and ZM\Logger::fetch()->debugOn() ) {
 ob_start();
 phpinfo(INFO_VARIABLES);
 ZM\Debug(ob_get_contents());
 ob_end_clean();
 }
 global $Servers;
 $Servers = ZM\Server::find();
 if ( (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') or (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ) {
 $protocol = 'https';
 }
 else {
 $protocol = 'http';
 }
 define('ZM_BASE_PROTOCOL', $protocol);
 // Absolute URL's are unnecessary and break compatibility with reverse proxies // define( "ZM_BASE_URL", $protocol.'://'.$_SERVER['HTTP_HOST'] );
 // Use relative URL's instead define('ZM_BASE_URL', '');
 require_once('includes/functions.php');
 if ( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ) {
 ZM\Debug('OPTIONS Method, only doing CORS');
 # Add Cross domain access headers CORSHeaders();
 return;
 }
 if ( isset($_GET['skin']) ) {
 $skin = $_GET['skin'];
 }
 else if ( isset($_COOKIE['zmSkin']) ) {
 $skin = $_COOKIE['zmSkin'];
 }
 else if ( defined('ZM_SKIN_DEFAULT') ) {
 $skin = ZM_SKIN_DEFAULT;
 }
 else {
 $skin = 'classic';
 }
 if (!is_dir('skins/'.$skin) ) {
 $skins = array_map('basename', glob('skins/*', GLOB_ONLYDIR));
 if ( !in_array($skin, $skins) ) {
 ZM\Error("Invalid skin '$skin' setting to ".$skins[0]);
 $skin = $skins[0];
 }
 }
 global $css;
 if ( isset($_GET['css']) ) {
 $css = $_GET['css'];
 }
 else if ( isset($_COOKIE['zmCSS']) ) {
 $css = $_COOKIE['zmCSS'];
 }
 else if ( defined('ZM_CSS_DEFAULT') ) {
 $css = ZM_CSS_DEFAULT;
 }
 else {
 $css = 'classic';
 }
 if (!is_dir("skins/$skin/css/$css")) {
 $css_skins = array_map('basename', glob('skins/'.$skin.'/css/*', GLOB_ONLYDIR));
 if (count($css_skins)) {
 if (!in_array($css, $css_skins)) {
 ZM\Error("Invalid skin css '$css' setting to " . $css_skins[0]);
 $css = $css_skins[0];
 if (isset($_COOKIE['zmCSS'])) {
 unset($_COOKIE['zmCSS']);
 setcookie('zmCSS', '', time() - 3600);
 }
 }
 else {
 $css = '';
 }
 }
 else {
 ZM\Error("No css options found at skins/$skin/css");
 $css = '';
 }
 }
 define('ZM_BASE_PATH', dirname($_SERVER['REQUEST_URI']));
 define('ZM_SKIN_PATH', "skins/$skin");
 define('ZM_SKIN_NAME', $skin);
 $skinBase = array();
 // To allow for inheritance of skins if (!file_exists(ZM_SKIN_PATH)) ZM\Fatal("Invalid skin '$skin'");
 $skinBase[] = $skin;
 zm_session_start();
 if ( !isset($_SESSION['skin']) || isset($_REQUEST['skin']) || !isset($_COOKIE['zmSkin']) || ($_COOKIE['zmSkin'] != $skin) ) {
 $_SESSION['skin'] = $skin;
 zm_setcookie('zmSkin', $skin);
 }
 if ( !isset($_SESSION['css']) || isset($_REQUEST['css']) || !isset($_COOKIE['zmCSS']) || ($_COOKIE['zmCSS'] != $css) ) {
 $_SESSION['css'] = $css;
 zm_setcookie('zmCSS', $css);
 }
 # Add Cross domain access headers CORSHeaders();
 // Check for valid content dirs if ( !is_writable(ZM_DIR_EVENTS) ) {
 ZM\Warning("Cannot write to event folder ".ZM_DIR_EVENTS.". Check that it exists and is owned by the web account user.");
 }
 # Globals # Running is global but only do the daemonCheck if it is actually needed $running = null;
 $action = null;
 $error_message = null;
 $redirect = null;
 $view = isset($_REQUEST['view']) ? detaintPath($_REQUEST['view']) : null;
 $user = null;
 $request = isset($_REQUEST['request']) ? detaintPath($_REQUEST['request']) : null;
 require_once('includes/auth.php');
 # Only one request can open the session file at a time, so let's close the session here to improve concurrency. # Any file/page that sets session variables must re-open it. session_write_close();
 require_once('includes/Storage.php');
 require_once('includes/Event.php');
 require_once('includes/Group.php');
 require_once('includes/Monitor.php');
 // lang references $user[Language] so must come after auth require_once('includes/lang.php');
 foreach ( getSkinIncludes('skin.php') as $includeFile ) {
 require_once $includeFile;
 }
 if (isset($_POST['action'])) {
 # Actions can only be performed on POST because we don't check csrf on GETs. $action = detaintPath($_POST['action']);
 }
 else if (isset($_REQUEST['action']) and $_REQUEST['action'] and empty($_REQUEST['request'])) {
 ZM\Error('actions can no longer be performed without POST. Requested: '.$_REQUEST['action']. ' for ' .$view);
 }
 # The only variable we really need to set is action. The others are informal. isset($view) || $view = NULL;
 isset($request) || $request = NULL;
 isset($action) || $action = NULL;
 if ( (!$view and !$request) or ($view == 'console') ) {
 check_timezone();
 }
 ZM\Debug("View: $view Request: $request Action: $action User: " . ( isset($user) ? $user['Username'] : 'none' ));
 if ( ZM_ENABLE_CSRF_MAGIC && ( $action != 'login' ) && ( $view != 'view_video' ) && // only video no html ( $view != 'image' ) && // view=image doesn't return html, just image data. ( $request != 'control' ) && //( $view != 'frames' ) && // big html can overflow ob ( $view != 'archive' ) // returns data && ( (!isset($_SERVER['CONTENT_TYPE']) or ($_SERVER['CONTENT_TYPE'] != 'application/csp-report')) ) ) {
 require_once('includes/csrf/csrf-magic.php');
 #ZM\Debug("Calling csrf_check with the following values: \$request = \"$request\", \$view = \"$view\", \$action = \"$action\"");
 csrf_check();
 }
 # If I put this here, it protects all views and popups, but it has to go after actions.php because actions.php does the actual logging in. if ( ZM_OPT_USE_AUTH and (!isset($user)) and ($view != 'login') and ($view != 'none') ) {
 if ($request) {
 # requests only return json header('HTTP/1.1 401 Unauthorized');
 exit;
 }
 $view = 'none';
 $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=login';
 zm_session_start();
 $_SESSION['postLoginQuery'] = $_SERVER['QUERY_STRING'];
 session_write_close();
 }
 else if ( ZM_SHOW_PRIVACY && ($view != 'privacy') && ($view != 'options') && (!$request) && canEdit('System') ) {
 $view = 'none';
 $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=privacy';
 $request = null;
 }
 # Need to include actions because it does auth if ( $action and $view and !$request ) {
 if ( file_exists('includes/actions/'.$view.'.php') ) {
 require_once('includes/actions/'.$view.'.php');
 }
 else {
 ZM\Debug("No includes/actions/$view.php for action $action");
 }
 }
 if ( isset($_REQUEST['redirect']) ) {
 $redirect = '?view='.detaintPath($_REQUEST['redirect']);
 }
 if ($redirect) {
 ZM\Debug("Redirecting to $redirect");
 header('Location: '.$redirect);
 return;
 }
 if ( $request ) {
 foreach ( getSkinIncludes('ajax/'.$request.'.php', true, true) as $includeFile ) {
 if ( !file_exists($includeFile) ) ZM\Fatal("Request '$request' does not exist");
 require_once $includeFile;
 }
 return;
 }
 # Add CSP Headers $cspNonce = bin2hex(zm_random_bytes(16));
 if ( $includeFiles = getSkinIncludes('views/'.$view.'.php', true, true) ) {
 ob_start();
 CSPHeaders($view, $cspNonce);
 foreach ( $includeFiles as $includeFile ) {
 if (!file_exists($includeFile)) {
 ZM\Error("View '$view' does not exist, redirecting to console");
 header('Location: ?view=console');
 return;
 }
 require_once $includeFile;
 }
 // If the view overrides $view to 'error', and the user is not logged in, then the // issue is probably resolvable by logging in, so provide the opportunity to do so. // The login view should handle redirecting to the correct location afterward. if ( $view == 'error' && !isset($user) ) {
 $view = 'login';
 foreach ( getSkinIncludes('views/login.php', true, true) as $includeFile ) require_once $includeFile;
 }
 while (ob_get_level() > 0) ob_end_flush();
 }
 # end if include files for view // If the view is missing or the view still returned error with the user logged in, // then it is not recoverable. if ( !$includeFiles || $view == 'error' ) {
 foreach ( getSkinIncludes('views/error.php', true, true) as $includeFile ) require_once $includeFile;
 }
 ?> 
Since the text starts at the line with the 'patter' typo, I followed this post viewtopic.php?t=33658 to change that typo from 'patter' to 'pattern', but I still get the text result in the web browser.


Following another post viewtopic.php?t=29382 I changed '#User=www-data' to 'User=www-data' (just removed the '#') in the file /lib/systemd/system/zoneminder.service. But it didn't help either.

I am not used to php language, nor the complexity of network systems. I looked at https://www.w3schools.com/php/php_mysql_intro.asp to read about the php syntax and the rest of the php file apparently seems ok.

The command: sudo systemctl status zoneminder.service seems to inform that everything is OK too (to me).

Code: Select all

● zoneminder.service - ZoneMinder CCTV recording and surveillance system
     Loaded: loaded (/lib/systemd/system/zoneminder.service; enabled; preset: enabled)
     Active: active (running) since Tue 2024-11-26 12:57:31 CET; 52min ago
   Main PID: 5121 (zmdc.pl)
      Tasks: 6 (limit: 55255)
     Memory: 105.3M
        CPU: 3.005s
     CGroup: /system.slice/zoneminder.service
             ├─5121 /usr/bin/perl -wT /usr/bin/zmdc.pl startup
             ├─5149 /usr/bin/perl -wT /usr/bin/zmfilter.pl --filter_id=1 --daemon
             ├─5153 /usr/bin/perl -wT /usr/bin/zmfilter.pl --filter_id=2 --daemon
             ├─5160 /usr/bin/perl -wT /usr/bin/zmwatch.pl
             ├─5165 /usr/bin/perl -wT /usr/bin/zmupdate.pl -c
             └─5169 /usr/bin/perl -wT /usr/bin/zmstats.pl

Nov 26 12:57:31 anndrewhost sudo[5155]:     root : PWD=/usr/share/zoneminder/www ; USER=www-data ; COMM>
Nov 26 12:57:31 anndrewhost sudo[5155]: pam_unix(sudo:session): session opened for user www-data(uid=33>
Nov 26 12:57:31 anndrewhost sudo[5155]: pam_unix(sudo:session): session closed for user www-data
Nov 26 12:57:31 anndrewhost sudo[5161]:     root : PWD=/usr/share/zoneminder/www ; USER=www-data ; COMM>
Nov 26 12:57:31 anndrewhost sudo[5161]: pam_unix(sudo:session): session opened for user www-data(uid=33>
Nov 26 12:57:31 anndrewhost sudo[5161]: pam_unix(sudo:session): session closed for user www-data
Nov 26 12:57:31 anndrewhost sudo[5166]:     root : PWD=/usr/share/zoneminder/www ; USER=www-data ; COMM>
Nov 26 12:57:31 anndrewhost sudo[5166]: pam_unix(sudo:session): session opened for user www-data(uid=33>
Nov 26 12:57:31 anndrewhost sudo[5166]: pam_unix(sudo:session): session closed for user www-data
Nov 26 12:57:31 anndrewhost systemd[1]: Started zoneminder.service - ZoneMinder CCTV recording and surv>
No clue why I can't access the web interface.

Any help would be much appreciated. Thanks.
mikb
Posts: 673
Joined: Mon Mar 25, 2013 12:34 pm

Re: Can't access web interface

Post by mikb »

The fundamental fault here seems to be that the web-server is doing the bare-minimum here ...

You asked to receive the contents of "something.php" and it served you, literally, the content of that file. Unprocessed.

Of course, what _should_ happen is that .php script _runs_ and the output from _that_ is served to you.

Seems a common problem outside of ZM too :(

https://www.bing.com/search?form=&q=why ... plain+text
anndrew
Posts: 12
Joined: Tue Nov 26, 2024 11:02 am

Re: Can't access web interface

Post by anndrew »

Thank you mikb for your reply. That gives me new clues to continue searching... :)

In these two posts:
https://stackoverflow.com/questions/355 ... plain-text
https://unix.stackexchange.com/question ... trol-panel

they comment I would need the PHP libraries, either the libapache2-mod-php or the PHP 5 library for Apache. the first one is already installed but I don't have the second (PHP5) library available in my distro. But that was an old post at stackoverflow, so I guess the equivalent would be the libapache2-mod-php8.2 in my system. It was already installed.

I will continue searching for a way to make php scripts running in my web browser...

Thanks!
anndrew
Posts: 12
Joined: Tue Nov 26, 2024 11:02 am

Re: Can't access web interface

Post by anndrew »

Hi again,

I found a similar issue here: viewtopic.php?t=10394

Following answers there, I made a PHP file at /usr/share/zoneminder/www/testing.php
containing just these three lines:

Code: Select all

<?PHP
phpinfo();
?>
It is supposed to give php information. When I try to run it from the web browser via: http://localhost/zm/testing.php nothing happens, just a blank page.

Following the same post, since I had not the zm folder /var/www/zm, I did:

Code: Select all

ln -s /usr/share/zoneminder /var/www/zm 
But it doesn't fix it either.

The url http://localhost/zm/index.php still gives the plain text commented earlier.
anndrew
Posts: 12
Joined: Tue Nov 26, 2024 11:02 am

Re: Can't access web interface

Post by anndrew »

In case any of my searching or attemps could give someone any clue about my issue, I will be updating here any info/output I find that could help.

(Sorry if I am making this thread too long with rubish but, being a newbie with ZoneMinder and networks in general, I am at a point that can't tell what is important from what is not.)

When I write this in the mozilla web browser:

Code: Select all

http://localhost:80

I get the Apache2 Debian Default Page saying "it works!". Here is a screenshot:

Image

So at least I know apache2 is not the problem... :/

Here is the output of php -v:

Code: Select all

PHP 8.2.24 (cli) (built: Sep 27 2024 04:16:10) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.24, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.24, Copyright (c), by Zend Technologies
And a PHP test:

Code: Select all

anndrew@anndrewhost:~$ echo '<?php echo `php -i`."\n"; ?>' > php_test.php 
anndrew@anndrewhost:~$ cat php_test.php 
<?php echo `php -i`."\n"; ?>
anndrew@anndrewhost:~$ php php_test.php | head
phpinfo()
PHP Version => 8.2.24

System => Linux anndrewhost 6.1.0-28-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.119-1 (2024-11-22) x86_64
Build Date => Sep 27 2024 04:16:10
Build System => Linux
Server API => Command Line Interface
Virtual Directory Support => disabled
Configuration File (php.ini) Path => /etc/php/8.2/cli
Loaded Configuration File => /etc/php/8.2/cli/php.ini
A list of installed php modules:

Code: Select all

$ php --modules
[PHP Modules]
apcu
calendar
Core
ctype
curl
date
dom
exif
FFI
fileinfo
filter
ftp
gd
gettext
hash
iconv
intl
json
libxml
mbstring
mysqli
mysqlnd
openssl
pcntl
pcre
PDO
pdo_mysql
Phar
posix
random
readline
Reflection
session
shmop
SimpleXML
sockets
sodium
SPL
standard
sysvmsg
sysvsem
sysvshm
tokenizer
xml
xmlreader
xmlwriter
xsl
Zend OPcache
zip
zlib

[Zend Modules]
Zend OPcache
A list of active services (those with a '+'):

Code: Select all

sudo service --status-all
 [ - ]  alsa-utils
 [ - ]  anacron
 [ - ]  apache-htcacheclean
 [ + ]  apache2
 [ + ]  apparmor
 [ + ]  binfmt-support
 [ + ]  bzflag
 [ - ]  console-setup.sh
 [ + ]  cron
 [ + ]  cups
 [ + ]  cups-browsed
 [ + ]  dbus
 [ + ]  exim4
 [ - ]  gdomap
 [ - ]  hddtemp
 [ - ]  hwclock.sh
 [ - ]  keyboard-setup.sh
 [ + ]  kmod
 [ + ]  lightdm
 [ + ]  lm-sensors
 [ + ]  mariadb
 [ + ]  networking
 [ + ]  openvpn
 [ + ]  pcscd
 [ - ]  plymouth
 [ + ]  plymouth-log
 [ + ]  procps
 [ - ]  pulseaudio-enable-autospawn
 [ - ]  rsync
 [ - ]  saned
 [ - ]  scsitools-pre.sh
 [ - ]  scsitools.sh
 [ + ]  smartmontools
 [ - ]  speech-dispatcher
 [ + ]  ssh
 [ - ]  sudo
 [ - ]  sysstat
 [ + ]  tor
 [ + ]  udev
 [ + ]  ufw
 [ - ]  x11-common
 [ + ]  zoneminder
Last edited by anndrew on Tue Nov 26, 2024 6:49 pm, edited 1 time in total.
anndrew
Posts: 12
Joined: Tue Nov 26, 2024 11:02 am

Re: Can't access web interface

Post by anndrew »

Update.
I have read in this post https://stackoverflow.com/questions/512 ... ource-code that in order for apache to open php at web browsers apache's httpd.conf file should have the PHP MIME type in it. Some line similar to:

Code: Select all

AddType application/x-httpd-php .php
I have checked that my /etc/apache2/apache2.conf doesn't contain any reference to AddType or php at all. So there I go and added it at the end of the file:

Code: Select all

AddType application/x-httpd-php .php
I restarted apache and php services and tried entering the ZoneMinder web interface, but no success yet. However I think I am getting closer, since now I get a file downloaded (it corresponds to the same file comment at the beginning of the post (/usr/share/zoneminder/www/index.php).

I also tried both with the original file /usr/share/zoneminder/www/index.php and with the corrected typo (patter / pattern). With both I get the file downloaded.

Please, any insights, or anything else I should try?
User avatar
iconnor
Posts: 3266
Joined: Fri Oct 29, 2010 1:43 am
Location: Toronto
Contact:

Re: Can't access web interface

Post by iconnor »

sudo a2enmod php8.2
sudo systemctl reload apache2
anndrew
Posts: 12
Joined: Tue Nov 26, 2024 11:02 am

Re: Can't access web interface

Post by anndrew »

Thank you so much iconnor. Using your commands I finally got it!! Can't believe it! :)

Here is what I encountered:

I tried those two commands but initially got a 'conflict' message:

Code: Select all

$ sudo a2enmod php8.2
Considering dependency mpm_prefork for php8.2:
Considering conflict mpm_event for mpm_prefork:
ERROR: Module mpm_event is enabled - cannot proceed due to conflicts. It needs to be disabled first!
Considering conflict mpm_worker for mpm_prefork:
ERROR: Could not enable dependency mpm_prefork for php8.2, aborting
Following these post https://stackoverflow.com/questions/470 ... -php-files I run these commands:

Code: Select all

    sudo a2dismod mpm_event              # ===>  this went ok.
    sudo systemctl restart apache2       # Got an error: Job for apache2.service failed because the control process exited with error code, but I ignore it and continued.
    sudo a2enmod mpm_prefork             # ===>  this went ok.
    sudo systemctl restart apache2       # ===>  this went ok.
    sudo a2enmod php8.2                  # ===>  this went ok.
    sudo systemctl restart apache2       # ===>  this went ok.
After that I could enter the web interface!

Here, a screenshot to show the initial web interface appearance, with the privacy statements.
Image

And the ZoneMinder interface:
Image

I can now start learning about ZoneMinder. :)
Post Reply