04.1Architecture explorer
Follow the call.
Select a component to see what it does and who it talks to, or press play and watch a call travel through AZOREL PBX — signalling and media, each on its own path.
Components
Select a component in the diagram or from the list.
Text description of the architecture
- Phones & softphones — SIP endpoints
- SIP user agents registered as extensions. They reach the platform only through OpenSIPS (signalling, plain or TLS) and RTPengine (media). Supported devices fetch their configuration automatically over HTTPS: Yealink templates, mobile softphones by QR code.
- → OpenSIPS: SIP signalling — SIP from phones and softphones (UDP, TCP or TLS)
- → RTPengine: RTP media — RTP voice to and from phones
- → Reverse proxy: Provisioning (HTTPS) — Devices download their configuration
- SIP trunks — Carriers
- SIP trunks authenticated by registration or by IP. Inbound calls are matched by DID and caller ID; outbound calls follow dial patterns with digit rewriting and trunk hunting. Live trunk status is read from FreeSWITCH.
- → OpenSIPS: SIP signalling — SIP from and to carriers
- → RTPengine: RTP media — RTP voice to and from carriers
- OpenSIPS — SIP edge
- SIP edge / session border controller. Terminates public TLS, rejects malformed SIP, enforces ACLs, rate limits, GeoIP rules and bans, and hides the internal topology. It is not a registrar: REGISTER and new dialogs are relayed to FreeSWITCH. Its live state is pushed by the backend, and it sets up each call's media relay in RTPengine.
- → FreeSWITCH: SIP signalling — SIP relayed on the internal network
- → RTPengine: Control — Sets up and tears down each media relay
- RTPengine — Media border
- Media relay at the network edge. Every RTP stream between the outside world and the call engine is relayed here, so FreeSWITCH never sends or receives media on the public internet. OpenSIPS creates and tears down each relay over RTPengine's control protocol; media-side NAT traversal happens here too.
- → FreeSWITCH: RTP media — RTP relayed on the internal network
- FreeSWITCH — Call engine · internal
- Registrar of record and dialplan execution — bridging, IVR, queues, conferences, parking, voicemail, recording, music on hold. Internal network only. The SIP directory and the dialplan are fetched live from the backend via mod_xml_curl on every REGISTER and INVITE; call events stream to the backend over ESL. Codecs: Opus, G.722, G.711.
- Go backend — Control plane · API
- Go modular monolith: REST API, authentication and RBAC, audit log, configuration generator, provisioning engine, ESL client, xml_curl handler and a WebSocket/SSE hub for live views. Structural configuration is generated, validated, swapped atomically and reloaded per component.
- → FreeSWITCH: Control — Directory and dialplan (xml_curl), events and call control (ESL)
- → OpenSIPS: Control — Live ACL, rate-limit and ban state
- → PostgreSQL: State — Reads and writes all configuration and records
- → Redis: State — Live state and rate-limit counters
- PostgreSQL — Source of truth
- Source of truth for all business data — extensions, trunks, routes, IVR menus, call detail records, audit log — with versioned schema migrations.
- Redis — Live state
- Ephemeral, reconstructable state only: live call and registration snapshots for dashboards and login rate-limit counters. If it is lost, the system rebuilds it from PostgreSQL and fresh engine events.
- Next.js — Admin interface
- Next.js administration interface, reachable only through the HTTPS reverse proxy. It works through the backend API; live views of calls and registrations are pushed over WebSocket.
- → Go backend: Control — REST API and live WebSocket updates
- Reverse proxy — TLS
- HTTPS reverse proxy terminating TLS in front of the admin interface. Device provisioning requests are forwarded to the provisioning engine in the backend.
- → Next.js: Control — Forwards to the admin interface
- → Go backend: Provisioning (HTTPS) — Provisioning requests to the provisioning engine
- Admin browser — HTTPS
- Signs in to the admin interface over HTTPS with an Argon2id-hashed password and TOTP; every permission is checked on the server per role.
- → Reverse proxy: Control — Administration over HTTPS
- 1. A call starts. A phone dials. Its SIP INVITE goes to OpenSIPS — the only way into the platform.
- 2. The edge checks it. OpenSIPS validates the message, applies ACLs, rate limits and GeoIP rules, then relays it to FreeSWITCH on the internal network.
- 3. A routing decision. FreeSWITCH asks the backend for the dialplan for this exact call; the backend answers from the configuration stored in PostgreSQL.
- 4. The call is handled. FreeSWITCH executes the route: it rings an extension or a ring group, plays an IVR menu, queues the caller — or selects a trunk.
- 5. The destination rings. The outgoing INVITE leaves through OpenSIPS to the destination: another phone or a carrier's SIP trunk.
- 6. The voice flows. OpenSIPS tells RTPengine to open a media relay. Each call leg's RTP passes through RTPengine at the edge and is exchanged with FreeSWITCH on the internal network — never directly with the internet.
- 7. Everyone sees it live. Call events reach the backend over ESL; live state goes to Redis and appears instantly in the admin interface over WebSocket. When the call ends, its record is written to PostgreSQL.
