Skip to main content

ADR-0173: Navin telephony platform: Asterisk, Kamailio, LiveKit SIP, SeaweedFS, multi-tenant and HA

  • Status: accepted
  • Date: 2026-11-03
  • Scope: Navin Manager catalogue (navin-manager/catalog/services/asterisk.yaml, kamailio.yaml, rtpengine.yaml, livekit*.yaml), telephony domain of the Control Plane (services/control-plane/src/eai/domains/telephony), migrations sql/postgres/V202__telephony*.sql and following, "Telephony" section of the portal (portal/src)
  • Related documents: ADR-0101 (licence policy), ADR-0166 (high availability declared per service), ADR-0171 (hardened installation), telephony guides (docs/en/guides/telephony)

Context​

The customer asks for a sellable enterprise telephony: PBX, SIP proxy, SIP gateway to LiveKit, voice AI agents, multi-tenant, high availability, web interfaces, no demonstration. Two platforms exist and keep their role: the Navin Manager and its agents install and run the infrastructure; Navin Enterprise AI Platform configures and administers the uses. LiveKit Server is already in the catalogue (binary and podman methods, distributed mode on Redis) and the Control Plane signs LiveKit room tokens for realtime voice; LiveKit SIP, LiveKit Egress, the agent workers, Asterisk, Kamailio and RTPengine do not exist.

Decision​

1. Two planes, explicit interfaces​

WhoThrough whatDoes what
Navin ManagerNavin agents on the hostsinstallation, versions, system configuration, ports, certificates, clusters, HA, backups, health checks, rollback
Navin EnterpriseAsterisk AMI and ARI, Kamailio JSONRPC, LiveKit Twirp API, SeaweedFS S3tenants, extensions, trunks, numbers, routing, IVR, queues, agents, recordings, CDR, quotas
Navin EnterpriseManager API (existing platform_manager domain)reads the inventory and the state of the services; every infrastructure operation is asked of the Manager

The Control Plane runs no system command. The Manager manages no extension, IVR, queue or business rule.

2. Services of the Manager catalogue​

ServiceComponentsMethodsRole
asteriskasterisk (pool)packagePBX: PJSIP, dialplan, queues, voicemail, ConfBridge, MixMonitor, ARI, AMI, CDR and CEL
kamailiokamailio (at least 2 in HA)packageSIP edge: TLS, WSS, NAT, anti-flood, anti-bruteforce, dispatcher toward Asterisk and LiveKit SIP
rtpenginertpenginepackageoptional: RTP anchoring, difficult NAT, media interconnection; never installed by default
livekitlivekit-serverbinary, podmanexisting, completed without changing a deployment that works
livekit-siplivekit-sippodmanSIP gateway to the LiveKit rooms
livekit-egresslivekit-egresspodmanLiveKit recordings to SeaweedFS
livekit-ingresslivekit-ingresspodmanoptional, not needed by telephony (RTMP, WHIP)
livekit-agentslivekit-agents (workers)pythonruns the Navin voice AI agents

Default ports (the planner refuses a conflict on one host):

ServicePortExposure
Kamailio5060 UDP and TCP, 5061 TLS (SIP); 7443 WSS (softphones)public (carriers, phones)
Kamailio5071 HTTP (JSONRPC and /metrics)administration network
Asterisk5070 UDP and TCP (SIP from Kamailio only)internal signalling network
Asterisk8088 HTTP, 8089 HTTPS (ARI, /metrics); 5038 AMI, 5039 AMI TLSadministration network
Asterisk10000 to 19999 UDP (RTP, SRTP, DTLS-SRTP)media network
LiveKit SIP5090 UDP and TCP (SIP); 20000 to 29999 UDP (RTP)internal and media
RTPengine2223 UDP (ng protocol); 30000 to 39999 UDPadministration and media
LiveKit Server7880 (signalling), 50000 to 50100 UDP (existing)existing

AMI, ARI, JSONRPC and the metrics ports are never public: they listen on the administration address of the host and the Manager firewall opens them only to the declared sources.

3. Delivery of the functional configuration​

  • Asterisk. The Manager installs the system files (asterisk.conf, modules.conf, pjsip.conf with the transports, extensions.conf, queues.conf, voicemail.conf, confbridge.conf, manager.conf, ari.conf, http.conf, rtp.conf, prometheus.conf, cdr.conf, cel.conf); each includes a managed file (#tryinclude pjsip_navin.conf, extensions_navin.conf, queues_navin.conf, voicemail_navin.conf, confbridge_navin.conf). Navin Enterprise compiles these managed files per PBX pool from the tenants, extensions, trunks, numbers, rules, IVR and queues; it validates them, versions them (text, SHA-256 fingerprint, author), delivers them to every node of the pool through AMI (CreateConfig, UpdateConfig), activates them through AMI (pjsip reload, dialplan reload, queue reload all, voicemail reload, module reload app_confbridge.so), reads the result back (GetConfig) and can go back to the previous version. ARI is used for call control (channels, bridges, recordings, transfers); AMI also carries the events (CDR through cdr_manager, CEL through cel_manager, contact and queue states).
  • Naming. Short tenant id tid = t followed by the first 12 hexadecimal characters of its UUID. Endpoints {tid}-{extension}, contexts {tid}-internal, {tid}-inbound, {tid}-outbound, {tid}-ivr-{flow}, queues {tid}-{queue}, accountcode = UUID of the tenant, variable NAVIN_TENANT on every channel. No context of a tenant references an object of another tenant; the compiler checks it.
  • Kamailio. The Manager writes the dispatcher list from the topology (set 1: shared Asterisk pool, set 2: LiveKit SIP, sets 100 and above: dedicated pools). Navin Enterprise pushes the routing of the tenants through JSONRPC into the hash tables tenant_domains (SIP domain to tenant and set) and did_routes (E.164 number to tenant, set and branch pbx or ai), reconciles at regular intervals and after every Kamailio restart (core.uptime), and drives the drain of the destinations (dispatcher.set_state). The Kamailio instances replicate these tables through DMQ.
  • LiveKit SIP. Navin Enterprise creates through the LiveKit API the inbound and outbound trunks and the dispatch rules of every tenant (names prefixed by tid, metadata tenant_id), starts the outbound calls of the agents (CreateSIPParticipant) and the transfers to an extension (TransferSIPParticipant, SIP REFER).
  • Two distinct branches. PBX branch: Kamailio to Asterisk. Direct AI branch: Kamailio to LiveKit SIP (number routed ai). AI branch through the PBX: Asterisk dials PJSIP/{agent}@livekit-sip from an IVR or a queue. The AI to human transfer goes through a REFER to Kamailio, which routes the extension to its Asterisk.
  • Correlation. Asterisk sets the header X-Navin-Call-Id (UUID); LiveKit SIP copies it into a participant attribute; the Navin call session links X-Navin-Call-Id, the Asterisk uniqueid and linkedid, the SIP Call-ID, the LiveKit room and participant.

4. Data of Navin Enterprise​

Tables of the eai schema, all with tenant_id, isolated by the existing tenancy mechanisms of the Control Plane: telephony_tenants (model shared or dedicated, SIP domain, pool, quotas, retention), pbx_instances (shared or dedicated pool, Manager service, references of the AMI and ARI secrets), sip_trunks, phone_numbers, extensions, routing_rules, ivr_flows and their versions, call_queues, queue_members, telephony_agents (humans), voice_agents (AI), telephony_config_versions (publications), call_sessions, call_events, call_recordings, voicemail_messages, telephony_quotas. The existing audit journal of the Control Plane is reused, not duplicated. SIP passwords, trunk secrets, AMI and ARI credentials: in the existing vault, never returned by the API (write only fields, has_secret).

5. SeaweedFS storage​

One bucket navin-telephony, opaque keys tenants/{tenant_uuid}/{category}/{yyyy}/{mm}/{uuid}, categories call-recordings, voicemail, ivr-prompts, conference-recordings, ai-voice-recordings, audio-exports. The objects are encrypted by Navin Enterprise before upload. Reading and download only through Navin Enterprise: signed URLs of a few minutes, permission checks, audit; the S3 credentials never leave the server. Asterisk recordings: MixMonitor writes into recording/navin/{tid}/; Navin Enterprise fetches them through ARI (GET /recordings/stored/{name}/file), encrypts them, uploads them, then deletes them through ARI. LiveKit Egress writes into the bucket navin-livekit-egress with credentials limited to that bucket; at the end of a recording (signed webhook), Navin Enterprise moves it into the tenant layout.

6. WebRTC softphone​

The portal softphone uses JsSIP (MIT) in SIP over secure WebSocket toward Kamailio (WSS, path), which relays to the Asterisk of the tenant; DTLS-SRTP media with ICE between the browser and Asterisk (webrtc=yes). The browser never receives the SIP password of the extension: Navin Enterprise issues ephemeral credentials (Kamailio auth_ephemeral module, HMAC with a shared secret kept in the vault, one hour at most); the WebRTC endpoints of Asterisk accept only the Kamailio addresses. A LiveKit room is not an extension.

7. Multi-tenant​

shared model: shared Asterisk pool, isolation by contexts, SIP domains, LiveKit prefixes, storage prefixes and authorisations. dedicated model: Asterisk pool (and, when needed, LiveKit SIP) dedicated to the tenant, its own dispatcher set. Quotas per tenant: concurrent calls, calls per second (CPS, enforced by Kamailio), allowed destinations and countries, maximum duration, retention of recordings.

8. High availability: guarantees per scenario​

FailureNew callsCalls in progress
One Kamailio instancetaken by the other instance (DNS SRV, several addresses at the carrier, or a network load balancer)the dialogs routed by the lost instance fail on their next request
One Asterisk node of the poolrouted to the other nodes as soon as the OPTIONS probe of the dispatcher marks it downlost: there is no call state shared between Asterisk nodes
One LiveKit SIP or LiveKit Server noderouted to the other nodeslost for the SIP participants of that node
One AI agent workertaken by another workerthe agent session stops; the fallback rule routes to a human queue
PostgreSQL, Redis, SeaweedFSexisting HA modes of the catalogue (Patroni, Sentinel, replication)depends on the service

A virtual IP address is not a universal solution; no capacity and no call survival is announced without a test.

9. Observability​

Metrics: res_prometheus of Asterisk, xhttp_prom of Kamailio, Prometheus ports of LiveKit, LiveKit SIP and Egress, collected by the Prometheus of the catalogue; logs through Alloy; alerts through Alertmanager; business indicators (calls, CPS, quality, queues, consumption) computed by Navin Enterprise from the CDR, CEL and events.

10. Licences​

Asterisk (GPL-2.0), Kamailio (GPL-2.0-or-later), RTPengine (GPL-3.0) and JsSIP (MIT) stay separate components, used through their documented network interfaces; no GPL code enters the proprietary code of Navin. The redistribution of the GPL binaries in the offline bundle comes with the notices and the corresponding sources.

Consequences​

  • The Manager gains five services and configuration templates; Navin Enterprise gains a telephony domain, its migrations, its compilers and a section of the portal.
  • The Control Plane depends on the Asterisk AMI and ARI, the Kamailio JSONRPC and the LiveKit API, reached through the bindings of the navin-enterprise service of the catalogue.
  • Load tests and multi-host failure tests run on a dedicated environment with SIPp; no test is sent to a carrier without its agreement.