matomo-org / matomo

Empowering People Ethically with the leading open source alternative to Google Analytics that gives you full control over your data. Matomo lets you easily collect data from websites & apps and visualise this data and extract insights. Privacy is built-in. Liberating Web Analytics. Star us on Github? +1. And we love Pull Requests!
https://matomo.org/
GNU General Public License v3.0
19.64k stars 2.62k forks source link

[Bug] opcache.save_comments=0 breaks Matomo #21794

Open mikkeschiren opened 8 months ago

mikkeschiren commented 8 months ago

What happened?

After updating (or installing Matomo 5 fresh), I can not longer delete users, or see Install TagManager code in the TagManager interface.

We think I could be caused by rules in our nginx.conf, that are more restricted then the recommended nginx.conf.

What should happen?

Deleting users should work from UI.

How can this be reproduced?

This is isolated to our environment, I will provide nginx.conf.

Matomo version

5.0.1

PHP version

8.1.27

Server operating system

Linyx/Alpine

What browsers are you seeing the problem on?

Firefox, Chrome

Computer operating system

Mac

Relevant log output

Uncaught exception in API: /var/www/html/core/API/Proxy.php(486): Please specify a value for 'userLogin'. [Query: ?date=2024-01-11&idSite=1&period=day, CLI mode: 0]

Validations

mikkeschiren commented 8 months ago

Nginx conf:

worker_processes 5;
load_module modules/ngx_http_geoip2_module.so;
# load_module modules/ngx_http_naxsi_module.so;
events {
    worker_connections 768;
}
pid        /tmp/nginx.pid;
http {
    upstream backend {
        server matomo:9000;
    }
    include /etc/nginx/mime.types;
    geoip2 /usr/share/geoip/GeoLite2-Country.mmdb {
      $geoip2_data_country_code default=SE source=$http_x_forwarded_for country iso_code;
    }
    client_max_body_size  200M;
    server_tokens         off;
    client_body_timeout   600s;
    client_header_timeout 600s;
    client_body_temp_path /tmp/client_temp;
    proxy_temp_path       /tmp/proxy_temp_path;
    fastcgi_temp_path     /tmp/fastcgi_temp;
    uwsgi_temp_path       /tmp/uwsgi_temp;
    scgi_temp_path        /tmp/scgi_temp;
    include               /etc/nginx/mime.types;
    default_type          application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    log_format  main_geo  '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for" '
                        '$geoip2_data_country_code';
    access_log            /var/log/nginx/access.log  main_geo;
    sendfile              on;
    keepalive_timeout     0;

    server {
      listen 80;
      server_name matomo.loc;
    root /var/www/html;
    index index.php;
    error_page 404 /404.html;
        location = 404.html {
            root /usr/share/nginx/html;
        }
    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root /usr/share/nginx/html;
        }
    proxy_read_timeout 600s;
    proxy_send_timeout 600s;
    proxy_connect_timeout 600s;
    ## Redirects all requests to index.php and Matomo.
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ js/container_.*_preview\.js$ {
        expires off;
        add_header Cache-Control 'private, no-cache, no-store';
    }

    location ~* /(js)/.*.(js|php)$ {
        expires 30s;
        add_header Cache-Control "public, no-transform";
        allow all;
    }

    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    ## Allow access to index.php to make dashboard work.
    location ~ ^/(index).php  {
        # include /etc/nginx/naxsi.rules;
        # # whitelisting and config of naxsi rules.
        # # whitelist whole rule 11. Need to b debugged why needed.
        # BasicRule wl:11;
        try_files $uri =404;
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        if (!-f $document_root$fastcgi_script_name) {
        return 404;
        }

        proxy_read_timeout 600s;
        proxy_send_timeout 600s;
        proxy_connect_timeout 600s;
        fastcgi_read_timeout 600s;
        fastcgi_send_timeout 600s;
        proxy_set_header Connection "";
        proxy_http_version 1.1;
        proxy_set_header   Host      $http_host;
        proxy_set_header   X-Real-IP         $remote_addr;
        proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_set_header   X-Forwarded-Host  $host;
        proxy_set_header   X-Forwarded-Port  $server_port;

        fastcgi_param HTTP_PROXY "";
        fastcgi_pass backend;
        fastcgi_index index.php;
        fastcgi_param PHP_VALUE "max_execution_time=3600
        post_max_size=1500M
        upload_max_filesize=32M
        max_input_time=3600
        max_file_uploads=300";
        include fastcgi_params;
    }

    ## Allow access to heatmapsessionsrecording plugin is needed to make it work.
    location = /plugins/HeatmapSessionRecording/configs.php {
        # include /etc/nginx/naxsi.rules;
        # # whitelisting and config of naxsi rules.
        # # whitelist whole rule 11. Need to b debugged why needed.
        # BasicRule wl:11;
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        if (!-f $document_root$fastcgi_script_name) {
        return 404;
        }
        fastcgi_read_timeout 120s;
        fastcgi_send_timeout 120s;
        fastcgi_param HTTP_PROXY "";
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi_params;
    }

    ## Allow access to static media files.
    location ~ \.(gif|ico|jpg|png|svg|js|css|htm|html|mp3|mp4|wav|ogg|avi|ttf|eot|woff|woff2|json)$ {
        allow all;
        ## Cache images,CSS,JS and webfonts for an hour
        ## Increasing the duration may improve the load-time, but may cause old files to show after an Matomo upgrade
        expires 1h;
        add_header Pragma public;
        add_header Cache-Control "public";
    }
    # location ~ ^/(status)$ {
    #   access_log off;

    #   # allow 127.0.0.1;
    #   # allow 1.2.3.4;
    #   # deny all;

    #   fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    #   fastcgi_index index.php;
    #   include fastcgi_params;
    #   ## Now the port or socket of the php-fpm pool we want the status of
    #   fastcgi_pass 127.0.0.1:9000;
    #   # fastcgi_pass unix:/run/php-fpm/your_socket.sock;
    # }
    ## Deny access to all other .php files.
        location ~* ^.+\.php$ {
            deny all;
            return 403;
        }

        ## Deny access to key matomo folders and files that dashboard should not serve.
        location ~ /(config|tmp|core|lang|libs|vendor|plugins|misc/user|piwik.js|piwik.php|matomo.js|matomo.php) {
            deny all;
            return 403;
        }

        ## Deny access to all files starting with ".ht"
        location ~ /\.ht {
            deny  all;
            return 403;
        }

        ## Deny access to compose.json and package.json
        location ~ ^/[^.]*\.json$ {
            deny  all;
            return 403;
        }
        ## Deny access to compose.lock and other lock files in root
        location ~ ^/[^.]*\.lock$ {
            deny  all;
            return 403;
        }
    }
}
mikkeschiren commented 8 months ago

Additional info: The interface runs on seperate URL than the tracking, that is why we are blocking access to tracking scripts from it.

sgiehl commented 8 months ago

@mikkeschiren Can you see any failing request in the browser console?

mikkeschiren commented 8 months ago

No, errors shown:

bild
mikkeschiren commented 8 months ago

Though, when I try to get the Install code for TagManager, I get:

bild
mikkeschiren commented 8 months ago

Additional, this is the fastcgi_params for the nginx.conf

    fastcgi_param   COUNTRY_CODE            $geoip2_data_country_code;
    fastcgi_param   QUERY_STRING            $query_string;
    fastcgi_param   REQUEST_METHOD          $request_method;
    fastcgi_param   CONTENT_TYPE            $content_type;
    fastcgi_param   CONTENT_LENGTH          $content_length;

    fastcgi_param   SCRIPT_FILENAME         $document_root$fastcgi_script_name;
    fastcgi_param   SCRIPT_NAME             $fastcgi_script_name;
    fastcgi_param   PATH_INFO               $fastcgi_path_info;
    fastcgi_param   PATH_TRANSLATED         $document_root$fastcgi_path_info;
    fastcgi_param   REQUEST_URI             $request_uri;
    fastcgi_param   DOCUMENT_URI            $document_uri;
    fastcgi_param   DOCUMENT_ROOT           $document_root;
    fastcgi_param   SERVER_PROTOCOL         $server_protocol;

    fastcgi_param   GATEWAY_INTERFACE       CGI/1.1;
    fastcgi_param   SERVER_SOFTWARE         nginx/$nginx_version;

    fastcgi_param   REMOTE_ADDR             $remote_addr;
    fastcgi_param   REMOTE_PORT             $remote_port;
    fastcgi_param   SERVER_ADDR             $server_addr;
    fastcgi_param   SERVER_PORT             $server_port;
    fastcgi_param   SERVER_NAME             $server_name;

    fastcgi_param   HTTPS                   $https;

    # PHP only, required if PHP was built with --enable-force-cgi-redirect
    fastcgi_param   REDIRECT_STATUS         200;
mikkeschiren commented 8 months ago

Ok - further debugging - it seems that I even get the issue with the recommended nginx conf. I check if the hosting environment has something to do with it.

sgiehl commented 8 months ago

I checked removing a user locally and that works without problems. Do you maybe have a WAF set up or similar, that blocks certain data?

mikkeschiren commented 8 months ago

I have a couple of protection things outside Matomo in the hosting - but would be easier to debug if you know anything related to ajax requests has changed in Matomo 5 in general, as we didnt have the issue in Matomo 4.

sgiehl commented 8 months ago

No change that I'm aware of. Both versions should use jQuery for sending the ajax requests.

mikkeschiren commented 8 months ago

Ok, we can close this at this point, I will reopen if I find what causing it.

mikkeschiren commented 7 months ago

I found the cause, but it took some time for debugging. We had this in php ini:

opcache.save_comments=0

For some reason that setting broke many ajax calls in Matomo 5, or in the PHP version we upgraded to. Setting it to:

opcache.save_comments=1

fixes the issue.

PHP documentation states

If disabled, all documentation comments will be discarded from the opcode cache to reduce the size of the optimised code. Disabling this configuration directive may break applications and frameworks that rely on comment parsing for annotations, including Doctrine, Zend Framework 2 and PHPUnit.

mikkeschiren commented 7 months ago

Maybe something that should be added to the documentation @sgiehl ?

sgiehl commented 7 months ago

Thanks @mikkeschiren for getting back. Matomo 5 indeed parses the comments for e.g. API methods.

@Stan-vw We should short-term reserve some time, to check if we can reproduce the problems with using opcache.save_comments=0. If so we should consider adjusting the documentation and adding a new diagnostic check, as this could be something more people could have problems with.