PearlPBX2 — Швидкий старт
Два способи запустити PearlPBX2, залежно від того, що вам потрібно. Повний опис можливостей, архітектури та конфігурації — в README.md.
Вимоги
- Варіант 1 (Ansible): голий хост Debian або Ubuntu, і все.
install.shсам встановлює Ansible, аinstall.ymlрозгортає решту — Python, PostgreSQL, Redis та Asterisk 22 (компілюється з початкового коду) — на цільовому хості. Нічого встановлювати вручну заздалегідь не потрібно. - Варіант 2 (Docker Compose): лише Docker і Docker Compose. Весь стек (Python 3.10+/Django 5.2, PostgreSQL 14+, Redis 7+, Asterisk 22+) працює повністю в контейнерах.
Що ви отримуєте одразу, “з коробки”
Свіжа інсталяція засіює робочу демо-АТС, а не порожню базу даних. Після першого прогону міграцій/деплою у вас уже є:
| Внутрішні номери | Що це |
|---|---|
201–210 |
10 SIP-користувачів (ppbxuser201…ppbxuser210), випадкові паролі |
211–220 |
10 WebRTC (wss) SIP-користувачів (webrtcuser…webrtcuser10) на transport-wss, випадкові паролі |
130 |
Ехо-тест |
131 / 132 |
Логін/логаут агента черги (PauseQueueMember) |
140 |
Перевірити IVR із внутрішнього телефона |
141 |
Черга Sales |
142 |
Черга Support |
Плюс:
- Дві черги, Sales і Support, з усіма 10 користувачами як членами
- Англомовне IVR (
ivr-main): “press 1 for Sales, press 2 for Support”, 2 повтори при таймауті/невірній цифрі, потім fallback у Sales - Приклад SIP-транка,
myprovider(csbc.myprovider.net, користувачtest/secret) — заглушка, яку треба замінити на реального провайдера (див. Заміна прикладного транка) - Дві таблиці маршрутизації: Incoming (будь-який вхідний дзвінок → IVR) і Outgoing
(усі 20 SIP-користувачів —
201–210і WebRTC211–220— маршрутизуються через неї: внутрішні номери,130–142, та все інше — назовні черезmyprovider)
Все це засіює manage.py seed_quickstart, яка виконується лише один раз, на
свіжій інсталяції — див. Нотатки / наступні кроки, як це гарантується.
Найшвидший старт
Одна команда, без ручних кроків — виконує те саме, що Варіант 1 / Варіант 2 нижче, і в кінці виводить згенерований логін/пароль адміна.
# Продакшн-інсталяція (Debian/Ubuntu) — клонує в /opt/PearlPBX2
curl -fsSL https://pearlpbx2.com/quickstart-install.sh | sudo bash
# Docker-пісочниця (будь-яка ОС з Docker) — клонує в ./PearlPBX2
curl -fsSL https://pearlpbx2.com/quickstart-docker.sh | bash
Далі — що робить кожен варіант і як виконати кроки вручну.
Варіант 1: Ansible (продакшн-інсталяція)
Потрібен хост Debian або Ubuntu (плейбук напряму використовує apt і systemd — інші дистрибутиви не підтримуються).
Розгортає Asterisk (компільований з початкового коду), PostgreSQL, Redis, nginx, systemd-юніти та фаєрвол на свіжому хості — без ручних кроків:
git clone https://github.com/radetsky/PearlPBX2.git
cd PearlPBX2
sudo ./install.sh
install.sh сам встановлює Ansible, якщо потрібно, і запускає ansible/install.yml (додайте -v для докладного виводу Ansible), логуючи в /var/log/pearlpbx2-install.log. Після завершення створіть адміністратора:
./manage.sh createsuperuser
потім відкрийте https://<ваш-хост>/admin/.
Щоб пізніше підтягнути оновлення, запустіть sudo ./update.sh з тієї ж директорії — він запускає ansible/update.yml, який зберігає історію для відкату (rollback.sh) на випадок, якщо оновлення треба скасувати. update.sh ніколи повторно не засіює quickstart-дані, описані вище, тож його безпечно запускати на живій системі.
Дивіться ansible/group_vars/all.yml для змінних, які він використовує (директорія інсталяції, назва БД, версія Asterisk тощо), і ansible/roles/ — що робить кожна роль.
TLS-сертифікат
За замовчуванням install.sh видає самопідписаний сертифікат, тож браузер попереджатиме при першому відвідуванні. Для довіреного сертифіката Let’s Encrypt перезапустіть:
sudo ./install.sh --domain <ваш-домен> --email <[email protected]m>
Опційно: синхронізація MP3-бекапів
Відредагуйте /etc/PearlPBX/syncmp3/env і встановіть BACKUP_DIR (наприклад, змонтований NAS або iSCSI-том). Синхронізація запускається щодня о 03:00 через cron.
Опційно: Slack-сповіщення про стан сервера
- Створіть Slack Incoming Webhook: https://api.slack.com/apps → New App → Incoming Webhooks
- Вставте URL вебхука в
/etc/PearlPBX/system_monitor/env.
Сповіщення надходять кожні 15 хвилин (диск, CPU, пам’ять, сервіси).
Опційно: Slack-сповіщення про неопрацьовані вхідні дзвінки
- Створіть Slack Incoming Webhook: https://api.slack.com/apps → New App → Incoming Webhooks
- Вставте URL вебхука в
/etc/PearlPBX/AGI/env. - Додайте до catch-all extension у дialplan:
ДивітьсяAGI(unmatched_call.py,${CALLERID(num)},${EXTEN},${CHANNEL});services/agi/README.md— там також описаноmissed_call.py.
Якщо інсталяція перервалась
- Якщо перервався
apt:sudo dpkg --configure -a - Якщо пошкоджено env-файл:
sudo rm /etc/PearlPBX/PearlPBX2/env, потім перезапустітьinstall.sh
Варіант 2: Docker Compose (рекомендовано — для оцінки, розробки)
git clone https://github.com/radetsky/PearlPBX2.git
cd PearlPBX2
cp env.sample .env
# Відредагуйте .env — вкажіть креденшли БД, потім згенеруйте та впишіть:
# 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
Відкрийте http://localhost:8000/admin/, увійдіть і одразу переходьте до
Apply Changes — quickstart-дані вище вже є в
базі, їх лише треба один раз “виштовхнути” в Asterisk.
Нотатки:
pearlpbx2автоматично прогоняє міграції та quickstart-посів при кожному старті (docker-entrypoint.sh) — ручнийmigrateне потрібен. Посів спрацьовує лише один раз; наступні рестарти — no-op.asterisk-initзасіює мінімальний AMI-увімкненийmanager.confперед першим стартом Asterisk, тожfastagi/dashboard-listenerодразу підключаються; “Apply Changes” пізніше перезаписує його реальним згенерованим конфігом з тими самими креденшлами.- Callback-демон — опційний (він робить реальні вихідні дзвінки):
docker compose --profile callback up -d callback-service. docker-compose.override.ymlпідхоплюється автоматично і дає контейнеруpearlpbx2hot-reload вихідного коду для локальної розробки; запустітьdocker compose -f docker-compose.yml up -d, щоб його пропустити.
Отримайте SIP-креденшли
Паролі 201–210 генеруються випадково і зберігаються тільки в базі даних. В адмінці перейдіть у SIP Users, відкрийте 201 (або будь-якого іншого) і подивіться поле Password — ця інструкція далі використовує 201 і 202.
Зареєструйте два софтфони
У будь-якому SIP-клієнті (Zoiper, Linphone, настільний телефон, …) зареєструйте два акаунти, використовуючи креденшли вище:
- Server: хост/IP вашого PBX
- Transport: UDP, порт
5060 - Username / Password:
ppbxuser201/ пароль з адмінки (і так само для 202)
Підключіть WebRTC-користувача
Посів також створив 10 WebRTC (wss) SIP-користувачів, webrtcuser…webrtcuser10
(внутрішні номери 211–220), на транспорті transport-wss. Їхні паролі —
там само, де й у 201–210: SIP Users в адмінці.
WebRTC-користувачі авторизуються через MD5 digest (auth_type=md5), а не
через відкритий пароль — більшість WebRTC-бібліотек (SIP.js, JsSIP) самі
обчислюють HA1 з username/realm/secret і ніколи не надсилають пароль по
мережі. У посіві це вже налаштовано — просто передайте той самий secret як
пароль у ваш WebRTC-клієнт.
Docker Compose: контейнер asterisk прокидає порт 8088 напряму на
хост, тож браузерний клієнт підключається без шифрування, напряму:
ws://<докер-хост>:8088/asterisk/ws
(prefix=asterisk береться з http.conf, який засіює
docker/asterisk-bootstrap.sh при першому старті.) Жодного проксі не
потрібно — Docker-пісочниця не для продакшн-трафіку, тож звичайний ws
достатній.
Ansible (bare-metal): HTTP/WebSocket-сервер Asterisk слухає лише
127.0.0.1:8088 (contrib/configs/http.conf), і порт 8088 ніколи не
відкривається у фаєрволі — весь зовнішній трафік, включно з
WebRTC-сигналізацією, йде через nginx на 443. Роль nginx проксіює
location /asterisk/ на http://127.0.0.1:8088/asterisk/, тож браузерний
клієнт використовує той самий хост і порт, що й адмінка, через TLS:
wss://<ваш-хост>/asterisk/ws
sudo ./install.sh налаштовує це на свіжому хості автоматично — вручну
нічого робити не треба. На системі, встановленій до появи цього проксі,
sudo ./update.sh його не додасть (він не чіпає nginx чи http.conf) —
запустіть sudo ./install.sh повторно, щоб підхопити новий конфіг nginx, і
вручну змініть bindaddr в /etc/asterisk/http.conf на 127.0.0.1.
WebSocket-з’єднання до недовіреного сертифіката неможливо прийняти
“наскрізь”, як звичайну сторінку, тож wss:// потребує сертифіката, якому
браузер справді довіряє. Інсталятор отримує його автоматично, у такому
порядку пріоритету:
- Є домен — передайте його, і інсталятор запросить звичайний
90-денний сертифікат Let’s Encrypt через HTTP-01:
sudo ./install.sh --domain pbx.example.com --email [email protected] - Домену немає, але є публічна IP — інсталятор автоматично запитує
сертифікат Let’s Encrypt на IP-адресу
(термін дії 6 днів, продовжується systemd-таймером кожні кілька годин).
Нічого передавати не треба — це те, що отримає звичайний
sudo ./install.shна більшості VPS. - Нічого з цього недосяжне (немає публічної IP або порт 80 заблокований) — інсталятор відкочується до самопідписаного сертифіката; браузер один раз попередить, і потрібно підтвердити перехід.
Перевірити, що вийшло: cat /etc/PearlPBX/tls-mode. Деталі про продовження
та додавання домену пізніше — у Посібнику адміністратора → TLS-сертифікати.
Apply Changes
Ніщо з вищесказаного не дійде до Asterisk, доки ви не натиснете застосування. В адмінці перейдіть у
Admin → Apply Changes (/admin/apply). Це перегенерує extensions.ael,
pjsip.conf, queues.conf, queuerules.conf, manager.conf, musiconhold.conf
та confbridge.conf з бази даних, робить бекап попередніх версій і
перезавантажує Asterisk. Зробіть це один раз зараз, і потім після кожної зміни через
адмінку.
Тестові сценарії дзвінків
Робіть це по порядку — кожен наступний спирається на попередній.
| № | Сценарій | Набрати | Очікуваний результат / перевірка |
|---|---|---|---|
| 1 | Ехо-тест | 130 |
Ви почуєте власний голос у відлунні. asterisk -rx "core show channels" покаже дзвінок. |
| 2 | Внутрішній дзвінок | 201 набирає 202 |
202 дзвонить. asterisk -rx "pjsip show endpoints" покаже обох як Avail. |
| 3 | Трансфер | Під час розмови, blind-трансфер через # або attended через *, ціль 202 або 141 |
Див. Трансфер нижче |
| 4 | Вихід у зовнішній світ | Наберіть будь-який зовнішній номер | Не спрацює, доки не замінити прикладний транк. Потім asterisk -rx "pjsip show registrations" має показати myprovider як Registered. |
| 5 | IVR із внутрішнього телефона | 140, потім натисніть 1 або 2 |
Ви потрапите в Sales або Support. asterisk -rx "queue show Sales" покаже дзвінок. |
| 6 | Продакшн вхідний дзвінок | Подзвоніть на свій DID ззовні | Маршрутизується через Incoming → ivr-main. asterisk -rx "pjsip set logger on" — щоб побачити SIP-трасу наживо. |
(Docker Compose: перед кожним asterisk -rx "..." додайте docker compose exec asterisk.)
Трансфер
Коди функцій трансферу беруться з contrib/configs/features.conf:
# = blind-трансфер, * = attended-трансфер (секція [featuremap]). Обидва
потребують опцій t/T у Dial(), через який прийшов дзвінок — вони вже присутні
в кожному засіяному екстеншені (наприклад, Dial(PJSIP/${EXTEN}@myprovider,120,tT)).
Ви можете зателефонувати з 201 абонента на 202 і підчас розмови натиснувши #130# ви переведете вашу розмову на ехо тест. Для вас дзвінок має закінчитись, а ваш абонент має почути вітання demo-echotest.
Після ініціації трансферу Asterisk резолвить набрані цифри через глобальну
змінну TRANSFER_CONTEXT, а не через контекст самого каналу —
засіяна як:
globals {
TRANSFER_CONTEXT=Outgoing;
}
Саме тому користувачі на таблиці маршрутизації Outgoing: це дозволяє
цілі трансферу бути або внутрішнім номером (_2XX), або зовнішнім номером (_X.) через
myprovider — з одного, консистентного контексту.
Заміна прикладного транка
myprovider (csbc.myprovider.net / test / secret) — це заглушка, вона
ніколи не зареєструється. В Admin → SIP Uplinks and Peers → myprovider замініть:
registration_uri/contact_uri/match_hosts— хостнейм SBC вашого провайдераusername/secret— креденшли вашого акаунта
Потім Apply Changes і перевірте:
asterisk -rx "pjsip show registrations"
myprovider має перейти зі стану Rejected/No response у Registered.
Нотатки / наступні кроки
- Міжнародні дзвінки заблоковані за замовчуванням. Таблиця
Outgoingмаршрутизує_00X!(міжнародні префікси) у контекстinternational-calls, який просто розриває виклик — безпечний дефолт, щоб свіжа інсталяція з прикладними креденшлами ніколи не стала вектором toll fraud. Видаліть або перенаправте цейDialplanExtension, коли будете готові дозволити такі дзвінки. Outgoingпроти легасі-таблиціPEARLPBX.PEARLPBXдосі існує (цеsettings.PEARLPBX_DEFAULT_ROUTING_TABLE, використовується як fallback в інших місцях), але жоден SIP-користувач більше не маршрутизується через неї після запуску quickstart-посіву — всі вони наOutgoing.- Кілька транків / маршрутизація за найменшою вартістю. Засіяний контекст
outbound-externalнабираєmyproviderнапряму. Для кількох транків перейдіть наAGI(agi://127.0.0.1:4573/dial-trunk-group,...)— див.services/fastagi/README.mdдля груп транків із фейловером. - Музика на утриманні (MOH) для черг використовує
contrib/moh/on_hold_music.wav— замініть файли в класі MOHdefaultна власні. - Запис розмов не увімкнений за замовчуванням; налаштування
MixMonitorдив. в admin-guide.md. - Сам quickstart-посів — це
manage.py seed_quickstart; вона перевіряє, чи вже існує будь-якаQueue,SIPPeerабо таблиця маршрутизаціїIncoming/Outgoing, і нічого не робить, якщо так — тож її безпечно запускати вручну. Ansible-івськийinstall.ymlвикликає її один раз, з тим самим гейтом “перша інсталяція на цьому хості”, що й для генерації секретів;update.ymlїї взагалі не викликає.