Tutoriales de VPS
Instalar Matomo en un VPS (2026): Docker, MariaDB, HTTPS con Caddy, archivado programado y copias de seguridad
Despliega Matomo 5 y MariaDB en un VPS con Docker Compose, configura HTTPS con Caddy, dominios de confianza, archivado CLI programado, opciones de privacidad, copia y restauración, y actualizaciones seguras.

Instalar Matomo en un VPS (2026): Docker, MariaDB, HTTPS con Caddy, archivado programado y copias de seguridad
Si no quieres entregar los datos de tráfico de tu sitio web a Google Analytics pero necesitas canales de referencia, conversiones de página, eventos y análisis de comercio electrónico, Matomo es una de las soluciones autoalojadas más maduras disponibles. Los datos permanecen en tu propio VPS y en tu propia base de datos, y no pierdes la visibilidad por completo porque un servicio de analítica de terceros esté bloqueado por bloqueadores de anuncios o afectado por condiciones de red regionales.
Pero Matomo no termina cuando arranca un contenedor. La persistencia de la base de datos, el proxy inverso, los hosts de confianza, el archivado en segundo plano, la configuración de privacidad y las copias de seguridad recuperables: si omites cualquiera de estos puntos, pueden aparecer problemas cuando aumente el tráfico.
Este tutorial usa la imagen oficial matomo:5-apache y MariaDB 11.4, desplegados con Docker Compose, con Caddy encargándose de HTTPS. Matomo solo escucha en el 127.0.0.1:8080 del VPS, la base de datos no expone ningún puerto público y se ejecuta una tarea de archivado CLI cada hora.
Estas tres herramientas no resuelven exactamente los mismos problemas.
| Necesidad | Herramienta más adecuada | Principal contrapartida |
|---|---|---|
| Necesitas canales, objetivos, eventos, comercio electrónico y análisis detallado de visitantes | Matomo | Completo, pero con mayor coste de mantenimiento de base de datos y archivado |
| Solo necesitas métricas ligeras como páginas, fuentes y dispositivos | Umami | Interfaz sencilla, menor uso de recursos, menor profundidad analítica |
| No quieres operarlo y aceptas el procesamiento de datos por terceros | Google Analytics | Fácil de integrar, pero la privacidad, el control de datos y el bloqueo de anuncios requieren una evaluación aparte |
| El cumplimiento exige que los datos permanezcan en tu propia infraestructura | Matomo On-Premise | Mayor control de datos, pero "autoalojado" no significa automáticamente conforme |
Si solo quieres saber cuántos visitantes recibes cada día y qué páginas son las más populares, empieza con Autoalojar Umami para analítica web en un VPS. Si necesitas conversiones de objetivos, búsqueda interna, seguimiento de descargas, flujos de usuarios o políticas de retención de datos más detalladas, desplegar Matomo es la mejor inversión.
Para una instalación en un solo servidor con hasta 100.000 páginas vistas al mes, la recomendación mínima oficial de Matomo es 2 núcleos de CPU, 2 GB de RAM y 50 GB de SSD. Como MariaDB también se ejecuta en Docker, conviene comprar memoria adicional.
| Páginas vistas al mes | Configuración recomendada | Notas |
|---|---|---|
| Menos de 100.000 | 2 núcleos, 4 GB de RAM, 50 GB de SSD | Blogs pequeños y sitios corporativos; el despliegue en un solo servidor es lo más sencillo |
| De 100.000 a 1.000.000 | 4 núcleos, 8 GB de RAM, 200 GB de SSD o más | El archivado CLI es obligatorio y hay que vigilar continuamente el crecimiento de la base de datos |
| Más de 1.000.000 | Pruebas de carga y planificación por separado | Puede que haya que separar la base de datos, los procesos de archivado y el almacenamiento de objetos |
El crecimiento del disco depende del volumen de tráfico, el número de eventos, el periodo de retención de registros y si se guardan datos de visita sin procesar, así que no puedes estimarlo solo por el tamaño de los archivos del sitio. El sistema usado aquí es Ubuntu 24.04 LTS; apunta los registros A / AAAA de analytics.example.com al VPS con antelación y abre solo SSH, 80 y 443.
Instala Docker Engine y el plugin Compose desde el repositorio oficial de Docker y luego confirma que usas Compose v2:
docker --version
docker compose version
Crea los directorios de despliegue y copias de seguridad:
sudo mkdir -p /opt/matomo/backups
sudo chown -R "$USER":"$USER" /opt/matomo
cd /opt/matomo
Si este VPS también ejecuta otros contenedores, revisa primero la lista de comprobación de configuración de producción de Docker Compose en un VPS para unificar la rotación de registros, las comprobaciones de estado y la estrategia de actualización.
La cuenta de base de datos de la aplicación y la contraseña de root deben ser distintas:
openssl rand -hex 32
openssl rand -hex 32
nano .env
chmod 600 .env
Escribe ambos valores aleatorios en /opt/matomo/.env:
MARIADB_ROOT_PASSWORD=替换成第一组随机值
MATOMO_DATABASE_PASSWORD=替换成第二组随机值
Nunca hagas commit de .env en Git ni escribas contraseñas en texto plano en el archivo Compose.
Crea /opt/matomo/compose.yaml:
services:
db:
image: mariadb:11.4
container_name: matomo-db
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: "${MARIADB_ROOT_PASSWORD:?set MARIADB_ROOT_PASSWORD in .env}"
MARIADB_DATABASE: matomo
MARIADB_USER: matomo
MARIADB_PASSWORD: "${MATOMO_DATABASE_PASSWORD:?set MATOMO_DATABASE_PASSWORD in .env}"
command:
- --max-allowed-packet=64M
- --innodb-buffer-pool-size=512M
volumes:
- matomo_db:/var/lib/mysql
healthcheck:
test:
- CMD-SHELL
- >-
mariadb-admin ping -h 127.0.0.1 -uroot
-p$$MARIADB_ROOT_PASSWORD --silent
interval: 10s
timeout: 5s
retries: 20
start_period: 30s
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
app:
image: matomo:5-apache
container_name: matomo
restart: unless-stopped
depends_on:
db:
condition: service_healthy
ports:
- "127.0.0.1:8080:80"
environment:
MATOMO_DATABASE_HOST: db
MATOMO_DATABASE_ADAPTER: mysql
MATOMO_DATABASE_TABLES_PREFIX: matomo_
MATOMO_DATABASE_USERNAME: matomo
MATOMO_DATABASE_PASSWORD: "${MATOMO_DATABASE_PASSWORD:?set MATOMO_DATABASE_PASSWORD in .env}"
MATOMO_DATABASE_DBNAME: matomo
PHP_MEMORY_LIMIT: 512M
volumes:
- matomo_data:/var/www/html
healthcheck:
test:
- CMD-SHELL
- >-
php -r '$$c=@fsockopen("127.0.0.1",80,$$e,$$s,5);
exit($$c ? 0 : 1);'
interval: 30s
timeout: 10s
retries: 10
start_period: 60s
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
volumes:
matomo_db:
name: matomo_db
matomo_data:
name: matomo_data
matomo:5-apache sigue las versiones de parche y menores de Matomo 5, así que una sola reconstrucción no saltará directamente a la siguiente versión mayor. mariadb:11.4 está fijado a la serie 11.4, evitando una etiqueta mayor flotante en producción. En una máquina de 2 GB puedes cambiar primero --innodb-buffer-pool-size a 256M; no dejes que la caché de la base de datos acapare la memoria que necesitan el sistema y PHP.
Antes de iniciar, haz que Compose expanda las variables y comprueba el YAML:
docker compose config >/dev/null
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=100 app
La primera inicialización crea la base de datos y los archivos de Matomo. Cuando ambos servicios muestren healthy, comprueba el punto de entrada local:
curl -I http://127.0.0.1:8080
sudo ss -lntp | grep ':8080'
La dirección de escucha debe ser 127.0.0.1:8080, no 0.0.0.0:8080. MariaDB no tiene configuración ports, y el 3306 nunca debe ser visible desde internet.
Edita /etc/caddy/Caddyfile:
analytics.example.com {
encode zstd gzip
reverse_proxy 127.0.0.1:8080
request_body {
max_size 64MB
}
}
Comprueba y carga la configuración:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
curl -I https://analytics.example.com
Caddy pasa X-Forwarded-For, X-Forwarded-Host y X-Forwarded-Proto. Cuando Matomo está detrás de un proxy inverso HTTPS, comprueba también la configuración de [General] en config/config.ini.php después de la instalación:
[General]
assume_secure_protocol = 1
force_ssl = 1
proxy_ip_read_last_in_list = 0
trusted_hosts[] = "analytics.example.com"
trusted_hosts es la protección de nombre de host que Matomo habilita por defecto; no la desactives sin más para silenciar advertencias. Después de cambiarla, ejecuta:
docker compose exec app php console config:get General
docker compose exec app php console cache:clear
Si no estás familiarizado con los certificados, el DNS y la configuración multidominio de Caddy, consulta la guía completa de proxy inverso con Caddy en un VPS.
Abre https://analytics.example.com en el navegador. En la página de base de datos, introduce:
| Campo | Valor |
|---|---|
| Servidor de base de datos | db |
| Usuario | matomo |
| Contraseña | MATOMO_DATABASE_PASSWORD de .env |
| Nombre de la base de datos | matomo |
| Prefijo de tablas | matomo_ |
No introduzcas localhost ni 127.0.0.1; esos apuntan al propio contenedor de Matomo, no a MariaDB en la red de Compose.
El asistente crea después el administrador, añade el primer sitio web y genera el código de seguimiento JavaScript. Coloca el código de seguimiento antes de </head> en todas las páginas de tu sitio; para WordPress, Shopify o CMS habituales, prefiere plugins oficiales o de la comunidad con mantenimiento activo para que el código no se pierda tras una actualización del tema.
Después de la instalación, verifica:
docker compose exec app php console diagnostics:run
docker compose exec app php console core:archive --url=https://analytics.example.com
docker compose logs --tail=100 app
Luego visita tu sitio en una ventana de incógnito y confirma que aparece una visita de prueba en "Visitantes en tiempo real" de Matomo. Ver que la página carga con normalidad no demuestra que las solicitudes de seguimiento y las tareas de archivado funcionen.
Matomo agrega los datos de visita sin procesar en informes. Los sitios pequeños pueden activar el archivado mediante solicitudes del navegador, pero la recomendación oficial es cambiar al archivado CLI programado cuando el tráfico supere las 500 páginas vistas al día o la respuesta del servidor se ralentice. En producción, configura Cron directamente: es más predecible.
Primero ejecútalo manualmente una vez y confirma que no hay errores:
cd /opt/matomo
docker compose exec -T app php /var/www/html/console core:archive \
--url=https://analytics.example.com
Confirma la ruta absoluta de Docker:
command -v docker
Luego edita el Cron de root:
sudo crontab -e
Añade una línea; si el paso anterior no fue /usr/bin/docker, sustituye por la ruta real:
5 * * * * cd /opt/matomo && /usr/bin/docker compose exec -T app php /var/www/html/console core:archive --url=https://analytics.example.com >> /var/log/matomo-archive.log 2>&1
Cuando el archivado CLI funcione de forma estable, desactiva el archivado activado por el navegador:
docker compose exec app php console config:set General enable_browser_archiving = 0
docker compose exec app php console config:get General enable_browser_archiving
Revisa los registros con regularidad para que Cron no falle repetidamente por problemas de ruta, certificados o base de datos:
sudo tail -n 100 /var/log/matomo-archive.log
El autoalojamiento solo significa que controlas la infraestructura; no significa que tu sitio cumpla automáticamente con el RGPD, la CCPA o las normativas locales de privacidad. Como mínimo, revisa estos puntos en "Administración → Privacidad":
- Para la anonimización de IP, enmascara 2 o 3 bytes y actívala antes de recopilar tráfico real por primera vez;
- Define periodos de retención para los registros de visita sin procesar y los informes históricos; no guardes indefinidamente datos sin valor de negocio;
- Si no necesitas identificar usuarios entre sesiones, usa seguimiento sin cookies y verifica cómo cambia la precisión;
- Habilita un mecanismo para que los usuarios se excluyan del seguimiento e indica en tu política de privacidad la finalidad de la recopilación y el periodo de retención;
- No metas información personal como correos, nombres o notas de pedido en URL, títulos de página o dimensiones personalizadas;
- Decide si necesitas una plataforma de gestión del consentimiento según tu región, método de seguimiento y finalidad; no trates "Matomo" como una conclusión universal que te exime de un banner de cookies.
Matomo ofrece capacidad de anonimización de IP por defecto, pero la configuración final y la base legal siguen siendo responsabilidad del operador del sitio. Haz que los responsables legales o de privacidad confirmen las necesidades del negocio antes de hacer cambios.
Una copia de seguridad completa incluye al menos MariaDB y el volumen matomo_data. La base de datos contiene datos de sitio, visitas e informes, mientras que el volumen de datos contiene config/config.ini.php, plugins y archivos de la aplicación.
Crear una copia de seguridad de la base de datos:
cd /opt/matomo
mkdir -p backups
docker compose exec -T db sh -c \
'mariadb-dump --single-transaction --quick --routines --triggers \
--databases "$MARIADB_DATABASE" -uroot -p"$MARIADB_ROOT_PASSWORD"' \
| gzip > "backups/matomo-db-$(date +%F-%H%M).sql.gz"
Hacer copia de seguridad del volumen de datos de Matomo:
docker run --rm \
-v matomo_data:/source:ro \
-v "$PWD/backups:/backup" \
alpine sh -c 'tar -C /source -czf /backup/matomo-data.tar.gz .'
Los archivos de copia de seguridad no deben estar solo en el mismo VPS. Sincronízalos cifrados con almacenamiento de objetos u otra máquina y realiza simulacros de restauración con regularidad. Puedes seguir el proceso de copia de seguridad externa y verificación del tutorial de simulacro de copia de seguridad y restauración en un VPS.
Para restaurar, primero detén las escrituras de Matomo, restaura el volumen de datos, luego importa el SQL en un MariaDB nuevo y, por último, inicia los servicios y ejecuta:
docker compose exec app php console core:update
docker compose exec app php console diagnostics:run
docker compose exec app php console core:archive --url=https://analytics.example.com
La aceptación de la restauración debe comprobar conjuntamente el inicio de sesión del administrador, los informes históricos, las visitas en tiempo real, el script de seguimiento y el archivado por Cron, no solo que la página de inicio se abra.
Matomo maneja datos de visitantes y cuentas de administrador, así que no pospongas las actualizaciones de seguridad durante mucho tiempo. Antes de actualizar, lee las notas de la versión de Matomo y los cambios de la imagen, y luego ejecuta:
cd /opt/matomo
docker compose config >/dev/null
# 先完成并验证数据库、matomo_data 两类备份
docker compose pull
docker compose up -d
docker compose exec app php console core:update
docker compose exec app php console diagnostics:run
docker compose ps
Después de actualizar, verifica al menos:
- La página de inicio HTTPS y el panel de administración son accesibles;
- Las nuevas visitas en tiempo real llegan a Matomo;
- Los informes históricos no han desaparecido;
core:archivese ejecuta correctamente de forma manual;- Los registros de Caddy, Matomo y MariaDB no muestran errores persistentes.
No uses la etiqueta latest para actualizar automáticamente entre versiones mayores, ni hagas copia de seguridad solo del archivo Compose. Lo verdaderamente irremplazable es la base de datos, la configuración y los plugins que instalaste.
Primero comprueba si la base de datos está healthy:
docker compose ps
docker compose logs --tail=200 db
docker compose exec app getent hosts db
El nombre de host en el asistente de instalación debe ser db, y la cuenta, la contraseña y el nombre de la base de datos deben coincidir exactamente con el archivo Compose. Cambiar .env en una base de datos ya inicializada no restablece automáticamente la cuenta de la base de datos.
Confirma que el único punto de entrada es https://analytics.example.com, que Caddy pasa correctamente las cabeceras de reenvío y que assume_secure_protocol y force_ssl están configurados. No hagas que la CDN, Caddy y Matomo realicen cada uno redirecciones HTTP conflictivas al mismo tiempo.
Ejecuta core:archive manualmente y revisa /var/log/matomo-archive.log. Cuando crezca el tráfico, primero confirma si el archivado funciona, si hay espacio en disco suficiente y si MariaDB tiene consultas lentas, antes de añadir CPU a ciegas.
Confirma el X-Forwarded-For de Caddy y configura proxy_client_headers, proxy_host_headers y proxy_ip_read_last_in_list según la cadena de proxy real. Si además hay Cloudflare delante, confía solo en fuentes de proxy explícitas; nunca trates las cabeceras enviadas por clientes arbitrarios como la IP real.
En la pestaña Network de las herramientas de desarrollo del navegador, busca matomo.php y confirma que la solicitud no es un 404, un 403 ni está bloqueada por una política de seguridad de contenido. Luego revisa el ID del sitio, la URL de Matomo, los bloqueadores de anuncios y la configuración de "excluir tus propias visitas".
- Matomo solo escucha en
127.0.0.1:8080y MariaDB no mapea ningún puerto público - El dominio, HTTPS, los hosts de confianza y la configuración del proxy inverso son coherentes
- El administrador usa una contraseña fuerte y tiene habilitada la autenticación de dos factores cuando esté disponible
- Las visitas de prueba aparecen en visitantes en tiempo real
- El archivado CLI cada hora se ejecuta correctamente y los registros son observables
- La anonimización de IP, las cookies, la retención de datos y las políticas de exclusión están confirmadas
- Tanto la base de datos como
matomo_datatienen copias de seguridad externas - Se ha completado un simulacro de restauración y se ha registrado el tiempo de recuperación
- Hay copias de seguridad antes de las actualizaciones y se verifican el seguimiento y el archivado después
Una vez completados estos pasos, esta instalación de Matomo no es solo "la página se abre", sino un entorno de producción con HTTPS, persistencia, controles de privacidad, archivado automático y capacidad de recuperación. Para los equipos que valoran de verdad los datos propios y las conversiones del sitio web, este coste operativo es el precio del control de los datos.