RustPBX Basics: Extensions — From Zero to First Registration

M
Miuda Team
Building conversational AI tooling

This is part of a Basics series covering the everyday tasks of running a RustPBX instance. Start here: create extensions, get devices registered, and understand the options you’ll actually use.

Create an Extension

Console first: Extensions → New Extension, fill the number, display name, and a SIP password. Under the hood this calls the same API you can script:

curl -X PUT http://<host>:8080/api/extensions \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "extension": "1001",
    "display_name": "Alice Zhang",
    "email": "alice@example.com",
    "sip_password": "choose-something-long"
  }'

For bulk onboarding there’s CSV import (Extensions → CSV Import) or the POST /api/extensions/import endpoint.

Extensions console with departments, status and forwarding columns

The list view carries the columns you’ll actually triage on: department, registration status, login state, public access, and forwarding mode — searchable without a page refresh.

Register a Device

Any SIP endpoint works — softphone, desk phone, WebRTC client:

FieldValue
Serverhost:5060 (UDP/TCP) or wss://host/ws for WebRTC
Usernamethe extension number (1001)
Passwordthe SIP password

RustPBX tracks registrations in the locator registry; Diagnostics → SIP shows live bindings, and stale ones can be dropped from the console when a device vanishes without a BYE.

Registration Without Passwords: JWT

For voice bots, dialers, and browser clients where per-device SIP passwords are painful, enable JWT registration:

[proxy.jwt_auth]
enabled = true
secret = "a-long-shared-secret"
user_id_claim = "userId"

A REGISTER (or WebSocket connect with ?token=) carrying a valid JWT whose userId claim matches the extension registers without a digest challenge. A short-lived pre-auth binding then fast-tracks in-dialog requests.

Busy? Let Callers Wait

Since 0.5, a forward route targeting an extension can carry a [busy_wait] (camp-on) table — the caller waits with looping audio and the extension is retried every retry_interval_secs:

[busy_wait]
enabled = true
max_wait_secs = 120
retry_interval_secs = 15
hold_audio = "sounds/hold-music.wav"

Lifecycle Hooks

Addons react to extension changes — create a voicemail mailbox on extension create, clean up recordings on delete — through on_extension_created / on_extension_updated / on_extension_deleting. Hook errors log but never block the operation.

When Registration Fails

The 90% cases, in order:

  1. Wrong realm/user — the extension number must be the SIP username; check Diagnostics → SIP → Locator for whether the device ever registered.
  2. Firewall — UDP 5060 open, and the RTP range open for media; WebRTC needs WSS + STUN/TURN instead.
  3. Clock skew — digest auth uses timestamps; a device minutes off fails challenges intermittently.
  4. ACL — remember ACLs apply to inbound trunk paths; a device failing to register is usually password/port, not ACL.

Housekeeping

  • Password rotation: bulk-reset quarterly via the API.
  • Offline review: Diagnostics → SIP registrations, look for long-offline extensions.
  • Decommission: disable from the detail page, then remove queue/skill bindings.

Full details: the Extension Management guide. Next in the series: call forwarding.

Get new posts by email

Deep dives on Rust telephony, contact centers and wholesale voice. No spam.

Thanks — you're on the list.

We use cookies for anonymous analytics to improve the site. Nothing is loaded until you accept. Privacy Policy