En resumen. Boop es un buzón de notificaciones autohospedado que envía eventos de tus apps a tu iPhone. Se ejecuta como un solo binario de Go con una base de datos SQLite, se despliega con docker compose up -d --build y escucha en el puerto 8080. Las notificaciones van de tu servidor a APNs de Apple sin un relay alojado. Necesitas una cuenta de Apple Developer para compilar y firmar la app de iOS.
La mayoría de los servicios de seguimiento de errores te piden registrarte, enviar los stack traces a su cloud y pagar por usuario cuando termina el nivel gratuito. Boop sigue otra ruta. Un buzón de notificaciones autohospedado es un servidor pequeño que administras, recibe eventos de tus aplicaciones y los reenvía a tu celular como notificaciones push, sin terceros de por medio.
Boop tiene licencia MIT, está escrito en Go y guarda todo en un solo archivo SQLite. Un ejemplo práctico: tu pg_dump nocturno termina, un curl de una línea envía el resultado a Boop y, un segundo después, tu celular vibra con «Backup complete». Esta guía explica cómo desplegar Boop en un VPS, conectarlo con las notificaciones push de Apple y enviar tu primer evento.
Qué necesitas antes de comenzar
El servidor exige pocos recursos: un host Docker con un nombre de host público. La configuración de Apple toma más tiempo porque tú mismo compilas y firmas la app de iOS.
- Un servidor Linux con Docker Engine y el plugin Docker Compose. El servidor de Boop es pequeño. El autor del proyecto indica que usa cerca de 8 MB de memoria en su propia máquina.
- Un dominio o subdominio que apunte al servidor y use HTTPS. Tu celular obtiene del servidor los detalles completos de cada evento, así que debe ser accesible desde fuera de tu red.
- Una cuenta de Apple Developer, una Mac con Xcode y un iPhone con iOS 26. La app de Boop para iOS es open source y tú mismo la compilas y firmas.
- Acceso root o mediante
sudopor SSH y unos 30 minutos.
Paso 1: Ejecuta Boop con Docker
Boop queda disponible en el puerto 8080 después de clonar el repositorio y ejecutar un comando de Compose. El paso que muchos omiten es crear el directorio de datos:
git clone https://github.com/chrisgreg/boop && cd boop
cp .env.example .env
mkdir -p data && chown 1000:1000 data
docker compose up -d --buildLa línea chown 1000:1000 es necesaria en hosts Linux. La imagen se ejecuta con el uid 1000. Si root crea el directorio montado mediante bind, SQLite no puede escribir en /data/boop.db.
Comprueba que el servidor esté activo:
curl http://localhost:8080/healthUn servidor en buen estado devuelve {"status":"ok"}. La interfaz web escucha en el puerto 8080, pero un VPS no tiene un escritorio desde el cual abrirla. Reenvía el puerto a tu computadora mediante SSH:
ssh -L 8080:localhost:8080 you@your-serverDeja abierta esa sesión y carga http://localhost:8080 en el navegador de tu laptop. Aparecerá el asistente de configuración: comprobación del servidor, APNs, vinculación, tu primer proyecto y una notificación de prueba.
Usa el túnel en lugar de exponer el puerto 8080 a internet. Todavía no configuraste las credenciales de administración y, hasta que lo hagas en el paso 2, cualquiera que encuentre el host podrá acceder a los endpoints administrativos de ese puerto. El túnel mantiene la interfaz fuera de internet durante la configuración inicial. Como alternativa, vincula el puerto publicado a loopback. Cambia la entrada ports de Compose a 127.0.0.1:8080:8080 y accede a la interfaz mediante el proxy inverso después de completar el paso 2.
Las credenciales de APNs son opcionales en esta etapa. Sin ellas, los eventos se almacenan y aparecen en la interfaz web, pero se omiten las notificaciones push. Así puedes probar tus integraciones antes de entrar al portal de Apple Developer.
Si prefieres no ejecutar Docker, cada versión ofrece otra opción: un binario estático sin dependencias para Linux en amd64 y arm64, con la interfaz web integrada. Configura BOOP_DATABASE_PATH con una ubicación que permita escritura, ya que el valor predeterminado es /data/boop.db:
BOOP_DATABASE_PATH=./boop.db ./boopPaso 2: Protege Boop con HTTPS y restringe la interfaz de administración
Configura BOOP_ADMIN_USER y BOOP_ADMIN_PASSWORD antes de que el servidor sea accesible desde internet. Si dejas ambas variables sin configurar, cualquiera que encuentre el host podrá acceder a todos los endpoints administrativos. Esa decisión es intencional para quienes ejecutan Boop detrás de Tailscale o una VPN, pero resulta insegura por accidente en una IP pública.
En .env:
BOOP_BASE_URL=https://boop.example.com
BOOP_ADMIN_USER=you
BOOP_ADMIN_PASSWORD=a-long-password-hereBOOP_BASE_URL tiene más importancia de la que parece. Es la URL incluida en el código QR de vinculación. Si todavía apunta a localhost, tu celular escaneará un código que apunta al propio dispositivo.
Coloca delante un proxy inverso con un certificado válido. Nginx y Caddy funcionan. El servidor solo necesita que el tráfico se reenvíe al puerto 8080. Reinícialo para aplicar los cambios:
docker compose up -dLas sesiones de administración duran 30 días y se guardan en memoria, por lo que reiniciar el servidor cierra tu sesión. Los endpoints administrativos rechazan las credenciales de proyectos y dispositivos. Una clave de API filtrada desde una app nunca concede permisos de administración.
Paso 3: Configura las notificaciones push de Apple
APNs requiere cuatro elementos del portal de Apple Developer: tu Team ID, el Key ID de una clave de autenticación de APNs, el bundle ID de tu compilación de Boop y el propio archivo de clave .p8.
- Crea un identificador de App para tu compilación de Boop para iOS y habilita Push Notifications.
- En Keys, crea una clave de autenticación de APNs y descarga el archivo
.p8. Apple solo permite descargarlo una vez. - Anota el Key ID y el Team ID que aparecen en la esquina superior derecha del portal.
En el servidor, coloca la clave en ./secrets/apns.p8, quita el comentario del volumen de secretos en docker-compose.yml y completa .env:
APNS_TEAM_ID=XXXXXXXXXX
APNS_KEY_ID=XXXXXXXXXX
APNS_BUNDLE_ID=com.example.boop
APNS_PRIVATE_KEY_PATH=/run/secrets/apns.p8
APNS_ENVIRONMENT=productionReinicia con docker compose up -d. La página de configuración debería indicar que APNs está configurado. Si no es así, consulta la sección de solución de problemas antes de generar claves nuevas.
Paso 4: Compila la app de iOS y vincula tu celular
La app de Boop para iOS no está en la App Store, así que debes compilarla y firmarla en Xcode. Abre ios/Boop.xcodeproj, establece tu equipo de desarrollo y el mismo bundle ID que agregaste en APNS_BUNDLE_ID. Después, instala la compilación en tu celular. La app está dirigida a iOS 26 e incluye una extensión de servicio de notificaciones.
La vinculación usa un código QR de un solo uso. En la interfaz web, ve a Devices, elige Pair iPhone y escanea el código con la app. El payload es pequeño:
{"version": 1, "server": "https://boop.example.com", "token": "pair_..."}El token es válido durante 10 minutos, funciona una sola vez y puede revocarse. La app lo intercambia por una credencial de dispositivo, se registra en APNs y envía su token al servidor. Comprueba toda la cadena desde Settings y después selecciona Send test notification. Si tu celular vibra, todo el recorrido funciona.
Paso 5: Envía tu primer evento
La integración solo requiere una solicitud POST a /api/v1/events con la clave de API de un proyecto. Crea un proyecto en la interfaz web y copia su clave, que se muestra una sola vez:
curl https://boop.example.com/api/v1/events \
-H "Authorization: Bearer boop_proj_..." \
-H "Content-Type: application/json" \
-d '{"title": "Deploy complete", "level": "success"}'Una llamada correcta devuelve {id, created_at}. Los niveles son info, success, warning, error y critical.
Los eventos con más información incluyen datos estructurados. Boop representa correctamente secciones reconocidas como exception, stacktrace, tags, context y breadcrumbs. Tras ocultar los datos sensibles, conserva cualquier otro contenido sin cambios:
curl https://boop.example.com/api/v1/events \
-H "Authorization: Bearer boop_proj_..." \
-H "Content-Type: application/json" \
-d '{
"title": "KeyError", "body": "key :can_palette? not found",
"level": "error", "source": "error_tracker", "fingerprint": "uini-keyerror",
"data": {
"exception": {"type": "KeyError", "message": "key :can_palette? not found"},
"tags": {"environment": "production"}
}
}'Si lo incluyes en una función de shell, podrás usarlo desde cualquier tarea cron o script de despliegue:
boop() { curl -fsS "$BOOP_URL/api/v1/events" -H "Authorization: Bearer $BOOP_API_KEY" \
-H "Content-Type: application/json" -d "{\"title\": \"$1\", \"body\": \"${2:-}\", \"level\": \"${3:-info}\"}"; }
pg_dump mydb > backup.sql && boop "Backup complete" "" success || boop "Backup failed" "$(tail -1 backup.log)" errorExisten bibliotecas cliente para Elixir y Node.js, además de un paquete de Laravel mantenido por la comunidad. Boop también admite el protocolo de ingesta de Sentry. Un SDK de Sentry del lado del servidor puede enviarle reportes si SENTRY_DSN apunta a tu host de Boop y usa una clave de API de proyecto como clave pública. Mantén ese DSN en el servidor. A diferencia de una clave pública real de Sentry, una clave de proyecto de Boop puede escribir eventos.
Configuración para el primer día
Cuatro ajustes te evitarán problemas después: retención, ocultamiento de datos, acciones y silencios.
Retención. El valor predeterminado de BOOP_RETENTION_DAYS es 90. Configúralo como 0 para conservar los eventos de forma indefinida. La variable de entorno sobrescribe en cada inicio cualquier valor guardado en la interfaz web. Déjala sin configurar si quieres administrar la retención desde Settings.
Ocultamiento de datos. Los valores de claves como password, secret, token, api_key, authorization y private_key se sustituyen por [REDACTED] antes del almacenamiento. La coincidencia no distingue mayúsculas de minúsculas y trata - y _ de la misma forma. Agrega tus propias claves en Settings.
Acciones. Un evento puede incluir hasta tres botones que abran una URL. Aparecen tanto en la notificación como en los detalles del evento. Las etiquetas admiten hasta 40 caracteres y las URL deben ser absolutas. Un botón «Open in Stripe» en un evento de pago reduce cuatro pasos a un solo toque.
Silencios. Una tarea que falla de forma intermitente no tiene que despertarte. Haz clic en Silence events like this en cualquier evento y establece coincidencias por fingerprint, título o fuente, para un proyecto o para todos. Los eventos coincidentes siguen llegando al buzón marcados como silenciados, pero no se envía ninguna notificación push.
La agrupación funciona junto con los silencios. Envía el mismo fingerprint para el mismo problema y el buzón lo agrupará en una fila con KeyError ×47 · First seen 09:31 · Last seen 10:42. Cada ocurrencia sigue almacenándose y enviándose por push. La agrupación solo ordena la presentación, no modifica las alertas.
Dónde ejecutar Boop
Un VPS pequeño es un buen lugar para Boop. La carga consiste en un solo proceso de Go que escribe en un archivo SQLite, además de conexiones TLS ocasionales hacia Apple. El consumo de CPU y memoria es mínimo. Lo que sí importa es tener una dirección pública estable y buen uptime, porque tu celular obtiene del servidor los detalles completos del evento cada vez que abres una notificación.
Core VPS es la línea de Contabo optimizada en costos para cargas constantes y de baja demanda como esta. Cloud VPS 4 incluye 8 GB de RAM, mucho más de lo que Boop necesita, y deja capacidad para tu proxy inverso y otros servicios autohospedados en el mismo servidor.
Respalda data/boop.db con un snapshot coherente en lugar de copiar el archivo directamente:
sqlite3 data/boop.db ".backup backup.db"Guarda un respaldo de la clave .p8 separado de la base de datos. Si la pierdes, tendrás que generar una clave APNs nueva y volver a vincular tus dispositivos.
Solución de problemas: cuatro fallas frecuentes
La mayoría de los problemas de Boop se deben a la configuración y no a errores del software. Cuatro casos concentran gran parte de los reportes.
APNs sigue apareciendo sin configurar después de un despliegue. Causa: APNS_PRIVATE_KEY_PATH tiene un valor, pero no existe un archivo en esa ruta. Esto ocurre cuando copias todo .env.example y también configuras APNS_PRIVATE_KEY en línea. La ruta siempre tiene prioridad sobre la clave en línea. Solución: usa una opción u otra y deja la variable que no necesites completamente sin configurar.
SQLite no puede escribir en /data/boop.db. Causa: root creó el directorio ./data montado mediante bind, mientras la imagen se ejecuta con el uid 1000. Solución: ejecuta chown 1000:1000 data o cambia a un volumen con nombre. En Dokploy, usa docker-compose.dokploy.yml. Ese archivo lo configura y elimina el puerto publicado para que solo puedas acceder al servidor mediante tu proxy HTTPS.
El QR de vinculación se escanea, pero el celular no puede conectarse. Causa: BOOP_BASE_URL no está configurado o apunta a localhost. El payload del QR envía el celular a una dirección que no existe desde su red. Solución: configura BOOP_BASE_URL con la URL HTTPS pública y genera un token de vinculación nuevo.
No llegan notificaciones push desde una compilación de depuración de Xcode. Causa: el valor predeterminado de APNS_ENVIRONMENT es production, pero una compilación de depuración se registra en el gateway sandbox. Solución: configura APNS_ENVIRONMENT=sandbox durante el desarrollo y vuelve al valor anterior antes de publicar la app.
Preguntas frecuentes
¿Boop funciona en Android?
No. Boop envía notificaciones mediante APNs de Apple y el único cliente es una app open source para iOS que tú mismo compilas, por lo que actualmente necesitas un iPhone con iOS 26. En el repositorio del proyecto aparece un cliente nativo de escritorio entre las funciones planeadas. Los eventos siempre están disponibles en la interfaz web integrada, sin importar la plataforma, así que los usuarios de Android pueden consultar el buzón desde un navegador sin notificaciones push.
¿Necesito una cuenta de Apple Developer de pago?
Sí, en la práctica. Para crear una clave de autenticación de APNs debes usar la sección Keys de Certificates, Identifiers and Profiles. Esto requiere el rol Account Holder o Admin en un equipo inscrito. Un perfil de aprovisionamiento gratuito también vence después de siete días, por lo que tendrías que recompilar y reinstalar la app cada semana. Considera el costo de la membresía anual si usarás Boop de forma permanente.
¿Cuántos recursos de servidor necesita Boop?
Muy pocos. El autor del proyecto indica que el servidor usa cerca de 8 MB de memoria en su propia máquina. La base de datos es un solo archivo SQLite cuyo tamaño depende del volumen de eventos y del periodo de retención. El límite práctico lo determinan tu proxy inverso y el sistema operativo. Cualquier VPS básico con 1 GB de RAM o más tiene capacidad suficiente, y la CPU permanece casi inactiva entre eventos.
¿Puedo usar Boop con un SDK de Sentry existente?
Sí. Boop implementa el endpoint de sobres del SDK de Sentry, así que cualquier SDK actual de Sentry del lado del servidor puede enviarle reportes si apuntas <code>SENTRY_DSN</code> a tu host de Boop y usas una clave de API de proyecto como clave pública. Las excepciones se convierten en eventos de Boop con el tipo y el valor como título, y se conservan los fingerprints de agrupación de Sentry. Las transacciones y sesiones se aceptan, pero se ignoran.
¿Qué ocurre con los eventos mientras mi celular está sin conexión?
No se pierde nada. Cada evento se almacena en SQLite en tu servidor, sin importar si se entrega la notificación push. El buzón de la app y la interfaz web muestran todo el historial dentro del periodo de retención. La notificación solo incluye un título, el cuerpo y el ID del evento. La app obtiene los detalles desde tu servidor cuando la abres.
¿Puede un agente de IA leer mi buzón de Boop?
Sí. Boop expone un endpoint de Model Context Protocol de solo lectura en <code>/mcp</code> mediante Streamable HTTP. Incluye herramientas para enumerar proyectos, buscar eventos y obtener un evento completo o todas las ocurrencias de un fingerprint. Configura <code>BOOP_MCP_TOKEN</code> con al menos 16 caracteres y úsalo como bearer token. Boop no contiene ningún modelo, solo proporciona contexto estructurado.


