Matomo (fka PIWIK)

Matomo kommt von InnoCraft und hiess bis Januar 2018 PIWIK. Es konkurriert mit Google Analytics, ist aber Open Source und kann self-hosted betrieben werden.

Matomo sollte wegen Content Security Policy Headern am besten auf einem eigenen Host (z.B. analytics.example.com) und nicht unter der URL der Webseite betrieben werden. Für Matomo müssen die CSP recht offen sein („data:“ erlaubt), was von Security-Scannern moniert wird, und im Falle eines Mischens/Betrieb unter der Webseite (mysite.ch/analytics) die Webseite in einem Security-Ranking runterstufen könnte.

Installation

Ein aktuelles PHP unter Apache httpd verwenden, als Datenbank ist MariaDB empfohlen.

PHP: memory_limit >= 192M setzen.

Darüber hinaus wird benötigt:

dnf -y install php php-pdo php-mysqlnd php-mbstring php-gd php-dom

Download:

rm -f /tmp/latest.zip*
rm -rf /tmp/matomo*
wget https://builds.matomo.org/latest.zip --output-document=/tmp/latest.zip
unzip -o /tmp/latest.zip -d /var/www/html/
rm -rf /var/www/html/matomo/tmp/*

chown -R apache:apache /var/www/html/matomo
find /var/www/html/matomo/tmp -type f -exec chmod 644 {} \;
find /var/www/html/matomo/tmp -type d -exec chmod 755 {} \;
find /var/www/html/matomo/tmp/assets -type f -exec chmod 644 {} \;
find /var/www/html/matomo/tmp/assets -type d -exec chmod 755 {} \;
find /var/www/html/matomo/tmp/cache -type f -exec chmod 644 {} \;
find /var/www/html/matomo/tmp/cache -type d -exec chmod 755 {} \;
find /var/www/html/matomo/tmp/tcpdf -type f -exec chmod 644 {} \;
find /var/www/html/matomo/tmp/tcpdf -type d -exec chmod 755 {} \;
find /var/www/html/matomo/tmp/templates_c -type f -exec chmod 644 {} \;
find /var/www/html/matomo/tmp/templates_c -type d -exec chmod 755 {} \;

SELinux:

semanage fcontext --add --type httpd_sys_rw_content_t "/var/www/html/matomo/config(/.*)?"
semanage fcontext --add --type httpd_sys_rw_content_t "/var/www/html/matomo/matomo.js"
semanage fcontext --add --type httpd_sys_rw_content_t "/var/www/html/matomo/piwik.js"
semanage fcontext --add --type httpd_sys_rw_content_t "/var/www/html/matomo/tmp(/.*)?"

restorecon -Fvr /var/www/html/matomo

Wenn Matomo hinter einem Reverse Proxy läuft:

/var/www/html/matomo/config/config.ini.php
[General]
; for Reverse Proxying https://matomo.org/faq/how-to-install/faq_98/
assume_secure_protocol = 1
proxy_client_headers[] = HTTP_X_FORWARDED_FOR
proxy_host_headers[] = HTTP_X_FORWARDED_HOST

Cronjob für automatische Datenarchivierung und -optimierung einrichten. Sind diese nicht aktiv, macht sich das nach einiger Zeit im Betrieb in kaputten Widgets in der Weboberfläche aufgrund von Timeouts wegen zu grosser Datenmengen bemerkbar.

# Matomo Auto Archiving
5 * * * * /usr/bin/php /var/www/html/matomo/console core:archive --url=https://analytics.example.com/ > /var/log/matomo-archive.log 2>&1

Der gleiche Cronjob als Systemd-Timer:

/etc/systemd/system/matomo-archive.service
[Unit]
Description=Matomo Archive Service

[Service]
ExecStart=/usr/bin/php /var/www/html/matomo/console --matomo-domain=analytics.example.com core:archive
Type=oneshot
User=root

[Install]
WantedBy=basic.target
/etc/systemd/system/matomo-archive.timer
[Unit]
Description=Matomo Archive Timer

[Timer]
OnCalendar=05:07:00
Unit=matomo-archive.service

[Install]
WantedBy=timers.target

Jetzt die Instanz per http://matomo/index.php aufrufen und im Setup-Wizard den ersten Benutzer anlegen.

Update/Upgrade

Eine bestehende Matomo-Installation wird wie folgt per Kommandozeile aktualisiert:

Dateibasis aktualisieren:

INSTALL_DIR=/var/www/html/matomo
MATOMO_URL=analytics.example.com

rm -f /tmp/latest.zip*
rm -rf /tmp/matomo*

wget https://builds.matomo.org/latest.zip --output-document=/tmp/latest.zip
unzip -o /tmp/latest.zip -d /tmp

mkdir -p $INSTALL_DIR
\cp -r /tmp/matomo/* $INSTALL_DIR/

rm -rf /tmp/matomo

chmod +w $INSTALL_DIR/matomo.js
chmod +w $INSTALL_DIR/config/config.ini.php
chown -R apache:apache $INSTALL_DIR
restorecon -Fvr $INSTALL_DIR

systemctl restart php-fpm.service

Das eigentliche Upgrade:

php $INSTALL_DIR/console --matomo-domain=$MATOMO_URL core:update
php $INSTALL_DIR/console --matomo-domain=$MATOMO_URL core:clear-caches
php $INSTALL_DIR/console --matomo-domain=$MATOMO_URL core:run-scheduled-tasks

php $INSTALL_DIR/console diagnostics:run

Plugins aktualisieren:

  1. Plugin-Liste ausgeben. Uns interessieren nur die «optional» Plugins.

Aktuelle Plugins anzeigen lassen
sudo -u apache php /var/www/html/matomo/console plugin:list
+-----------------------+-------------------+---------------+
| Plugin                | Core or optional? | Status        |
+-----------------------+-------------------+---------------+
| CustomVariables       | Optional          | Activated     |
| FormAnalytics         | Optional          | Not activated |
| MediaAnalytics        | Optional          | Not activated |
| Provider              | Optional          | Activated     |
| ChatGPT               | Optional          | Activated     |
| DataExport            | Optional          | Not activated |
| LoginOIDC             | Optional          | Not activated |
| ForceOIDCLogin        | Optional          | Not activated |
| RebelOIDC             | Optional          | Activated     |
+-----------------------+-------------------+---------------+
  1. Kompatibilität prüfen (Requirements):

  1. Wenn die Requirements passen, können die Plugins aktualisiert werden:

Plugins aktualisieren per CLI
sudo -u apache php /var/www/html/matomo/console plugin:install-or-update CustomVariables FormAnalytics MediaAnalytics Provider ChatGPT DataExport LoginOIDC ForceOIDCLogin RebelOIDC

Matomo Console Cheat Sheet

cd /var/www/html/matomo

./console list

./console core:clear-caches

./console core:archive
./console core:archive --url=https://analytics.example.com > /var/log/matomo-archive.log 2>&1
./console core:convert-to-utf8mb4 --show
./console core:run-scheduled-tasks
./console core:update

# You'll find the names of all sections in /var/www/html/matomo/config/global.ini.php

./console config:get --section=APISettings
./console config:get --section=ArrayCache
./console config:get --section=Cache
./console config:get --section=ChainedCache
./console config:get --section=CoreUpdater
./console config:get --section=Debug
./console config:get --section=Deletelogs
./console config:get --section=Deletereports
./console config:get --section=Development
./console config:get --section=FileCache
./console config:get --section=General
./console config:get --section=GeoIp2
./console config:get --section=Languages
./console config:get --section=Live
./console config:get --section=log
./console config:get --section=Login
./console config:get --section=LoginOIDC
./console config:get --section=mail
./console config:get --section=Plugins
./console config:get --section=PluginsInstalled
./console config:get --section=PrivacyManager
./console config:get --section=proxy
./console config:get --section=RedisCache
./console config:get --section=Segments
./console config:get --section=Tracker
./console config:get --section=TwoFactorAuth

./console config:set --section database --key=host --value=127.0.0.1

./console database:optimize-archive-tables 2016-0{1..9} 2016-1{0..2} 2017-0{1..9} 2017-1{0..2}

./console diagnostics:run

Matomo ohne Tracking-Code (matomo.js)

Adblocker verhindern die Ausführung der matomo.js. Wer trotzdem grundlegende Statistiken haben möchte, kann den Webserver anweisen, bei Bedarf sogar in Echtzeit direkt nach Matomo zu loggen.

Zunächst das Python-Script https://github.com/matomo-org/matomo-log-analytics/blob/5.x-dev/import_logs.py z.B. in /usr/local/sbin/import_logs.py auf dem Webserver ablegen, welcher die Seite über die Domain-Namen verarbeitet (also beispielsweise auf dem Reverse Proxy). Eventuell den Shebang auf #!/usr/bin/python3 ändern, damit das Skript auch wirklich ausgeführt werden kann.

In Matomo muss im „Administration“-Bereich (oben rechts über das Gear-Icon erreichbar) unter Personal > Security ein neues „Auth Token“ angelegt werden. Die „Description“ könnte „srv-proxy site.example.com import_logs.py“ lauten, wenn es ein Token für „site.example.com“ auf dem Reverse Proxy „srv-proxy“ sein soll.

Dann:

chmod +x /usr/local/sbin/import_logs.py

Bemerkung

  • Mit --url ist die URL des Matomo-Servers gemeint, nicht die der auszuwertenden Seite.

  • --token-auth muss von einem User mit Admin- oder Superuser-Rechten kommen.

  • Es funktionieren (Stand 2024-01) nur Auth-Token, bei denen „Only allow secure requests“ („Secure use only“) NICHT aktiv ist.

  • Das Import-Tool prüft rein gar nichts vor dem Import. Mehrfache Aufrufe auf die gleichen Log-Daten führen in Matomo also auch zu mehrfach gezählten Daten.

Real-time-Auswertung der Logfiles
chown apache:apache /usr/local/sbin/import_logs.py

Für eine die Apache vHost-Definition anpassen:

vhost.conf
# Matomo Realtime Logging
LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" matomo
CustomLog "||/usr/local/sbin/import_logs.py \
    --debug \
    --enable-bots \
    --enable-http-errors \
    --idsite=1234 \
    --output=/var/log/matomo.log \
    --recorders=4 \
    --token-auth=2ac48e93-2ca7-4df3-9e7c-c81b36d0a474 \
    --url=https://analytics.example.com \
    -" matomo

Auswertung aktivieren:

httpd -t
setsebool -P httpd_can_network_connect on
systemctl reload httpd

SELinux:

semanage fcontext --add --type httpd_log_t "/var/log/matomo.log"
restorecon -Fv /var/log/matomo.log
Periodische Auswertung der Logfiles

Per Cronjob oder systemd-timer folgenden Aufruf konfigurieren:

/usr/local/sbin/import_logs.py \
    --debug \
    --enable-bots \
    --enable-http-errors \
    --idsite=1234 \
    --output=/var/log/matomo.log \
    --recorders=4 \
    --token-auth=2ac48e93-2ca7-4df3-9e7c-c81b36d0a474 \
    --url=https://analytics.example.com \
    /path/to/analytics.example.com-access.log

Um bereits rotierte Logfiles von gestern zu importieren, folgendes Konstrukt verwenden:

/usr/local/sbin/import_logs.py \
    ... \
    $(date --date=yesterday +/path/to/analytics.example.com-access.log-\%Y\%m\%d)

Logging:

tail -f /var/log/audit/audit.log /var/log/httpd/analytics.example.com-error.log /var/log/matomo.log

Alle Parameter liefert import_logs.py --help, dokumentiert in der Projekt-README.

Daten aufräumen

Rohdaten für einen bestimmten Tag löschen:

  • Zunächst Rohdaten per Matomo > Administration > Privacy > GDPR Tools löschen, beispielsweise auf Basis „Time in UTC“ „Starts with“ „2020-12-09“. Muss evtl. mehrfach wiederholt werden, da die Seite die Ergebnisliste begrenzt.

  • Dann historische Daten entfernen: ./console core:invalidate-report-data --periods=all --cascade --dates=2020-12-09,2020-12-10 --sites=2

GeoIP

Im Web-GUI unter System > Geolocation nachsehen, wie eine GeoIP-Datenbank (Maxmind empfohlen) aufzusetzen ist.

Troubleshooting

Probleme?
php /var/www/html/matomo/console diagnostics:run
Probleme nach dem Update? z.B. PHP Fatal error:  Cannot override final method Piwik\Plugin\ConsoleCommand::execute() in /var/www/html/matomo/plugins/CoreConsole/Commands/GenerateAngularComponent.php on line 27 beim Aufruf von console

Der oben beschriebene (und von Matomo empfohlene) Update-Vorgang aktualisiert nur bestehende und neue Files auf dem Server, löscht aber niemals alte Files. Das kann zu Problemen führen, wenn es Files in einer neueren Version von Matomo nicht mehr geben sollte. Um dies zu beheben müssen die überflüssigen Files entfernen werden, am besten indem die Files auf dem Server mit den Files in der ZIP-Datei vergleicht werden. Bei der obigen Fehlermeldung hilft folgendes (siehe https://github.com/matomo-org/matomo/issues/21718):

\rm -f /var/www/html/matomo/plugins/CoreConsole/Commands/GenerateAngularComponent.php
\rm -f /var/www/html/matomo/plugins/CoreConsole/Commands/GenerateAngularConstructBase.php
\rm -f /var/www/html/matomo/plugins/CoreConsole/Commands/GenerateAngularDirective.php

php /var/www/html/matomo/console diagnostics:run
Unable to write in the cache directory (var/www/html/matomo/tmp/templates_c/8a).
php /var/www/html/matomo/console core:clear-caches
Unable to execute check for https://analytics.example.com/tmp/: curl_exec: Connection timed out after 2000 milliseconds. Hostname requested was: analytics.example.com

Matomo rennt bei lokalem Aufruf von curl https://analytics.example.com in einen Timeout. Könnte an fehlenden /etc/hosts-Einträgen auf dem Matomo-Host liegen.