
Matomo is what you reach for when you’re done negotiating with hosted analytics. You want the data on infrastructure you control.
If you need funnels, goals, campaign tracking, and privacy-first settings—without handing raw traffic data to a third party—you can deploy Matomo on a VPS and keep the entire analytics stack inside your own account.
This is an open-source spotlight, not a “copy/paste 47 commands” lab. You’ll still get real deployment guidance: Docker Compose, Nginx + HTTPS, MariaDB sizing, backups, and updates.
The goal is to help you make the operational calls that matter before you put analytics in production.
Why Matomo fits teams moving off Google Analytics
Google Analytics works until it doesn’t. Retention limits, sampling in some reporting paths, and compliance reviews can turn every tracking change into a meeting.
Matomo gives you a full analytics suite that runs under your control. That usually makes governance and access rules simpler.
Matomo is open source (GPLv3). That means you can run it and modify it.
It also means you should keep custom changes small. Otherwise, upgrades can turn into an annual project.
- Who it’s for: product teams, agencies, SaaS operators, and e-commerce sites that need detailed reporting and ownership of raw analytics data.
- Who should choose something smaller: hobby sites or single-page marketing sites that only need basic pageviews and referrers.
Hosted analytics vs self-hosted Matomo: the real tradeoffs
Self-hosting isn’t “free.” You trade subscription fees for server ownership and ongoing maintenance.
The payoff is control. You decide retention, encryption, access, and where the data physically sits.
| Decision point | Hosted/proprietary analytics | Matomo on your VPS |
|---|---|---|
| Data ownership | Vendor-controlled pipeline | You control DB + logs + exports |
| Compliance | Depends on vendor terms + region | Depends on your server location + policies |
| Cost model | Monthly per event/site/user | Predictable VPS + storage costs |
| Performance | Vendor scales it | You size CPU/RAM/IO for peak traffic |
| Operational work | Low | Backups, updates, monitoring, hardening |
Plan your VPS resources before you deploy Matomo on a VPS
Matomo’s “feel” is mostly database IO. Tracking requests are small, but writes add up quickly.
Archiving (turning raw visits into reports) is where CPU and memory usage can jump.
Use this as a practical baseline for 2026 deployments:
- Small site (up to ~100k pageviews/month): 2 vCPU, 2–4 GB RAM, NVMe storage, 30–60 GB disk.
- Growing site (100k–1M pageviews/month): 2–4 vCPU, 4–8 GB RAM, NVMe strongly recommended, 80–200 GB disk.
- High traffic (multi-site, millions of pageviews/month): 4–8 vCPU, 8–16 GB RAM, tuned MariaDB, separate DB volume, and a real backup strategy.
If you already run WordPress, WooCommerce, or multiple apps on the same box, don’t stack analytics on top. You don’t want report generation competing with checkout traffic.
A dedicated analytics VPS creates a clean boundary.
For production, start with a HostMyCode VPS with NVMe storage. If you’d rather not own patching, OS hardening, and performance tuning, managed VPS hosting is often the calmer path.
That matters for analytics that gets questioned every Monday morning.
Architecture that stays boring: Docker Compose + Nginx + MariaDB
You can run Matomo directly on the host. Docker Compose usually makes upgrades, rollbacks, and migrations easier to reason about.
The common layout looks like this:
- Matomo (PHP-FPM or Apache container) for the application
- MariaDB for storage
- Nginx on the host as a reverse proxy handling HTTPS and headers
You can also run Nginx in Docker. Host-level Nginx is often simpler when you already proxy several services.
It also helps when you share certificates or want consistent access/error logging in one place.
Matomo vs “lightweight” self-hosted analytics
If you’re weighing Matomo against smaller tools, the split is straightforward:
- Matomo: deep reports, goals, funnels, segmentation, multi-site management, and a large plugin ecosystem. Heavier footprint.
- Umami/Plausible-style tools: simpler dashboards, lighter DB load, and less operational overhead. Fewer reporting dimensions.
Pick Matomo when stakeholders need answers like “which campaign drove signups that later converted to paid users,” without exporting half your data into a BI pipeline.
Deploy Matomo on a VPS: Compose layout you can live with
Assume Ubuntu or Debian, Docker + Docker Compose plugin installed, and a DNS A/AAAA record like analytics.example.com pointing at the VPS.
A clean directory layout:
/opt/matomo/compose.yml/opt/matomo/.env(DB passwords, salts)/opt/matomo/data/(Matomo config + plugins + uploads)/opt/matomo/db/(MariaDB volume)
Example compose.yml (trimmed to what you’ll actually maintain):
services:
db:
image: mariadb:11
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
environment:
MARIADB_DATABASE: matomo
MARIADB_USER: matomo
MARIADB_PASSWORD: ${MARIADB_PASSWORD}
MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
volumes:
- ./db:/var/lib/mysql
restart: unless-stopped
matomo:
image: matomo:latest
environment:
MATOMO_DATABASE_HOST: db
MATOMO_DATABASE_ADAPTER: mysql
MATOMO_DATABASE_TABLES_PREFIX: matomo_
MATOMO_DATABASE_USERNAME: matomo
MATOMO_DATABASE_PASSWORD: ${MARIADB_PASSWORD}
MATOMO_DATABASE_DBNAME: matomo
volumes:
- ./data:/var/www/html
depends_on:
- db
restart: unless-stopped
Two operational notes that save you trouble later:
- Pin versions once stable. “latest” is fine for evaluation. For production, switch to explicit tags after your first successful upgrade cycle.
- Keep DB and app volumes on fast storage. Analytics writes punish slow disks. NVMe is not optional on busy sites.
Nginx reverse proxy with HTTPS (and the headers you actually want)
Put Matomo behind Nginx and Let’s Encrypt. If you already use Caddy for TLS automation, that’s fine too.
With Nginx, the server block should do the essentials. Terminate HTTPS, pass the real client IP, keep tracking endpoints working, and set sensible security headers.
Typical Nginx site file:
- Ubuntu/Debian:
/etc/nginx/sites-available/analytics.example.com→ symlink intosites-enabled
Example config (assumes Matomo container exposed on localhost port 8080 via an internal Docker network or a published port):
server {
listen 80;
server_name analytics.example.com;
location /.well-known/acme-challenge/ { root /var/www/letsencrypt; }
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;
client_max_body_size 16m;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
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;
}
}
If you want a repeatable TLS setup for VPS-hosted services, Caddy is hard to beat. HostMyCode has a practical walkthrough you can reuse: Set Up Let’s Encrypt With Caddy for a VPS Site.
Database choice: why MariaDB is usually the right default
Matomo uses MySQL-compatible databases, and MariaDB is a solid default for VPS installs. It’s widely understood, fast on NVMe, and straightforward to back up.
Start with the database on the same VPS. Split it out only after you measure a real need.
Do three things early:
- Set utf8mb4 so you don’t hit character issues in referrers and campaign parameters.
- Watch disk usage on
/opt/matomo/db. Analytics tables grow quietly. - Schedule archiving so report generation doesn’t happen on-demand during office hours.
Make archiving predictable (and keep it off the critical path)
Archiving is where people get surprised. Without scheduled archiving, Matomo may generate reports when someone opens a dashboard.
That can cause slow pages and sudden CPU/DB IO spikes.
The fix is a cron job that runs archiving on a schedule. With Docker, run the console command inside the container.
The exact command and frequency depend on your setup, so treat this as a pattern:
# Example pattern (run as root or a service user)
# crontab -e
5 * * * * docker compose -f /opt/matomo/compose.yml exec -T matomo php /var/www/html/console core:archive --url=https://analytics.example.com
Hourly works for most sites. For low traffic, you can run it less often.
For high traffic, keep it hourly and size the VPS accordingly.
Backups: what to copy, how often, and what to test
A Matomo backup has two parts. If you only back up one, the restore will be incomplete.
- MariaDB dump (the analytics data)
- Matomo volume (
config, installed plugins, uploaded assets)
At minimum, run daily backups with 7–30 days retention, plus one longer-lived monthly snapshot.
Store backups off the VPS. Local copies help with fast restores, but they don’t protect you from disk loss.
A practical MariaDB dump command (run from the VPS host):
# Creates a consistent dump; add compression in real use
docker compose -f /opt/matomo/compose.yml exec -T db \
mariadb-dump -u root -p"$MARIADB_ROOT_PASSWORD" --single-transaction matomo \
> /backups/matomo/matomo-$(date +%F).sql
Then archive the application data:
tar -C /opt/matomo -czf /backups/matomo/matomo-data-$(date +%F).tar.gz data
Restore testing is the step teams skip, and the step they regret later.
Once per quarter, restore into a throwaway VPS. Confirm you can log in and see reports.
If you want a backup workflow style guide written for operators, borrow the testing mindset from: Set Up PostgreSQL Backups With pg_dump + Restore Test. The tooling differs, but the restore discipline is the same.
Updates: the safe cadence for production
Matomo upgrades are often smooth. “Often” still isn’t a plan.
Treat updates like any other customer-facing service:
- Step 1: take a fresh DB dump and a tarball of
/opt/matomo/data - Step 2: pull images (or bump pinned tags) and restart
- Step 3: run the web updater and verify tracking still records visits
- Step 4: watch logs and DB size for a day
Typical Docker flow:
cd /opt/matomo
docker compose pull
docker compose up -d
docker compose logs -f --tail=200
One common failure mode is plugin compatibility. If you depend on specific plugins, run upgrades on a staging VPS first.
A small staging box is cheaper than breaking reporting for everyone.
Privacy and compliance knobs you should set on day one
Self-hosting doesn’t automatically make analytics “compliant.” You still need sane defaults and an enforceable policy.
These are the settings teams usually start with:
- IP anonymization (reduce personal data exposure)
- Respect Do Not Track if it matches your policy
- Data retention rules so logs don’t live forever
- Access controls: separate admin from read-only users, enforce strong passwords, and restrict admin access by IP if possible
If you run other self-hosted services, you’ll recognize the pattern. “Privacy-friendly” still requires explicit settings.
The same thinking shows up in other projects we’ve covered, like running Pi-hole on a VPS where configuration decisions matter as much as the install.
Operational quick checks (the ones you’ll actually use)
When someone says “analytics feels slow,” you need quick signal before you change anything.
These checks cover most VPS builds:
- CPU/RAM pressure:
uptime,free -h,top(watch for archiving spikes) - Disk IO and free space:
df -h,iostat -xz 1(NVMe helps, but full disks still crush DB performance) - MariaDB size growth: check your volume usage; analytics tables can grow faster after marketing pushes
- Nginx errors:
/var/log/nginx/error.log(timeouts, upstream issues)
If you’re standardizing monitoring, Matomo is a good reason to do it properly. Here’s a proven VPS pattern we’ve shared: Deploy Grafana on a VPS With Docker, TLS, and Backups.
Where Matomo should live in your hosting stack
For most teams, the clean setup is simple. Keep websites and apps where they already run.
Put analytics on a dedicated VPS with one job.
That separation stops analytics load from stealing resources from revenue-critical services.
- Running WordPress? Keep Matomo separate from your WordPress hosting. WordPress load spikes are unpredictable enough.
- Running multiple client sites? Consider a larger VPS (or a dedicated server) and allocate per-client views with Matomo’s multi-site support.
- Need more headroom? Move to a dedicated machine when DB growth and archiving jobs justify it.
If you’re migrating from an existing analytics setup and want the infrastructure move to be uneventful, HostMyCode migrations can help you plan cutover and DNS timing without breaking tracking scripts mid-campaign.
Summary: self-hosted analytics that you can own and operate
Matomo is one of the few open-source analytics platforms that still feels complete for teams that leaned hard on GA.
You get data ownership, predictable infrastructure costs, and privacy defaults you can enforce. The trade is operational. You run it like a service.
Size the VPS for IO, schedule archiving, back up the database, and update with a rollback plan.
If you want a straightforward place to run it, start with a HostMyCode VPS for full control. Or choose managed VPS hosting if you’d rather keep your team focused on product than patch cycles.
Matomo rewards predictable CPU and fast storage, and it gets easier to manage when you can scale the VPS as traffic grows. If you’re replacing GA and want analytics you control end to end, HostMyCode can provision the right-sized VPS and keep it steady with managed VPS hosting options.
FAQ
Should I run Matomo on the same server as my website?
For small sites, you can. For anything revenue-critical, keep Matomo on a separate VPS so archiving and DB writes don’t compete with your web app.
Does Matomo need MariaDB, or can I use something else?
Matomo is designed around MySQL-compatible databases. MariaDB is a common default for self-hosted deployments because it’s easy to operate and back up.
What’s the biggest performance pitfall after deployment?
Skipping scheduled archiving. Without it, report generation can happen during dashboard views, causing slow pages and surprise CPU spikes.
What do I need to back up to restore Matomo completely?
Back up the MariaDB database and the Matomo data directory/volume (configuration, plugins, and uploads). Restoring only one of those usually leads to a broken or incomplete instance.
How do updates usually fail in production?
The most common issues are plugin incompatibilities and running updates without a tested rollback. Take a DB dump first, then upgrade, then verify tracking and dashboards.