
Matomo is the analytics platform you reach for when “good enough” dashboards stop being acceptable. It’s also a strong choice when you can’t send user data to someone else’s SaaS.
If you want heatmaps, goals, ecommerce tracking, privacy controls, and ownership of the raw data, you can install Matomo on a VPS. That keeps the full stack inside your boundary. Your web logs, database, and retention policy all stay under your control.
This guide targets production sites. You’ll deploy Matomo with Docker Compose, place Nginx in front as a reverse proxy with HTTPS, set up backups you can restore, and follow upgrade habits that won’t break tracking at 2 a.m.
Why Matomo fits teams that can’t use hosted analytics
Matomo is a self-hosted web analytics platform (open-source, GPLv3) that runs on infrastructure you control. It’s a good fit if you:
- Need data residency and want to choose where analytics data lives (country, region, disk).
- Have compliance or contractual constraints that make third-party trackers a headache.
- Want features like goals, funnels, ecommerce reporting, campaign attribution, custom dimensions, and user ID tracking.
- Prefer first-party analytics endpoints (your own domain) to reduce ad-blocker interference.
From an ops perspective, Matomo is a standard web app. It’s PHP in front, a database behind it, and scheduled jobs that build and refresh reports.
Your CPU, RAM, disk I/O, backups, and TLS choices show up in dashboard speed. They also affect how “fresh” reports feel.
Install Matomo on a VPS: how it compares to hosted options
Most teams land on Matomo after bumping into GA4 constraints. Others get tired of “analytics-lite” tools.
The trade-offs are straightforward:
- GA4 / other hosted analytics: quickest to start, but you give up control. Sampling/limits, policy shifts, and data export friction can become real constraints.
- Plausible / Umami: lighter to operate and easier to explain. Great for pageviews and events, but intentionally narrower in scope.
- Matomo: heavier than the lightweight tools, but much more feature-complete. You get deep reporting, a plugin ecosystem, and on-prem control—if you run it properly.
If you’re weighing Matomo against a simpler stack, the infrastructure questions are similar.
Our perspective on the “full pipeline” side of self-hosted analytics is in self-host Plausible Analytics on a VPS.
Resource planning: what your VPS should look like
Matomo performance depends on traffic, event volume, retention settings, and how often you archive reports. In practice, the database is usually the first bottleneck. PHP is rarely the first limit.
- Small site (a few thousand pageviews/day): 1–2 vCPU, 2 GB RAM, NVMe storage recommended.
- Growing property (tens of thousands/day, more events): 2–4 vCPU, 4–8 GB RAM, NVMe, and a clear backup window.
- Busy analytics hub (multiple sites, heavy ecommerce/events): 4+ vCPU, 8–16 GB RAM, fast disk, and consider moving DB to a dedicated instance.
Disk performance matters more than people expect. Analytics writes constantly. Slow storage turns archiving into a backlog.
If you’re committing to owning your analytics, start with a VPS tier that won’t choke on I/O.
A sensible baseline is a HostMyCode VPS with NVMe storage and enough RAM to keep MariaDB comfortable.
Deployment overview (Docker Compose + Nginx reverse proxy)
You have two realistic deployment options:
- Docker Compose (recommended for most operators): repeatable deploys, simpler upgrades, clean separation of services.
- Traditional LEMP (Nginx + PHP-FPM + MariaDB on host): totally workable, but upgrades and extensions tend to get fiddly over time.
Here you’ll run Matomo with Docker Compose. Nginx stays on the host as the reverse proxy and TLS terminator.
This keeps certificates, logs, and routing in one predictable place. It also helps when you host more than one app on the same VPS.
Assumptions:
- Ubuntu or Debian on a VPS (other distros work; paths may differ).
- A domain or subdomain like
analytics.example.compointing to your server. - Ports 80 and 443 open to the internet; SSH restricted.
Compose stack: Matomo + database + scheduled archiving
Create a working directory (for example /opt/matomo). Keep the configuration somewhere you can reproduce it.
Ideally, use a private repo. If that’s not an option, maintain clear internal docs.
sudo mkdir -p /opt/matomo
sudo chown -R root:root /opt/matomo
cd /opt/matomo
A typical Compose layout includes:
- matomo: the PHP web app container
- db: MariaDB (or MySQL) for Matomo data
- cron: runs Matomo’s scheduled tasks (archives reports)
Example docker-compose.yml (trimmed to the essentials, with conservative defaults):
services:
db:
image: mariadb:11
command: --max-allowed-packet=256M --innodb-buffer-pool-size=1G
environment:
MARIADB_DATABASE: matomo
MARIADB_USER: matomo
MARIADB_PASSWORD: CHANGE_ME_STRONG
MARIADB_ROOT_PASSWORD: CHANGE_ME_ROOT_STRONG
volumes:
- ./db:/var/lib/mysql
restart: unless-stopped
matomo:
image: matomo:latest
depends_on:
- db
environment:
MATOMO_DATABASE_HOST: db
MATOMO_DATABASE_ADAPTER: mysql
MATOMO_DATABASE_TABLES_PREFIX: matomo_
MATOMO_DATABASE_USERNAME: matomo
MATOMO_DATABASE_PASSWORD: CHANGE_ME_STRONG
MATOMO_DATABASE_DBNAME: matomo
volumes:
- ./matomo:/var/www/html
restart: unless-stopped
cron:
image: matomo:latest
depends_on:
- db
entrypoint: ["/bin/sh", "-c"]
command: ["while true; do php /var/www/html/console core:archive --url=https://analytics.example.com; sleep 3600; done"]
volumes:
- ./matomo:/var/www/html
restart: unless-stopped
Notes you’ll care about later:
- Pin versions once stable. “latest” works for a trial, not for long-term operations. After your first upgrade cycle, lock to a major/minor tag you’ve tested.
- The archiver runs hourly here. High-traffic sites may need it more often. Low-traffic sites can often run it daily.
- The
innodb-buffer-pool-sizeline is a starting point. Tune it to your RAM. On a 4 GB VPS, 1 GB is often reasonable if Matomo is the main workload.
Bring the stack up:
docker compose up -d
If you’re operating Docker on a VPS with tight storage, watch disk usage early. Images, volumes, and logs grow quietly.
Our cleanup playbook in disk space troubleshooting on a Linux VPS is a helpful safety net.
Nginx reverse proxy + HTTPS (clean SSL termination)
Even with Matomo in containers, handle TLS and routing at the host layer. Nginx keeps access logs in one place.
It also simplifies rate limiting and avoids certificate sprawl.
1) Create an Nginx server block such as /etc/nginx/sites-available/analytics.example.com:
server {
listen 80;
server_name analytics.example.com;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
server_name analytics.example.com;
ssl_certificate /etc/letsencrypt/live/analytics.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/analytics.example.com/privkey.pem;
# Keep uploads and API calls from failing on larger payloads
client_max_body_size 32m;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
2) Publish Matomo’s container port to localhost. Add to the matomo service:
ports:
- "127.0.0.1:8080:80"
Reload Compose and Nginx:
docker compose up -d
sudo nginx -t && sudo systemctl reload nginx
3) Issue a Let’s Encrypt certificate. If you want the full command-by-command walkthrough (plus common failure modes like bad DNS, wrong server_name, or blocked ACME challenges), use our updated guide: Configure HTTPS with Let’s Encrypt on a VPS.
Once HTTPS is live, finish Matomo setup in the web installer at https://analytics.example.com. Use the Compose DB credentials.
Keep the generated config/config.ini.php inside your persistent volume.
Privacy and hardening knobs you should set early
Matomo can run in a privacy-friendly mode, but you need to set the defaults up front. Make these decisions during setup. Don’t wait until you’ve collected months of data.
- IP anonymization: enable it if you don’t need full IPs for security analytics.
- Respect Do Not Track: helpful for privacy posture; validate it against your reporting needs.
- Cookie consent and retention: align with your policy and local requirements.
- Limit admin access: use strong passwords and enforce 2FA for Matomo users.
Also lock down the VPS. At minimum, allow only SSH, HTTP, and HTTPS. Use SSH keys.
If you want a clean baseline, follow our UFW firewall setup and apply the same posture to your analytics host.
Backups that work: database dumps + persistent volumes
Matomo isn’t “just a database.” Back up both the DB and the Matomo persistent volume:
- Database: visits, actions, users, configuration, queued archives
- Matomo volume (
./matomo): configuration, plugins, and uploaded assets
A practical backup pattern on a single VPS:
- Nightly compressed database dump
- Nightly tar archive of the Matomo volume
- Copy both to offsite storage (object storage, backup VPS, or remote filesystem)
- Monthly restore test to a staging VPS
Example backup script (store as /usr/local/sbin/backup-matomo.sh):
#!/bin/sh
set -eu
BASE=/opt/matomo
DEST=/var/backups/matomo
TS=$(date +%F_%H%M)
mkdir -p "$DEST"
# Database dump
cd "$BASE"
docker compose exec -T db mariadb-dump -u root -p"$MARIADB_ROOT_PASSWORD" matomo \
| gzip > "$DEST/matomo_db_$TS.sql.gz"
# Matomo persistent volume
tar -C "$BASE" -czf "$DEST/matomo_volume_$TS.tar.gz" matomo
# Optional: keep only 14 days locally
find "$DEST" -type f -mtime +14 -delete
You’ll notice a problem: the script references $MARIADB_ROOT_PASSWORD. Don’t hardcode secrets into scripts.
Use one of these approaches:
- Read credentials from an
.envfile owned by root (chmod 600) - Use Docker secrets (better if you already manage secrets properly)
- Use a dedicated DB backup user with limited permissions
Schedule it with cron or a systemd timer. If you prefer timers (better logging, fewer “silent failures”), our companion piece replace cron jobs with systemd timers shows a clean pattern.
Finally: verify restores. A backup you haven’t restored is a theory.
If you want a repeatable restore drill format, adapt the checklist style from our VPS backup verification tutorial to Matomo’s DB + volume pair.
Updates and upgrades: minimize risk, keep data consistent
Matomo upgrades are usually painless. That’s exactly why they can bite you.
Your website can keep working while analytics quietly stops collecting data. Treat updates like you’d treat a payment plugin update.
- Back up first: DB + volume, and confirm you have disk headroom for snapshots.
- Read the Matomo release notes: watch for DB migrations and PHP requirements.
- Upgrade in a maintenance window: you’ll likely run DB migrations via the web UI.
- Pin image versions after you’ve stabilized on a release train.
Typical Docker-based update flow:
cd /opt/matomo
docker compose pull
docker compose up -d
# Watch logs for errors
docker compose logs -f --tail=200
If Matomo prompts you to run an update in the UI, do it right after the container refresh.
Then confirm archiving still runs by checking the cron container logs:
docker compose logs --tail=200 cron
Plugins are the other common source of surprises. If you depend on specific plugin features, keep a small staging VPS. Rehearse upgrades there first.
That’s a perfect use for a second VPS.
Operational checks: know when Matomo is falling behind
Once Matomo is in production, the same problems tend to repeat. Watch for these three early:
- Archive lag: dashboards look stale because archiving isn’t finishing. Fix it by tuning the DB, adding resources, or adjusting the archiving schedule.
- DB growth surprises: retention isn’t set, or you’re keeping high-detail tracking forever. Fix it by setting retention and purge rules early.
- Blocked tracking requests: ad blockers or a CSP change breaks collection. A first-party analytics subdomain helps, but you still need to test after frontend/security changes.
You can catch most of this with basic monitoring. Use uptime checks on /. Also run a periodic check that the tracking endpoint returns expected status codes.
If you want a practical setup for a small fleet, follow our server monitoring setup guide and include Matomo’s Nginx and database metrics.
Where Matomo belongs in your hosting stack
Analytics is infrastructure, so treat it like infrastructure. For one site, running Matomo alongside your app on the same VPS can work.
Isolate resources and pay attention to disk I/O. If you track multiple properties, or if reporting is client-facing, give Matomo its own instance.
- Agency or reseller model: host Matomo separately, enforce per-client user access, and document your retention policy.
- SaaS product team: keep analytics on a dedicated VPS so app deploys don’t interrupt tracking.
- High traffic: consider a dedicated server for predictable disk and CPU, or split DB and app across hosts.
Summary: stable Matomo starts with boring ops
Matomo is a solid choice for full-featured, self-hosted analytics in 2026. Run it with Docker Compose, terminate TLS with Nginx on the host, and design backups around the database and the persistent volume.
Upgrade deliberately. Then verify archiving and confirm tracking still fires.
Keeping it “boring” mostly means avoiding resource pressure. A properly sized HostMyCode VPS (or managed VPS hosting if you want fewer moving parts) gives Matomo the CPU, RAM, and fast storage it needs to stay responsive as traffic grows.
If you’re planning to self-host analytics for multiple sites, don’t cram it onto a hobby box. Start with a VPS sized for steady database writes and predictable disk I/O, then add monitoring and backups on day one. HostMyCode offers VPS and managed VPS hosting that work well for Matomo, especially when you need stable performance and easy scaling.
FAQ
Can I run Matomo and my website on the same VPS?
Yes for low-to-moderate traffic, but watch database disk I/O and RAM. If Matomo archiving competes with your app’s database, dashboards lag and your site may slow down.
Do I need HTTPS for Matomo?
You should. HTTPS protects admin sessions and prevents tracking requests from being blocked or downgraded by browsers. It also keeps your analytics endpoint consistent across modern security policies.
What exactly do I need to back up?
Back up the Matomo database and the persistent Matomo volume (config and plugins). Only backing up the database is a common mistake that complicates restores.
How do I know if Matomo archiving is failing?
Check the cron/archiver container logs and look for repeated errors or long runtimes. If dashboards show stale data, archiving is often the first place to investigate.
Is Matomo open source?
Yes. The Matomo core platform is open source under the GPLv3 license. Some features may be provided via optional plugins, so review plugin licensing before standardizing on them.