Autoalojar Plausible Analytics en un VPS con Docker Compose

14 min de lectura·Matthieu·privacygdprdocker-composeanalyticsplausibleclickhouse|

Despliega Plausible Community Edition en tu VPS con Docker Compose. Guía completa que cubre instalación, integración del script de seguimiento, eventos personalizados, copias de seguridad y actualizaciones.

Plausible Analytics ofrece analítica web sin cookies, sin recopilación de datos personales y sin banners de consentimiento. Autoalojar la Community Edition significa que los datos de tus visitantes nunca salen de tu servidor. Esta guía cubre el ciclo de vida completo: despliegue de Plausible CE v3.2.0 con Docker Compose, integración del script de seguimiento, configuración de eventos personalizados, copias de seguridad y actualizaciones.

Requisitos previos: Un VPS con al menos 4 GB de RAM ejecutando Docker y Docker Compose Docker en producción en un VPS: qué falla y cómo solucionarlo, un nombre de dominio apuntando a tu servidor, y un reverse proxy gestionando TLS Traefik vs Caddy vs Nginx: reverse proxy Docker comparado.

¿Qué es Plausible Community Edition y en qué se diferencia de la versión Cloud?

Plausible CE es la versión autoalojada, gratuita y con licencia AGPL de Plausible Analytics. Se ejecuta como tres contenedores Docker: la aplicación web Plausible (Elixir), PostgreSQL para cuentas de usuario y ClickHouse para el almacenamiento de eventos analíticos. Obtienes el mismo panel de control respetuoso con la privacidad que la versión cloud de pago. Tus datos permanecen en tu servidor. La CE se publica dos veces al año como versión de soporte a largo plazo.

Las diferencias:

Característica Cloud Community Edition
Panel de analítica
Privacidad (sin cookies)
Eventos y objetivos personalizados
Stats API (v2)
Informes por correo Sí (requiere SMTP)
Funnels y objetivos de ingresos No
Sites API No
Conector Looker Studio No
Integración Google Search Console Sí (requiere configuración)
SSO / gestión de equipos No
Soporte premium Solo comunidad
Frecuencia de actualizaciones Semanal Dos veces al año
Gestión de infraestructura Gestionada Tú te encargas

La versión cloud funciona con un modelo de suscripción. Consulta la página de precios de Plausible para las tarifas actuales. El autoalojamiento solo te cuesta los recursos de tu VPS.

¿Cuáles son los requisitos del sistema para autoalojar Plausible?

ClickHouse es el componente más exigente. Necesita al menos 2 GB de RAM en reposo y consume más durante consultas complejas sobre grandes conjuntos de datos. La CPU debe soportar instrucciones SSE 4.2 (todos los procesadores x86_64 modernos lo hacen; ARM64 con NEON también funciona). Dimensiona tu VPS en consecuencia.

Recurso Mínimo Recomendado
RAM 2 GB 4 GB
CPU 1 vCPU (SSE 4.2) 2 vCPU
Disco 10 GB 20 GB+
Docker 20.10+ Última versión estable
Docker Compose v2.x Última versión estable

El crecimiento del disco depende del tráfico. Calcula aproximadamente 1 GB por cada 1-2 millones de páginas vistas almacenadas en ClickHouse. Con volúmenes bajos de tráfico (menos de 100.000 páginas vistas al mes), el uso de disco es insignificante.

¿Cómo se instala Plausible Analytics con Docker Compose?

Clona el repositorio oficial de la Community Edition en el tag v3.2.0, configura las variables de entorno e inicia los contenedores. El proceso completo lleva unos cinco minutos.

Clona el repositorio:

git clone -b v3.2.0 --single-branch https://github.com/plausible/community-edition plausible-ce
cd plausible-ce

Esto te da el compose.yml, los archivos de configuración de ClickHouse y un README.

¿Cómo se configuran las variables de entorno?

Crea un archivo .env en el directorio plausible-ce. Dos variables son obligatorias. El resto son opcionales, pero algunas se recomiendan encarecidamente.

Genera primero los secretos:

openssl rand -base64 48

Esto produce una cadena de 64 caracteres. Cópiala para SECRET_KEY_BASE.

Genera una clave separada para el cifrado TOTP:

openssl rand -base64 32

Ahora crea el archivo .env:

cat > .env << 'EOF'
BASE_URL=https://plausible.example.com
SECRET_KEY_BASE=<your-64-char-secret>
TOTP_VAULT_KEY=<your-32-char-key>
DISABLE_REGISTRATION=invite_only

# SMTP for email reports and password resets
MAILER_EMAIL=plausible@example.com
SMTP_HOST_ADDR=mail.example.com
SMTP_HOST_PORT=587
SMTP_USER_NAME=plausible@example.com
SMTP_USER_PWD=<your-smtp-password>
SMTP_HOST_SSL_ENABLED=false
EOF

Restringe los permisos del archivo ya que contiene secretos:

chmod 600 .env
ls -la .env
-rw------- 1 root root 412 Mar 20 10:00 .env

Qué hace cada variable:

  • BASE_URL: La URL pública donde Plausible es accesible. Debe coincidir con la configuración de tu reverse proxy.
  • SECRET_KEY_BASE: Cifra las sesiones y genera claves derivadas. Mínimo 64 bytes. Nunca la compartas.
  • TOTP_VAULT_KEY: Cifra los secretos de autenticación de dos factores con AES256-GCM. Si se omite, se deriva de SECRET_KEY_BASE vía PBKDF2, pero establecerla explícitamente es más seguro para la rotación de claves.
  • DISABLE_REGISTRATION: Establécelo en invite_only (por defecto) o true después de crear tu cuenta. Impide que desconocidos se registren en tu instancia.
  • Variables SMTP: Necesarias para informes por correo, restablecimiento de contraseña e invitaciones. Sin SMTP, Plausible funciona pero las funciones de correo están desactivadas.

¿Cómo se configura un reverse proxy con TLS para Plausible?

Plausible escucha en el puerto 8000 por defecto. Tu reverse proxy redirige el tráfico HTTPS hacia él. Si ya tienes Caddy o Traefik funcionando desde Traefik vs Caddy vs Nginx: reverse proxy Docker comparado, añade Plausible como nuevo upstream.

Crea un compose.override.yml para conectar Plausible a la red de tu reverse proxy:

services:
  plausible:
    networks:
      - proxy
      - default

networks:
  proxy:
    external: true

Si usas Caddy, añade esto a tu Caddyfile:

plausible.example.com {
    reverse_proxy plausible:8000
}

Si usas Traefik, añade labels al override:

services:
  plausible:
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.plausible.rule=Host(`plausible.example.com`)"
      - "traefik.http.routers.plausible.tls.certresolver=letsencrypt"
      - "traefik.http.services.plausible.loadbalancer.server.port=8000"
    networks:
      - proxy
      - default

networks:
  proxy:
    external: true

Alternativamente, Plausible tiene soporte integrado para Let's Encrypt. Establece HTTP_PORT=80 y HTTPS_PORT=443 en tu archivo .env, luego expón esos puertos en el override:

services:
  plausible:
    ports:
      - 80:80
      - 443:443

Este enfoque es más sencillo pero implica que Plausible gestiona TLS por sí mismo, lo que puede generar conflictos si otros servicios comparten el mismo servidor.

Iniciar los contenedores

docker compose up -d

Se inician tres contenedores: plausible_db (PostgreSQL 16), plausible_events_db (ClickHouse 24.12) y plausible (la aplicación web). El contenedor Plausible ejecuta las migraciones de base de datos automáticamente al arrancar.

Comprueba que los tres estén operativos:

docker compose ps
NAME                  IMAGE                                          STATUS
plausible             ghcr.io/plausible/community-edition:v3.2.0     Up 30s (healthy)
plausible_db          postgres:16-alpine                             Up 35s (healthy)
plausible_events_db   clickhouse/clickhouse-server:24.12-alpine      Up 35s (healthy)

Los tres deberían mostrar (healthy). Si ClickHouse muestra (health: starting), espera un minuto más. Ejecuta un healthcheck vía wget contra su interfaz HTTP.

Crear tu cuenta de administrador

Abre https://plausible.example.com en tu navegador. Verás el formulario de registro. Crea tu cuenta. Con DISABLE_REGISTRATION=invite_only, los nuevos usuarios solo pueden registrarse si los invitas explícitamente desde el panel de control.

Después del registro, bloquea completamente los registros si eres el único usuario:

Edita .env y cambia:

DISABLE_REGISTRATION=true

Luego reinicia:

docker compose up -d

¿Cómo se añade el script de seguimiento de Plausible a tu sitio?

Después de iniciar sesión, haz clic en «Add a website» e introduce tu dominio. Plausible genera un fragmento de código de seguimiento. La etiqueta script por defecto tiene este aspecto:

<script defer data-domain="yoursite.com" src="https://plausible.example.com/js/script.js"></script>

Reemplaza plausible.example.com con la URL real de tu instancia Plausible. Añade esta etiqueta al <head> de cada página que quieras rastrear.

¿Cómo se añade Plausible a un sitio HTML estático?

Pega la etiqueta script directamente en el <head> de tu HTML:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>My Site</title>
    <script defer data-domain="yoursite.com" src="https://plausible.example.com/js/script.js"></script>
</head>
<body>
    <!-- content -->
</body>
</html>

Para generadores de sitios estáticos (Hugo, Jekyll, 11ty), añade la etiqueta script a tu plantilla base o partial head.

¿Cómo se añade Plausible a un sitio WordPress?

El plugin oficial Plausible Analytics para WordPress (v2.5.4, más de 10.000 instalaciones activas) gestiona todo desde el panel de WordPress.

  1. Instala el plugin: Plugins > Añadir nuevo > Buscar «Plausible Analytics»
  2. Ve a Ajustes > Plausible Analytics
  3. Introduce la URL de tu instancia autoalojada (ej. https://plausible.example.com)
  4. Introduce el nombre de dominio a rastrear
  5. Guarda

El plugin inyecta el script de seguimiento automáticamente. También soporta seguimiento de conversiones WooCommerce y seguimiento automático de envíos de formularios para Contact Form 7, WPForms y Ninja Forms.

¿Cómo se añade Plausible a una aplicación Next.js?

Usa el paquete next-plausible (v3.12.5, 36.000 descargas semanales).

npm i next-plausible

Para el App Router (Next.js 13+), añade el provider en tu layout raíz:

import PlausibleProvider from "next-plausible";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <head>
        <PlausibleProvider
          domain="yoursite.com"
          customDomain="https://plausible.example.com"
          selfHosted
        />
      </head>
      <body>{children}</body>
    </html>
  );
}

Para rastrear eventos personalizados en componentes, usa el hook usePlausible:

"use client";
import { usePlausible } from "next-plausible";

export default function SignupButton() {
  const plausible = usePlausible();
  return (
    <button onClick={() => plausible("Signup")}>
      Sign up
    </button>
  );
}

¿Cómo se añade Plausible a una aplicación de página única?

Para React, Vue, Svelte o cualquier SPA, añade la etiqueta script a tu index.html. Plausible detecta automáticamente los cambios de ruta a través de la History API. No se necesita configuración adicional.

Si tu SPA usa enrutamiento basado en hash (/#/path), usa la extensión hash:

<script defer data-domain="yoursite.com" src="https://plausible.example.com/js/script.hash.js"></script>

¿Cómo se rastrean eventos personalizados y objetivos en Plausible?

Los eventos personalizados permiten rastrear acciones más allá de las páginas vistas: clics en botones, envíos de formularios, descargas de archivos, registros. Plausible ofrece dos métodos: un enfoque sin código mediante clases CSS y una API JavaScript para seguimiento dinámico.

Primero, activa el script mejorado que soporta eventos personalizados. Reemplaza la fuente del script por defecto:

<script defer data-domain="yoursite.com" src="https://plausible.example.com/js/script.tagged-events.js"></script>

Método de clases CSS (sin JavaScript)

Añade una clase CSS con el formato plausible-event-name=EventName a cualquier elemento HTML:

<a href="/signup" class="plausible-event-name=Signup">Create Account</a>

<button class="plausible-event-name=Download+PDF">Download Report</button>

<form class="plausible-event-name=Contact+Form+Submit">
  <!-- form fields -->
</form>

Usa + para espacios en los nombres de eventos. Algunos CMS (Webflow) reemplazan = por -. En ese caso, usa un doble guion --: plausible-event-name--Signup.

API JavaScript para eventos dinámicos

Llama a la función plausible() directamente para eventos que necesiten lógica condicional o propiedades dinámicas:

// Simple event
plausible("Signup");

// Event with custom properties
plausible("Download", {
  props: { format: "PDF", document: "annual-report" }
});

// Event with a callback (useful for redirects)
plausible("Outbound Link", {
  props: { url: "https://example.com" },
  callback: () => { window.location = "https://example.com"; }
});

Crear el objetivo en tu panel de control

Los eventos no aparecen en tu panel de control hasta que crees un objetivo correspondiente. Ve a Site Settings > Goals > Add Goal. Selecciona «Custom event» e introduce el nombre exacto del evento (ej. Signup). El nombre distingue entre mayúsculas y minúsculas y debe coincidir con tu código.

¿Cómo se usa la Stats API de Plausible?

Plausible incluye una Stats API (v2) para acceder a tus datos analíticos de forma programática. En tu instancia autoalojada, la URL base de la API es https://plausible.example.com/api/v2/query.

Crea una clave API: ve a Account Settings > API Keys > New API Key > Stats API.

Consulta el número de visitantes de los últimos 7 días:

curl --request POST \
  --header 'Authorization: Bearer YOUR-API-KEY' \
  --header 'Content-Type: application/json' \
  --url 'https://plausible.example.com/api/v2/query' \
  --data '{
    "site_id": "yoursite.com",
    "metrics": ["visitors", "pageviews", "bounce_rate"],
    "date_range": "7d"
  }'
{
  "results": [
    {
      "metrics": [1423, 3847, 42],
      "dimensions": []
    }
  ],
  "query": {
    "site_id": "yoursite.com",
    "metrics": ["visitors", "pageviews", "bounce_rate"],
    "date_range": ["2026-03-13", "2026-03-20"]
  }
}

Desglose de visitantes por página:

curl --request POST \
  --header 'Authorization: Bearer YOUR-API-KEY' \
  --header 'Content-Type: application/json' \
  --url 'https://www.example.com/api/v2/query' \
  --data '{
    "site_id": "yoursite.com",
    "metrics": ["visitors", "pageviews"],
    "date_range": "30d",
    "dimensions": ["event:page"],
    "pagination": {"limit": 5}
  }'

La API soporta filtrado, dimensiones temporales (time:day, time:month) y ordenación. El límite de tasa es de 600 peticiones por hora. Consulta la referencia completa de la Stats API para todas las métricas y dimensiones disponibles.

¿Cómo se configuran los informes por correo?

Los informes por correo requieren una configuración SMTP funcional en tu archivo .env (cubierta en la sección de configuración anterior). Una vez configurado SMTP, cualquier usuario puede activar informes semanales o mensuales desde el panel de Plausible.

Ve a Site Settings > Email Reports. Añade las direcciones de los destinatarios. Plausible envía un resumen de visitantes, páginas más visitadas y fuentes de tráfico en la frecuencia que elijas.

Si los correos no llegan, revisa los logs del contenedor Plausible:

docker compose logs plausible | grep -i mail

Problemas habituales: puerto SMTP incorrecto (usa 587 para STARTTLS, 465 para TLS implícito con SMTP_HOST_SSL_ENABLED=true), o fallos de autenticación.

¿Cómo se hace una copia de seguridad de una instancia Plausible autoalojada?

Plausible almacena datos en dos bases de datos y un volumen. Perder cualquiera de ellos significa perder datos. Haz copia de seguridad de los tres.

Datos Almacenamiento Método de backup
Cuentas de usuario, configuración de sitios PostgreSQL pg_dump
Eventos analíticos ClickHouse Backup de volumen o comando BACKUP
Certificados, uploads Volumen plausible-data Copia de volumen

Copia de seguridad de PostgreSQL

docker compose exec plausible_db pg_dump -U postgres plausible_db | gzip > backup-postgres-$(date +%F).sql.gz

Copia de seguridad de ClickHouse

ClickHouse 24.12 soporta el comando BACKUP de forma nativa. Ejecútalo dentro del contenedor:

docker compose exec plausible_events_db clickhouse-client \
  --query "BACKUP DATABASE plausible_events_db TO Disk('backups', 'plausible-$(date +%F).zip')"

Si el disco backups no está configurado, usa un backup a nivel de volumen:

docker compose stop plausible_events_db
docker run --rm \
  -v plausible-ce_event-data:/source:ro \
  -v $(pwd)/backups:/backup \
  alpine tar czf /backup/clickhouse-$(date +%F).tar.gz -C /source .
docker compose start plausible_events_db

Esto detiene ClickHouse brevemente. Para copias de seguridad sin tiempo de inactividad, configura el disco backups en ClickHouse o usa clickhouse-backup.

Automatización

Crea un script en /opt/plausible-backup.sh:

#!/bin/bash
set -euo pipefail
BACKUP_DIR=/opt/backups/plausible
mkdir -p "$BACKUP_DIR"
cd /opt/plausible-ce

# PostgreSQL
docker compose exec -T plausible_db pg_dump -U postgres plausible_db \
  | gzip > "$BACKUP_DIR/postgres-$(date +%F).sql.gz"

# ClickHouse volume
docker run --rm \
  -v plausible-ce_event-data:/source:ro \
  -v "$BACKUP_DIR":/backup \
  alpine tar czf "/backup/clickhouse-$(date +%F).tar.gz" -C /source .

# Plausible data volume
docker run --rm \
  -v plausible-ce_plausible-data:/source:ro \
  -v "$BACKUP_DIR":/backup \
  alpine tar czf "/backup/plausible-data-$(date +%F).tar.gz" -C /source .

# Rotate: keep 14 days
find "$BACKUP_DIR" -name "*.gz" -mtime +14 -delete

echo "Backup complete: $(ls -lh $BACKUP_DIR/*$(date +%F)*)"
chmod 700 /opt/plausible-backup.sh

Prográmalo con cron para ejecución diaria:

crontab -e

Añade:

0 3 * * * /opt/plausible-backup.sh >> /var/log/plausible-backup.log 2>&1

Para más información sobre estrategias de backup de volúmenes Docker, consulta Copia de seguridad y restauración de volúmenes Docker en un VPS.

¿Cómo se actualiza Plausible Community Edition de forma segura?

Plausible CE se publica dos veces al año. Fija tu versión a un tag específico en compose.yml para actualizaciones predecibles. La configuración por defecto ya fija la versión v3.2.0.

Estrategias de fijación de versión:

Nivel Ejemplo de tag Qué se actualiza automáticamente
Patch (más seguro) v3.2.0 Nada. Solo actualizaciones manuales.
Minor v3.2 Releases de corrección (bugfixes)
Major v3 Releases minor y de corrección

Recomendado: fija a nivel de patch y actualiza manualmente tras leer las notas de la versión.

Procedimiento de actualización

  1. Lee las notas de la versión en busca de cambios incompatibles

  2. Haz copia de seguridad de tus bases de datos (ejecuta el script de backup anterior)

  3. Descarga la nueva versión:

cd /opt/plausible-ce
git fetch --tags
git checkout v3.3.0  # replace with the target version
  1. Inicia los contenedores actualizados:
docker compose up -d

Plausible ejecuta las migraciones de base de datos automáticamente al arrancar. Observa los logs durante el primer inicio:

docker compose logs -f plausible

Busca [info] Migrations up to XXXXXXXX applied successfully en la salida. Si ves errores de migración, no descartes los datos antiguos. Consulta la página wiki de actualización para instrucciones específicas por versión.

  1. Limpia la imagen antigua:
docker image prune -f

Los parches de seguridad no se retroportan a versiones anteriores. Suscríbete a las notificaciones de releases en GitHub: ve al repositorio, haz clic en Watch > Custom > Releases.

¿Es Plausible autoalojado compatible con el RGPD sin cookies?

Sí. Plausible no establece cookies. No recopila ni almacena datos personales. Los visitantes únicos se cuentan mediante un hash de la dirección IP del visitante combinada con la cadena User-Agent. Este hash se renueva cada 24 horas y nunca se almacena en bruto. La dirección IP sin procesar se descarta después del hashing.

Esto significa:

  • No se necesita banner de consentimiento de cookies bajo el RGPD, CCPA o PECR
  • No hay tratamiento de datos personales, por lo que los requisitos de base legal del artículo 6 del RGPD no aplican
  • El autoalojamiento garantiza que los datos nunca salen de tu servidor ni pasan por un encargado de tratamiento externo
  • Sigues siendo el único responsable del tratamiento, sin necesidad de contratos de encargado de tratamiento para analítica

Si alojas tu VPS en la UE (los servidores de Virtua Cloud están ubicados en centros de datos europeos), tus datos analíticos permanecen en la UE. Sin problemas de transferencia relacionados con Schrems II.

Por eso muchos desarrolladores independientes y preocupados por la privacidad abandonan Google Analytics. Sin banners de consentimiento, sin fricción para los visitantes y sin contratos de encargado de tratamiento que gestionar.

Monitorizar el consumo de recursos de ClickHouse

ClickHouse es el componente que más recursos consume. En reposo con bajo tráfico, usa alrededor de 500 MB de RAM. Durante consultas sobre grandes conjuntos de datos, puede llegar a 2-3 GB. Si tu VPS tiene solo 2 GB de RAM total, puedes sufrir OOM kills en periodos de carga.

Monitoriza el uso de memoria:

docker stats plausible_events_db --no-stream
CONTAINER ID   NAME                  CPU %   MEM USAGE / LIMIT   MEM %
a1b2c3d4e5f6   plausible_events_db   0.50%   487MiB / 3.84GiB    12.38%

La configuración de ClickHouse incluida con Plausible CE ya contiene ajustes para entornos con recursos limitados (vía low-resources.xml y default-profile-low-resources-overrides.xml). Estos limitan el uso de memoria para merges y consultas.

Si necesitas ajustar más, crea un archivo clickhouse/custom.xml y móntalo en compose.override.yml. Para límites de recursos en Docker Compose, consulta Límites de recursos, healthchecks y políticas de reinicio en Docker Compose.

Revisa los logs de ClickHouse en busca de advertencias:

docker compose logs plausible_events_db | grep -i "memory\|oom"

¿Algo no funciona?

Los contenedores no arrancan: Revisa docker compose logs <service>. Causas habituales: conflictos de puertos, variables .env faltantes, ClickHouse fallando la comprobación SSE 4.2 en CPUs antiguas.

«Bad Request» en la página de login: Tu BASE_URL no coincide con la URL que estás usando. Plausible verifica la cabecera origin contra BASE_URL para prevenir ataques CSRF.

El script de seguimiento no registra visitas: Abre las herramientas de desarrollo del navegador, revisa la pestaña Red para peticiones a /api/event. Una respuesta 202 significa que el evento fue aceptado. Si ves errores CORS, tu reverse proxy está eliminando cabeceras. Asegúrate de que el proxy pase la cabecera Host.

Los informes por correo no se envían: Verifica las credenciales SMTP. Revisa los logs con docker compose logs plausible | grep -i smtp. Prueba tu servidor SMTP de forma independiente con swaks o openssl s_client.

ClickHouse terminado por el OOM killer: Tu VPS no tiene suficiente RAM. Actualiza a al menos 4 GB, o reduce max_memory_usage en una configuración personalizada de ClickHouse.

El panel muestra cero visitantes después de la instalación: El script de seguimiento puede estar bloqueado por bloqueadores de anuncios. Considera hacer proxy del script a través de tu dominio principal. La documentación de Plausible lo llama proxy setup.

Para monitorizar la disponibilidad de tu instancia Plausible, consulta Auto-alojar Uptime Kuma y Beszel en un VPS con Docker Compose.