Changedetection.io es una aplicación de código abierto que revisa páginas web a intervalos fijos y te avisa cuando su contenido cambia. Sirve para vigilar precios, disponibilidad de productos, avisos legales o páginas de estado sin depender de un servicio externo. En este tutorial la desplegarás con Docker Compose en Ubuntu 24.04, junto a un navegador Chromium para páginas que cargan contenido con JavaScript, la publicarás detrás de Nginx con HTTPS y configurarás filtros y notificaciones.

Requisitos previos

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 1 GB de RAM (el navegador Chromium consume la mayor parte).
  • Un usuario no root con privilegios sudo.
  • Docker Engine y el plugin de Docker Compose instalados desde el repositorio oficial de Docker.
  • Un dominio o subdominio, por ejemplo cambios.your_domain, con un registro A apuntando a la IP del servidor.
  • Los puertos 80 y 443 abiertos en el firewall.

Paso 1: Crear el archivo de Docker Compose

Changedetection.io guarda toda su configuración y el historial de cambios en un directorio de datos. Crea un directorio para el proyecto:

sudo mkdir -p /opt/changedetection
cd /opt/changedetection

Crea el archivo de Compose:

sudo nano /opt/changedetection/compose.yaml

Añade el siguiente contenido. El servicio sockpuppetbrowser es el Chromium que mantiene el propio proyecto para renderizar páginas con JavaScript:

services:
  changedetection:
    image: ghcr.io/dgtlmoon/changedetection.io:latest
    container_name: changedetection
    hostname: changedetection
    volumes:
      - ./datastore:/datastore
    environment:
      - BASE_URL=https://cambios.your_domain
      - PLAYWRIGHT_DRIVER_URL=ws://sockpuppetbrowser:3000
    ports:
      - "127.0.0.1:5000:5000"
    depends_on:
      - sockpuppetbrowser
    restart: unless-stopped

  sockpuppetbrowser:
    image: dgtlmoon/sockpuppetbrowser:latest
    hostname: sockpuppetbrowser
    cap_add:
      - SYS_ADMIN
    environment:
      - SCREEN_WIDTH=1920
      - SCREEN_HEIGHT=1024
      - SCREEN_DEPTH=16
      - MAX_CONCURRENT_CHROME_PROCESSES=10
    restart: unless-stopped

Sustituye cambios.your_domain por tu dominio. BASE_URL se usa para generar los enlaces que aparecen en las notificaciones. El puerto 5000 solo escucha en 127.0.0.1, así que la aplicación no queda expuesta a Internet hasta que la publiques con Nginx.

Paso 2: Arrancar los contenedores

Descarga las imágenes y arranca los servicios en segundo plano:

sudo docker compose up -d

Comprueba que los dos contenedores están en marcha:

sudo docker compose ps
NAME                                  IMAGE                                        STATUS
changedetection                       ghcr.io/dgtlmoon/changedetection.io:latest   Up 20 seconds
changedetection-sockpuppetbrowser-1   dgtlmoon/sockpuppetbrowser:latest            Up 21 seconds

Verifica que la aplicación responde en local:

curl -sI http://127.0.0.1:5000 | head -n 1
HTTP/1.1 200 OK

Si no responde, revisa los logs con sudo docker compose logs changedetection.

Paso 3: Publicar la aplicación con Nginx y HTTPS

Instala Nginx y Certbot con su plugin para Nginx:

sudo apt update
sudo apt install nginx certbot python3-certbot-nginx

Crea el bloque de servidor:

sudo nano /etc/nginx/sites-available/changedetection
server {
    listen 80;
    listen [::]:80;
    server_name cambios.your_domain;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Las cabeceras Upgrade y Connection permiten el WebSocket que usa la interfaz para actualizar el estado de las comprobaciones en tiempo real. Activa el sitio, valida la sintaxis y recarga Nginx:

sudo ln -s /etc/nginx/sites-available/changedetection /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Abre los puertos web en UFW y solicita el certificado. Certbot modifica el bloque de servidor para servir HTTPS y redirigir HTTP:

sudo ufw allow 'Nginx Full'
sudo certbot --nginx -d cambios.your_domain

Abre https://cambios.your_domain en el navegador. Deberías ver la página principal con el campo para añadir una URL.

Paso 4: Proteger el panel con contraseña

Por defecto el panel no pide contraseña, así que cualquiera que conozca la URL podría usarlo. Ve a Settings > General, rellena el campo Password protection con una contraseña robusta y guarda. A partir de ese momento el panel pedirá la contraseña al entrar.

En la misma pestaña puedes ajustar el intervalo de comprobación por defecto (Time between check). Evita intervalos muy cortos: comprobar una web cada pocos minutos aumenta la carga y puede provocar que el sitio vigilado bloquee la IP de tu servidor.

Paso 5: Añadir la primera vigilancia

Cada URL vigilada se llama watch. En la página principal, escribe la URL en el campo superior, añade una etiqueta opcional (por ejemplo precios) y pulsa Watch. Changedetection.io hará una primera captura y a partir de ahí comparará cada comprobación con la anterior.

Para páginas que cargan el contenido con JavaScript (tiendas en React o Vue, por ejemplo), edita el watch y, en la pestaña Request, cambia el Fetch Method a la opción de Playwright/Chrome. Así la página se renderiza en el contenedor sockpuppetbrowser antes de compararse. El método HTTP simple es más rápido y consume menos memoria, así que úsalo siempre que la página funcione sin JavaScript.

Para comprobar que funciona, pulsa Recheck en el watch y abre Preview: debes ver el texto extraído de la página.

Paso 6: Filtrar solo la parte que te interesa

Vigilar una página completa genera falsos positivos por cambios en menús, banners o fechas. Edita el watch y ve a la pestaña Filters & Triggers. En el campo CSS/JSONPath/JQ/XPath Filters indica un selector por línea. Por ejemplo, para vigilar solo el precio de un producto:

.product-price

Los selectores XPath empiezan por // o por el prefijo xpath::

//span[@itemprop='price']

Para averiguar el selector correcto, abre la página en tu navegador, pulsa con el botón derecho sobre el elemento y usa Inspeccionar.

En el campo Ignore text puedes descartar líneas que cambian siempre. Las expresiones regulares se escriben entre barras. Este ejemplo ignora fechas y contadores de visitas:

/\d{1,2}\/\d{1,2}\/\d{4}/
/\d+ visitas/

Guarda y pulsa Recheck. En Preview solo debe aparecer el contenido que coincide con el filtro.

Paso 7: Configurar notificaciones

Changedetection.io envía los avisos con Apprise, que admite decenas de servicios mediante URLs. Ve a Settings > Notifications y añade una URL por línea en Notification URL List. Algunos formatos habituales:

tgram://your_bot_token/your_chat_id
discord://your_webhook_id/your_webhook_token
mailtos://your_user:[email protected]_domain?to=alertas@your_domain
ntfys://ntfy.sh/your_topic

Estos valores son marcadores de posición: sustitúyelos por el token de tu bot de Telegram, tu webhook de Discord o los datos de tu servidor SMTP. Pulsa Send test notification para comprobar que el aviso llega antes de guardar.

El cuerpo del mensaje admite variables, por ejemplo:

Cambio detectado en {{watch_title}}
{{watch_url}}

{{diff}}

Ver diferencias: {{diff_url}}

La configuración de Settings se aplica a todos los watches. Si un watch necesita un destino distinto, edítalo y define sus propias URLs en su pestaña Notifications.

Paso 8: Usar la API (opcional)

La API REST permite dar de alta watches desde scripts. Obtén la clave en Settings > API y guárdala en una variable:

export CD_API_KEY=your_api_key

Crea un watch nuevo:

curl -s -X POST "https://cambios.your_domain/api/v1/watch" \
  -H "x-api-key: $CD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/precios", "title": "Precios de example.com"}'
{"uuid": "3f1b2c1e-8d4a-4a7e-9c2b-5b7e1f0a9d12"}

Lista los watches existentes para confirmar que se ha creado:

curl -s "https://cambios.your_domain/api/v1/watch" -H "x-api-key: $CD_API_KEY"

Paso 9: Copias de seguridad y actualizaciones

Todos los datos están en /opt/changedetection/datastore. Para hacer una copia, detén el servicio un momento y empaqueta el directorio:

cd /opt/changedetection
sudo docker compose stop changedetection
sudo tar czf /root/changedetection-$(date +%F).tar.gz datastore
sudo docker compose start changedetection

Para actualizar a la última versión, descarga las imágenes nuevas y recrea los contenedores:

sudo docker compose pull
sudo docker compose up -d

Solución de problemas

Las páginas con JavaScript aparecen vacías. Comprueba que el watch usa el fetcher de Playwright/Chrome y que el contenedor del navegador está en marcha con sudo docker compose ps. Revisa sus logs con sudo docker compose logs sockpuppetbrowser --tail 50.

El sitio vigilado devuelve 403 o un captcha. Algunas webs bloquean peticiones automatizadas. Aumenta el intervalo de comprobación y prueba con el fetcher de Chrome, que se parece más a un navegador real.

Las notificaciones no llegan. Usa Send test notification y revisa el mensaje de error que muestra la interfaz. Los fallos más comunes son tokens mal copiados y servidores SMTP que exigen mailtos:// (TLS) en lugar de mailto://.

Demasiados avisos por cambios irrelevantes. Restringe el watch con un filtro CSS o XPath y añade patrones en Ignore text.

Conclusión

Tienes Changedetection.io funcionando en Docker detrás de Nginx con HTTPS, con renderizado de JavaScript, filtros para reducir falsos positivos y avisos por el canal que prefieras. Como siguientes pasos puedes usar Browser Steps para vigilar páginas que requieren hacer clic o iniciar sesión, organizar los watches por etiquetas con notificaciones propias y programar la copia de datastore con un temporizador de systemd.