Matomo auf dem Synology NAS installieren: DSGVO-konforme Webanalyse
Matomo als Zwei-Container-Stack auf dem Synology NAS einrichten: compose.yaml mit MariaDB, cookielosem Tracking und Archivierungs-Cron – DSGVO-konform ohne Cookie-Banner, vollständig unter eigener Kontrolle.

Wer seine Website-Statistiken rechtssicher erfassen will, ohne Daten an Google oder andere Dritte zu übermitteln, steht im DACH-Raum vor einer klaren Entscheidung: selbst hosten. Matomo ist die quelloffene Antwort darauf – eine vollständige Web-Analyse-Plattform, bei der alle Rohdaten auf deiner eigenen Hardware verbleiben. Auf dem Synology NAS lässt sich Matomo als moderner Drei-Service-Stack mit dem Container Manager betreiben: MariaDB als Datenbank, die eigentliche Matomo-App und ein dedizierter Cron-Container für die Archivierung. Das Ergebnis ist eine dauerhaft lauffähige, DSGVO-konforme Lösung, die kein Cookie-Banner erfordert – sofern du die richtigen Einstellungen aktivierst.
Voraussetzungen
- Synology NAS mit DSM 7.2 oder neuer, x86_64-Architektur empfohlen (z. B. DS923+, DS1522+, DS720+)
- Container Manager aus dem Synology Package Center installiert (Version 20.10+)
- Mindestens 2 GB freier RAM, 4 GB empfohlen für größere Installationen
- Mindestens 5 GB freier Speicher auf dem NAS-Volume (ca. 1 GB pro 1 Million gespeicherter Seitenaufrufe)
- SSH-Zugang zum NAS für das Anlegen der Ordner und Setzen der Berechtigungen
- Domain oder Subdomain (z. B.
analytics.deinedomain.de) mit gültigem SSL-Zertifikat für den HTTPS-Betrieb - Zugang zu den Websites, die getrackt werden sollen, um den Tracking-Code einzubauen
Schritt 1: Verzeichnisse anlegen und Berechtigungen setzen
Der Matomo-Apache-Container läuft intern als Benutzer www-data mit UID 33. Wenn das Verzeichnis vom NAS-Root angelegt wird, fehlen dem Container die nötigen Schreibrechte – Matomo quittiert das mit einem „not writable“-Fehler beim Setup. Daher müssen beide Datenpfade vorab korrekt vorbereitet werden.
Verbinde dich per SSH mit dem NAS und führe folgende Befehle aus:
sudo mkdir -p /volume1/docker/matomo/data
sudo mkdir -p /volume1/docker/matomo/db
sudo chmod -R 777 /volume1/docker/matomo/data
sudo chmod -R 777 /volume1/docker/matomo/dbFür einen dauerhaft sicheren Betrieb kannst du anschließend die Eigentümerschaft auf UID 33 einschränken:
sudo chown -R 33:33 /volume1/docker/matomo/dataDas db-Verzeichnis wird von MariaDB mit dem Root-Benutzer des Containers beschrieben – hier genügt chmod 777 beim ersten Start.
Verifizieren: Prüfe, ob beide Verzeichnisse existieren und die Rechte stimmen:
ls -la /volume1/docker/matomo/
# Erwartete Ausgabe: Zwei Unterordner „data" und „db", beide mit drwxrwxrwxSchritt 2: Compose-Projekt im Container Manager anlegen
Öffne im DSM den Container Manager und wechsle zu Projekt → Erstellen. Vergib den Projektnamen matomo und lege den Pfad auf /volume1/docker/matomo. Füge folgende compose.yaml ein:
services:
matomo-db:
image: mariadb:11.4
container_name: matomo-db
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: SICHER_AENDERN_ROOT
MARIADB_DATABASE: matomodb
MARIADB_USER: matomouser
MARIADB_PASSWORD: SICHER_AENDERN_USER
TZ: Europe/Berlin
volumes:
- /volume1/docker/matomo/db:/var/lib/mysql
command: --max_allowed_packet=1073741824
networks:
- matomo-net
matomo:
image: matomo:5-apache
container_name: matomo-app
restart: unless-stopped
ports:
- "8597:80"
environment:
MATOMO_DATABASE_HOST: matomo-db
MATOMO_DATABASE_USERNAME: matomouser
MATOMO_DATABASE_PASSWORD: SICHER_AENDERN_USER
MATOMO_DATABASE_DBNAME: matomodb
PHP_MEMORY_LIMIT: 512M
TZ: Europe/Berlin
volumes:
- /volume1/docker/matomo/data:/var/www/html
depends_on:
- matomo-db
networks:
- matomo-net
matomo-cron:
image: matomo:5-apache
container_name: matomo-cron
restart: unless-stopped
volumes:
- /volume1/docker/matomo/data:/var/www/html
entrypoint: >
/bin/sh -c "while true; do
php /var/www/html/console core:archive
--url=https://analytics.deinedomain.de;
sleep 3600;
done"
environment:
TZ: Europe/Berlin
depends_on:
- matomo-db
- matomo
networks:
- matomo-net
networks:
matomo-net:
driver: bridgeErsetze SICHER_AENDERN_ROOT und SICHER_AENDERN_USER durch starke, einmalige Passwörter (mindestens 16 Zeichen). Der Wert für MARIADB_PASSWORD und MATOMO_DATABASE_PASSWORD muss identisch sein. Passe außerdem die URL im matomo-cron-Entrypoint auf deine tatsächliche Domain an.
| Parameter | Wert | Hinweis |
|---|---|---|
| Image Matomo | matomo:5-apache | Stabile Produktionstag-Variante mit Apache; aktuell 5.11.0 (08.06.2026) |
| Image MariaDB | mariadb:11.4 | LTS-Version, Support bis 2029, mit Matomo 5.x getestet |
| Host-Port | 8597 | Auf Container-Port 80; in DSM-Firewall freigeben |
| Volume Matomo | /volume1/docker/matomo/data → /var/www/html | config.ini.php, Plugins, GeoIP |
| Volume MariaDB | /volume1/docker/matomo/db → /var/lib/mysql | Alle Analytics-Daten – Pflicht für Persistenz |
| DB-Port | 3306 (intern) | Nicht nach außen exponieren – Docker-Netzwerk genügt |
Verifizieren: Starte das Projekt und prüfe, ob alle drei Container laufen:
docker ps --filter "name=matomo"
# Erwartete Ausgabe: matomo-db, matomo-app und matomo-cron mit Status „Up"Prüfe außerdem die MariaDB-Logs auf den Bereitschaftshinweis:
docker logs matomo-db | grep "ready for connections"
# Erwartete Ausgabe: [Note] mariadbd: ready for connections.Schritt 3: Datenbankverbindung und Setup-Wizard abschließen
Öffne im Browser http://NAS-IP:8597. Der Matomo-Setup-Wizard führt dich in wenigen Schritten durch die Erstkonfiguration. Der kritischste Schritt ist die Datenbankeinrichtung – hier schlägt die Installation am häufigsten fehl, wenn der falsche Hostname eingetragen wird.
Trage auf der Datenbankseite folgende Werte ein:
- Datenbankserver:
matomo-db(der Container-Name – niemalslocalhostoder127.0.0.1) - Benutzername:
matomouser - Passwort: dein gewähltes
SICHER_AENDERN_USER-Passwort - Datenbankname:
matomodb - Tabellen-Prefix:
matomo_(Standard)
Sollte der Wizard mit „Could not connect to database“ scheitern, obwohl die Zugangsdaten stimmen, ist MariaDB noch nicht vollständig hochgefahren. Starte den Matomo-App-Container neu, sobald die DB-Logs „ready for connections“ zeigen:
docker restart matomo-appLege danach einen Super-Admin-Account an, füge deine erste Website hinzu und notiere die Website-ID – sie wird für den Tracking-Code benötigt.
Verifizieren: Führe direkt nach dem Setup einen manuellen Datenbankzugriff durch:
docker exec -it matomo-db mariadb -u matomouser -pSICHER_AENDERN_USER matomodb -e "SHOW TABLES LIKE 'matomo_%';"
# Erwartete Ausgabe: Liste der Matomo-Tabellen (matomo_site, matomo_log_visit, …)Schritt 4: Reverse Proxy und HTTPS einrichten
Für den Produktivbetrieb – und aus DSGVO-Sicht zur Verschlüsselung der übertragenen Besucherdaten – ist HTTPS zwingend. Im DSM-Reverse-Proxy (unter Systemsteuerung → Anmeldungsportal → Erweitert) legst du eine neue Regel an:
- Quelle: HTTPS, Port 443, Hostname
analytics.deinedomain.de - Ziel: HTTP,
localhost, Port8597
Anschließend muss Matomo wissen, dass es hinter einem Proxy läuft. Öffne die Datei /volume1/docker/matomo/data/config/config.ini.php und ergänze unter der Sektion [General]:
force_ssl = 1
assume_secure_protocol = 1
proxy_client_headers[] = HTTP_X_FORWARDED_FORDiese drei Zeilen sorgen dafür, dass Matomo echte Besucher-IPs korrekt ausliest statt der Proxy-IP 127.0.0.1 zu protokollieren, und dass alle internen Links auf HTTPS umgestellt werden.
Verifizieren: Rufe https://analytics.deinedomain.de im Browser auf. Das Matomo-Dashboard muss ohne Zertifikatswarnung und ohne HTTP-Weiterleitungsschleife erscheinen. In der Matomo-Verwaltung unter Diagnose → System-Check darf kein Fehler bezüglich HTTPS oder Proxy-Headern stehen.
Schritt 5: Cookieloses Tracking und IP-Anonymisierung aktivieren
Dies ist der entscheidende Schritt für den DSGVO-konformen Betrieb ohne Consent-Banner. Matomo selbst bestätigt: Wenn cookieloses Tracking aktiv ist und IP-Adressen ausreichend anonymisiert werden, ist nach der DSK-Orientierungshilfe für Webtracking kein Einwilligungsbanner erforderlich.
IP-Anonymisierung: Navigiere in der Matomo-Verwaltung zu Datenschutz → Anonymisierung und stelle die Anonymisierung auf mindestens 2 Byte ein – empfohlen sind 3 Byte. Damit sind die letzten zwei Oktette der IPv4-Adresse (bzw. die letzten 80 Bit bei IPv6) nicht mehr gespeichert, und es ist keine Rückführung auf einzelne Personen möglich.
Cookieless Tracking: Im Tracking-Code, den du in die <head>-Sektion deiner Website einbaust, fügst du vor dem trackPageView-Aufruf folgende Zeile ein:
_paq.push(['disableCookies']);Der vollständige Tracking-Code sieht dann so aus:
<script>
var _paq = window._paq = window._paq || [];
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.deinedomain.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>Browser-Archivierung deaktivieren: Da der Cron-Container die Archivierung übernimmt, deaktiviere die Browser-getriggerte Archivierung. Setze in config.ini.php unter [General]:
browser_archiving_disabled_enforce = 1Verifizieren: Öffne die getrackte Website im Browser, drücke F12, wechsle zum Netzwerk-Tab und lade die Seite neu. Filtere nach matomo – du solltest zwei erfolgreiche Requests sehen:
matomo.js → HTTP 200
matomo.php → HTTP 200 (oder 204)Prüfe außerdem in Matomo unter Besucher → Echtzeit: Dein eigener Seitenaufruf erscheint innerhalb weniger Sekunden. Im Browser-Cookie-Speicher (Entwicklertools → Anwendung → Cookies) darf kein _pk_id- oder _pk_ses-Cookie vorhanden sein.
Schritt 6: Archivierungs-Cron im Container verifizieren
Der matomo-cron-Container läuft als dauerhafter Prozess, der stündlich core:archive ausführt. Dieser Ansatz folgt der offiziellen Matomo-Dokumentation – die Alternative wäre ein DSM-Aufgabenplaner-Eintrag, aber der Cron-Container hat den Vorteil, dass er vollständig im Compose-Projekt verwaltet wird und beim Stack-Neustart automatisch wieder hochkommt.
Nach dem ersten Start wartet der Container bis zu 3600 Sekunden bis zur ersten Archivierung. Bis dahin sind historische Berichte im Dashboard noch nicht sichtbar – der Echtzeit-Bericht funktioniert jedoch sofort.
Verifizieren: Prüfe die Cron-Container-Logs auf erfolgreiche Archivierungsläufe:
docker logs matomo-cron --tail 30
# Erwartete Ausgabe nach dem ersten Durchlauf:
# Starting Matomo reports archiving...
# Archived website id = 1, 0 visits …Wenn du nicht so lange warten möchtest, kannst du die Archivierung einmalig manuell anstoßen:
docker exec matomo-app php /var/www/html/console core:archive --url=https://analytics.deinedomain.deTroubleshooting / Typische Fehler
- „Could not connect to database“ im Setup-Wizard: Fast immer startet Matomo, bevor MariaDB bereit ist.
depends_onwartet nur auf den Container-Start, nicht auf die DB-Bereitschaft. Lösung:docker logs matomo-db | grep "ready for connections"abwarten, danndocker restart matomo-app. - „not writable“-Fehler beim Setup: Die Verzeichnisse unter
/volume1/docker/matomo/data/haben unzureichende Schreibrechte für UID 33. Fix:sudo chmod -R 777 /volume1/docker/matomo/dataodersudo chown -R 33:33 /volume1/docker/matomo/data. - Falscher DB-Host im Setup: Als Datenbankserver muss der Container-Name
matomo-dbeingetragen werden – nichtlocalhostoder127.0.0.1. Beide Container müssen im gleichen Netzwerk (matomo-net) sein. - Tracking-Requests schlagen fehl (404/CORS): Die URL im Tracking-Code muss exakt der Matomo-Installations-URL entsprechen (inklusive abschließendem Schrägstrich). Bei HTTPS hinter dem Reverse Proxy:
force_ssl = 1undassume_secure_protocol = 1inconfig.ini.phpsetzen. - Dashboard zeigt keine historischen Daten: Archivierung wurde noch nicht ausgeführt. Cron-Container-Logs prüfen oder manuell mit
docker exec matomo-app php /var/www/html/console core:archive --url=…anstoßen. - „Packet too large“-Fehler bei GeoIP-Import oder großen Exporten: Der
--max_allowed_packet=1073741824-Parameter immatomo-db-Service muss vorhanden sein (bereits in der compose.yaml enthalten). - Nach Image-Update sind Einstellungen weg: Das Volume
/volume1/docker/matomo/datawurde nicht persistent gemountet. Immer den Bind-Mount aus der compose.yaml verwenden – niemals ohne Volume-Eintrag starten. - Nach Matomo-Update erscheinen Fehler im Dashboard: Nach jedem Image-Update (
docker pull matomo:5-apache+ Container-Neustart) zwingend den Update-Assistenten unter Administration → System-Check ausführen, um das Datenbankschema zu migrieren.
Häufige Fragen
Brauche ich für Matomo cookieless einen Cookie-Banner?
Nein. Wenn _paq.push(['disableCookies']) aktiv ist, IP-Adressen auf 3 Byte anonymisiert werden und keine personenbezogenen Daten in URLs oder Seitentiteln erfasst werden, ist nach der DSK-Orientierungshilfe für Webtracking kein Consent-Banner erforderlich. Matomo selbst bestätigt: Cookieless Tracking verwendet keine Fingerprinting-Methode und speichert nichts auf dem Gerät des Nutzers.
Muss ich einen Auftragsverarbeitungsvertrag (AVV) abschließen?
Nein – bei selbst gehostetem Matomo auf dem eigenen NAS bist du Verantwortlicher und Verarbeiter zugleich. Kein Dritter verarbeitet die Daten, daher ist kein AVV nötig. Einen AVV benötigst du nur, wenn ein externer Dienstleister (Hoster, Agentur) Zugriff auf die Analysedaten hat. Mehr zum Thema AVV und DSGVO-Dokumentation findest du in der Anleitung DSGVO-Praxis: TOMs dokumentieren und Auftragsverarbeitung regeln.
Wie verifiziere ich die Datenbankverbindung nach dem Start?
Drei Schritte: (1) docker logs matomo-db | grep "ready for connections" – zeigt, ob MariaDB gestartet ist. (2) docker exec -it matomo-db mariadb -u matomouser -p matomodb – erfolgreiche Verbindung bestätigt die Zugangsdaten. (3) Im Setup-Wizard Schritt „Datenbank einrichten“ – ein grünes Häkchen bestätigt den Verbindungserfolg.
Wie teste ich den Tracking-Code nach dem Einbau?
Öffne die Entwicklertools (F12) im Browser, wechsle zum Netzwerk-Tab und lade die Seite neu. Filtere nach „matomo“ – du solltest matomo.js und matomo.php mit HTTP 200 sehen. Prüfe zusätzlich unter Besucher → Echtzeit im Matomo-Dashboard: Dein eigener Aufruf erscheint innerhalb von Sekunden. Die Browser-Extension „Matomo Tag Checker“ hilft bei der Diagnose von Implementierungsfehlern.
Kann ich Matomo hinter dem Synology Reverse Proxy betreiben?
Ja, und für den Produktivbetrieb ist das die empfohlene Variante. Im DSM-Reverse-Proxy: Quelle HTTPS:443 → Ziel HTTP:localhost:8597. In config.ini.php dann force_ssl = 1, assume_secure_protocol = 1 und proxy_client_headers[] = HTTP_X_FORWARDED_FOR setzen, damit die echten Besucher-IPs übermittelt werden.
Was ist der Unterschied zu Umami als Alternative?
Beide laufen self-hosted und sind DSGVO-konform. Umami ist schlanker und schneller aufgesetzt. Matomo bietet deutlich mehr: Ziel-Tracking, E-Commerce-Auswertung, Heatmaps (via Plugin), A/B-Tests und eine detailliertere Segmentierung. Wer nur Seitenaufrufe und Herkunft braucht, findet in der Anleitung Umami auf der Synology: cookielose Webanalyse eine leichtgewichtige Alternative.
Fazit
Matomo auf dem Synology NAS ist die datenschutzrechtlich sauberste Lösung für Website-Betreiber im DACH-Raum, die mehr wollen als einfache Seitenaufrufe: vollständige Datenkontrolle, kein Drittland-Transfer, keine Google-Abhängigkeit. Das Compose-Projekt mit drei Services ist in unter einer Stunde einsatzbereit. Der entscheidende Unterschied zu vielen anderen Anleitungen liegt im Detail: der persistente MariaDB-Mount verhindert Datenverlust, der Cron-Container sorgt für zuverlässige Report-Archivierung, und die Kombination aus disableCookies() und 3-Byte-IP-Anonymisierung macht den Betrieb ohne Consent-Banner rechtssicher. Wer eine noch einfachere Alternative sucht, findet sie bei Umami auf der Synology – wer dagegen E-Commerce-Tracking, Conversion-Ziele oder Heatmaps braucht, ist mit Matomo besser aufgestellt.
Weiterführende Anleitungen und Quellen
- DSGVO-Praxis: TOMs dokumentieren und Auftragsverarbeitung regeln
- Nginx Proxy Manager auf der Synology einrichten: Reverse Proxy und SSL
Offizielle Dokumentation: Matomo Docker Hub Official Image · Matomo FAQ: Docker-Installation · Matomo: Cookieless ohne Consent-Banner