Architecture overview
An Exovo deployment is a set of cooperating containers managed by Docker Compose. Understanding what each one does makes logs easier to read, firewall rules easier to reason about, and troubleshooting much faster.
The container stack
Internet / LAN
│
80 / HTTPS port │ 5060/5061 (SIP — LAN only)
┌─────────────────┤ 5080 (public trunks), 5082 (LAN peers)
│ │ 5090 (tunnel)
▼ │ 5091 (VPN) 16384-16584 (media)
┌─────────┐ │ │
│ traefik │ │ ▼
│ (proxy) │ │ ┌──────────────────────────┐
└────┬────┘ │ │ core (FreeSWITCH) │
│ HTTP │ │ + tunnel (sidecar) │
▼ │ │ + phoneproxy (sidecar) │
┌─────────┐ ESL/API │ └──────────┬───────────────┘
│ web │◄───────────┼─────────────────┘
│ console │ │ 3478 + 16485-16584
└────┬────┘ │ │
│ SQL │ ▼
▼ │ ┌─────────┐
┌─────────┐ └──────────►│ turn │ (media relay,
│ db │ └─────────┘ browser calls)
└─────────┘
| Service | Image | Role |
|---|---|---|
traefik |
Traefik 3 | Reverse proxy: TLS termination, automatic certificates, HTTP→HTTPS |
web |
Exovo web | The web console and web client, provisioning, APIs, background workers |
core |
Exovo core | FreeSWITCH — SIP registration, call routing, media, voicemail, faxing |
db |
PostgreSQL | All configuration and history (users, rules, CDRs, chat, settings) |
turn |
coturn | Media relay so browsers behind NAT can send/receive call audio |
tunnel |
Exovo tunnel | The :5090 front door for the Exovo apps and on-site SBCs (mutual TLS) |
phoneproxy |
Exovo phoneproxy | Lets admins open a desk phone's own web UI through the console |
dockerproxy |
socket proxy | A locked-down, read-mostly window onto Docker for status and update checks |
Port reference
Every port the system listens on, and who is meant to reach it. Only the ports whose audience includes the internet ever need router forwarding — the per-scenario forwarding list is in the installation guide. In particular, 5060/5061 are for LAN phones and registering gateways only: remote phones come in through the SBC tunnel (5090) or VPN (5091), never by forwarding SIP.
| Port | Protocol | Service | Audience | Purpose |
|---|---|---|---|---|
| 80 | TCP | traefik | Internet | HTTP redirects and automatic certificate issuance |
| Configured HTTPS port (default 443) | TCP | traefik | Internet + LAN | Web console and client, provisioning and HTTPS APIs |
| 5060 | UDP + TCP | core | LAN only | SIP — local phone and gateway registration (internal profile) |
| 5061 | TCP | core | LAN only | SIP over TLS — local phones |
| 5080 | UDP + TCP | core | Trunk providers | SIP — public external/trunk profile |
| 5082 | UDP + TCP | core | LAN only | SIP — LAN trunks and gateway outbound calls (external-lan profile) |
| 5090 | TCP + UDP | tunnel | Internet | Exovo tunnel — SBC sites and the Exovo apps (mutual TLS) |
| 5091 | UDP | core | Internet | Remote-phone VPN (OpenVPN) |
| 8443 | TCP | core | Internet | Cisco phone VPN (AnyConnect via ocserv) |
| 443 | UDP | core | Internet | Cisco phone VPN — DTLS media path (optional) |
| 69, 6970 | UDP, TCP | core | LAN only | Cisco Enterprise provisioning (TFTP + HTTP config service), when enabled |
| 16384-16484 | UDP | core | Trunk providers + LAN | RTP call media |
| 16485-16584 | UDP | turn | Internet + LAN | TURN relay range (contiguous with RTP — forward 16384-16584 as one block) |
| 3478 | UDP + TCP | turn | Internet + LAN | TURN/STUN — media relay for browser calling |
The telephony core (FreeSWITCH)
core owns everything real-time: SIP registrations from phones and trunks, call routing, RTP
media, music on hold, voicemail and fax. It exposes SIP on 5060 (phones), 5061 (SIP over TLS)
and 5080 (public trunks) / 5082 (LAN peers), plus the RTP range 16384-16484/udp. It doesn't make
routing decisions on its own — for each call it asks the web app for dialplan instructions, so all configuration lives in
one place (the database). Routing changes take effect dynamically; SIP address changes require
a core restart. The LAN peer guide explains how local peers
advertise the configured Host IP Address independently of the public IP.
Two sidecars share the core's network namespace:
tunnelterminates the Exovo tunnel on port 5090 — the single mutual-TLS port that mobile apps and on-site SBCs use for SIP and media. It fetches its certificates from the web app on startup and holds no secrets of its own.phoneproxyreaches phone web UIs on the LAN or over the remote-phone VPN — networks the hardened web container deliberately can't see — so the console's "open phone UI" button works without exposing phones directly.
The web console and web client
web is a single ASP.NET application serving both the admin console and the end-user web client,
plus phone provisioning, the REST endpoints FreeSWITCH calls back into, and background workers
(backups, CRM sync, update checks, the license phone-home). It's the only service that talks to
the database, and it never faces the internet directly — Traefik fronts it.
Database and persistence
Users, routing and application settings live in PostgreSQL. Deployment settings such as the
HTTPS port live in /opt/exovo/.env; media and telephony state also live on the filesystem:
| Path on host | Contents |
|---|---|
/var/lib/exovo/db |
PostgreSQL data |
/var/lib/exovo/recordings |
Call recordings |
/var/lib/exovo/ivr |
Digital-receptionist and system prompts, voicemail audio and the 3CX voicemail import ledger |
/var/lib/exovo/fax |
Sent/received faxes |
/var/lib/exovo/certs, acme |
TLS certificates |
/var/lib/exovo/keys |
Data-protection keys (encrypts stored secrets) |
/var/lib/exovo/logs |
FreeSWITCH logs |
The built-in backup has configuration and full profiles. Choose Full to include voicemail and other bulk media; use that guide to confirm the profile and restore scope you need.
Reverse proxy and TLS
Traefik owns port 80 and the configured HTTPS TCP port (443 by default), redirects HTTP to the full HTTPS address, and either maintains an automatic certificate for your FQDN or serves the custom one you provided during onboarding. Everything web-ish — console, provisioning, phone-UI proxy — flows through it; internal services are never published directly.
How a call flows through the system
- A phone or registering gateway sends SIP to
coreon 5060; IP-authenticated public trunks use 5080 and IP-authenticated LAN peers use 5082. coreaskswebhow to route the call;webanswers from the database — user, ring group, queue, IVR, office-hours rules.- Media (RTP) flows directly between the endpoint and
core. Browser calls relay throughturn; mobile-app and SBC calls arrive inside the tunnel on 5090. - When the call ends,
corereports the call record toweb, which stores the CDR, triggers recording transcription and CRM journaling, and updates live dashboards.
Security posture, in brief
Containers run with dropped capabilities and no-new-privileges; the web app has no Docker
socket (the deny-by-default dockerproxy allows only status reads and a scoped restart); the
internet-facing tunnel holds no keys; and actions that need root on the host (updates, restores)
are performed by small systemd watchers reacting to marker files — the containers themselves
can't touch the host. Details in the security section.