Openmost — Ronan
Production-ready Docker stack for Matomo Analytics with Apache, PHP-FPM, MariaDB, and Redis, fully configurable via environment variables.
- Matomo (latest) — Web analytics
- PHP 8.5 FPM — Via Sury repo, OPcache + JIT optimized
- Apache — Secured vhost, gzip compression, browser caching, HTTP/2, HSTS/nosniff/X-Frame-Options headers
- MariaDB LTS — InnoDB tuning, configurable buffer pool
- Redis 7 — Optional cache backend for improved dashboard and tracking performance
- Backup — Daily gzipped dump with
--single-transaction+ integrity check + automatic retention - Archiving — Cron every 5 minutes + weekly scheduled tasks (GeoIP updates, etc.)
- Log rotation — Automatic daily rotation with 14-day retention
# 1. Clone and configure
cp .env.example .env
nano .env # Set: domain, passwords, sizing
# 2. Start
docker compose up -d
# 3. Complete the installation
# Open https://your-domain in the browserdocker-matomo/
├── Dockerfile # Multi-stage image (Debian + Apache + PHP-FPM)
├── docker-compose.yml # 4 services: MariaDB, Redis, Matomo, Backup
├── .env.example # Environment variables (copy to .env)
├── .dockerignore
├── config/
│ ├── apache-matomo.conf # HTTP vhost (compression, caching, HTTP/2)
│ ├── apache-ssl.conf # HTTPS vhost (TLS 1.2+, modern ciphers, HTTP/2)
│ ├── apache-security.conf # Security headers
│ ├── mariadb-custom.cnf # MariaDB extra config
│ ├── logrotate-matomo # Log rotation config
│ └── supervisord.conf # Supervisor (Apache + FPM + cron)
└── scripts/
├── entrypoint.sh # Dynamic configuration at startup
├── matomo-archive.sh # Matomo archiving wrapper
├── geoip-update.sh # Scheduled tasks runner (GeoIP, etc.)
└── backup.sh # MariaDB backup script
| Variable | Default | Description |
|---|---|---|
PHP_VERSION |
8.5 |
PHP version (Sury repo) |
MATOMO_VERSION |
latest |
Matomo version (latest or version number) |
| Variable | Default | Description |
|---|---|---|
DB_ROOT_PASSWORD |
rootchangeme |
MariaDB root password |
DB_NAME |
matomo |
Database name |
DB_USER |
matomo |
MariaDB user |
DB_PASSWORD |
changeme |
User password |
Passwords are mounted as Docker secrets — they do not appear in
docker inspectoutput.
| Variable | Default | Description |
|---|---|---|
INNODB_BUFFER_POOL_SIZE |
2G |
Buffer pool size (>= database size) |
INNODB_LOG_FILE_SIZE |
256M |
InnoDB log file size |
INNODB_FLUSH_LOG_TRX |
2 |
Flush 1x/sec (perf) vs every trx (1) |
INNODB_IO_CAPACITY |
200 |
Disk I/O capacity |
TMP_TABLE_SIZE |
64M |
In-memory temp tables |
MAX_HEAP_TABLE_SIZE |
64M |
Max memory table size |
| Variable | Default | Description |
|---|---|---|
PHP_MEMORY_LIMIT |
512M |
Memory limit per process |
PHP_MAX_EXECUTION_TIME |
300 |
Execution timeout (seconds) |
PHP_UPLOAD_MAX_FILESIZE |
64M |
Max upload size |
PHP_POST_MAX_SIZE |
64M |
Max POST size |
| Variable | Default | Description |
|---|---|---|
PHP_FPM_PM |
dynamic |
Process manager mode |
PHP_FPM_MAX_CHILDREN |
10 |
Max workers |
PHP_FPM_START_SERVERS |
4 |
Workers at startup |
PHP_FPM_MIN_SPARE |
2 |
Min idle workers |
PHP_FPM_MAX_SPARE |
6 |
Max idle workers |
PHP_FPM_MAX_REQUESTS |
500 |
Requests before recycle |
| Variable | Default | Description |
|---|---|---|
OPCACHE_MEMORY |
256 |
OPcache memory (MB) |
OPCACHE_MAX_FILES |
20000 |
Max cached files |
OPCACHE_REVALIDATE_FREQ |
60 |
Revalidation frequency (sec) |
OPCACHE_INTERNED_STRINGS |
16 |
Interned strings buffer (MB) |
OPCACHE_JIT |
1255 |
JIT mode (1255 = tracing, 0 = disabled) |
OPCACHE_JIT_BUFFER_SIZE |
64M |
JIT buffer size |
| Variable | Default | Description |
|---|---|---|
MATOMO_URL |
https://matomo.example.com |
URL for archiving |
MATOMO_ARCHIVE_CRON |
true |
Enable archive cron |
APACHE_SERVER_NAME |
matomo.example.com |
Apache domain name |
HTTP_PORT |
80 |
Exposed HTTP port |
HTTPS_PORT |
443 |
Exposed HTTPS port |
| Variable | Default | Description |
|---|---|---|
BACKUP_RETENTION_DAYS |
30 |
Dump retention in days (0 = disable backups) |
The stack includes a Redis service used as a cache backend for Matomo. On first startup, the entrypoint automatically configures Matomo to use Redis as a chained cache (array + redis), which improves dashboard loading times and reduces database queries.
Redis is not required for Matomo to function — it works perfectly fine without it. However, for high-traffic instances, Redis provides two key benefits:
- Cache backend — Configured automatically by this stack. Speeds up the Matomo dashboard by caching reports and metadata in memory.
- QueuedTracking plugin — For sites with very high traffic (millions of requests/day), the QueuedTracking plugin uses Redis to queue tracking requests and process them in batches, reducing database write contention. This plugin must be installed separately via the Matomo Marketplace and configured through the Matomo UI.
To disable Redis entirely, remove the redis service from docker-compose.yml and remove the REDIS_HOST environment variable from the matomo service.
Use a reverse proxy (Traefik, Caddy, Nginx Proxy Manager, Cloudflare) in front of the container. The container listens on HTTP; the proxy handles SSL termination.
The HTTPS vhost auto-enables when certificate files are detected. Uncomment in docker-compose.yml:
volumes:
- ./ssl/cert.pem:/etc/ssl/certs/matomo.pem:ro
- ./ssl/key.pem:/etc/ssl/private/matomo.key:roThe SSL vhost uses modern TLS configuration: TLS 1.2+ only, strong cipher suite, HTTP/2 enabled, session tickets disabled.
# Logs
docker compose logs -f matomo
docker compose logs -f mariadb
docker compose logs -f redis
# Shell into the Matomo container
docker compose exec matomo bash
# Manual archiving
docker compose exec matomo php /var/www/matomo/console core:archive --url=https://your-domain
# Run scheduled tasks (GeoIP updates, etc.)
docker compose exec matomo php /var/www/matomo/console scheduled-tasks:run --force
# Update Matomo
docker compose exec matomo php /var/www/matomo/console core:update
# Manual backup
docker compose exec backup /usr/local/bin/backup.sh
# List backups
docker compose exec backup ls -lh /var/backups/
# Restore
docker compose exec -T mariadb mariadb -u root -p"$DB_ROOT_PASSWORD" matomo < backup.sql| Profile | Host RAM | buffer_pool | FPM workers | OPcache | JIT buffer |
|---|---|---|---|---|---|
| Small (< 100k pages/month) | 4 GB | 1G | 5 | 128M | 32M |
| Medium (100k - 1M) | 8 GB | 2G | 10 | 256M | 64M |
| Large (1M - 10M) | 16 GB | 4G | 20 | 512M | 128M |
- The MariaDB image uses the
ltstag to always pull the latest stable LTS version. - PHP 8.5 is the latest stable release (November 2025).
config.ini.phpis only created on first startup. Subsequent changes are preserved via the Docker volume.- MariaDB data persists in the
matomo-mariadb-datavolume. - Database passwords are handled via Docker secrets (mounted as files in
/run/secrets/), not plain environment variables. - Backups use
--single-transactionfor consistent InnoDB dumps without table locks, andgzip -tto verify archive integrity. - Log rotation is handled automatically (14-day retention, gzip compression).