<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Matomo – Serverküche</title><link>https://serverkueche.de/tags/matomo/</link><description>Matomo – Neueste Beiträge von Serverküche</description><generator>Hugo</generator><language>de-DE</language><managingEditor>feedback@serverkueche.de (Serverküche)</managingEditor><webMaster>feedback@serverkueche.de (Serverküche)</webMaster><copyright>2026 Serverküche</copyright><lastBuildDate>Tue, 04 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://serverkueche.de/tags/matomo/index.xml" rel="self" type="application/rss+xml"/><item><title>Matomo cookielos selbst hosten: Analytics ohne Consent-Banner</title><link>https://serverkueche.de/tutorials/matomo-selbst-hosten/</link><pubDate>Tue, 04 Aug 2026 00:00:00 +0000</pubDate><author>feedback@serverkueche.de (Serverküche)</author><guid>https://serverkueche.de/tutorials/matomo-selbst-hosten/</guid><description>Matomo 5.12 mit Docker &amp; Traefik aufsetzen: datenschutzfreundliche Web-Analytics mit IP-Anonymisierung, ganz ohne Google und ohne Cookie-Banner.</description><content:encoded><![CDATA[<p>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.</p>
<h2 id="was-bauen-wir">Was bauen wir?</h2>
<p>Am Ende läuft <strong>Matomo 5.12</strong> in Docker hinter deinem Traefik-Reverse-Proxy, erreichbar unter deiner eigenen (Sub-)Domain mit gültigem HTTPS-Zertifikat. Als Datenbank kommt <strong>MariaDB 11.4</strong> dazu – beides in einem <code>compose.yaml</code>. Du bekommst ein vollwertiges Analytics-Dashboard, das Besucherzahlen, Herkunft, Geräte und beliebte Seiten auswertet – die Daten liegen ausschließlich auf deinem Server.</p>
<p>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 <a href="/tutorials/hitkeep-analytics-selbst-hosten/">HitKeep</a>.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-sky-300 bg-sky-50 dark:border-sky-800 dark:bg-sky-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">ℹ️</span>Hinweis
  </p>
  <div class="prose-kitchen text-sm">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.</div>
</div>
<h2 id="voraussetzungen">Voraussetzungen</h2>
<ul>
<li>Ein <a href="/tutorials/ssh-absichern/">abgesicherter Server</a> mit Debian 13 und einem sudo-Benutzer</li>
<li><a href="/tutorials/docker-installieren/">Docker &amp; Docker Compose installiert</a></li>
<li>Ein <a href="/tutorials/reverse-proxy-traefik/">laufender Traefik-Reverse-Proxy</a> mit dem externen Netzwerk <code>proxy</code> und dem Zertifikats-Resolver <code>le</code> – Matomo hängt sich dort ein</li>
<li>Eine (Sub-)Domain, deren A-/AAAA-Record <a href="/tutorials/domain-mit-server-verbinden/">auf deinen Server zeigt</a>, z. B. <code>statistik.DEINE-DOMAIN.de</code></li>
<li>Eine <a href="/tutorials/backups-mit-restic/">funktionierende Backup-Strategie mit Restic</a> – Analytics-Daten sammeln sich über Jahre an, die willst du nicht verlieren</li>
</ul>
<p>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 <a href="/serverempfehlung/">Server-Rechner</a> hilft dir bei der Einschätzung.</p>
<div class="not-prose my-6 overflow-hidden rounded-xl border border-paprika-200 bg-paprika-50 dark:border-paprika-800 dark:bg-paprika-900/20"
     data-track-content data-content-name="Affiliate-Box · /tutorials/matomo-selbst-hosten/" data-content-piece="VPS 1000 G12">
  <div class="flex items-center justify-between border-b border-paprika-200 bg-paprika-100 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-paprika-700 dark:border-paprika-800 dark:bg-paprika-900/40 dark:text-paprika-300">
    <span>🍳 Empfehlung</span>
    <span title="Mit * markierte Links sind Affiliate-Links.">Anzeige</span>
  </div>
  <div class="flex flex-col gap-4 p-4 sm:flex-row sm:items-center sm:justify-between">
    <div>
      <p class="text-lg font-bold text-slate-900 dark:text-white">VPS 1000 G12</p>
      <p class="mt-1 text-sm text-slate-600 dark:text-slate-300">4 vCore · 8 GB RAM · 256 GB NVMe</p>
      <p class="mt-1 text-sm font-semibold text-paprika-700 dark:text-paprika-400">ab 10,36 €/Monat</p>
      <p class="mt-2 text-sm text-slate-600 dark:text-slate-400">Reicht für Matomo neben ein paar weiteren kleinen Diensten.</p>
    </div>
    <a href="https://www.netcup.com/de/server/vps/vps-1000-g12-12m?ref=44083" rel="sponsored noopener" target="_blank"
   data-track-event="Affiliate|netcup: Affiliate-Box|VPS 1000 G12 · {page}"
   class="inline-flex shrink-0 items-center justify-center rounded-lg bg-paprika-600 px-5 py-2.5 font-semibold text-white transition-colors hover:bg-paprika-700">
  Zu netcup →
</a>

  </div><div class="px-4 pb-4"><p class="not-prose my-3 flex flex-wrap items-center gap-x-2 gap-y-1 rounded-lg border border-herb-500/40 bg-herb-50 px-3 py-2 text-sm text-slate-700 dark:bg-herb-900/20 dark:text-slate-200">
  <span>💶 <strong>5 € Gutschein</strong> für netcup-Neukunden:</span><code data-track-voucher="36nc17844976032"
        class="rounded bg-white px-2 py-0.5 font-mono text-sm font-semibold text-herb-800 dark:bg-slate-800 dark:text-herb-400">36nc17844976032</code>
  <span class="text-xs text-slate-500 dark:text-slate-400">(nur Neukunden, keine Domains)</span>
</p></div>
</div>

<h2 id="schritt-für-schritt">Schritt für Schritt</h2>
<h3 id="schritt-1-projektordner-anlegen-und-netzwerk-prüfen">Schritt 1: Projektordner anlegen und Netzwerk prüfen</h3>
<p>Wir legen für Matomo einen eigenen Ordner unter <code>/opt</code> an – so bleibt jeder Dienst sauber getrennt:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">mkdir -p /opt/matomo <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /opt/matomo</span></span></code></pre></div>
</div>
<p>Matomo muss ins selbe Docker-Netzwerk wie Traefik, damit der Proxy den Container erreicht. Prüfe, dass das Netzwerk <code>proxy</code> aus dem <a href="/tutorials/reverse-proxy-traefik/">Traefik-Tutorial</a> existiert:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker network ls <span class="p">|</span> grep proxy</span></span></code></pre></div>
</div>
<p>Du solltest eine Zeile mit <code>proxy</code> sehen. Falls nicht, richte zuerst Traefik ein – ohne den Proxy bekommt Matomo kein Zertifikat.</p>
<h3 id="schritt-2-passwörter-in-eine-env-auslagern">Schritt 2: Passwörter in eine <code>.env</code> auslagern</h3>
<p>Die Datenbank-Passwörter gehören <strong>nicht</strong> ins <code>compose.yaml</code>, sondern in eine separate <code>.env</code>. Wir lassen sie von <code>openssl</code> zufällig erzeugen:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">{</span>
</span></span><span class="line"><span class="cl">  <span class="nb">echo</span> <span class="s2">&#34;DB_PASSWORD=</span><span class="k">$(</span>openssl rand -hex 16<span class="k">)</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="nb">echo</span> <span class="s2">&#34;DB_ROOT_PASSWORD=</span><span class="k">$(</span>openssl rand -hex 16<span class="k">)</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="o">}</span> &gt; .env
</span></span><span class="line"><span class="cl">chmod <span class="m">600</span> .env</span></span></code></pre></div>
</div>
<p><code>chmod 600</code> sorgt dafür, dass nur <code>root</code> die Datei lesen kann. Wirf einmal einen Blick hinein, damit du die Werte kennst:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">cat .env</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">DB_PASSWORD=b51024e3f9a7c8d1e2f3a4b5c6d7e8f9
</span></span><span class="line"><span class="cl">DB_ROOT_PASSWORD=1a2b3c4d5e6f70819a0b1c2d3e4f5061</span></span></code></pre></div>
</div>
<h3 id="schritt-3-die-composeyaml-schreiben">Schritt 3: Die <code>compose.yaml</code> schreiben</h3>
<p>Lege die Datei <code>/opt/matomo/compose.yaml</code> mit folgendem Inhalt an. Ersetze im Traefik-Label <strong><code>statistik.DEINE-DOMAIN.de</code> durch deine echte (Sub-)Domain</strong>:</p>
<div class="sk-code">
  <span class="sk-code-head">YAML</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">db</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">mariadb:11.4</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">matomo-db</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span>--<span class="l">max-allowed-packet=64MB</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MARIADB_DATABASE</span><span class="p">:</span><span class="w"> </span><span class="l">matomo</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MARIADB_USER</span><span class="p">:</span><span class="w"> </span><span class="l">matomo</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MARIADB_PASSWORD</span><span class="p">:</span><span class="w"> </span><span class="l">${DB_PASSWORD}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MARIADB_ROOT_PASSWORD</span><span class="p">:</span><span class="w"> </span><span class="l">${DB_ROOT_PASSWORD}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">db:/var/lib/mysql</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">networks</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">intern]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l">unless-stopped</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">app</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">matomo:5.12-apache</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">matomo</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MATOMO_DATABASE_HOST</span><span class="p">:</span><span class="w"> </span><span class="l">db</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MATOMO_DATABASE_ADAPTER</span><span class="p">:</span><span class="w"> </span><span class="l">mysql</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MATOMO_DATABASE_USERNAME</span><span class="p">:</span><span class="w"> </span><span class="l">matomo</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MATOMO_DATABASE_PASSWORD</span><span class="p">:</span><span class="w"> </span><span class="l">${DB_PASSWORD}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MATOMO_DATABASE_DBNAME</span><span class="p">:</span><span class="w"> </span><span class="l">matomo</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">app:/var/www/html</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">depends_on</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">db]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">networks</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">proxy, intern]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l">unless-stopped</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.enable=true&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.matomo.rule=Host(`statistik.DEINE-DOMAIN.de`)&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.matomo.entrypoints=websecure&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.matomo.tls.certresolver=le&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.services.matomo.loadbalancer.server.port=80&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">networks</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">proxy</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">external</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">intern</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">external</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">db</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="l">app:</span></span></span></code></pre></div>
</div>
<p>Das Wichtigste an dieser Datei:</p>
<ul>
<li><strong>Zwei Netzwerke, bewusst getrennt.</strong> Nur der <code>app</code>-Container hängt im <code>proxy</code>-Netz und ist damit von außen erreichbar. Die Datenbank liegt im internen Netz <code>intern</code> und ist <strong>nicht</strong> über Traefik ansprechbar – genau richtig.</li>
<li><strong>Die <code>MATOMO_DATABASE_*</code>-Variablen</strong> füllen den Web-Installer im nächsten Schritt automatisch vor. Du musst die DB-Daten also nicht noch einmal von Hand eintippen.</li>
<li><strong><code>max-allowed-packet=64MB</code></strong> empfiehlt Matomo für die Datenbank, sonst kann der Import großer Berichte abbrechen.</li>
<li><strong>Kein Port nach außen.</strong> Weder Matomo noch die DB veröffentlichen einen Host-Port. Der einzige Weg hinein führt über Traefik und damit über HTTPS.</li>
</ul>
<h3 id="schritt-4-den-stack-starten">Schritt 4: Den Stack starten</h3>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose up -d</span></span></code></pre></div>
</div>
<p>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:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose ps</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">NAME        IMAGE                COMMAND                  SERVICE   CREATED          STATUS          PORTS
</span></span><span class="line"><span class="cl">matomo      matomo:5.12-apache   &#34;/entrypoint.sh apac…&#34;   app       15 seconds ago   Up 13 seconds   80/tcp
</span></span><span class="line"><span class="cl">matomo-db   mariadb:11.4         &#34;docker-entrypoint.s…&#34;   db        15 seconds ago   Up 14 seconds   3306/tcp</span></span></code></pre></div>
</div>
<p>Beide Container sollten <code>Up</code> sein. Traefik erkennt den neuen Container automatisch über die Labels und holt im Hintergrund ein Let&rsquo;s-Encrypt-Zertifikat für deine Domain. Das dauert meist nur wenige Sekunden. Prüfe von deinem eigenen Rechner aus, ob Matomo antwortet:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">curl -sI https://statistik.DEINE-DOMAIN.de <span class="p">|</span> head -1</span></span></code></pre></div>
</div>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">HTTP/2 200</span></span></code></pre></div>
</div>
<p>Ein <code>HTTP/2 200</code> bedeutet: Zertifikat steht, Traefik routet, Matomo läuft. Falls stattdessen ein Zertifikatsfehler kommt, gib Traefik ein paar Sekunden mehr – siehe „Wenn es nicht funktioniert&quot;.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-amber-400 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">⚠️</span>Installer sofort abschließen
  </p>
  <div class="prose-kitchen text-sm">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 <strong>direkt im Anschluss</strong> durch, statt die Instanz tagelang unfertig stehen zu lassen. Kannst du das nicht sofort erledigen, schütze die Domain solange temporär – etwa über <a href="/tutorials/reverse-proxy-traefik/">Traefik-BasicAuth</a> oder eine IP-Allowlist, die nur deine eigene Adresse durchlässt.</div>
</div>
<h3 id="schritt-5-den-web-installer-durchklicken">Schritt 5: Den Web-Installer durchklicken</h3>
<p>Öffne <code>https://statistik.DEINE-DOMAIN.de</code> im Browser. Matomo begrüßt dich mit einem achtstufigen Einrichtungsassistenten.</p>
<p><figure class="my-6"><img src="/tutorials/matomo-selbst-hosten/matomo-installer_hu_d554cd431256c6e7.webp" srcset="/tutorials/matomo-selbst-hosten/matomo-installer_hu_cb779c3e6f2a8245.webp 480w, /tutorials/matomo-selbst-hosten/matomo-installer_hu_d554cd431256c6e7.webp 768w, /tutorials/matomo-selbst-hosten/matomo-installer_hu_8d84b7a2787dcee.webp 1200w, /tutorials/matomo-selbst-hosten/matomo-installer_hu_31ffb833ce9eaaf5.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/matomo-selbst-hosten/matomo-installer_hu_68a5300c36b81093.webp"
    alt="Matomo-Installationsassistent im Browser, Willkommensseite mit der Schrittliste von „1. Willkommen&quot; bis „8. Glückwunsch&quot;" title="Der Web-Installer von Matomo 5.12 – acht Schritte bis zum fertigen Dashboard"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Der Web-Installer von Matomo 5.12 – acht Schritte bis zum fertigen Dashboard</figcaption></figure></p>
<p>Klicke dich durch die ersten Schritte:</p>
<ol>
<li><strong>Willkommen</strong> → <em>Weiter</em>.</li>
<li><strong>Systemprüfung</strong>: Matomo prüft PHP-Version, Erweiterungen und Schreibrechte. Dank des offiziellen Images bleibt die Liste fehlerfrei. Eine gelbe Warnung siehst du trotzdem: <em>Erzwungene SSL Verbindung</em>. Sie ist hier normal und kein Grund abzubrechen – Matomos eigene Option <code>force_ssl</code> ist schlicht noch nicht gesetzt, ausgeliefert wird trotzdem nur über HTTPS. Wir räumen sie in Schritt 7 aus. → <em>Weiter</em>.</li>
<li><strong>Datenbank einrichten</strong>: Die Felder sind bereits ausgefüllt (das erledigen die <code>MATOMO_DATABASE_*</code>-Variablen aus der <code>compose.yaml</code>). Kontrolliere kurz, dass als Server <code>db</code> steht, und klicke <em>Weiter</em>.</li>
<li><strong>Tabellen anlegen</strong>: Matomo legt sein Datenbankschema an. → <em>Weiter</em>.</li>
</ol>
<p>Jetzt legst du deinen <strong>Hauptadministrator</strong> an. Wähle einen Benutzernamen, ein starkes Passwort und eine echte E-Mail-Adresse (über sie kommen Sicherheits- und Update-Hinweise).</p>
<p>Danach richtest du die <strong>erste Website</strong> ein, die du tracken willst. Neben Name und URL ist die <strong>Zeitzone</strong> ein Pflichtfeld: Lässt du sie auf der Vorauswahl stehen, weist das Formular dich mit <em>Zeitzone der Webseite ist nicht gültig</em> zurück. Sie entscheidet, wann für deine Berichte ein neuer Tag beginnt – für eine deutsche Website also <em>Deutschland – Berlin</em>.</p>
<p><figure class="my-6"><img src="/tutorials/matomo-selbst-hosten/matomo-website_hu_3936c1d8e241247.webp" srcset="/tutorials/matomo-selbst-hosten/matomo-website_hu_8a2fdbf1810f52f5.webp 480w, /tutorials/matomo-selbst-hosten/matomo-website_hu_3936c1d8e241247.webp 768w, /tutorials/matomo-selbst-hosten/matomo-website_hu_a4686d3f264b903c.webp 1200w, /tutorials/matomo-selbst-hosten/matomo-website_hu_4efaf7384020a738.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/matomo-selbst-hosten/matomo-website_hu_c040438b74f32fc9.webp"
    alt="Formular „Webseite hinzufügen&quot; im Matomo-Installer mit den Feldern für Name, Adresse und Zeitzone der Website" title="Schritt 6: die erste zu trackende Website anlegen – die Zeitzone ist Pflicht"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Schritt 6: die erste zu trackende Website anlegen – die Zeitzone ist Pflicht</figcaption></figure></p>
<h3 id="schritt-6-den-tracking-code-einbauen">Schritt 6: Den Tracking-Code einbauen</h3>
<p>Im vorletzten Schritt zeigt dir Matomo den <strong>JavaScript-Tracking-Code</strong>. Das ist das kleine Snippet, das in jede Seite deiner Website gehört – idealerweise direkt vor <code>&lt;/head&gt;</code>:</p>
<p><figure class="my-6"><img src="/tutorials/matomo-selbst-hosten/matomo-tracking_hu_534bf696465dd87f.webp" srcset="/tutorials/matomo-selbst-hosten/matomo-tracking_hu_5bd94665cc4deb82.webp 480w, /tutorials/matomo-selbst-hosten/matomo-tracking_hu_534bf696465dd87f.webp 768w, /tutorials/matomo-selbst-hosten/matomo-tracking_hu_1f7424b9ebf1c69b.webp 1200w, /tutorials/matomo-selbst-hosten/matomo-tracking_hu_c377490661b56016.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/matomo-selbst-hosten/matomo-tracking_hu_4e3bf550cb936faf.webp"
    alt="Matomo-Installer zeigt den fertigen JavaScript-Tracking-Code zum Kopieren an" title="Der Tracking-Code – dieses Snippet kommt in den Head-Bereich deiner Website"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Der Tracking-Code – dieses Snippet kommt in den Head-Bereich deiner Website</figcaption></figure></p>
<div class="sk-code">
  <span class="sk-code-head">HTML</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="c">&lt;!-- Matomo --&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="kd">var</span> <span class="nx">_paq</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">_paq</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">_paq</span> <span class="o">||</span> <span class="p">[];</span>
</span></span><span class="line"><span class="cl">  <span class="nx">_paq</span><span class="p">.</span><span class="nx">push</span><span class="p">([</span><span class="s1">&#39;disableCookies&#39;</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">_paq</span><span class="p">.</span><span class="nx">push</span><span class="p">([</span><span class="s1">&#39;trackPageView&#39;</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">_paq</span><span class="p">.</span><span class="nx">push</span><span class="p">([</span><span class="s1">&#39;enableLinkTracking&#39;</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">var</span> <span class="nx">u</span><span class="o">=</span><span class="s2">&#34;//statistik.DEINE-DOMAIN.de/&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="nx">_paq</span><span class="p">.</span><span class="nx">push</span><span class="p">([</span><span class="s1">&#39;setTrackerUrl&#39;</span><span class="p">,</span> <span class="nx">u</span><span class="o">+</span><span class="s1">&#39;matomo.php&#39;</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">    <span class="nx">_paq</span><span class="p">.</span><span class="nx">push</span><span class="p">([</span><span class="s1">&#39;setSiteId&#39;</span><span class="p">,</span> <span class="s1">&#39;1&#39;</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">    <span class="kd">var</span> <span class="nx">d</span><span class="o">=</span><span class="nb">document</span><span class="p">,</span> <span class="nx">g</span><span class="o">=</span><span class="nx">d</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;script&#39;</span><span class="p">),</span> <span class="nx">s</span><span class="o">=</span><span class="nx">d</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s1">&#39;script&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="nx">g</span><span class="p">.</span><span class="kr">async</span><span class="o">=</span><span class="kc">true</span><span class="p">;</span> <span class="nx">g</span><span class="p">.</span><span class="nx">src</span><span class="o">=</span><span class="nx">u</span><span class="o">+</span><span class="s1">&#39;matomo.js&#39;</span><span class="p">;</span> <span class="nx">s</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">g</span><span class="p">,</span><span class="nx">s</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">})();</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="c">&lt;!-- End Matomo Code --&gt;</span></span></span></code></pre></div>
</div>
<p>Die Zeile <code>_paq.push(['disableCookies']);</code> (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&quot;, „Connect Matomo&quot;), die das Snippet automatisch einbinden. Nach dem letzten Schritt („Fertig&quot;) meldest du dich mit deinem eben angelegten Konto an und landest im Dashboard.</p>
<p><figure class="my-6"><img src="/tutorials/matomo-selbst-hosten/matomo-dashboard_hu_6c3e00340bcdaff5.webp" srcset="/tutorials/matomo-selbst-hosten/matomo-dashboard_hu_e3134bedcd9f4f4d.webp 480w, /tutorials/matomo-selbst-hosten/matomo-dashboard_hu_6c3e00340bcdaff5.webp 768w, /tutorials/matomo-selbst-hosten/matomo-dashboard_hu_393ce8a7a4434be4.webp 1200w, /tutorials/matomo-selbst-hosten/matomo-dashboard_hu_882486362124748.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/matomo-selbst-hosten/matomo-dashboard_hu_c542ba15f54f9421.webp"
    alt="Matomo-Dashboard nach der Installation mit dem Besucherüberblick und dem Verwaltungsmenü" title="Das fertige Matomo-Dashboard – alle Daten liegen auf deinem Server"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Das fertige Matomo-Dashboard – alle Daten liegen auf deinem Server</figcaption></figure></p>
<p>Das Dashboard bündelt die wichtigsten Berichte: <em>Besuche in Echtzeit</em>, den <em>Graph der letzten Besuche</em>, die <em>Besucherübersicht</em>, eine <em>Besucherkarte</em> und unter <em>Kanaltypen</em> die Herkunft der Besucher (Suchmaschine, Direktzugriff, Verweis). Über das Menü links kommst du tiefer – <strong>Besucher</strong> (Geräte, Browser, Standort), <strong>Verhalten</strong> (Seiten, Ein- und Ausstiege) und <strong>Akquisition</strong> (welche Kanäle Besucher bringen). Genau die Fragen, die Google Analytics beantwortet – nur eben auf deinem Server.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-amber-400 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">⚠️</span>Admin-Konto absichern
  </p>
  <div class="prose-kitchen text-sm">Dein Matomo-Konto sieht das komplette Besuchsverhalten deiner Website – ein lohnendes Ziel. Vergib ein langes, einmaliges Passwort und aktiviere unter Verwaltung → <em>Persönlich → Sicherheit</em> die <strong>Zwei-Faktor-Authentifizierung</strong> (das Plugin ist bereits an Bord). So kommt selbst bei geleaktem Passwort niemand an deine Daten.</div>
</div>
<h3 id="schritt-7-datenschutz-einstellungen-prüfen-der-wichtige-teil">Schritt 7: Datenschutz-Einstellungen prüfen (der wichtige Teil)</h3>
<p>Matomo 5.12 startet datenschutzfreundlicher, als viele erwarten: Die IP-Anonymisierung ist <strong>ab Werk aktiv</strong>. 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 <strong>Verwaltung</strong> (Zahnrad) → im Menü links <strong>Privatsphäre → Daten anonymisieren</strong>.</p>
<p><figure class="my-6"><img src="/tutorials/matomo-selbst-hosten/matomo-datenschutz_hu_55903b7d60128429.webp" srcset="/tutorials/matomo-selbst-hosten/matomo-datenschutz_hu_1e894dab13857d15.webp 480w, /tutorials/matomo-selbst-hosten/matomo-datenschutz_hu_55903b7d60128429.webp 768w, /tutorials/matomo-selbst-hosten/matomo-datenschutz_hu_8a167696f93ecb96.webp 1200w, /tutorials/matomo-selbst-hosten/matomo-datenschutz_hu_b21bee2c85fdd52c.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/matomo-selbst-hosten/matomo-datenschutz_hu_2c2d5f1e8974e74c.webp"
    alt="Matomo-Seite „Daten anonymisieren&quot; mit aktivierter IP-Anonymisierung und der Auswahl der maskierten Bytes" title="Privatsphäre → Daten anonymisieren: die IP-Anonymisierung steht bereits auf zwei Bytes"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Privatsphäre → Daten anonymisieren: die IP-Anonymisierung steht bereits auf zwei Bytes</figcaption></figure></p>
<p>Drei Stellschrauben sind entscheidend:</p>
<ul>
<li><strong>Anonymisiere die IP-Adresse von Besuchern</strong>: steht schon auf <em>Ja</em>, maskiert werden standardmäßig <strong>2 byte(s)</strong> – aus <code>203.0.113.45</code> wird also <code>203.0.xxx.xxx</code> (Matomo markiert diese Stufe selbst als <em>Empfohlen</em>). Kontrolliere nur, dass das so geblieben ist; damit ist der einzelne Besucher nicht mehr identifizierbar.</li>
<li><strong>Tracking ohne Cookies erzwingen</strong>: einschalten. Matomo ergänzt dann <code>matomo.js</code> 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 <code>disableCookies</code> landet – ein Sicherheitsnetz für den Punkt, an dem dein Consent-Banner-Verzicht hängt.</li>
<li><strong>„Do Not Track&quot;</strong>: liegt unter <em>Privatsphäre → Benutzer Opt-Out</em>. Matomo stuft die Unterstützung inzwischen selbst als <strong>veraltet</strong> ein – weil Browser das Signal ungefragt senden oder gar nicht mehr unterstützen, „empfehlen wir nicht mehr, diese Option zu aktivieren&quot;. Verlass dich also nicht darauf. Der belastbare Weg steht auf derselben Seite: der <strong>Opt-out-Baustein</strong> (iframe oder eigenes Formular), den du in deine Datenschutzerklärung einbaust.</li>
</ul>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-herb-400 bg-herb-50 dark:border-herb-700 dark:bg-herb-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">🧑‍🍳</span>Tipp
  </p>
  <div class="prose-kitchen text-sm">Unter <em>Privatsphäre → Daten anonymisieren → Lösche regelmäßig alte Daten aus der Datenbank</em> kannst du Matomo anweisen, Rohdaten nach z. B. 180 Tagen automatisch zu löschen. Das reduziert Datenmenge <strong>und</strong> Datenschutz-Risiko – die aggregierten Berichte bleiben erhalten.</div>
</div>
<p>Bleibt noch der Schalter, den die Systemprüfung aus Schritt 5 angemahnt hat: <code>force_ssl</code>. 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 <code>config/config.ini.php</code> im Volume:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> /opt/matomo
</span></span><span class="line"><span class="cl">docker compose <span class="nb">exec</span> -u www-data app sed -i <span class="s1">&#39;/^\[General\]/a force_ssl = 1&#39;</span> config/config.ini.php</span></span></code></pre></div>
</div>
<p><code>sed</code> hängt die Zeile <code>force_ssl = 1</code> direkt unter den Abschnitt <code>[General]</code>; <code>-u www-data</code> sorgt dafür, dass die Datei ihrem bisherigen Besitzer gehört und Matomo sie weiter schreiben kann. Lade danach das Dashboard neu – unter <em>Verwaltung → Diagnose → Systemprüfung</em> ist die Warnung <em>Erzwungene SSL Verbindung</em> verschwunden.</p>
<h3 id="schritt-8-berichte-per-cron-archivieren">Schritt 8: Berichte per Cron archivieren</h3>
<p>In der Grundeinstellung berechnet Matomo seine Berichte „on the fly&quot;, 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.</p>
<p>Trage dazu auf dem Host einen Cronjob ein, der alle 15 Minuten das Archivierungskommando im Container ausführt:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">crontab -e</span></span></code></pre></div>
</div>
<p>Füge diese Zeile hinzu (Domain anpassen):</p>
<div class="sk-code">
  <span class="sk-code-head">Ausgabe</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">*/15 * * * * cd /opt/matomo &amp;&amp; docker compose exec -T -u www-data app ./console core:archive --url=https://statistik.DEINE-DOMAIN.de &gt;&gt; /opt/matomo/archive.log 2&gt;&amp;1</span></span></code></pre></div>
</div>
<p>Das Log landet bewusst in <code>/opt/matomo/archive.log</code> und nicht unter <code>/var/log</code>: Läuft dein Cron als sudo-Benutzer (nicht als <code>root</code>), scheitert ein Schreibzugriff auf <code>/var/log</code> still. In <code>/opt/matomo</code> hast du Schreibrechte, und du findest das Log direkt beim Projekt.</p>
<p>Anschließend schaltest du die alte Betriebsart ab: Verwaltung → <em>Allgemeine Einstellungen</em> → <em>Archivierungseinstellungen</em>, dort <strong>„Berichte archivieren, wenn diese im Browser angezeigt werden&quot;</strong> auf <strong>Nein</strong> 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.</p>
<h2 id="wenn-es-nicht-funktioniert">Wenn es nicht funktioniert</h2>
<div class="troubleshoot not-prose">
<p><strong>Der Browser zeigt einen Zertifikatsfehler oder <code>404 page not found</code>.</strong> Traefik hat das
Let&rsquo;s-Encrypt-Zertifikat noch nicht geholt, oder der DNS-Record zeigt nicht auf den Server. Prüfe
mit <code>dig statistik.DEINE-DOMAIN.de</code>, dass die IP stimmt, und sieh in die Traefik-Logs. Den genauen
Container-Namen aus deinem Traefik-Setup findest du mit <code>docker ps | grep traefik</code>, dann <code>docker logs &lt;container-name&gt;</code> (bei uns z. B. <code>docker logs traefik-traefik-1</code>). Die HTTP-Challenge
scheitert, wenn Port 80 nicht von außen erreichbar ist – kontrolliere deine
<a href="/tutorials/firewall-ufw-einrichten/">Firewall</a> und die
<a href="/tutorials/netcup-firewall-einrichten/">netcup-Firewall</a>.</p>
<p><strong>Der Installer meldet <code>SQLSTATE... Connection refused</code> oder hängt bei der Datenbank.</strong> MariaDB war
beim ersten Start noch nicht bereit. Gib der DB einen Moment und lade die Seite neu. Prüfe mit
<code>docker compose logs db</code>, ob dort <code>ready for connections</code> steht. Erscheint stattdessen ein
Zugangsfehler, passen <code>DB_PASSWORD</code> in der <code>.env</code> und die bereits angelegte DB nicht mehr zusammen –
dann hilft ein sauberer Neustart mit <code>docker compose down -v</code> (Achtung: löscht die Daten) und
<code>docker compose up -d</code>.</p>
<p><strong>Warnung „Es sieht so aus, als ob die <code>trusted_hosts</code>-Einstellung nicht korrekt ist&quot;.</strong> 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 <code>config/config.ini.php</code> ein.</p>
<p><strong>Im Dashboard tauchen keine Besuche auf.</strong> 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 <code>matomo.php</code>
rausgeht. In Matomo hilft <em>Verwaltung → Diagnose → Tracking Fehlschläge</em>.</p>
<p><strong>Das Dashboard lädt sehr langsam.</strong> Die On-the-fly-Archivierung rechnet bei jedem Aufruf. Richte
den Archivierungs-Cron aus Schritt 8 ein und stelle die Berichterstellung auf Cron um.</p>

</div>

<h2 id="wartung--backups">Wartung &amp; Backups</h2>
<p><strong>Updates</strong> sind bei Matomo unkritisch, aber regelmäßig fällig – etwa monatlich erscheint eine neue Version. Weil wir den Image-Tag auf <code>5.12</code> gepinnt haben, ziehst du Sicherheits-Patches innerhalb der 5.12-Reihe so:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">cd</span> /opt/matomo <span class="o">&amp;&amp;</span> docker compose pull <span class="o">&amp;&amp;</span> docker compose up -d</span></span></code></pre></div>
</div>
<p>Beim ersten Aufruf nach einem Update prüft Matomo, ob ein <strong>Datenbank-Upgrade</strong> nötig ist, und führt es nach einem Klick aus.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-amber-400 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">⚠️</span>Vor einem Major-Upgrade: Backup und Release-Notes
  </p>
  <div class="prose-kitchen text-sm">Für einen Sprung auf eine neue Hauptversion (z. B. 5.12 → 6.x) hebst du den Tag in der <code>compose.yaml</code> 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 <strong>unbedingt ein Backup</strong> (siehe unten), bevor du das neue Image startest.</div>
</div>
<p><strong>Backups</strong> umfassen zwei Dinge: die Datenbank (alle Besuchsdaten) und das <code>app</code>-Volume (deine Konfiguration in <code>config/config.ini.php</code>). Erstelle regelmäßig einen Datenbank-Dump …</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose <span class="nb">exec</span> -T db sh -c <span class="s1">&#39;exec mariadb-dump -u matomo -p&#34;$MARIADB_PASSWORD&#34; matomo&#39;</span> &gt; /opt/matomo/dump.sql</span></span></code></pre></div>
</div>
<p>… und nimm diesen Dump zusammen mit dem Ordner <code>/opt/matomo</code> in deine <a href="/tutorials/backups-mit-restic/">Restic-Off-Site-Backups</a> auf. Ein netcup-Snapshot des ganzen Servers ist eine gute Ergänzung, aber <a href="/tutorials/netcup-snapshots-scp/">kein Ersatz für ein echtes Off-Site-Backup</a> – liegt beides beim selben Anbieter, sind bei einem Totalausfall auch beide weg.</p>
<p><strong>Laufender Betrieb:</strong> 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 <a href="/tutorials/uptime-kuma-monitoring/">Uptime-Kuma-Monitoring</a> auf – ein einfacher HTTP-Check auf deine Statistik-Domain genügt.</p>
<p>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.</p>
]]></content:encoded></item></channel></rss>