modxcms / revolution

MODX Revolution - Content Management Framework
https://modx.com/
GNU General Public License v2.0
1.36k stars 529 forks source link

Blank page at sub.domain.com/manager/ #16229

Closed tvquizphd closed 2 years ago

tvquizphd commented 2 years ago

Bug report

Summary

After "Installation finished in 1.9130 s" following instructions, I see only a blank page at /manager/. I'm hosting the page with nginx.

Step to reproduce

wget https://modx.com/download/direct/modx-3.0.1-pl-sdk.zip
unzip modx-3.0.1-pl.zip
mv modx-3.0.1-pl sub.domain.com
cd sub.domain.com/setup/

Vim replacements after I copy config.dist.new.xml to config.xml:

:%s@/www/modx/@/var/www/sub.domain.com@gc
:%s/db_username/root/gc
:%s/db_password/pass/gc
:%s@/modx/@/@gc

I change <http_host>localhost</http_host> to <http_host>sub.domain.com</http_host>

I run:

php ./index.php --installmode=new --core_path=/var/www/sub.domain.com/core/

My /etc/php/8.0/fpm/php.ini has this:

pdo_mysql.default_socket=/var/run/mysqld/mysqlx.sock
mysqli.default_socket = /var/run/mysqld/mysqlx.sock

I ensure the fastcgi_pass in my nginx config is

fastcgi_pass unix:/run/php/php-fpm.sock;

which matches my /etc/php/8.0/fpm/pool.d/www.conf:

listen = /run/php/php-fpm.sock

This code runs correctly:

<?php
/* Connect to an ODBC database using driver invocation */
$dsn = 'mysql:dbname=testdb;host=localhost';
$user = 'dbuser';
$password = 'dbpass';

try {
  $dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
  echo 'Connection failed: ' . $e->getMessage();
}
?>

Observed behavior

The manager page is blank. It is a 200 response with a completely blank file. Here are the response headers:

Cache-Control: no-store, no-cache, must-revalidate
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html; charset=UTF-8
Date: Fri, 22 Jul 2022 20:17:52 GMT
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Pragma: no-cache
Server: nginx/1.18.0 (Ubuntu)
Transfer-Encoding: chunked

In my nginx logs, i see the following:

2022/07/22 19:55:16 [error] 17007#17007: *7 FastCGI sent in stderr: "PHP message: PHP Warning:  Trying to access array offset on value of type bool in /var/www/sub.domain.com/core/vendor/xpdo/xpdo/src/xPDO/Om/xPDOObject.php on line 251PHP message: PHP Warning:  Trying to access array offset on value of type bool in /var/www/sub.domain.com/core/vendor/xpdo/xpdo/src/xPDO/Om/xPDOObject.php on line 251" while reading response header from upstream, client: 71.232.26.159, server: sub.domain.com, request: "GET /manager/ HTTP/1.1", upstream: "fastcgi://unix:/run/php/php-fpm.sock:", host: "sub.domain.com"

Expected behavior

The manager console should be shown... right?

Environment

My Versions

ModX 3.01 PHP 8.0.21 Nginx 1.18.0 Ubuntu 20.04.4 LTS mysql Ver 14.14 Distrib 5.7.37, for Linux Google Chrome browser, for MacOS

My Nginx config

server {

    server_name sub.domain.com;
    root /var/www/sub.domain.com;
    index index.php;
    client_max_body_size 30M;

    listen [::]:443 ssl; # managed by Certbot
    listen 443 ssl; # managed by Certbot

    location / {
        root /var/www/sub.domain.com;
        if (!-e $request_filename) {
                rewrite ^/(.*)$ /index.php?q=$1 last;
        }
    }

    location ~ \.php$ {

            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(.*)$;
            fastcgi_pass unix:/run/php/php-fpm.sock;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include fastcgi_params;
            fastcgi_ignore_client_abort on;
            fastcgi_param  SERVER_NAME $http_host;
    }

    location ~ /\.ht {
            deny  all;
    }

    ssl_certificate /etc/letsencrypt/live/sub.domain.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/sub.domain.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

My core/config.inc.php:

<?php^M
/**^M
 *  MODX Configuration file^M
 */^M
$database_type = 'mysql';^M
$database_server = 'localhost';^M
$database_user = 'root';^M
$database_password = '************';^M
$database_connection_charset = 'utf8';^M
$dbase = 'modx_modx';^M
$table_prefix = 'modx_';^M
$database_dsn = 'mysql:host=localhost;dbname=modx_modx;charset=utf8';^M
$config_options = array (
  'override_table' => 'MyISAM',
);^M
$driver_options = array (
);^M
^M
$lastInstallTime = 1658519707;^M
^M
$site_id = 'modx62db009b3a1610.81763680';^M
$site_sessionname = 'SN62db009b3376f';^M
$https_port = '443';^M
$uuid = 'c56fa809-53c7-407a-90b7-16139bb1cbef';^M
^M
if (!defined('MODX_CORE_PATH')) {^M 
    $modx_core_path= '/var/www/domain.example.com/core/';^M
    define('MODX_CORE_PATH', $modx_core_path);^M
}^M
if (!defined('MODX_PROCESSORS_PATH')) {^M 
    $modx_processors_path= '/var/www/domain.example.com/core/src/Revolution/Processors/';^M
    define('MODX_PROCESSORS_PATH', $modx_processors_path);^M
}^M
if (!defined('MODX_CONNECTORS_PATH')) {^M 
    $modx_connectors_path= '/var/www/domain.example.com/connectors/';^M
    $modx_connectors_url= '/connectors/';^M
    define('MODX_CONNECTORS_PATH', $modx_connectors_path);^M
    define('MODX_CONNECTORS_URL', $modx_connectors_url);^M
}^M
if (!defined('MODX_MANAGER_PATH')) {^M 
    $modx_manager_path= '/var/www/domain.example.com/manager/';^M
    $modx_manager_url= '/manager/';^M
    define('MODX_MANAGER_PATH', $modx_manager_path);^M
    define('MODX_MANAGER_URL', $modx_manager_url);^M
}^M
if (!defined('MODX_BASE_PATH')) {^M 
    $modx_base_path= '/var/www/domain.example.com';^M
    $modx_base_url= '/';^M
    define('MODX_BASE_PATH', $modx_base_path);^M
    define('MODX_BASE_URL', $modx_base_url);^M
}^M
if(defined('PHP_SAPI') && (PHP_SAPI == "cli" || PHP_SAPI == "embed")) {^M 
    $isSecureRequest = false;^M
} else {^M 
    $isSecureRequest = ((isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') || $_SERVER['SERVER_PORT'] == $https_port);^M
}^M
if (!defined('MODX_URL_SCHEME')) {^M 
    $url_scheme=  $isSecureRequest ? 'https://' : 'http://';^M
    define('MODX_URL_SCHEME', $url_scheme);^M
}^M
if (!defined('MODX_HTTP_HOST')) {^M 
    if(defined('PHP_SAPI') && (PHP_SAPI == "cli" || PHP_SAPI == "embed")) {^M 
        $http_host='domain.example.com';^M
        define('MODX_HTTP_HOST', $http_host);^M
    } else {^M 
        $http_host= array_key_exists('HTTP_HOST', $_SERVER) ? htmlspecialchars($_SERVER['HTTP_HOST'], ENT_QUOTES) : 'domain.example.com';^M
        if ($_SERVER['SERVER_PORT'] != 80) {^M 
            $http_host = str_replace(':' . $_SERVER['SERVER_PORT'], '', $http_host); // remove port from HTTP_HOST^M
        }^M 
        $http_host .= in_array($_SERVER['SERVER_PORT'], [80, 443]) ? '' : ':' . $_SERVER['SERVER_PORT'];^M
        define('MODX_HTTP_HOST', $http_host);^M
    }^M 
}^M
if (!defined('MODX_SITE_URL')) {^M 
    $site_url= $url_scheme . $http_host . MODX_BASE_URL;^M
    define('MODX_SITE_URL', $site_url);^M
}^M
if (!defined('MODX_ASSETS_PATH')) {^M 
    $modx_assets_path= '/var/www/domain.example.com/assets/';^M
    $modx_assets_url= '/assets/';^M
    define('MODX_ASSETS_PATH', $modx_assets_path);^M
    define('MODX_ASSETS_URL', $modx_assets_url);^M
}^M
if (!defined('MODX_LOG_LEVEL_FATAL')) {^M 
    define('MODX_LOG_LEVEL_FATAL', 0);^M
    define('MODX_LOG_LEVEL_ERROR', 1);^M
    define('MODX_LOG_LEVEL_WARN', 2);^M
    define('MODX_LOG_LEVEL_INFO', 3);^M
    define('MODX_LOG_LEVEL_DEBUG', 4);^M
}^M
~         

Any guidance at all would be helpful!

tvquizphd commented 2 years ago

In my nginx logs, something looks a bit off with the number of colons/protocols in this "upstream" request:

upstream: "fastcgi://unix:/run/php/php-fpm.sock:"
Mark-H commented 2 years ago

Are all those ^M in the actual config file? That's kinda weird looking.

MODX doesn't control that nginx upstream configuration, I don't know enough about nginx to really give guidance on that.

Is there anything in the browser dev tools when you try to access the manager? And there's absolutely nothing in the response to the 200 response?

What about the MODX log, at core/cache/logs/error.log? Anything there?

There should also be a setup log in core/cache/logs/ (with the timestamp in the filename), worth reviewing that for any warnings or errors.

The PHP warnings in your log I believe are resolved in 3.0.2 with an xPDO update.

tvquizphd commented 2 years ago

Thank you so much for your reply!


^M is how vim displays 0xD, the carriage return character. It shows up when people or software use both types of return characters.

Nothing shows up in the browser dev tools expect for the 200 network request, which returns a fully empty file of 0 bytes. The total size is 344 bytes, which is just the headers.

Here is the MODX log:

[2022-07-22 19:55:09] (ERROR @ /var/www/domain.example.com/setup/includes/modinstallsettings.class.php : 164) PHP warning: fopen(/var/www/domain.example.com/core/cache/setup/settings.cache.php): Failed to open stream: No such file or directory

Oh, here's something obvious in the setup log...

[2022-07-22 19:55:07] (ERROR in xPDO\xPDOConnection::connect @ /var/www/domain.example.com/core/vendor/xpdo/xpdo/src/xPDO/xPDOConnection.php : 89) SQLSTATE[HY000] [1049] Unknown database 'modx_modx'
[2022-07-22 19:55:07] (ERROR in xPDO\xPDOConnection::connect @ /var/www/domain.example.com/core/vendor/xpdo/xpdo/src/xPDO/xPDOConnection.php : 89) SQLSTATE[HY000] [1049] Unknown database 'modx_modx'
[2022-07-22 19:55:07] (ERROR in xPDO\xPDO::getValue @ /var/www/domain.example.com/core/vendor/xpdo/xpdo/src/xPDO/xPDO.php : 1111) No valid PDOStatement provided to getValue
[2022-07-22 19:55:07] (ERROR in xPDO\xPDOConnection::connect @ /var/www/domain.example.com/core/vendor/xpdo/xpdo/src/xPDO/xPDOConnection.php : 89) SQLSTATE[HY000] [1049] Unknown database 'modx_modx'

When I login to mysql command line and type:

use modx_modx;
mysql> show tables;

I see that the DB does in fact appear to have 70 tables:

+------------------------------------+
| Tables_in_modx_modx                |
+------------------------------------+
| modx_access_actiondom              |
| modx_access_category               |
| modx_access_context                |
| modx_access_elements               |
| modx_access_media_source           |
| modx_access_menus                  |
| modx_access_namespace              |
| modx_access_permissions            |
| modx_access_policies               |
| modx_access_policy_template_groups |
| modx_access_policy_templates       |
| modx_access_resource_groups        |
| modx_access_resources              |
| modx_access_templatevars           |
| modx_actiondom                     |
| modx_actions_fields                |
| modx_active_users                  |
| modx_categories                    |
| modx_categories_closure            |
| modx_content_type                  |
| modx_context                       |
| modx_context_resource              |
| modx_context_setting               |
| modx_dashboard                     |
| modx_dashboard_widget              |
| modx_dashboard_widget_placement    |
| modx_deprecated_call               |
| modx_deprecated_method             |
| modx_document_groups               |
| modx_documentgroup_names           |
| modx_element_property_sets         |
| modx_extension_packages            |
| modx_fc_profiles                   |
| modx_fc_profiles_usergroups        |
| modx_fc_sets                       |
| modx_lexicon_entries               |
| modx_manager_log                   |
| modx_media_sources                 |
| modx_media_sources_contexts        |
| modx_media_sources_elements        |
| modx_member_groups                 |
| modx_membergroup_names             |
| modx_menus                         |
| modx_namespaces                    |
| modx_property_set                  |
| modx_register_messages             |
| modx_register_queues               |
| modx_register_topics               |
| modx_session                       |
| modx_site_content                  |
| modx_site_htmlsnippets             |
| modx_site_plugin_events            |
| modx_site_plugins                  |
| modx_site_snippets                 |
| modx_site_templates                |
| modx_site_tmplvar_access           |
| modx_site_tmplvar_contentvalues    |
| modx_site_tmplvar_templates        |
| modx_site_tmplvars                 |
| modx_system_eventnames             |
| modx_system_settings               |
| modx_transport_packages            |
| modx_transport_providers           |
| modx_user_attributes               |
| modx_user_group_roles              |
| modx_user_group_settings           |
| modx_user_messages                 |
| modx_user_settings                 |
| modx_users                         |
| modx_workspaces                    |
+------------------------------------+
70 rows in set (0.00 sec)
Mark-H commented 2 years ago

In your earlier post it looks like you're using root, and setup apparently managed to create tables... but I'd almost think the user may not have access to the specific database?

Perhaps with the installation you relied on the CLI user having access, while the front-end PHP accesses MySQL differently and hasn't been authorized on whatever that internal IP/definition may be?

tvquizphd commented 2 years ago

I'm doing everything as root, and I've specified that MODX should use the root user and password. See the core/config.inc.php:

$database_user = 'root';^M
$database_password = '************';^M

Reading your second sentence, that does seem likely. I can try setting up a non-root db user. I'm off for the weekend on this, but I'll report back next week. It seems like you may have the answer though.

tvquizphd commented 2 years ago

I’ve created a new MySQL user with ALL PRIVILEGES, and I updated my core/config/config.inc.php with the new username and password. I’lll keep trying things. Maybe the setup needs to be run with the new user credenrials?

tvquizphd commented 2 years ago

The issue seems to be with fastcgi and PHP

I will update if I find a solution— then I’d make a PR against the modx nginx docs if I find the right changes to my nginx config.

tvquizphd commented 2 years ago

I followed nginx fastcgi instructions to some success.

My nginx config location looks like this now:

    location ~ [^/]\.php(/|$) {
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        if (!-f $document_root$fastcgi_script_name) {
            return 404;
        }

        # Mitigate https://httpoxy.org/ vulnerabilities
        fastcgi_param HTTP_PROXY "";

        fastcgi_pass unix:/run/php/php-fpm.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
    }

I replaced manager/index.php with this:

<?php var_export($_SERVER)?>

and I see what seems like a valid result on visiting domain.example.com/manager, so it seems fastcgi and nginx are working as advertised:

array ( 'USER' => 'www-data', 'HOME' => '/var/www', 'HTTP_CONNECTION' => 'keep-alive', 'HTTP_ACCEPT_ENCODING' => 'gzip, deflate, br', 'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.9', 'HTTP_USER_AGENT' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Mobile/15E148 Safari/604.1', 'HTTP_COOKIE' => 'PHPSESSID=******', 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'HTTP_HOST' => 'domain.example.com', 'REDIRECT_STATUS' => '200', 'SERVER_NAME' => 'domain.example.com', 'SERVER_PORT' => '443', 'SERVER_ADDR' => '****', 'REMOTE_USER' => '', 'REMOTE_PORT' => '57927', 'REMOTE_ADDR' => '*****', 'SERVER_SOFTWARE' => 'nginx/1.18.0', 'GATEWAY_INTERFACE' => 'CGI/1.1', 'HTTPS' => 'on', 'REQUEST_SCHEME' => 'https', 'SERVER_PROTOCOL' => 'HTTP/1.1', 'DOCUMENT_ROOT' => '/var/www/domain.example.com', 'DOCUMENT_URI' => '/manager/index.php', 'REQUEST_URI' => '/manager/', 'SCRIPT_NAME' => '/manager/index.php', 'CONTENT_LENGTH' => '', 'CONTENT_TYPE' => '', 'REQUEST_METHOD' => 'GET', 'QUERY_STRING' => '', 'SCRIPT_FILENAME' => '/var/www/domain.example.com/manager/index.php', 'FCGI_ROLE' => 'RESPONDER', 'PHP_SELF' => '/manager/index.php', 'REQUEST_TIME_FLOAT' => 1658544812.546169, 'REQUEST_TIME' => [1658544812](tel:1658544812), )

Edit— will update if I make any progress with actual ModX index.php files

tvquizphd commented 2 years ago

I’ve dumped

ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);

into index.php, and now I see this when I access domain.example.com/manager

Warning: Trying to access array offset on value of type bool in /var/www/domain.example.com/core/vendor/xpdo/xpdo/src/xPDO/Om/xPDOObject.php on line 251

Warning: Trying to access array offset on value of type bool in /var/www/domain.example.com/core/vendor/xpdo/xpdo/src/xPDO/Om/xPDOObject.php on line 251
tvquizphd commented 2 years ago

Should I open an issue at https://github.com/modxcms/xpdo ?

Here is the line of the error

It’s trying to index errorInfo, which is a Boolean.

possibly related: https://github.com/modxcms/xpdo/issues/137

Mark-H commented 2 years ago

Sure, a summarized report would be good there.

But even with that tracked down, that doesn't explain your empty manager. Does it work better if you disable the error_reporting and display_errors?

tvquizphd commented 2 years ago

If I disable error_reporting and display_errors, then the manager is still empty as before, even after running the setup again with the new mysql user.

oh, I just realized I assume I can do this:

rm -rf /var/www/domain.example.com
unzip modx-3.0.1-pl-sdk.zip
mv modx-3.0.1-pl-sdk /var/www/domain.example.com
cd /var/www/domain.example.com/setup
cp ~/config.xml.backup config.xml

then I drop the MySQL database, create a new empty database called modx_modx, then run the setup command again.

is attempting to re-install modx this way possibly causing me problems, assuming I made no mistakes along the way?

tvquizphd commented 2 years ago

next I will try running this helper script to install modx instead of the default cli instructions.

https://github.com/craftsmancoding/modx_utils/blob/master/installmodx.php

edit: Here are the install logs:

[2022-07-24 11:39:40] (ERROR in xPDO\xPDOConnection::connect @ /var/www/domain.example.com/core/vendor/xpdo/xpdo/src/xPDO/xPDOConnection.php : 89) SQLSTATE[HY000] [2002] No such file or directory
[2022-07-24 11:39:40] (ERROR in xPDO\xPDOConnection::connect @ /var/www/domain.example.com/core/vendor/xpdo/xpdo/src/xPDO/xPDOConnection.php : 89) SQLSTATE[HY000] [2002] No such file or directory
[2022-07-24 11:39:40] (ERROR in xPDO\xPDO::getValue @ /var/www/domain.example.com/core/vendor/xpdo/xpdo/src/xPDO/xPDO.php : 1111) No valid PDOStatement provided to getValue
[2022-07-24 11:39:40] (ERROR in xPDO\xPDOConnection::connect @ /var/www/domain.example.com/core/vendor/xpdo/xpdo/src/xPDO/xPDOConnection.php : 89) SQLSTATE[HY000] [2002] No such file or directory
[2022-07-24 11:39:40] (ERROR @ /var/www/domain.example.com/setup/includes/request/modinstallclirequest.class.php : 298) Could not connect to database server: SQLSTATE[HY000] [2002] No such file or directory
tvquizphd commented 2 years ago

Oh my, I've solved this issue!

I searched for the Connection failed: SQLSTATE[HY000] [2002] No such file or directory error message, and the owner of "Infinity Free" replied that I should replace "localhost" with 127.0.0.1--- they were so certain that they said:

This is 100% guaranteed the one and only case that can cause this error.

I'll make a pull request against this repository, suggesting this replacement:

<database_server>localhost</database_server>

to

<database_server>127.0.0.1</database_server>

This should affect config.dist.new.xml and config.dist.upgrade-advanced.xml.