Use case · Web analytics

Matomo self-hosted on a dedicated server: requirements, install and hardening

A self-hosted Matomo needs a web server, PHP and a MySQL or MariaDB database, and for up to about 100,000 tracked pageviews a month Matomo's own minimum recommendation is one machine with 2 CPUs, 2 GB of RAM and a 50 GB SSD. This page takes Matomo On-Premise (formerly Piwik) from a bare Ubuntu box to a hardened install: firewall first, the wizard reached only through an SSH tunnel, archiving on cron, then TLS, trusted hosts, backups and updates.

See the machines

Software requirements

Matomo is a PHP application with a MySQL or MariaDB database behind it, served by Apache, Nginx, IIS or LiteSpeed. The requirements FAQ lists two sets of versions, and it is worth reading them with their scope.

Matomo releasePHPDatabase
Matomo 4.16 and 5 (5.14.2 is current stable)PHP 8MySQL 5.5 or greater, or MariaDB
Matomo 6.0.0 (in beta)8.1 or newerMySQL 8.0+ or MariaDB 10.6+

Build to the 6.0.0 column now and the next major upgrade will not need a new database. PHP needs pdo and pdo_mysql or mysqli; Matomo also recommends gd (sparklines and graphs in email reports), curl, xml, mbstring and the CLI binary, which the archiving job uses. The database user needs SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, DROP, ALTER, CREATE TEMPORARY TABLES and LOCK TABLES on its own schema; FILE is optional and speeds up archiving through LOAD DATA INFILE.

Sizing by monthly page views

Matomo's tiers are set in page views per month, and its FAQ adds that every tracked request counts toward the load: pageviews, events, downloads. The number of sites and of custom segments adds to it too. The figures below are Matomo's "minimum recommended configuration" for each tier, quoted from its requirements FAQ, not measurements of ours.

Page views per monthMatomo's minimum recommended configuration
Up to 100,000One server for app and database: 2 CPU, 2 GB RAM, 50 GB SSD
Up to 1 millionOne server can be sufficient: 4 CPU, 8 GB RAM, 250 GB SSD
Up to 10 millionTwo servers: app with 8 CPU, 16 GB RAM, 100 GB SSD; database with 8 CPU, 16 GB RAM, 400 GB SSD
Up to 100 millionTwo or three app servers (16 CPU, 16+ GB each), a 16-CPU / 32 GB / 1 TB SSD database, a load balancer

The same FAQ also says that above 1 million actions a month it recommends a separate database server, so treat the 1-million row as the ceiling for one box. The database only grows: the archiving guide says Matomo deletes archives of incomplete periods but keeps every other day, week, month and year. Archiving is also where memory goes; the archiving guide suggests a PHP memory_limit of 512M or 2G for smaller instances and calls 8G common for medium to large ones.

Which machine to run it on

A dedicated server gives Matomo the whole machine: no other tenant competing for disk I/O while archiving reads a full day of raw logs, root to set PHP and database limits, and an unmetered port, so tracking requests from a busy site never become a transfer bill. On the dedicated range, the classes map onto Matomo's rows like this:

  • Up to roughly 100,000 a month: a Moonshot cartridge, which the range describes as one service per machine. The NVMe cartridges suit a database that only grows.
  • Up to 1 million: a single-socket server, the range's base for a web or application server with its database on the same box. Make sure the disks are SSD or NVMe with at least 250 GB, since the racked single-socket lines ship with spinning SAS or SATA disks (a 16-core Xeon D NVMe cartridge also fits this row). Choose memory first, since archiving and the database both want it.
  • Past that: two machines, with a dual-socket server as the database, the class the range lists for busy databases. See NVMe dedicated servers for the disk side.

Matomo On-Premise stores data in whatever country the server is in. For data that should stay in the EU, Amsterdam and Bucharest are two of the five cities; see European dedicated servers and the full list on server locations. A racked machine is handed over in about 30 minutes once payment is approved; a built-to-order line takes 4 to 24 hours.

Install with the wizard kept private

The Matomo installer is a web page, and whoever reaches it first creates the super user, the single account with the highest permissions. Since Matomo 5.2.0 the installer locks itself 72 hours after first access, but that window is still open to anyone who can reach port 80. So the firewall goes on before Apache is installed, and you finish the wizard through an SSH tunnel. Ubuntu's ufw writes IPv6 rules too when IPV6=yes is set in /etc/default/ufw; check that before enabling it.

# Firewall first: SSH only, IPv4 and IPv6
grep IPV6= /etc/default/ufw        # expect IPV6=yes
sudo ufw allow OpenSSH
sudo ufw enable

# Web server, PHP and database
sudo apt update
sudo apt install apache2 mariadb-server php php-curl php-gd php-cli php-mysql php-xml php-mbstring unzip
sudo mysql_secure_installation

# Matomo, downloaded from matomo.org only
cd /tmp && wget https://builds.matomo.org/matomo.zip && unzip -q matomo.zip
sudo mv /tmp/matomo /var/www/html/matomo
sudo chown -R www-data:www-data /var/www/html/matomo

Make the schema and its account from inside the client (sudo mysql), not as a shell argument, so the password never lands in ps output or shell history:

CREATE DATABASE matomo;
CREATE USER 'matomo'@'localhost' IDENTIFIED BY 'long-random-password';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, DROP, ALTER,
  CREATE TEMPORARY TABLES, LOCK TABLES ON matomo.* TO 'matomo'@'localhost';
EXIT;
  1. On your workstation, start a tunnel through your own login: ssh -N -L 8080:127.0.0.1:80 you@your-server.
  2. Browse to http://localhost:8080/matomo/. The wizard runs a system check, then asks for the database host (localhost), user, password and name; the password goes in the form, not on a command line.
  3. Create the super user with a long password and keep it in a password manager. Add the first website and copy its JavaScript tracking tag.
  4. Only now open the web ports: sudo ufw allow 'Apache Full', which covers 80 and 443 on IPv4 and IPv6. Point DNS at the server and put a certificate on Apache, for example with certbot.

Archiving on cron, TLS and trusted hosts

By default Matomo builds reports when someone opens them in the browser, which on anything but a tiny site means slow dashboards and failed requests. Matomo's guide replaces that with core:archive run hourly from cron, as the web-server user to avoid permission mismatches, and then switches browser-triggered archiving off. Create the log directory outside the web root first: sudo install -d -o www-data -g www-data -m 750 /var/log/matomo. Then three files change:

# Our snippet, not Matomo's docs: /etc/apache2/conf-available/matomo.conf
# then: sudo a2enconf matomo && sudo systemctl reload apache2
# lets Matomo's own .htaccess files guard tmp/ and config/
<Directory /var/www/html/matomo>
    AllowOverride All
</Directory>

# /var/www/html/matomo/config/config.ini.php, add under the existing [General]
trusted_hosts[] = "analytics.example.org"
force_ssl = 1
browser_archiving_disabled_enforce = 1

# /etc/cron.d/matomo-archive
5 * * * * www-data /usr/bin/php /var/www/html/matomo/console core:archive --url=https://analytics.example.org/matomo/ > /var/log/matomo/archive.log 2>&1

trusted_hosts is Matomo's defence against host header injection attacks. Matomo sets the hostname used during installation as the first trusted host; our inference is that this will be the tunnel's localhost address, so check the existing trusted_hosts[] line and add the public name, or Matomo shows an untrusted-hostname warning. Add force_ssl = 1 only after https:// loads: Matomo then redirects every plain request, and its FAQ warns that enabling it before SSL works can leave Matomo unreachable. Test the job once by hand with sudo -u www-data /usr/bin/php /var/www/html/matomo/console core:archive --url=https://analytics.example.org/matomo/.

Run archiving as www-data, never as root. A root run writes cache files into tmp/ that the web server then cannot overwrite.

GeoIP, privacy settings and licensing

Country and city reports need a geolocation database. Under Administration, Settings, Geolocation, Matomo downloads the free DB-IP City Lite file and can keep it updated; MaxMind's GeoIP2 databases are the alternative and need a MaxMind account. The updater writes to misc/, which is one more reason the tree belongs to www-data.

For GDPR work Matomo ships IP anonymisation, a visitor opt-out, cookieless tracking, a GDPR tools screen that exports or deletes one visitor's data, data-retention purges of old raw logs, and settings to disable the visits log and visitor profiles. Turn them on before the first page view is tracked; your legal basis and privacy notice remain your own job.

Matomo core is free software under the GNU GPL v3 or later. The Marketplace also sells premium plugins, such as Media Analytics, Audit Log and Experiments (A/B testing); those are not under an open-source licence and may not be redistributed. If a handful of headline numbers is all you need, our Plausible self-hosted guide covers a lighter stack.

Backups and updates

  • Database: Matomo's backup FAQ uses mysqldump --extended-insert --no-autocommit --quick --single-transaction. Our suggestion, not Matomo's: on Ubuntu, MariaDB's root account logs in over the local socket, so a nightly root script called from cron can start with umask 077, so the dump is not world-readable, and then run mysqldump --extended-insert --no-autocommit --quick --single-transaction matomo | gzip > /var/backups/matomo-$(date +%F).sql.gz with no password anywhere (written straight into a crontab line, the % would need escaping). Past about 10 GB or a million actions a month, the FAQ points to Percona XtraBackup instead.
  • config/config.ini.php: it holds the database password and the state of the install. Back it up with the dump, keep both the dump and the config copies at mode 600, and copy both off the machine.
  • Test a restore. Matomo's security guide says so explicitly; a dump you have never loaded is a hope, not a backup.
  • Updates: with the tree owned by www-data, the one-click updater under Administration works. Manually: back up the config, unpack the new matomo.zip over the old tree, run sudo chown -R www-data:www-data /var/www/html/matomo again (our step, so the files unpacked by your login go back to the web-server user), then sudo -u www-data php /var/www/html/matomo/console core:update, which the update guide recommends over the browser on busy servers. The diagnostics:unexpected-files console command lists leftovers from the old release.

Matomo's security guide also recommends two-factor authentication for every account and a database unreachable from the internet: check that MariaDB's bind-address is 127.0.0.1, and leave port 3306 closed in ufw.

Questions

Is self-hosted Matomo free?

The core is free to download and licensed under the GNU GPL v3 or later. Premium plugins such as Media Analytics, Audit Log and A/B testing are sold on the Matomo Marketplace; those carry their own licence. The server is the other cost.

Can Matomo and its database share one server?

Yes, up to around a million page views a month. Matomo's FAQ says one server can be sufficient up to that point and recommends a separate database server above it. Put the database on fast SSD or NVMe, because it grows with every archived period.

Why does the dashboard say archiving was triggered from the browser?

Because no cron job has taken over. Add the core:archive line to cron as www-data, confirm it runs cleanly, then set browser_archiving_disabled_enforce = 1. Reports then come from pre-processed archives and the dashboard loads quickly.

What happens if I miss the 72-hour installer window?

From Matomo 5.2.0 the installer refuses access 72 hours after it was first opened. To reset it, remove the installation_first_accessed line from config/config.ini.php and reload. If you finish the wizard through an SSH tunnel on day one, you never meet it.

Put Matomo on its own machine

Choose a line by your monthly page views: memory first, then disks.

See the machines

Related on Server Room

Other use cases