Matomo is an open-source web analytics platform that you host yourself, so visitor data never leaves your server. In this tutorial you will install Matomo on Ubuntu 24.04 with Nginx, PHP-FPM 8.3 and MySQL 8, secure it with a Let's Encrypt certificate, run the web installer, and set up the cron job that pre-processes reports. You will finish with a tracked website and basic privacy settings.
Prerequisites
To follow this guide you need:
- A server running Ubuntu 24.04 LTS with at least 2 GB of RAM, for example a CubePath VPS. Busy sites (hundreds of thousands of pageviews per month) need more memory and CPU for archiving.
- A non-root user with
sudoprivileges. - A domain name for Matomo, referred to as
your_domain(for exampleanalytics.example.com), with a DNS A record pointing toyour_server_ip.
Step 1 - Installing Nginx and opening the firewall
Install Nginx from the Ubuntu repositories:
sudo apt update
sudo apt install nginx
Allow SSH, HTTP and HTTPS through UFW and enable the firewall:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
Check that Nginx is running:
systemctl status nginx --no-pager
● nginx.service - A high performance web server and a reverse proxy server
Active: active (running)
Step 2 - Installing PHP 8.3 and the required extensions
Ubuntu 24.04 ships PHP 8.3, which Matomo 5 supports. Install PHP-FPM with the extensions Matomo's system check asks for:
sudo apt install php-fpm php-cli php-mysql php-xml php-mbstring php-curl php-gd php-intl php-zip unzip
Confirm the version and that the extensions are loaded:
php -v
php -m | grep -E 'curl|gd|intl|mbstring|mysqli|pdo_mysql|xml|zip'
Matomo's reports use more memory than PHP's default 128 MB allows on larger sites. Open the PHP-FPM configuration:
sudo nano /etc/php/8.3/fpm/php.ini
Find and set these values:
memory_limit = 512M
max_execution_time = 300
Restart PHP-FPM to apply them:
sudo systemctl restart php8.3-fpm
Step 3 - Creating the MySQL database
Install MySQL server:
sudo apt install mysql-server
Run the hardening script, which removes anonymous users and the test database:
sudo mysql_secure_installation
On Ubuntu the MySQL root account authenticates through the Unix socket, so sudo mysql logs you in without a password. Open the MySQL shell:
sudo mysql
Create a database and a dedicated user. Replace your_strong_password with a password of your own:
CREATE DATABASE matomo CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'matomo'@'localhost' IDENTIFIED BY 'your_strong_password';
GRANT ALL PRIVILEGES ON matomo.* TO 'matomo'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Verify that the new user can connect:
mysql -u matomo -p -e 'SHOW DATABASES;'
+--------------------+
| Database |
+--------------------+
| information_schema |
| matomo |
| performance_schema |
+--------------------+
Step 4 - Downloading Matomo
Download the latest release from the official build server and extract it to /var/www:
cd /tmp
curl -fLO https://builds.matomo.org/matomo.zip
sudo unzip -q matomo.zip -d /var/www/
The archive creates /var/www/matomo. Give the PHP-FPM user ownership so Matomo can write its configuration, cache and the web-based updater can replace files:
sudo chown -R www-data:www-data /var/www/matomo
ls /var/www/matomo
You should see index.php, matomo.php, matomo.js and directories such as config, core and plugins.
Step 5 - Configuring the Nginx server block
Create a server block for Matomo:
sudo nano /etc/nginx/sites-available/matomo
This configuration follows Matomo's official Nginx recommendations: only the PHP entry points Matomo needs are executed, and internal directories are blocked.
server {
listen 80;
listen [::]:80;
server_name your_domain;
root /var/www/matomo;
index index.php;
add_header Referrer-Policy origin always;
add_header X-Content-Type-Options "nosniff" always;
location ~ ^/(index|matomo|piwik|js/index|plugins/HeatmapSessionRecording/configs)\.php$ {
include snippets/fastcgi-php.conf;
fastcgi_param HTTP_PROXY "";
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~* ^.+\.php$ {
deny all;
return 403;
}
location / {
try_files $uri $uri/ =404;
}
location ~ ^/(config|tmp|core|lang) {
deny all;
return 403;
}
location ~ /\.ht {
deny all;
return 403;
}
location ~ js/container_.*_preview\.js$ {
expires off;
add_header Cache-Control 'private, no-cache, no-store';
}
location ~ \.(gif|ico|jpg|png|svg|js|css|htm|html|mp3|mp4|wav|ogg|avi|ttf|eot|woff|woff2)$ {
allow all;
expires 1h;
add_header Pragma public;
add_header Cache-Control "public";
}
location ~ ^/(libs|vendor|plugins|misc|node_modules) {
deny all;
return 403;
}
location ~ /(.*\.md|LEGALNOTICE|LICENSE) {
default_type text/plain;
}
}
Nginx evaluates regex locations in order, so the static file rule comes before the rule that blocks plugins, letting the browser load plugin images and stylesheets while PHP files in those directories stay blocked.
Enable the site, disable the default one, test and reload:
sudo ln -s /etc/nginx/sites-available/matomo /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
Step 6 - Enabling HTTPS with Let's Encrypt
Install Certbot and request a certificate. Certbot adds the TLS configuration and an HTTP to HTTPS redirect to the server block:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d your_domain
Check that renewal works:
sudo certbot renew --dry-run
Step 7 - Running the web installer
Open https://your_domain in your browser and follow the installer:
- System Check: every item should be green. If an extension is missing, install it with
apt, restartphp8.3-fpmand reload the page. - Database Setup: server
127.0.0.1, loginmatomo, the password you set in Step 3, database namematomo, table prefixmatomo_, adapterPDO\MYSQL. - Super User: create the administrator account with a strong password and a real email address.
- Set up a Website: enter the name and URL of the first site to track and its time zone.
- Tracking Code: copy the snippet shown (you can find it later under Administration > Websites > Tracking Code).
When the installer finishes, force HTTPS for the Matomo interface. Open the configuration file it created:
sudo nano /var/www/matomo/config/config.ini.php
Add force_ssl = 1 under the existing [General] section:
[General]
force_ssl = 1
Step 8 - Adding the tracking code to your website
Paste the snippet from the installer just before the closing </head> tag of every page on the tracked site. It looks like this, with your domain and the site ID Matomo assigned:
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://your_domain/";
_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 -->
Visit the tracked site in a browser without an ad blocker, then open Visitors > Visits Log in Matomo. Your visit appears there within seconds.
Step 9 - Scheduling report archiving
By default Matomo builds reports when someone opens the dashboard, which becomes slow as data grows. The recommended setup is to archive from cron and disable browser-triggered archiving. Create a cron file that runs the archiver every hour as www-data:
echo '5 * * * * www-data /usr/bin/php /var/www/matomo/console core:archive --url=https://your_domain/ > /dev/null' | sudo tee /etc/cron.d/matomo-archive
Run the archiver once by hand to confirm it works:
sudo -u www-data php /var/www/matomo/console core:archive --url=https://your_domain/
The command ends with a summary line reporting how many archives were processed and no errors. Then, in Matomo, go to Administration > System > General settings and set Archive reports when viewed from the browser to No.
Step 10 - Reviewing privacy settings
Matomo can run without consent banners in many jurisdictions when it is configured to minimise personal data. Go to Administration > Privacy > Anonymize data and:
- Enable IP anonymisation and choose to mask at least 2 bytes of the address.
- Under Regularly delete old raw data, set a retention period for raw visit logs that matches your privacy policy. Aggregated reports are kept.
If you need visitor consent, the tracking code supports _paq.push(['requireConsent']); together with your consent banner. Check the rules that apply to your audience before deciding.
Step 11 - Backing up Matomo
A complete backup is the database plus config/config.ini.php. Create a script:
sudo nano /usr/local/bin/matomo-backup
#!/usr/bin/env bash
set -euo pipefail
backup_dir="/var/backups/matomo"
stamp="$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup_dir"
mysqldump --single-transaction --quick matomo | gzip > "$backup_dir/matomo-db-$stamp.sql.gz"
cp /var/www/matomo/config/config.ini.php "$backup_dir/config-$stamp.ini.php"
find "$backup_dir" -type f -mtime +14 -delete
It runs as root, so mysqldump authenticates through the socket without a stored password. Make it executable, test it and schedule it nightly:
sudo chmod 750 /usr/local/bin/matomo-backup
sudo /usr/local/bin/matomo-backup
ls -lh /var/backups/matomo
echo '30 2 * * * root /usr/local/bin/matomo-backup' | sudo tee /etc/cron.d/matomo-backup
Copy the backups to another server or object storage regularly.
Updating Matomo
When a new version is available, Matomo shows a notice to the Super User. Take a backup, then use the one-click updater in the interface or update from the command line after replacing the files:
sudo -u www-data php /var/www/matomo/console core:update
Troubleshooting
- 502 Bad Gateway: PHP-FPM is not running or the socket path is wrong. Check
systemctl status php8.3-fpmand that/run/php/php8.3-fpm.sockexists. - The system check reports that
tmpis not writable: runsudo chown -R www-data:www-data /var/www/matomoagain. - No visits recorded: check in the browser developer tools that the request to
https://your_domain/matomo.phpreturns204or200, and test without ad blockers. - Archiving runs out of memory: raise
memory_limitin/etc/php/8.3/cli/php.ini, which is the file theconsolecommand uses.
Conclusion
Matomo is now running on Ubuntu 24.04 with Nginx, PHP 8.3 and MySQL, served over HTTPS, archiving reports from cron and backing up nightly. Next, add your other websites under Administration > Websites > Manage, configure goals for the conversions you care about, and install a geolocation database (Administration > System > Geolocation) for accurate country and city reports.
