
Matomo Docker Compose: alternativa la Google Analytics
Google Analytics e gratuit pentru ca platesti cu altceva: datele vizitatorilor tai, un banner de cookie-uri pe care majoritatea il inchid enervati si rapoarte pe care le vezi doar prin ochii altcuiva. Daca ai site-ul unei firme mici, un blog sau pagina de prezentare a unui SaaS, exista o varianta mai curata. Matomo este o platforma open source de web analytics pe care o instalezi pe propriul server, deci fiecare afisare de pagina ramane pe hardware pe care il controlezi, intr-un data center pe care il poti numi. In acest tutorial il instalam cu Docker Compose pe un VPS proaspat, il punem in spatele unui HTTPS automat, adaugam pe site un cod de tracking fara cookie-uri si configuram arhivarea in fundal care tine rapoartele rapide.
Matomo (fostul Piwik) se gaseste pe matomo.org , cu codul sursa pe github.com/matomo-org/matomo , sub licenta GPLv3. Varianta self-hosted e gratuita, cu pluginuri optionale platite pentru lucruri ca heatmaps sau teste A/B. Tot ce folosim mai jos face parte din nucleul gratuit.
Ce este Matomo si de ce l-ai gazdui singur
Matomo functioneaza ca majoritatea instrumentelor de analytics. Un fisier JavaScript mic (matomo.js) ruleaza in browserul vizitatorului si trimite o cerere HTTP minuscula catre serverul tau Matomo (matomo.php) la fiecare afisare de pagina, click pe un link extern sau download. Matomo salveaza aceste “hit-uri” brute intr-o baza de date. Periodic, un proces numit arhivare transforma datele brute in rapoarte: vizite pe zi, pagini populare, surse de trafic, tari, dispozitive si asa mai departe. Dashboard-ul citeste rapoartele deja calculate, de aceea ramane rapid chiar si cu milioane de hit-uri.
De ce sa te complici cu gazduirea proprie in loc de Google Analytics?
- Datele sunt ale tale. Nu pleaca de pe server, nimeni nu le foloseste pentru reclame si tu decizi cat timp le pastrezi.
- Fara esantionare. Fiecare vizita conteaza, rapoartele nu sunt estimate dintr-un subset.
- GDPR devine mult mai simplu. Cu tracking fara cookie-uri si IP-uri anonimizate, multe site-uri pot rula analytics fara banner de consimtamant (detalii si limite la pasul 9).
- Se incarca repede. Tracker-ul e un singur script mic, servit de pe domeniul tau.
Cativa termeni inainte sa incepem
Daca unele notiuni sunt noi, iata versiunea scurta:
- Container: un pachet izolat care contine o aplicatie plus tot ce ii trebuie ca sa ruleze (biblioteci, runtime). Foloseste kernelul Linux al serverului, deci e mult mai usor decat o masina virtuala.
- Docker Compose: un instrument care porneste mai multe containere impreuna, dintr-un singur fisier YAML (
compose.yaml), inclusiv retelele si stocarea lor. - Volum: un folder care supravietuieste cand containerul e recreat. Fara volume, baza de date ar disparea la fiecare update.
- Port: o “usa” numerotata a serverului. Traficul web foloseste portul 80 (HTTP) si 443 (HTTPS), SSH foloseste portul 22.
- Reverse proxy: un server web pus in fata aplicatiei, care se ocupa de HTTPS si trimite cererile mai departe catre aplicatie. Folosim Caddy, care obtine si reinnoieste automat certificate gratuite Let’s Encrypt.
- Cron: planificatorul din Linux care ruleaza comenzi la ore fixe. Il folosim ca sa pornim arhivarea Matomo in fiecare ora.
Cum se leaga piesele intre ele
Stack-ul nostru are trei containere: Caddy (HTTPS), Matomo (aplicatia cu Apache si PHP) si MariaDB (baza de date). Doar Caddy publica porturi catre internet. Matomo si MariaDB comunica printr-o retea Docker privata si nu pot fi accesate din exterior.
Un detaliu din diagrama conteaza mult pentru securitate: Docker isi scrie propriile reguli de firewall si ocoleste ufw pentru orice port pe care il publica. De aceea nu publicam niciodata baza de date sau portul intern al lui Matomo si de aceea ufw apare doar in fata SSH. Daca un container nu are sectiunea ports:, nimic din internet nu il poate atinge, indiferent ce reguli are ufw.
De ce ai nevoie
- Un VPS DreamServer cu Debian 13 sau Ubuntu 24.04, ideal KVM, cu minimum 2 GB RAM, 2 vCPU si 20 GB de disc.
- Un utilizator cu sudo si acces SSH la server.
- Un domeniu sau subdomeniu pe care il controlezi, de exemplu
analytics.example.com. Il folosim in toate exemplele, inlocuieste-l peste tot cu al tau. - Porturile 80 si 443 libere pe VPS (fara alt server web, ca Apache sau nginx, instalat direct pe host).
- Cam 45 de minute.
O nota pentru cei pe LXC: Docker intr-un container LXC neprivilegiat functioneaza doar daca are activata optiunea de nesting, iar ufw de multe ori nu isi poate incarca modulele de kernel in LXC. Daca ai un VPS LXC si ceva din pasii 1 sau 2 nu merge, cere suportului nostru activarea nesting-ului sau foloseste un VPS KVM, unde totul de mai jos functioneaza exact cum e scris.
Cat de mare trebuie sa fie VPS-ul?
Matomo in sine e modest. Momentul greu e arhivarea, cand PHP citeste hit-urile brute din MariaDB si construieste rapoartele. Pentru un site mic, cu cateva mii de afisari pe zi, cifrele arata aproximativ asa:
Ca regula orientativa, recomandarile Matomo pun site-urile sub aproximativ 100.000 de afisari pe luna pe un singur server cu 2 CPU si 2 GB RAM. Un trafic mult mai mare cere in principal mai multa memorie pentru MariaDB si mai mult disc pentru datele brute, iar ambele se pot mari usor mai tarziu.
Procedura pe scurt
Iata toata treaba in noua pasi. Fiecare titlu numerotat de mai jos corespunde unei casete din diagrama.
Pasul 1: DNS si firewall
Caddy poate obtine certificatul doar daca subdomeniul de analytics indica deja spre VPS. In panoul furnizorului de DNS, creeaza o inregistrare A pentru analytics.example.com cu adresa IPv4 a VPS-ului. Daca VPS-ul are IPv6, adauga si o inregistrare AAAA, dar numai cu adresa corecta: o inregistrare AAAA gresita e cel mai des motiv pentru care validarea Let’s Encrypt esueaza.
Verifica daca numele se rezolva (poate dura cateva minute dupa ce creezi inregistrarea):
getent hosts analytics.example.com
Ar trebui sa vezi adresa IP a VPS-ului langa nume. Daca nu apare nimic, mai asteapta putin si incearca din nou.
Acum firewall-ul de pe host. Permitem SSH primul, ca activarea firewall-ului sa nu te blocheze afara. Daca SSH-ul tau ruleaza pe alt port, foloseste acel numar in loc de 22.
sudo apt update
sudo apt install -y ufw
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443
sudo ufw enable
sudo ufw status verbose
ufw allow 443 fara protocol deschide si TCP, si UDP, partea UDP fiind pentru HTTP/3. Ultima comanda ar trebui sa listeze cele trei reguli cu ALLOW IN. Tehnic vorbind, regulile pentru 80 si 443 nu sunt cele care lasa traficul sa ajunga la Caddy (de asta se ocupa Docker, cum am explicat mai sus), dar documenteaza intentia si pastreaza lucrurile coerente daca vreodata rulezi un server web direct pe host.
Pasul 2: Instalam Docker Engine si pluginul Compose
Incepem cu un sistem complet actualizat:
sudo apt update && sudo apt full-upgrade -y
Daca s-a instalat un kernel nou, reporneste serverul inainte sa continui. Pe Ubuntu, fisierul /var/run/reboot-required apare cand e nevoie de restart (ls /var/run/reboot-required). Pe Debian, fisierul nu este creat intotdeauna, asa ca reporneste pur si simplu daca update-ul a instalat un pachet linux-image nou.
Instalam Docker din repository-ul oficial Docker, nu din pachetele distributiei, pentru ca acolo gasim Engine-ul actual si pluginul docker compose. Blocul de mai jos merge si pe Debian, si pe Ubuntu: citeste numele si codename-ul distributiei din /etc/os-release, apoi scrie repository-ul in formatul deb822 folosit acum de Docker.
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
. /etc/os-release
sudo curl -fsSL "https://download.docker.com/linux/${ID}/gpg" -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources > /dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/${ID}
Suites: ${VERSION_CODENAME}
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Verificam instalarea:
sudo docker run --rm hello-world
sudo docker compose version
Prima comanda afiseaza mesajul “Hello from Docker!”, a doua versiunea Compose (v2.x sau mai noua). In ghidul asta folosim sudo in fata comenzilor Docker. Ai putea adauga utilizatorul in grupul docker, dar tine minte ca apartenenta la acest grup inseamna practic acces de root.
Pasul 3: Folderul proiectului si parolele
Tot ce tine de acest stack sta in /opt/matomo: fisierul Compose, configuratia Caddy, un fisier cu secrete si fisierele Matomo.
sudo mkdir -p /opt/matomo
cd /opt/matomo
sudo sh -c 'umask 077; cat > /opt/matomo/.env <<EOF
MARIADB_ROOT_PASSWORD=$(openssl rand -hex 24)
MATOMO_DB_PASSWORD=$(openssl rand -hex 24)
EOF'
sudo ls -l /opt/matomo/.env
Comanda genereaza doua parole aleatoare de 48 de caractere, una pentru contul root din MariaDB si una pentru utilizatorul matomo, si le salveaza in .env. Docker Compose citeste automat acest fisier si inlocuieste valorile in compose.yaml. Folosim intentionat parole hexazecimale: fara ghilimele, semne de dolar sau alte caractere care ar putea strica YAML-ul sau fisierul de configurare Matomo. umask 077 face fisierul lizibil doar pentru root, iar ls -l ar trebui sa arate -rw-------.
Important: MariaDB citeste aceste parole doar la prima pornire, cu volumul de date gol. Daca modifici .env mai tarziu, parola din baza de date nu se schimba. Lasa fisierul asa cum e si fa-i backup.
Pasul 4: Scriem compose.yaml si Caddyfile
Cream fisierul Compose:
sudo nano /opt/matomo/compose.yaml
Lipeste acest continut:
services:
db:
image: mariadb:11.8
restart: unless-stopped
command: --max-allowed-packet=64MB
environment:
MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
MARIADB_DATABASE: matomo
MARIADB_USER: matomo
MARIADB_PASSWORD: ${MATOMO_DB_PASSWORD}
MARIADB_AUTO_UPGRADE: "1"
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
matomo:
image: matomo:5-apache
restart: unless-stopped
depends_on:
db:
condition: service_healthy
environment:
MATOMO_DATABASE_HOST: db
MATOMO_DATABASE_ADAPTER: mysql
MATOMO_DATABASE_TABLES_PREFIX: matomo_
MATOMO_DATABASE_USERNAME: matomo
MATOMO_DATABASE_PASSWORD: ${MATOMO_DB_PASSWORD}
MATOMO_DATABASE_DBNAME: matomo
volumes:
- ./matomo:/var/www/html
caddy:
image: caddy:2-alpine
restart: unless-stopped
depends_on:
- matomo
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
volumes:
db_data:
caddy_data:
caddy_config:
Ce face fiecare parte:
- db ruleaza MariaDB. Imaginea creeaza baza de date
matomosi utilizatorul la prima pornire.--max-allowed-packet=64MBe valoarea recomandata de Matomo pentru inserari masive.MARIADB_AUTO_UPGRADEactualizeaza automat tabelele de sistem cand tragi o versiune de patch 11.8 mai noua. Healthcheck-ul ii permite lui Compose sa astepte pana cand baza de date accepta efectiv conexiuni. - matomo ruleaza imaginea oficiala Matomo cu Apache si PHP. Variabilele
MATOMO_DATABASE_*precompleteaza ecranul de baza de date din installer-ul web. Montarea./matomopastreaza codul, configuratia si pluginurile Matomo in/opt/matomo/matomo, unde le poti edita si salva usor. Nu are sectiuneports:, deci doar Caddy ajunge la el. - caddy e singurul container cu porturi publicate. Volumele lui pastreaza certificatele TLS intre reporniri.
Despre tag-urile imaginilor: matomo:5-apache urmeaza linia majora actuala Matomo 5, mariadb:11.8 este seria actuala cu suport pe termen lung, iar caddy:2-alpine versiunea majora curenta de Caddy. Evitam :latest, care ar putea sari pe neasteptate la o versiune majora noua. Inainte de instalare, verifica changelog-ul Matomo
, notele de release MariaDB si paginile cu tag-uri ale imaginilor, poate exista ceva mai nou.
Acum configuratia Caddy:
sudo nano /opt/matomo/Caddyfile
{
email tu@domeniul-tau.ro
}
analytics.example.com {
encode zstd gzip
@private path /config/* /tmp/* /core/* /lang/*
respond @private 403
reverse_proxy matomo:80
}
Inlocuieste adresa de email (Let’s Encrypt o foloseste pentru avertismente de expirare, iar domeniile de exemplu precum example.com sunt respinse) si domeniul. Blocul @private refuza accesul direct la folderele interne Matomo, la fel ca regulile recomandate chiar de Matomo pentru configuratiile nginx. reverse_proxy matomo:80 trimite restul cererilor catre containerul Matomo, folosind numele serviciului ca hostname. Caddy adauga si header-ele X-Forwarded-For si X-Forwarded-Proto, in care ii vom spune lui Matomo sa aiba incredere la pasul 6.
Verificam fisierul Compose de greseli:
cd /opt/matomo
sudo docker compose config --quiet
Daca nu apare nimic, fisierul e valid.
Pasul 5: Pornim stack-ul si rulam installer-ul Matomo
cd /opt/matomo
sudo docker compose up -d
sudo docker compose ps
La prima pornire se descarca imaginile, asa ca da-i un minut. docker compose ps ar trebui sa arate trei servicii cu statusul Up, iar serviciul db ar trebui sa apara (healthy). Verificam daca Caddy a obtinut certificatul:
sudo docker compose logs caddy | grep -i "certificate obtained"
Ar trebui sa vezi o linie care contine certificate obtained successfully. Daca nu, sari la sectiunea de depanare.
Deschide https://analytics.example.com in browser imediat. Pana termini installer-ul, oricine gaseste URL-ul il poate completa si devine administrator, deci nu-l lasa la jumatate. Installer-ul te poarta prin aceste ecrane:
- Welcome, apoi System Check: tot ce e important ar trebui sa fie verde. Avertismentele despre functii optionale sunt in regula.
- Database Setup: datorita variabilelor de mediu, campurile sunt deja completate (server
db, loginmatomo, baza de datematomo, prefixmatomo_, adaptor PDO\MYSQL). Doar confirmi. - Crearea tabelelor: dureaza cateva secunde.
- Superuser: alegi un nume de utilizator, o parola puternica si emailul tau. Acesta e contul de admin.
- Set up a website: introduci numele si adresa primului site pe care vrei sa-l urmaresti, plus fusul orar.
- Tracking code: arata snippet-ul JavaScript. Il poti sari deocamdata, adaugam o versiune imbunatatita la pasul 7.
- Congratulations: decizi daca activezi suportul pentru Do Not Track, apoi intri in dashboard.
Pasul 6: Matomo trebuie sa aiba incredere in reverse proxy
Din punctul de vedere al lui Matomo, toate cererile vin acum de la Caddy, prin HTTP simplu, de la un IP intern Docker de tipul 172.18.0.4. Fara modificarea urmatoare, toti vizitatorii ar avea aceeasi adresa IP, iar Matomo ar putea genera link-uri http://. Rezolvam asta in fisierul de configurare Matomo, care se afla in folderul montat:
sudo nano /opt/matomo/matomo/config/config.ini.php
Gaseste sectiunea [General] existenta (nu crea una noua) si adauga sub ea aceste linii:
assume_secure_protocol = 1
force_ssl = 1
proxy_client_headers[] = HTTP_X_FORWARDED_FOR
proxy_host_headers[] = HTTP_X_FORWARDED_HOST
assume_secure_protocolii spune lui Matomo ca utilizatorii vad de fapt HTTPS, chiar daca Caddy vorbeste cu el prin HTTP.force_sslface ca Matomo sa construiasca mereu URL-uri HTTPS.proxy_client_headers[]il face sa citeasca IP-ul real al vizitatorului din header-ul setat de Caddy.proxy_host_headers[]face acelasi lucru pentru numele de host.
Daca installer-ul a scris deja unele dintre aceste linii, nu le dubla. Increderea in X-Forwarded-For e sigura aici, pentru ca Matomo e accesibil doar prin Caddy, iar Caddy inlocuieste orice valoare falsificata trimisa de un client. Salveaza, apoi reporneste containerul ca sa fii sigur ca modificarea e preluata:
cd /opt/matomo
sudo docker compose restart matomo
Pasul 7: Adaugam pe site codul de tracking fara cookie-uri
In Matomo, deschide Administration (iconita roata) > Websites > Manage ca sa adaugi alte site-uri; fiecare primeste un site ID numeric. Primul site creat in installer are ID 1. Iata snippet-ul standard Matomo cu o singura linie in plus, disableCookies, care face tracking-ul fara cookie-uri:
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.example.com/";
_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 -->
Pune-l chiar inainte de tag-ul </head> pe fiecare pagina, sau in setarea de “header scripts” a CMS-ului ori in sablonul temei. Schimba URL-ul si site ID-ul cu ale tale. Scriptul se incarca asincron, deci nu incetineste pagina.
Ce schimba disableCookies: Matomo nu mai seteaza cookie-urile _pk_id si _pk_ses. Vizitele sunt numarate in continuare, iar in cadrul aceleiasi vizite paginile sunt grupate printr-un hash de scurta durata calculat pe server. Compromisul e ca un vizitator care revine in alta zi e de obicei numarat ca vizitator nou, deci “vizitatori care revin” si “vizitatori unici” devin aproximari. Pentru majoritatea site-urilor mici e o afacere foarte buna in schimbul faptului ca nu salvezi nimic in browserul vizitatorului.
Daca site-ul tau e o aplicatie single-page (React, Vue si altele similare), snippet-ul urmareste doar prima incarcare. La fiecare schimbare de ruta, trimite ['setCustomUrl', urlNou] si apoi din nou ['trackPageView'].
Ca sa verifici: deschide site-ul intr-o fereastra privata, apoi in Matomo mergi la Visitors > Real-time. Vizita ta ar trebui sa apara in cateva secunde, cu IP-ul tau public real, nu cu o adresa Docker 172.x.x.x. Daca folosesti un ad blocker, dezactiveaza-l pentru test, unele liste blocheaza matomo.js.
Pasul 8: Configuram arhivarea prin cron
Implicit, Matomo construieste rapoartele cand cineva deschide dashboard-ul (“arhivare declansata din browser”). Pe un site cu trafic real, asta face dashboard-ul lent si poate da timeout pe intervale lungi. Solutia e sa construim rapoartele in fundal, la fiecare ora, iar dashboard-ul doar sa le citeasca.
Mai intai, ne asiguram ca cron e instalat si pornit. Ubuntu Server il are implicit, iar imaginile minimale de Debian uneori nu. Serviciul se numeste cron pe ambele:
sudo apt install -y cron
sudo systemctl enable --now cron
Rulam arhivarea o data manual, ca sa vedem ca merge:
cd /opt/matomo
sudo docker compose exec -T --user www-data matomo php /var/www/html/console core:archive --url=https://analytics.example.com/
--user www-data ruleaza comanda cu acelasi utilizator ca serverul web, ca fisierele de cache sa aiba proprietarul corect. -T dezactiveaza terminalul interactiv, pe care cron nu il are. Ar trebui sa vezi linii de log pentru fiecare site si perioada, apoi un sumar si un mesaj ca arhivarea s-a terminat.
Acum o programam la fiecare ora, la minutul 5:
sudo tee /etc/cron.d/matomo-archive > /dev/null <<'EOF'
# Matomo: construieste rapoartele in fiecare ora, la minutul 5
5 * * * * root /usr/bin/docker compose -f /opt/matomo/compose.yaml exec -T --user www-data matomo php /var/www/html/console core:archive --url=https://analytics.example.com/ > /var/log/matomo-archive.log 2>&1
EOF
Fisierele din /etc/cron.d au o coloana in plus pentru utilizator (aici root, necesar pentru Docker). Rezultatul ultimei rulari ajunge in /var/log/matomo-archive.log, suprascris de fiecare data, deci fisierul nu creste. Dupa urmatoarea ora fixa, verifica-l cu sudo cat /var/log/matomo-archive.log.
La final, opreste arhivarea din browser in Matomo: Administration > System > General settings, la setarile de arhivare pune Archive reports when viewed from the browser pe No si Archive reports at most every X seconds pe 3600. Salveaza. De acum, dashboard-urile se incarca aproape instant, iar cifrele de azi se actualizeaza o data pe ora (Real-time si Visits Log raman mereu live).
Pasul 9: Setarile de confidentialitate pentru GDPR
Tracking-ul fara cookie-uri e jumatate din poveste. Cealalta jumatate se afla in Administration > Privacy:
- Anonymize data: pune Anonymize Visitors’ IP addresses pe Yes, mascheaza 2 bytes (de exemplu
192.168.xxx.xxx) si pune Also use the anonymized IP addresses when enriching visits pe Yes. Astfel Matomo nu salveaza niciodata IP-ul complet, iar detectia tarii foloseste varianta mascata. - Replace User ID with a pseudonym, daca vei folosi vreodata functia User ID.
- Regularly delete old raw data: activeaz-o si alege o perioada, de exemplu 180 de zile. Se sterg jurnalele detaliate de vizite, iar rapoartele agregate raman, cu conditia ca arhivarea (pasul 8) sa fi procesat deja datele, lucru care se intampla in fiecare ora.
- Users opt-out: Matomo genereaza un snippet de opt-out pe care il poti pune in pagina de politica de confidentialitate, ca vizitatorii sa refuze urmarirea cu un click.
- GDPR Tools: iti permite sa gasesti, sa exporti sau sa stergi toate datele despre un anumit vizitator, daca cineva isi exercita drepturile.
In functie de versiunea Matomo, pagina de anonimizare poate oferi si un comutator care forteaza tracking-ul fara cookie-uri pentru toate site-urile. Daca il vezi, activeaza-l ca plasa de siguranta, pentru cazul in care cineva foloseste snippet-ul implicit fara disableCookies.
Pe partea juridica: in mai multe tari din UE, autoritatile accepta ca masurarea audientei fara cookie-uri, cu IP-uri anonimizate, folosita doar pentru statisticile tale si neimpartita cu terti, poate rula fara consimtamant. Regulile difera de la o tara la alta si asta nu e consultanta juridica, asa ca mentioneaza Matomo in politica de confidentialitate si verifica cu cine se ocupa de conformitate la tine.
Optional, in Administration > System > Geolocation poti instala o baza de date DB-IP gratuita, pentru detectia tarii si a orasului mai precisa decat ghicitul implicit dupa limba browserului.
Cum tii Matomo la zi
Sunt doua straturi de actualizat. Imaginile (Caddy, MariaDB, PHP si Apache din imaginea Matomo) se actualizeaza asa:
cd /opt/matomo
sudo docker compose pull
sudo docker compose up -d
sudo docker image prune -f
Aplicatia Matomo e alta poveste. In imaginea oficiala, fisierele PHP ale lui Matomo sunt copiate in ./matomo la prima pornire a containerului. Dupa aceea ele traiesc in folderul tau, deci o imagine noua nu le modifica. Cand apare o versiune noua de Matomo, interfata de admin afiseaza o notificare: fa un backup (sectiunea urmatoare), apoi foloseste actualizarea cu un click. Daca actualizarea bazei de date e mare, termin-o din linia de comanda in loc de browser:
cd /opt/matomo
sudo docker compose exec --user www-data matomo php /var/www/html/console core:update --yes
Backup si restaurare Matomo
Conteaza doua lucruri: baza de date si folderul /opt/matomo (secrete, fisierul Compose, Caddyfile si configuratia Matomo). Comanda de mai jos face dump-ul bazei de date prin container, trimitand parola prin variabila MYSQL_PWD in loc de linia de comanda, si il comprima in folderul tau home:
cd /opt/matomo
sudo docker compose exec -T db sh -c 'MYSQL_PWD="$MARIADB_PASSWORD" mariadb-dump --single-transaction --quick -u matomo matomo' | gzip > ~/matomo-db-$(date +%F).sql.gz
sudo tar czf ~/matomo-files-$(date +%F).tar.gz -C /opt/matomo .env compose.yaml Caddyfile matomo
sudo chown "$USER": ~/matomo-files-$(date +%F).tar.gz
chown conteaza: o arhiva creata cu sudo tar apartine lui root si nu ai putea s-o descarci cu scp ca utilizator normal. Copiaza ambele fisiere in afara serverului, de exemplu pe laptop sau pe un spatiu de backup. Un backup care sta doar pe acelasi VPS nu e un backup.
Pentru restaurare, importa intotdeauna intr-o baza de date goala, niciodata peste cea activa. Opreste intai Matomo, ca cererile de tracking sa nu ajunga intr-o baza restaurata pe jumatate, si comenteaza linia din cron cat lucrezi:
cd /opt/matomo
sudo docker compose stop matomo
sudo docker compose exec -T db sh -c 'MYSQL_PWD="$MARIADB_ROOT_PASSWORD" mariadb -u root -e "DROP DATABASE IF EXISTS matomo; CREATE DATABASE matomo;"'
gunzip -c ~/matomo-db-2026-11-10.sql.gz | sudo docker compose exec -T db sh -c 'MYSQL_PWD="$MARIADB_PASSWORD" mariadb -u matomo matomo'
sudo docker compose start matomo
Inlocuieste numele fisierului cu data backup-ului tau. Utilizatorul matomo isi pastreaza drepturile pe baza de date recreata. Cand muti totul pe un server nou, dezarhiveaza fisierele in /opt/matomo, porneste doar serviciul db (creeaza o baza noua si goala pe baza .env), importa dump-ul, apoi porneste tot.
Depanare: greseli frecvente
Caddy nu obtine certificatul. Verifica daca getent hosts analytics.example.com intoarce IP-ul VPS-ului, daca nu ai o inregistrare AAAA gresita si daca nimic altceva nu foloseste porturile 80 sau 443: sudo ss -tlnp | grep -E ':(80|443) '. Daca Apache sau nginx e instalat pe host, opreste-l si dezactiveaza-l. Apoi ruleaza sudo docker compose restart caddy si citeste sudo docker compose logs caddy.
Installer-ul nu se poate conecta la baza de date. Ruleaza sudo docker compose ps si asteapta pana db arata (healthy). Daca ai editat .env dupa prima pornire, parolele nu mai corespund: MariaDB le citeste doar la primul start. La o instalare complet noua, fara date, cea mai simpla solutie e sudo docker compose down -v (sterge volumul bazei de date) urmat de sudo docker compose up -d.
Toate vizitele au acelasi IP 172.x.x.x. Setarile de proxy de la pasul 6 lipsesc sau sunt in sectiunea gresita. Trebuie sa fie sub [General] in config.ini.php.
Bucla de redirectionari sau “too many redirects”. Ai pus force_ssl = 1 fara assume_secure_protocol = 1. Adauga-le pe amandoua.
Avertismentul “untrusted host”. Ai deschis Matomo sub alt nume decat cel folosit la instalare. Adauga numele ca linie separata trusted_hosts[] = "nume" in [General].
Rapoartele sunt goale, dar Real-time arata vizite. Arhivarea nu ruleaza. Citeste /var/log/matomo-archive.log, verifica systemctl status cron si ruleaza comanda manuala de la pasul 8.
Erori de permisiuni in tmp/. Cineva a rulat consola ca root. Repara proprietarul cu sudo docker compose exec matomo chown -R www-data:www-data /var/www/html/tmp si foloseste mereu --user www-data.
Mai putine vizite decat te asteptai. Unii vizitatori folosesc ad blockere care blocheaza scriptul Matomo. E normal pentru orice instrument de analytics, nu alerga dupa o precizie de 100%.
Note de securitate
- Termina installer-ul imediat dupa prima pornire. Un installer neterminat poate fi revendicat de oricine.
- Activeaza autentificarea in doi pasi pentru contul de admin: click pe numele tau > Security > Two-factor authentication. Foloseste parole puternice pentru toti utilizatorii Matomo si da-le celorlalti doar drept de “view”.
- Publica doar porturile lui Caddy. MariaDB si Matomo nu au sectiune
ports:si, pentru ca porturile publicate de Docker ocolesc ufw, pastreaza lucrurile asa. - Protejeaza
.env(mod 600) si backup-urile: contin parolele bazei de date, iar baza contine datele vizitatorilor. - Tine totul actualizat: host-ul cu
apt, imaginile cudocker compose pull, iar Matomo cu updater-ul lui. Ia in calculunattended-upgradespentru patch-urile de securitate ale host-ului. - Securizeaza SSH: autentificare cu chei, fara login de root cu parola. ufw protejeaza SSH, nu porturile Docker.
- Daca dashboard-ul e folosit de putini oameni, poti restrictiona interfata de admin la IP-uri cunoscute in Caddyfile, dar lasa
matomo.jssimatomo.phppublice, altfel tracking-ul se opreste.
Deci, merita Matomo self-hosted?
Daca vrei analytics care respecta vizitatorii, pastreaza datele in infrastructura ta si nu depinde de termenii unei terte parti, Matomo cu Docker Compose e una dintre cele mai practice variante: trei containere, HTTPS automat, tracking fara cookie-uri si arhivare orara care tine rapoartele rapide. Odata instalat, are nevoie mai ales de cate un update si de backup-uri regulate.
Poti rula tot acest stack pe un VPS in data center-ul nostru din Romania, cu datele ramase in UE. Daca preferi sa nu te ocupi singur de update-uri, backup-uri si optimizari, echipa noastra de administrare servere poate instala, securiza si intretine Matomo pentru tine.
Intrebari frecvente
Matomo chiar e gratuit?
Da. Varianta self-hosted, Matomo On-Premise, e gratuita si open source sub GPLv3, fara limite de site-uri sau afisari. Unele functii avansate, ca heatmaps, inregistrari de sesiuni sau teste A/B, sunt pluginuri platite, dar tot ce e in acest tutorial face parte din nucleul gratuit.
Mai am nevoie de banner de cookie-uri cu Matomo fara cookie-uri?
De multe ori nu, pentru analytics in sine, dar depinde de tara si de ce altceva incarca site-ul. Tracking-ul fara cookie-uri, cu IP-uri anonimizate, folosit doar pentru statisticile proprii, e acceptat fara consimtamant de mai multe autoritati din UE. Alte instrumente de pe site (video-uri incorporate, scripturi de reclame, widget-uri de chat) pot cere in continuare consimtamant. Verifica cu consultantul tau juridic.
Pot importa datele vechi din Google Analytics?
Da. Matomo ofera in marketplace pluginul gratuit Google Analytics Importer, care aduce rapoartele istorice din proprietatea GA in Matomo. Pe proprietati mari importul poate dura mult, asa ca porneste-l din timp.
O singura instanta Matomo poate urmari mai multe site-uri?
Da. Adauga fiecare site in Administration > Websites > Manage. Fiecare primeste propriul site ID, pe care il pui in snippet-ul site-ului respectiv. Un VPS mic poate duce fara probleme multe site-uri cu trafic redus.
De ce MariaDB si nu SQLite sau PostgreSQL?
Matomo suporta oficial doar MySQL si MariaDB. MariaDB e complet open source, bine testat cu Matomo si are o imagine Docker oficiala cu healthcheck integrat, ceea ce il face alegerea fireasca pentru acest stack.