# VoIP Reference Card — FusionPBX / SignalWire / Landline ## FusionPBX server - **Host:** VM130 on PVE1, `10.48.200.130` — moved on-prem from an old DO droplet (`134.209.72.226`, now **destroyed** — do not reference that IP anymore, any doc saying FusionPBX is at `134.209.72.226` is stale). - **Web UI:** `https://fusion.orbishosting.com` (NPM proxies to `10.48.200.130:80`) - **SSH:** `root@10.48.200.130` via PVE1 hop, password `Joker1974!!!` (no longer needs the old DO-relay hop) - **DB:** PostgreSQL (not MySQL), `fusionpbx` / `fusionpbx` / `RSfAjzefyYmufVqtnrYpz90yHaQ`, `psql -U fusionpbx -h 127.0.0.1 -d fusionpbx` - Timezone: America/Chicago ## SIP registration settings (for a device/softphone registering against this PBX) | Setting | Value | |---|---| | SIP Server/Domain | `fusion.orbishosting.com` (or `10.48.200.130`) — **must be the domain name for some devices** (see FXO gotcha below), not always interchangeable with the IP | | Port (LAN) | `5060` UDP/TCP | | Port (WAN, per FortiGate forwards) | `5080` UDP or `5081` TCP/TLS | | Auth username | extension number, e.g. `1000` | | Auth password | per-extension, from `v_extensions.password` in the FusionPBX DB | Example working extensions (query `select extension, password, effective_caller_id_name from v_extensions;` for current full list): | Ext | Who | |---|---| | 1000 | Myron Blair (Desk) | | 1001 | Myron Blair | | 1002 | Tommy Ivy | | 1003 | Kitchen | | 1004 | Master Bedroom | | 1050 | Landline FXO gateway (Grandstream ATA, see below) | | 1091 | "Landline" ring group (rings all 8 phones) | **Extension key/BLF provisioning:** category differs by phone model — T57W/T48S use `category=line` in `v_device_keys`, the AX86R WiFi phone only has a `programmable` keys section (no `line` section). Guessing wrong silently produces no key at all — check the actual Smarty templates at `/var/www/fusionpbx/resources/templates/provision/yealink//*.cfg` before assuming a key type. ## SignalWire outbound trunk (carrier side — separate from the extension/phone side above) FusionPBX registers **to** SignalWire as a SIP gateway (this is the outbound carrier trunk, not something a phone registers against): - Gateway UUID: `c0e12aab-2406-44ee-ac38-6602116eaf2f`, username `orbis` - Realm: `orbis-hosting-0364f5f67488.sip.signalwire.com` - Space: `orbis-hosting.signalwire.com`, Project ID `16fbbcfd-1c94-4827-869c-0364f5f67488` - Check status: `fs_cli -x "sofia status"` on VM130 — should show `REGED` for `external::c0e12aab-...` ### SignalWire API gotchas (cost real debugging time — read before touching SignalWire) 1. **Credential types are NOT interchangeable.** The dashboard shows a `PSK_`-prefixed Signing Key at the top of the API Credentials page that looks like "the" token but gives a real 401 on classic REST calls. A `pat_`-prefixed Personal Access Token also 401s. **Only a named Project Token (`PT`-prefix, created in a separate table further down the same page) works** for REST Basic Auth (`ProjectID:PT...`) and the Relay SDK. 2. **Setting the SIP registration password requires the `relay` API, not the `Fabric` API.** `PUT /api/fabric/resources/sip_endpoints/{fabric_id}` returns HTTP 200 but does NOT affect registration auth. The correct call is `PUT https://{space}/api/relay/rest/endpoints/sip/{inner_sip_endpoint_id}` with `{"password":"..."}` — the inner sip_endpoint id is a *different* id than the Fabric resource id that wraps it. Symptom of using the wrong one: gateway stuck `FAIL_WAIT` with `[904] Operation has no matching challenge` even though the wire-level 401 challenge is valid. 3. **Outbound INVITE `From` header user-part must equal the digest auth username** (`orbis`), not the caller's DID/Caller ID. In FusionPBX this is `v_gateways.caller_id_in_from` — must be `false`. If wrong: INVITE gets 407, retries with Proxy-Authorization, gets ANOTHER 407 with the same nonce (looks like a FreeSWITCH bug, isn't). 4. **Destination must be full 11-digit E.164** (`+1` + 10 digits) — a dialplan bridge producing `+8172662022` (missing the `1`) gets `404`/`NO_ROUTE_DESTINATION`, easily misdiagnosed as "SignalWire doesn't recognize this number." 5. **Trial-tier gotcha:** even with the right token, sending SMS to an unverified number returns `422 integration_test_verified_caller_required`. 6. **FreeSWITCH `fs_cli chat` to a registered phone** needs the destination prefixed with the Sofia **profile name**: `chat sip|@|internal/@|` — just `user@domain` silently fails ("Invalid chat interface"). 7. **Diagnostic method that actually works for SIP auth issues:** independently reconstruct the digest (MD5 HA1/HA2/response) in a standalone script using the exact nonce/realm/uri from a live packet capture, compare byte-for-byte to what FreeSWITCH sent. Proves credentials/computation bug (mismatch) vs. carrier-side policy rejection (match, still rejected) before chasing further theories. ## FortiGate SIP/RTP port forwards (VIPs, verify live via `show firewall vip` — the doc's static tables drift) ``` fusion-sip-5080 (udp), fusion-sip-5080-tcp, fusion-sip-5081-tcp, fusion-sip-5081-udp, fusion-rtp (udp 16384-32768) → all forward to 10.48.200.130 (FusionPBX) ``` **WAN IP drifts silently and semi-regularly** — when it does, all VIP `extip` fields need updating, or calls will connect at the signaling level but have one-way/no audio (RTP arriving at the *real* current WAN IP with no matching forward rule). Always `curl ifconfig.me` from any on-prem host to check the *actual* live WAN IP before trusting a documented value. **FortiGate SIP ALG** (`default-voip-alg-mode`) must stay `proxy-based` (the default) — switching to `kernel-helper-based` breaks inbound call routing entirely (the inbound dialplan's `${sip_to_user}` handling is tuned around ALG being active). **FusionPBX's sofia.conf is cached independently of FreeSWITCH's process** at `/var/cache/fusionpbx/.configuration.sofia.conf` (Lua file cache) — any sofia profile/gateway DB or vars.xml change needs this file cleared too, not just a service/process restart. ## Landline/FXO integration (Grandstream ATA, working as of 2026-07-18) Old Flyingvoice FTA5111 (`10.48.200.119`) is **retired — do not reuse without a firmware fix from the vendor.** It has a 100%-reproducible crash-on-save bug (firmware V3.20) confirmed via extensive testing; not a config mistake. **Current device:** Grandstream HT8xx-family ATA at `10.48.200.45` (admin/Joker1974!!!), registered as **extension 1050**. FXO config (`/cgi-bin/config_a2`, Advanced Settings → FXO Port): - Primary SIP Server = `fusion.orbishosting.com` — **must be the domain, not the IP** (extension 1050 is only provisioned under that domain name in FreeSWITCH's directory, even though `10.48.200.130` also technically exists as a domain). - SIP User ID/Auth ID = `1050`, password = ext 1050's FusionPBX password. - `PSTN Ring Thru FXS` = **No** (device defaults to Yes — rings a nonexistent local FXS phone instead of routing to SIP). - Stage Method = default **2** (2-stage dialing) — gives the "landline button" real dial tone (SIP call seizes the line, ATA plays back real dial tone, DTMF passthrough). **Inbound PSTN→VoIP routing is on a DIFFERENT page** — Basic Settings (`/cgi-bin/config2`), NOT the FXO Port page: - `Unconditional Call Forward to VOIP`: User ID = `1091` (the "Landline" ring group, rings all 8 phones), Sip Server = `fusion.orbishosting.com`, port `5060`. - Without this field, incoming landline calls have nowhere to go once FXS-thru is disabled — easy to miss since the FXO page itself has no inbound-destination field. **Grandstream ATA web quirk:** login is `POST /cgi-bin/dologin`, but every subsequent settings-changing `POST /cgi-bin/update` needs a `session_token` hidden field (separate from login's `csrf_token`) scraped fresh from whatever config page you just loaded — omitting it silently bounces to a re-login page with the submission discarded, no error shown. Partial POSTs (only the fields you want changed) work fine.