Zum Inhalt springen
Serverküche
Suche

Die Suche wird geladen … (nur in der veröffentlichten Seite verfügbar).

Anwendungen Schwierigkeit: Fortgeschritten

Matomo cookielos selbst hosten: Analytics ohne Consent-Banner

Matomo 5.12 mit Docker & Traefik aufsetzen: datenschutzfreundliche Web-Analytics mit IP-Anonymisierung, ganz ohne Google und ohne Cookie-Banner.

· 12 Min. Lesezeit ·Dauer: ca. 45 Minuten
Inhaltsverzeichnis

Google Analytics kennt jeden deiner Besucher besser als du selbst – und schickt die Daten in die USA. Mit Matomo holst du dir die Web-Analytics zurück auf den eigenen Server: DSGVO-konform, IP-anonymisiert und in vielen Fällen ganz ohne Cookie-Banner.

Was bauen wir?

Am Ende läuft Matomo 5.12 in Docker hinter deinem Traefik-Reverse-Proxy, erreichbar unter deiner eigenen (Sub-)Domain mit gültigem HTTPS-Zertifikat. Als Datenbank kommt MariaDB 11.4 dazu – beides in einem compose.yaml. Du bekommst ein vollwertiges Analytics-Dashboard, das Besucherzahlen, Herkunft, Geräte und beliebte Seiten auswertet – die Daten liegen ausschließlich auf deinem Server.

Der eigentliche Gewinn gegenüber Google Analytics ist der Datenschutz: Wir kontrollieren die IP-Anonymisierung und konfigurieren Matomo so, dass es ohne Cookies auskommt. Das ist die technische Grundlage dafür, dass du in vielen Fällen auf einen nervigen Consent-Banner verzichten kannst. Matomo ist dabei das Vollpaket – wenn du nur wissen willst, welche Seiten wie oft aufgerufen werden, reicht auch das deutlich schlankere HitKeep.

Hinweis

Dieses Tutorial ersetzt keine Rechtsberatung. Ob du konkret einen Cookie-Banner brauchst, hängt von deinem Einsatz ab. Die hier gezeigte Konfiguration (keine Cookies, IP-Anonymisierung, Opt-out-Möglichkeit) ist aber genau die, die Matomo und viele Datenschutzbehörden als Basis für einen einwilligungsfreien Betrieb nennen.

Voraussetzungen

Matomo ist genügsam: Für eine kleine bis mittlere Website reicht der VPS 1000 locker. Erst bei sehr viel Traffic oder wenn viele andere Dienste mitlaufen, lohnt der Blick auf mehr RAM – unser Server-Rechner hilft dir bei der Einschätzung.

🍳 Empfehlung Anzeige

VPS 1000 G12

4 vCore · 8 GB RAM · 256 GB NVMe

ab 10,36 €/Monat

Reicht für Matomo neben ein paar weiteren kleinen Diensten.

Zu netcup →

💶 5 € Gutschein für netcup-Neukunden:36nc17844976032 (nur Neukunden, keine Domains)

Schritt für Schritt

Schritt 1: Projektordner anlegen und Netzwerk prüfen

Wir legen für Matomo einen eigenen Ordner unter /opt an – so bleibt jeder Dienst sauber getrennt:

Terminal
mkdir -p /opt/matomo && cd /opt/matomo

Matomo muss ins selbe Docker-Netzwerk wie Traefik, damit der Proxy den Container erreicht. Prüfe, dass das Netzwerk proxy aus dem Traefik-Tutorial existiert:

Terminal
docker network ls | grep proxy

Du solltest eine Zeile mit proxy sehen. Falls nicht, richte zuerst Traefik ein – ohne den Proxy bekommt Matomo kein Zertifikat.

Schritt 2: Passwörter in eine .env auslagern

Die Datenbank-Passwörter gehören nicht ins compose.yaml, sondern in eine separate .env. Wir lassen sie von openssl zufällig erzeugen:

Terminal
{
  echo "DB_PASSWORD=$(openssl rand -hex 16)"
  echo "DB_ROOT_PASSWORD=$(openssl rand -hex 16)"
} > .env
chmod 600 .env

chmod 600 sorgt dafür, dass nur root die Datei lesen kann. Wirf einmal einen Blick hinein, damit du die Werte kennst:

Terminal
cat .env
Ausgabe
DB_PASSWORD=b51024e3f9a7c8d1e2f3a4b5c6d7e8f9
DB_ROOT_PASSWORD=1a2b3c4d5e6f70819a0b1c2d3e4f5061

Schritt 3: Die compose.yaml schreiben

Lege die Datei /opt/matomo/compose.yaml mit folgendem Inhalt an. Ersetze im Traefik-Label statistik.DEINE-DOMAIN.de durch deine echte (Sub-)Domain:

YAML
services:
  db:
    image: mariadb:11.4
    container_name: matomo-db
    command: --max-allowed-packet=64MB
    environment:
      MARIADB_DATABASE: matomo
      MARIADB_USER: matomo
      MARIADB_PASSWORD: ${DB_PASSWORD}
      MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
    volumes:
      - db:/var/lib/mysql
    networks: [intern]
    restart: unless-stopped

  app:
    image: matomo:5.12-apache
    container_name: matomo
    environment:
      MATOMO_DATABASE_HOST: db
      MATOMO_DATABASE_ADAPTER: mysql
      MATOMO_DATABASE_USERNAME: matomo
      MATOMO_DATABASE_PASSWORD: ${DB_PASSWORD}
      MATOMO_DATABASE_DBNAME: matomo
    volumes:
      - app:/var/www/html
    depends_on: [db]
    networks: [proxy, intern]
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.matomo.rule=Host(`statistik.DEINE-DOMAIN.de`)"
      - "traefik.http.routers.matomo.entrypoints=websecure"
      - "traefik.http.routers.matomo.tls.certresolver=le"
      - "traefik.http.services.matomo.loadbalancer.server.port=80"

networks:
  proxy:
    external: true
  intern:
    external: false

volumes:
  db:
  app:

Das Wichtigste an dieser Datei:

  • Zwei Netzwerke, bewusst getrennt. Nur der app-Container hängt im proxy-Netz und ist damit von außen erreichbar. Die Datenbank liegt im internen Netz intern und ist nicht über Traefik ansprechbar – genau richtig.
  • Die MATOMO_DATABASE_*-Variablen füllen den Web-Installer im nächsten Schritt automatisch vor. Du musst die DB-Daten also nicht noch einmal von Hand eintippen.
  • max-allowed-packet=64MB empfiehlt Matomo für die Datenbank, sonst kann der Import großer Berichte abbrechen.
  • Kein Port nach außen. Weder Matomo noch die DB veröffentlichen einen Host-Port. Der einzige Weg hinein führt über Traefik und damit über HTTPS.

Schritt 4: Den Stack starten

Terminal
docker compose up -d

Beim ersten Start lädt Docker die Images (rund 310 MB Download, entpackt gut 1,3 GB) und legt die Volumes an. Prüfe danach den Status:

Terminal
docker compose ps
Ausgabe
NAME        IMAGE                COMMAND                  SERVICE   CREATED          STATUS          PORTS
matomo      matomo:5.12-apache   "/entrypoint.sh apac…"   app       15 seconds ago   Up 13 seconds   80/tcp
matomo-db   mariadb:11.4         "docker-entrypoint.s…"   db        15 seconds ago   Up 14 seconds   3306/tcp

Beide Container sollten Up sein. Traefik erkennt den neuen Container automatisch über die Labels und holt im Hintergrund ein Let’s-Encrypt-Zertifikat für deine Domain. Das dauert meist nur wenige Sekunden. Prüfe von deinem eigenen Rechner aus, ob Matomo antwortet:

Terminal
curl -sI https://statistik.DEINE-DOMAIN.de | head -1
Ausgabe
HTTP/2 200

Ein HTTP/2 200 bedeutet: Zertifikat steht, Traefik routet, Matomo läuft. Falls stattdessen ein Zertifikatsfehler kommt, gib Traefik ein paar Sekunden mehr – siehe „Wenn es nicht funktioniert".

Installer sofort abschließen

Sobald der Stack läuft, ist deine Matomo-URL öffentlich erreichbar – und der Web-Installer noch offen. Wer zuerst kommt, legt das Admin-Konto an. Klicke den Installer (Schritt 5 und 6) deshalb direkt im Anschluss durch, statt die Instanz tagelang unfertig stehen zu lassen. Kannst du das nicht sofort erledigen, schütze die Domain solange temporär – etwa über Traefik-BasicAuth oder eine IP-Allowlist, die nur deine eigene Adresse durchlässt.

Schritt 5: Den Web-Installer durchklicken

Öffne https://statistik.DEINE-DOMAIN.de im Browser. Matomo begrüßt dich mit einem achtstufigen Einrichtungsassistenten.

Matomo-Installationsassistent im Browser, Willkommensseite mit der Schrittliste von „1. Willkommen" bis „8. Glückwunsch"
Der Web-Installer von Matomo 5.12 – acht Schritte bis zum fertigen Dashboard

Klicke dich durch die ersten Schritte:

  1. WillkommenWeiter.
  2. Systemprüfung: Matomo prüft PHP-Version, Erweiterungen und Schreibrechte. Dank des offiziellen Images bleibt die Liste fehlerfrei. Eine gelbe Warnung siehst du trotzdem: Erzwungene SSL Verbindung. Sie ist hier normal und kein Grund abzubrechen – Matomos eigene Option force_ssl ist schlicht noch nicht gesetzt, ausgeliefert wird trotzdem nur über HTTPS. Wir räumen sie in Schritt 7 aus. → Weiter.
  3. Datenbank einrichten: Die Felder sind bereits ausgefüllt (das erledigen die MATOMO_DATABASE_*-Variablen aus der compose.yaml). Kontrolliere kurz, dass als Server db steht, und klicke Weiter.
  4. Tabellen anlegen: Matomo legt sein Datenbankschema an. → Weiter.

Jetzt legst du deinen Hauptadministrator an. Wähle einen Benutzernamen, ein starkes Passwort und eine echte E-Mail-Adresse (über sie kommen Sicherheits- und Update-Hinweise).

Danach richtest du die erste Website ein, die du tracken willst. Neben Name und URL ist die Zeitzone ein Pflichtfeld: Lässt du sie auf der Vorauswahl stehen, weist das Formular dich mit Zeitzone der Webseite ist nicht gültig zurück. Sie entscheidet, wann für deine Berichte ein neuer Tag beginnt – für eine deutsche Website also Deutschland – Berlin.

Formular „Webseite hinzufügen" im Matomo-Installer mit den Feldern für Name, Adresse und Zeitzone der Website
Schritt 6: die erste zu trackende Website anlegen – die Zeitzone ist Pflicht

Schritt 6: Den Tracking-Code einbauen

Im vorletzten Schritt zeigt dir Matomo den JavaScript-Tracking-Code. Das ist das kleine Snippet, das in jede Seite deiner Website gehört – idealerweise direkt vor </head>:

Matomo-Installer zeigt den fertigen JavaScript-Tracking-Code zum Kopieren an
Der Tracking-Code – dieses Snippet kommt in den Head-Bereich deiner Website

HTML
<!-- Matomo -->
<script>
  var _paq = window._paq = window._paq || [];
  _paq.push(['disableCookies']);
  _paq.push(['trackPageView']);
  _paq.push(['enableLinkTracking']);
  (function() {
    var u="//statistik.DEINE-DOMAIN.de/";
    _paq.push(['setTrackerUrl', u+'matomo.php']);
    _paq.push(['setSiteId', '1']);
    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
    g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
  })();
</script>
<!-- End Matomo Code -->

Die Zeile _paq.push(['disableCookies']); (im Original-Snippet nicht enthalten) haben wir bewusst ergänzt: Damit verzichtet Matomo komplett auf Cookies – ein wichtiger Baustein für den Betrieb ohne Consent-Banner. Betreibst du deine Website mit einem CMS wie WordPress, gibt es fertige Plugins („Matomo for WordPress", „Connect Matomo"), die das Snippet automatisch einbinden. Nach dem letzten Schritt („Fertig") meldest du dich mit deinem eben angelegten Konto an und landest im Dashboard.

Matomo-Dashboard nach der Installation mit dem Besucherüberblick und dem Verwaltungsmenü
Das fertige Matomo-Dashboard – alle Daten liegen auf deinem Server

Das Dashboard bündelt die wichtigsten Berichte: Besuche in Echtzeit, den Graph der letzten Besuche, die Besucherübersicht, eine Besucherkarte und unter Kanaltypen die Herkunft der Besucher (Suchmaschine, Direktzugriff, Verweis). Über das Menü links kommst du tiefer – Besucher (Geräte, Browser, Standort), Verhalten (Seiten, Ein- und Ausstiege) und Akquisition (welche Kanäle Besucher bringen). Genau die Fragen, die Google Analytics beantwortet – nur eben auf deinem Server.

Admin-Konto absichern

Dein Matomo-Konto sieht das komplette Besuchsverhalten deiner Website – ein lohnendes Ziel. Vergib ein langes, einmaliges Passwort und aktiviere unter Verwaltung → Persönlich → Sicherheit die Zwei-Faktor-Authentifizierung (das Plugin ist bereits an Bord). So kommt selbst bei geleaktem Passwort niemand an deine Daten.

Schritt 7: Datenschutz-Einstellungen prüfen (der wichtige Teil)

Matomo 5.12 startet datenschutzfreundlicher, als viele erwarten: Die IP-Anonymisierung ist ab Werk aktiv. Trotzdem gehst du die Seite einmal durch – erstens, um es mit eigenen Augen gesehen zu haben, zweitens, weil dort ein Schalter liegt, der dein cookieloses Tracking wirklich absichert. Öffne oben rechts Verwaltung (Zahnrad) → im Menü links Privatsphäre → Daten anonymisieren.

Matomo-Seite „Daten anonymisieren" mit aktivierter IP-Anonymisierung und der Auswahl der maskierten Bytes
Privatsphäre → Daten anonymisieren: die IP-Anonymisierung steht bereits auf zwei Bytes

Drei Stellschrauben sind entscheidend:

  • Anonymisiere die IP-Adresse von Besuchern: steht schon auf Ja, maskiert werden standardmäßig 2 byte(s) – aus 203.0.113.45 wird also 203.0.xxx.xxx (Matomo markiert diese Stufe selbst als Empfohlen). Kontrolliere nur, dass das so geblieben ist; damit ist der einzelne Besucher nicht mehr identifizierbar.
  • Tracking ohne Cookies erzwingen: einschalten. Matomo ergänzt dann matomo.js serverseitig um den passenden Code und ignoriert Tracking-Cookies zusätzlich beim Empfang. Das wirkt auch dann noch, wenn irgendwo doch das Original-Snippet ohne disableCookies landet – ein Sicherheitsnetz für den Punkt, an dem dein Consent-Banner-Verzicht hängt.
  • „Do Not Track": liegt unter Privatsphäre → Benutzer Opt-Out. Matomo stuft die Unterstützung inzwischen selbst als veraltet ein – weil Browser das Signal ungefragt senden oder gar nicht mehr unterstützen, „empfehlen wir nicht mehr, diese Option zu aktivieren". Verlass dich also nicht darauf. Der belastbare Weg steht auf derselben Seite: der Opt-out-Baustein (iframe oder eigenes Formular), den du in deine Datenschutzerklärung einbaust.

Tipp

Unter Privatsphäre → Daten anonymisieren → Lösche regelmäßig alte Daten aus der Datenbank kannst du Matomo anweisen, Rohdaten nach z. B. 180 Tagen automatisch zu löschen. Das reduziert Datenmenge und Datenschutz-Risiko – die aggregierten Berichte bleiben erhalten.

Bleibt noch der Schalter, den die Systemprüfung aus Schritt 5 angemahnt hat: force_ssl. Er weist unverschlüsselte Zugriffe in Matomo selbst ab, statt sich allein auf Traefik zu verlassen. In der Oberfläche gibt es ihn nicht, er steht in Matomos config/config.ini.php im Volume:

Terminal
cd /opt/matomo
docker compose exec -u www-data app sed -i '/^\[General\]/a force_ssl = 1' config/config.ini.php

sed hängt die Zeile force_ssl = 1 direkt unter den Abschnitt [General]; -u www-data sorgt dafür, dass die Datei ihrem bisherigen Besitzer gehört und Matomo sie weiter schreiben kann. Lade danach das Dashboard neu – unter Verwaltung → Diagnose → Systemprüfung ist die Warnung Erzwungene SSL Verbindung verschwunden.

Schritt 8: Berichte per Cron archivieren

In der Grundeinstellung berechnet Matomo seine Berichte „on the fly", sobald jemand das Dashboard öffnet. Das wird bei mehr Traffic langsam und ist offiziell nicht empfohlen. Besser: ein Cronjob rechnet die Berichte regelmäßig im Hintergrund vor.

Trage dazu auf dem Host einen Cronjob ein, der alle 15 Minuten das Archivierungskommando im Container ausführt:

Terminal
crontab -e

Füge diese Zeile hinzu (Domain anpassen):

Ausgabe
*/15 * * * * cd /opt/matomo && docker compose exec -T -u www-data app ./console core:archive --url=https://statistik.DEINE-DOMAIN.de >> /opt/matomo/archive.log 2>&1

Das Log landet bewusst in /opt/matomo/archive.log und nicht unter /var/log: Läuft dein Cron als sudo-Benutzer (nicht als root), scheitert ein Schreibzugriff auf /var/log still. In /opt/matomo hast du Schreibrechte, und du findest das Log direkt beim Projekt.

Anschließend schaltest du die alte Betriebsart ab: Verwaltung → Allgemeine EinstellungenArchivierungseinstellungen, dort „Berichte archivieren, wenn diese im Browser angezeigt werden" auf Nein stellen und speichern. So bleibt das Dashboard auch bei viel Traffic schnell – und die Systemprüfung meldet nicht mehr, dass Browser- und Cron-Archivierung gleichzeitig laufen.

Wenn es nicht funktioniert

Der Browser zeigt einen Zertifikatsfehler oder 404 page not found. Traefik hat das Let’s-Encrypt-Zertifikat noch nicht geholt, oder der DNS-Record zeigt nicht auf den Server. Prüfe mit dig statistik.DEINE-DOMAIN.de, dass die IP stimmt, und sieh in die Traefik-Logs. Den genauen Container-Namen aus deinem Traefik-Setup findest du mit docker ps | grep traefik, dann docker logs <container-name> (bei uns z. B. docker logs traefik-traefik-1). Die HTTP-Challenge scheitert, wenn Port 80 nicht von außen erreichbar ist – kontrolliere deine Firewall und die netcup-Firewall.

Der Installer meldet SQLSTATE... Connection refused oder hängt bei der Datenbank. MariaDB war beim ersten Start noch nicht bereit. Gib der DB einen Moment und lade die Seite neu. Prüfe mit docker compose logs db, ob dort ready for connections steht. Erscheint stattdessen ein Zugangsfehler, passen DB_PASSWORD in der .env und die bereits angelegte DB nicht mehr zusammen – dann hilft ein sauberer Neustart mit docker compose down -v (Achtung: löscht die Daten) und docker compose up -d.

Warnung „Es sieht so aus, als ob die trusted_hosts-Einstellung nicht korrekt ist". Matomo prüft aus Sicherheitsgründen, unter welchem Hostnamen es aufgerufen wird. Die Warnung erscheint, wenn du die Domain wechselst. Bestätige den korrekten Hostnamen über den Button in der Meldung – Matomo trägt ihn dann in config/config.ini.php ein.

Im Dashboard tauchen keine Besuche auf. Der Tracking-Code fehlt, ist falsch eingebaut, oder du besuchst deine Seite selbst (Matomo ignoriert dich, wenn deine IP ausgeschlossen ist). Öffne deine Website in einem privaten Fenster und prüfe im Netzwerk-Tab, ob ein Request an matomo.php rausgeht. In Matomo hilft Verwaltung → Diagnose → Tracking Fehlschläge.

Das Dashboard lädt sehr langsam. Die On-the-fly-Archivierung rechnet bei jedem Aufruf. Richte den Archivierungs-Cron aus Schritt 8 ein und stelle die Berichterstellung auf Cron um.

Wartung & Backups

Updates sind bei Matomo unkritisch, aber regelmäßig fällig – etwa monatlich erscheint eine neue Version. Weil wir den Image-Tag auf 5.12 gepinnt haben, ziehst du Sicherheits-Patches innerhalb der 5.12-Reihe so:

Terminal
cd /opt/matomo && docker compose pull && docker compose up -d

Beim ersten Aufruf nach einem Update prüft Matomo, ob ein Datenbank-Upgrade nötig ist, und führt es nach einem Klick aus.

Vor einem Major-Upgrade: Backup und Release-Notes

Für einen Sprung auf eine neue Hauptversion (z. B. 5.12 → 6.x) hebst du den Tag in der compose.yaml an. Ein Major-Upgrade zieht oft umfangreichere Datenbank-Migrationen nach sich, die sich nicht ohne Weiteres zurückrollen lassen. Lies deshalb vorher die Release-Notes und ziehe unbedingt ein Backup (siehe unten), bevor du das neue Image startest.

Backups umfassen zwei Dinge: die Datenbank (alle Besuchsdaten) und das app-Volume (deine Konfiguration in config/config.ini.php). Erstelle regelmäßig einen Datenbank-Dump …

Terminal
docker compose exec -T db sh -c 'exec mariadb-dump -u matomo -p"$MARIADB_PASSWORD" matomo' > /opt/matomo/dump.sql

… und nimm diesen Dump zusammen mit dem Ordner /opt/matomo in deine Restic-Off-Site-Backups auf. Ein netcup-Snapshot des ganzen Servers ist eine gute Ergänzung, aber kein Ersatz für ein echtes Off-Site-Backup – liegt beides beim selben Anbieter, sind bei einem Totalausfall auch beide weg.

Laufender Betrieb: Behalte den Speicherplatz im Auge – bei viel Traffic wächst die Datenbank. Die automatische Löschung alter Rohdaten (Schritt 7) und der Archivierungs-Cron (Schritt 8) halten Matomo dauerhaft schlank und schnell. Damit du merkst, wenn Matomo einmal nicht erreichbar ist, nimm die Instanz in dein Uptime-Kuma-Monitoring auf – ein einfacher HTTP-Check auf deine Statistik-Domain genügt.

Und der wichtigste Betriebs-Hinweis zum Schluss: Matomo lebt vom Datenschutz-Versprechen. Wer den Dienst einmal aufgesetzt hat, sollte die Anonymisierungs- und Lösch-Einstellungen aus Schritt 7 nicht wieder aufweichen – sie sind der Grund, warum du überhaupt ohne Consent-Banner auskommst. Prüfe nach jedem größeren Update kurz, dass sie noch stehen.

Zuletzt aktualisiert: 17.08.2026

Feedback per E-Mail: feedback@serverkueche.de

Das könnte dir auch schmecken