PearlPBX2

PearlPBX2 — Guía rápida

Dos formas de poner en marcha PearlPBX2, según lo que necesites. Consulta README.md para ver la lista completa de funciones, la arquitectura y la referencia de configuración.

Requisitos

Lo que obtienes desde el primer momento

Una instalación nueva siembra una PBX de demostración funcional, no una base de datos vacía. Después de la primera ejecución de migraciones/despliegue, ya tienes:

Extensiones Qué es
201–210 10 usuarios SIP (ppbxuser201…ppbxuser210), contraseñas aleatorias
211–220 10 usuarios SIP WebRTC (wss) (webrtcuser…webrtcuser10) en transport-wss, contraseñas aleatorias
130 Prueba de eco
131 / 132 Iniciar/cerrar sesión de un agente en la cola (PauseQueueMember)
140 Probar el IVR desde un teléfono interno
141 Cola Sales
142 Cola Support

Además:

Todo esto lo siembra manage.py seed_quickstart, que solo se ejecuta una vez, en una instalación nueva — ver Notas / próximos pasos para saber cómo se garantiza esto.

Inicio más rápido

Un solo comando, sin pasos manuales — hace lo mismo que la Opción 1 / Opción 2 más abajo, y al final imprime un usuario/contraseña de administrador generados.

# Instalación de producción (Debian/Ubuntu) — clona en /opt/PearlPBX2
curl -fsSL https://pearlpbx2.com/quickstart-install.sh | sudo bash

# Entorno de pruebas con Docker (cualquier SO con Docker) — clona en ./PearlPBX2
curl -fsSL https://pearlpbx2.com/quickstart-docker.sh | bash

Sigue leyendo para ver qué hace cada opción, o para ejecutar los pasos manualmente.

Opción 1: Ansible (instalación de producción)

Requiere un host Debian o Ubuntu (el playbook usa apt y systemd directamente — no se admiten otras distribuciones).

Aprovisiona Asterisk (compilado desde el código fuente), PostgreSQL, Redis, nginx, unidades systemd y el firewall en un host nuevo — sin pasos manuales:

git clone https://github.com/radetsky/PearlPBX2.git
cd PearlPBX2
sudo ./install.sh

install.sh instala Ansible por sí mismo si hace falta y ejecuta ansible/install.yml (añade -v para salida detallada de Ansible), registrando todo en /var/log/pearlpbx2-install.log. Cuando termine, crea el usuario administrador con:

./manage.sh createsuperuser

luego abre https://<tu-host>/admin/.

Para aplicar actualizaciones más adelante, ejecuta sudo ./update.sh desde el mismo directorio — este ejecuta ansible/update.yml, que mantiene un historial de reversión (rollback.sh) por si una actualización necesita deshacerse. update.sh nunca vuelve a sembrar los datos de quick-start descritos arriba, así que es seguro ejecutarlo en un sistema en producción.

Consulta ansible/group_vars/all.yml para las variables que usa (directorio de instalación, nombre de la BD, versión de Asterisk, etc.) y ansible/roles/ para lo que hace cada rol.

Certificado TLS

Por defecto, install.sh emite un certificado autofirmado, por lo que el navegador mostrará una advertencia en la primera visita. Para un certificado Let’s Encrypt de confianza, vuelve a ejecutar:

sudo ./install.sh --domain <tu-dominio> --email <[email protected]m>

Opcional: sincronización de copias de seguridad MP3

Edita /etc/PearlPBX/syncmp3/env y define BACKUP_DIR (por ejemplo, un volumen NAS o iSCSI montado). La sincronización se ejecuta diariamente a las 03:00 vía cron.

Opcional: alertas de servidor en Slack

  1. Crea un Slack Incoming Webhook: https://api.slack.com/apps → New App → Incoming Webhooks
  2. Pega la URL del webhook en /etc/PearlPBX/system_monitor/env.

Las alertas se disparan cada 15 minutos (disco, CPU, memoria, servicios).

Opcional: notificación en Slack de llamadas entrantes sin coincidencia

  1. Crea un Slack Incoming Webhook: https://api.slack.com/apps → New App → Incoming Webhooks
  2. Pega la URL del webhook en /etc/PearlPBX/AGI/env.
  3. Añade a tu extensión de dialplan catch-all:
    AGI(unmatched_call.py,${CALLERID(num)},${EXTEN},${CHANNEL});
    Consulta services/agi/README.md — también cubre missed_call.py.

Si la instalación se interrumpió

Opción 2: Docker Compose (recomendado — evaluación, desarrollo)

git clone https://github.com/radetsky/PearlPBX2.git
cd PearlPBX2

cp env.sample .env
# Edita .env — configura las credenciales de la BD, luego genera y rellena:
#   DJANGO_SECRET_KEY:       openssl rand -hex 50
#   ASTERISK_MANAGER_SECRET: openssl rand -base64 48

docker compose up -d
docker compose exec pearlpbx2 python manage.py createsuperuser

Abre http://localhost:8000/admin/, inicia sesión y ve directamente a Apply Changes — los datos de quick-start ya están en la base de datos, solo falta enviarlos a Asterisk una vez.

Notas:

Obtén tus credenciales SIP

Las contraseñas de 201–210 se generan aleatoriamente y solo se guardan en la base de datos. En el admin, ve a SIP Users, abre 201 (o cualquier otro) y revela el campo Password — estas instrucciones usan 201 y 202.

Registra dos softphones

En cualquier cliente SIP (Zoiper, Linphone, un teléfono de sobremesa, …), registra dos cuentas usando las credenciales anteriores:

Conecta un usuario WebRTC

La siembra también creó 10 usuarios SIP WebRTC (wss), webrtcuser…webrtcuser10 (extensiones 211–220), en el transporte transport-wss. Sus contraseñas están en el mismo lugar que las de 201–210: SIP Users en el admin.

Los usuarios WebRTC se autentican con MD5 digest (auth_type=md5), no con una contraseña en texto plano — la mayoría de las pilas SIP para WebRTC (SIP.js, JsSIP) calculan el digest HA1 a partir de username/realm/secret y nunca envían el secreto por la red. La siembra ya lo configura así; solo pasa el mismo secret como contraseña en tu cliente WebRTC.

Docker Compose: el contenedor asterisk publica el puerto 8088 directamente en el host, así que un cliente en el navegador se conecta directo, sin cifrar:

ws://<host-docker>:8088/asterisk/ws

(prefix=asterisk viene del http.conf que siembra docker/asterisk-bootstrap.sh en el primer arranque.) No hace falta ningún proxy — el sandbox de Docker no está pensado para tráfico de producción, así que ws simple es suficiente.

Ansible (bare-metal): el servidor HTTP/WebSocket de Asterisk solo escucha en 127.0.0.1:8088 (contrib/configs/http.conf), y el puerto 8088 nunca se abre en el firewall — todo el tráfico externo, incluida la señalización WebRTC, pasa por nginx en el 443. El rol nginx hace proxy de location /asterisk/ hacia http://127.0.0.1:8088/asterisk/, así que un cliente en el navegador usa el mismo host y puerto que el admin, sobre TLS:

wss://<tu-host>/asterisk/ws

sudo ./install.sh configura esto en un host nuevo automáticamente — no hay que hacer nada a mano. En un sistema instalado antes de que existiera este proxy, sudo ./update.sh no lo añadirá (no toca nginx ni http.conf) — vuelve a ejecutar sudo ./install.sh para aplicar la nueva config de nginx, y cambia bindaddr a mano en /etc/asterisk/http.conf a 127.0.0.1.

Una conexión WebSocket a un certificado no confiable no se puede aceptar “al vuelo” como una página normal, así que wss:// necesita un certificado en el que el navegador confíe de verdad. El instalador obtiene uno automáticamente, en este orden de preferencia:

  1. Tienes un dominio — pásalo y el instalador solicita un certificado Let’s Encrypt normal de 90 días vía HTTP-01:
    sudo ./install.sh --domain pbx.example.com --email [email protected]
  2. Sin dominio, pero con IP pública — el instalador solicita automáticamente un certificado Let’s Encrypt para direcciones IP (vigencia de 6 días, renovado cada pocas horas por un timer de systemd). No hay nada que pasar; esto es lo que obtienes con un sudo ./install.sh normal en la mayoría de VPS.
  3. Ninguna de las dos (sin IP pública, o puerto 80 bloqueado) — usa un certificado autofirmado como respaldo; el navegador avisará una vez y hay que aceptar la excepción.

Comprueba cuál obtuviste: cat /etc/PearlPBX/tls-mode. Detalles de renovación y cómo añadir un dominio más adelante en Guía del administrador → Certificados TLS.

Apply Changes

Nada de lo anterior llega a Asterisk hasta que lo apliques. En la interfaz de admin, ve a Admin → Apply Changes (/admin/apply). Esto regenera extensions.ael, pjsip.conf, queues.conf, queuerules.conf, manager.conf, musiconhold.conf y confbridge.conf a partir de la base de datos, hace una copia de seguridad de las versiones anteriores y recarga Asterisk. Hazlo una vez ahora, y de nuevo después de cualquier cambio realizado desde el admin.

Escenarios de prueba de llamadas

Haz esto en orden — cada paso se apoya en el anterior.

# Escenario Marcar Resultado esperado / verificación
1 Prueba de eco 130 Escucharás tu propia voz en bucle. asterisk -rx "core show channels" muestra la llamada.
2 Llamada interna 201 marca 202 202 suena. asterisk -rx "pjsip show endpoints" muestra ambos como Avail.
3 Transferencia Durante la llamada, transferencia ciega con # o asistida con *, destino 202 o 141 Ver Transferencia más abajo
4 Salida al mundo exterior Marca cualquier número externo Falla hasta que sustituyas el troncal de ejemplo. Luego asterisk -rx "pjsip show registrations" debería mostrar myprovider como Registered.
5 IVR desde un teléfono interno 140, luego pulsa 1 o 2 Caes en Sales o Support. asterisk -rx "queue show Sales" muestra la llamada.
6 Llamada entrante de producción Llama a tu DID desde el exterior Enrutada vía Incoming → ivr-main. asterisk -rx "pjsip set logger on" para ver la traza SIP en vivo.

(Docker Compose: antepón docker compose exec asterisk a cada asterisk -rx "...".)

Transferencia

Los códigos de función de transferencia vienen de contrib/configs/features.conf: # = transferencia ciega, * = transferencia asistida (sección [featuremap]). Ambas requieren las opciones t/T en el Dial() por el que entró la llamada — ya presentes en cada extensión sembrada (p. ej. Dial(PJSIP/${EXTEN}@myprovider,120,tT)).

Puedes llamar desde la extensión 201 a la 202, y durante la llamada, pulsar #130# para transferir tu llamada a la prueba de eco. Tu llamada debería finalizar, y la otra parte debería escuchar el saludo demo-echotest.

Una vez iniciada una transferencia, Asterisk resuelve los dígitos marcados a través de la variable global TRANSFER_CONTEXT, en lugar del contexto propio del canal — sembrada como:

globals {
    TRANSFER_CONTEXT=Outgoing;
}

Por eso los usuarios están en la tabla de enrutamiento Outgoing: es lo que permite que el destino de una transferencia sea tanto una extensión interna (_2XX) como un número externo (_X.) vía myprovider, desde un único contexto consistente.

Sustituir el troncal de ejemplo

myprovider (csbc.myprovider.net / test / secret) es un marcador de posición — nunca se registrará. En Admin → SIP Uplinks and Peers → myprovider, sustituye:

Luego Apply Changes y verifica:

asterisk -rx "pjsip show registrations"

myprovider debería pasar de Rejected/No response a Registered.

Notas / próximos pasos