If you want web analytics without handing visitor data to a third party, Matomo is the most established self-hosted option. You own the data, you control retention, and you can run it cookieless for GDPR-friendly tracking. The deployment is a classic PHP app backed by MySQL/MariaDB — with one important operational detail: the archiving cron.
This guide deploys Matomo with a managed database and gets the archiving job right.
Architecture
- Matomo app — PHP web app (the official
matomoimage bundles PHP + Apache). - Managed MySQL — stores all tracking data.
- Archiving cron — pre-aggregates report data so dashboards load fast.
Step 1: Provision managed MySQL
Matomo supports MySQL 5.7+ and 8.x (and MariaDB). On [PandaStack](https://dashboard.pandastack.io), create a managed MySQL database. Matomo's data volume grows with traffic, so size storage with headroom and use a tier with enough connections.
The connection details map to Matomo's setup:
MATOMO_DATABASE_HOST=<managed-host>
MATOMO_DATABASE_USERNAME=<user>
MATOMO_DATABASE_PASSWORD=<password>
MATOMO_DATABASE_DBNAME=matomo
MATOMO_DATABASE_ADAPTER=mysqlStep 2: Deploy the Matomo container
Use the official image. A minimal Dockerfile that pins a version:
FROM matomo:5-apache
# Image serves Matomo on port 80 via Apache- 1Push the repo (or reference the
matomo:5-apacheimage) to GitHub. - 2Create a container app on PandaStack.
- 3Set the
MATOMO_DATABASE_*env vars (password as a secret). - 4Expose port
80. - 5Attach a persistent volume at
/var/www/htmlso Matomo's config, plugins, and theconfig/config.ini.phpwritten during setup survive restarts. - 6Add a custom domain — SSL is automatic.
Step 3: Run the web installer
Visit your domain and Matomo's installer walks you through:
- 1System check.
- 2Database connection (use the managed MySQL details — the installer will create tables).
- 3Super-user account.
- 4Your first website to track.
After setup, Matomo writes config/config.ini.php to the persistent volume. This is why the volume mount matters — lose it and you lose your configuration.
Step 4: Set up the archiving cron — the key step
By default, Matomo computes reports on-the-fly when you open the dashboard. That's fine for a tiny site but becomes painfully slow as traffic grows, and it's a common reason people think "Matomo is slow." The fix is to disable browser-triggered archiving and run archiving on a schedule.
In Matomo's admin under *System > General settings*, turn off "archive reports when viewed from the browser" and set the archiving to be triggered by cron only.
Then create a cronjob that runs the archiver. PandaStack cronjobs run a one-off container on a schedule — point it at the Matomo console:
# Run hourly
php /var/www/html/console core:archive --url=https://analytics.example.comA reasonable schedule is hourly. The archiver pre-computes report data so dashboards load instantly regardless of traffic volume.
| Setting | Recommendation |
|---|---|
| Browser-triggered archiving | Disabled |
| Cron archiving frequency | Hourly (0 * * * *) |
| Console command | core:archive --url= |
Step 5: Add tracking to your site
Matomo gives you a JavaScript snippet (or you can use the server-side tracking API). The standard snippet:
<script>
var _paq = window._paq = window._paq || [];
_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>For privacy-first tracking, enable cookieless mode and IP anonymization in the admin.
Step 6: Privacy and compliance settings
Matomo's appeal is compliance, so configure it:
- Anonymize IPs (mask the last 1–2 bytes).
- Respect Do Not Track if you choose.
- Cookieless tracking to avoid consent banners in many jurisdictions.
- Data retention — auto-delete raw logs after N months while keeping aggregates.
Operating tips
- Back up MySQL regularly — it's your entire analytics history. Use scheduled backups.
- Monitor database growth — high-traffic sites accumulate data quickly; set retention.
- Keep Matomo updated — security patches ship regularly; update the image tag and redeploy.
- GeoIP — install a GeoIP database for accurate location reports.
References
- [Matomo installation guide](https://matomo.org/docs/installation/)
- [Setting up Matomo auto-archiving](https://matomo.org/docs/setup-auto-archiving/)
- [Matomo Docker image](https://hub.docker.com/_/matomo)
- [Matomo privacy settings](https://matomo.org/docs/privacy/)
---
The two things that make a Matomo deploy succeed are a properly sized managed MySQL and a cron-driven archiver — and PandaStack gives you both: managed MySQL with scheduled backups plus native cronjobs with per-run logs. Get analytics you actually own at [dashboard.pandastack.io](https://dashboard.pandastack.io).