Dashboard
System overview
Live state of the switch — active calls and trunk channels in use refresh every 10 seconds; the rest reload with the page.
Call-limit rejections — recent
Each of these is a real caller who got Busy()'d because this box was already at its licensed concurrent-call limit. Raise the limit with a license — see Settings -> Licensing.
| When | Caller | Where |
|---|---|---|
| Loading… | ||
Extensions
Loading…
Bulk import extensions
CSV with an extNumber,displayName header row (column order doesn't matter) — department and email are optional extra columns. Each row is created the same way as a single "New extension" would be; a bad row is reported back, not left unclear which one, and doesn't stop the rest of the file from importing.
Add a portalAccess column set to yes to also create a portal login for that row and email them an invite to set their own password — requires an email on that same row.
| Loading… | ||||||||
Trunks
SIP carriers and their registration state. Select one to inspect its configuration.
—
—Inbound routes
Loading…
| DID | Description | Trunk | Destination | |
|---|---|---|---|---|
| Loading… | ||||
Inventory
Phone numbers and physical phones you own, whether they're already assigned or sitting in reserve.
| DID | Label | Trunk | SMS owner | Status | Assigned to | ||
|---|---|---|---|---|---|---|---|
| Loading… | |||||||
Adding a DID here just registers the number — it doesn't require a destination.
Assigning one creates the same real inbound route the Call Flow Map and Inbound Routes page both already
use, so it shows up in both places immediately. Unassigning removes that route but keeps the DID in this
list, ready to be pointed somewhere else later instead of being deleted outright.
SMS owner is separate from call routing — it's which extension can text as this number from
RingStack Connect. Edit a DID to set it; a number with no SMS owner can't be used for self-service texting.
Loading…
Generate activation code
For a fresh, unclaimed phone — no MAC address needed. Give the code to whoever's setting up the phone; picking up the handset dials straight into a short prompt for it (or dial *7777 by hand if it doesn't auto-dial). Only works when this phone's HTTP provisioning URL (not TFTP) is what the network hands out — see Provisioning settings. Polycom, Grandstream, and Sangoma support is best-effort — unlike Yealink, not yet confirmed against real hardware. Pick one extension or several — you'll get a downloadable/emailable PDF either way.
Activation codes generated
| Extension | Code | Expires |
|---|
Pending activations
| Extension | Model | Created | Expires | Status |
|---|
New phone
| MAC address | Vendor | Model | Extension | Sidecar | Config | ||
|---|---|---|---|---|---|---|---|
| Loading… | |||||||
Set up a number
Answer a few questions about how you want calls handled, and we’ll build the whole thing together — the number, the hours, who picks up, and what happens if nobody does.
Call flow map
Every inbound route, time condition, call flow, IVR menu, flow module, ring group, and queue, wired together on one canvas. Build and rewire routing here by dragging cards — for tracing a path that already exists instead, see Route Checker.
Route Checker
Pick a starting point and see its full resolved path — every branch a call could take, given the current configuration. Read-only for now; edit the underlying route/IVR/time condition/etc. to change it. Not the same as Call flow map: that one is for building and wiring routing by dragging cards onto a canvas; this one is for tracing and auditing a path that already exists.
Pick a starting point above.
Call menus
Set up what callers hear and where their key presses send them.
New call menu
Plays each clip below in order — interruptible the whole way through, so a caller can press a key at any point, even mid-disclosure clip. Leave empty to play a short default beep.
Click a call menu on the canvas to edit its key press options here.
Outbound routes
Decide which outside line carries a call, and who's allowed to dial what. Routes are tried in order — the first match wins.
| Priority | Route | When someone dials… | Line(s) | |
|---|---|---|---|---|
| Loading… | ||||
Call logs
Loading…
| Time | From | To | Duration | Outcome | Recording |
|---|---|---|---|---|---|
| Loading… | |||||
API keys
Programmatic access for scripts and integrations that can't sign in interactively. View API documentation →
New API key
API keys
| Name | Key | Access | Created by | Last used | Expires | Status | ||
|---|---|---|---|---|---|---|---|---|
| Loading… | ||||||||
Rate limiting
Feedback
Notes left via the feedback bubble during testing. Nothing here is acted on automatically — review and prioritize before any work starts.
| When | Page | Note | From | Status | |
|---|---|---|---|---|---|
| Loading… | |||||
Fraud detection
Watches live call activity for toll-fraud call-rate spikes, domestic traffic pumping, and destinations you've flagged.
Thresholds
Flagged destination prefixes
Recent alerts
| Time | Type | Trunk | Extension | Destination | Count | Auto-suspended |
|---|---|---|---|---|---|---|
| Loading… | ||||||
Network / NAT
Whether this box sits on a public IP directly, or behind NAT — gets the SIP/RTP addressing right either way.
Keepalive & timeouts
Troubleshoot
Ask the AI to help diagnose a real problem — it can trace the dialplan for a number, check trunk/extension registration, and read recent Asterisk log errors. Read-only: it never changes anything itself.
Ask a question
reads live config/registration state and recent log lines — never changes anythingQueues
Group calls that ring several agents at once, and hold callers fairly in line when everyone's busy.
—
Agent self-service loginNew queue
Hot-desk sessions
*61 from the device to log in, *62 to log out.
| Device | Agent | Since | |
|---|---|---|---|
| Loading… | |||
Wallboard
Live queue status — calls waiting, longest wait, and agent availability, updating in real time.
Ring groups
Ring several phones for one call — no waiting line, no agents logging in or out, just "everyone's phone rings."
—
New ring group
Not directly dialable by number — reach it by routing a DID, IVR option, or other destination here by name. Need a direct dial code too? Add one from Custom Destinations after creating this group.
17704335939, the same digits you'd type into a phone.
Rings an outside phone number alongside (or instead of) extensions, dialed out through whichever outbound route already matches it — same routing an extension's own outbound dial would use. Digits only, no dashes/parens/spaces.
Voicemail
Every mailbox that has voicemail turned on, in one place. Reset a PIN, change where messages get emailed, or just find one below.
—
—| From | Received | Duration | |
|---|---|---|---|
| Loading… | |||
Utilities
Backups, packet capture, and other day-to-day admin tools that don't fit anywhere else.
Named, independently-scheduled backup jobs — each picks what to back up (database, generated config, voicemail, recordings, hold music, uploaded audio, branding — or all of it) and which destinations to sync to. Every archive lands on local disk first (a configurable path below); download, restore, or delete any copy in the history below. Restoring overwrites live data immediately, so it's a real, deliberate, type-to-confirm action, not a casual one.
Backup jobs
| Name | Schedule | Scope | Destinations | Last run | |
|---|---|---|---|---|---|
| Loading… | |||||
Add backup job
Backup history
Have a backup from another RingStack box, or one pulled from cold storage? Upload it here — it's validated and added below, then restores/downloads/deletes like any other.
| Date | Job | Size | |
|---|---|---|---|
| Loading… | |||
Settings
SIP signaling only — never captures RTP/call audio. Filter by extension, by IP, or just a port; watch it live, download the PCAP for Wireshark, or view a SIP call-flow ladder right here.
Continuous capture
New capture
| Started | Filter | Duration | Status | Size | Packets | |
|---|---|---|---|---|---|---|
| Loading… | ||||||
Where each backup gets copied for redundancy, beyond the local disk copies on the Backups tab — S3-compatible cloud storage, another server over SFTP or plain FTP, or a second path on this machine's own disk. Every enabled destination is independent; one failing never affects the others or the local backup itself.
Backup destinations
Every enabled destination gets a real copy of each backup, independently — for redundancy, not a fallback chain. Browse a destination to pull a copy back down (e.g. if the local copies on the Backups tab are gone) — once pulled, it restores/downloads/deletes like any local backup.
| Name | Type | Provider | Last sync | Status | |
|---|---|---|---|---|---|
| Loading… | |||||
Add backup destination
Plain FTP sends credentials and backup data unencrypted — prefer SFTP above whenever this connection crosses an untrusted network.
A local-disk destination is not real redundancy on its own — if this path resolves to the same physical disk as RingStack's own data (the primary local backup directory on the Backups tab, or the system drive), it protects against nothing if that disk fails. Point this at a genuinely separate disk or an already-mounted network share for real protection.
Email the call-volume/answer-rate summary and/or queue performance report on a recurring schedule — daily, weekly, or monthly — to whoever needs it, without them having to open RingStack. Uses the SMTP relay configured under Settings → Email delivery.
Report schedules
| Name | Report | Cadence | Recipients | Last sent | |
|---|---|---|---|---|---|
| Loading… | |||||
Add schedule
How long call detail records and call recordings are kept before they're automatically deleted. Off by default — nothing is purged until a retention period is set below.
Retention
—
Migrate extensions, trunks, inbound/outbound routes, ring groups, and queues from a real FreePBX "Backup and Restore" archive (.tar.gz). Nothing is written until you review the preview and confirm — every record is created through this app's own real API, with the same validation a manual entry gets. Imported trunks are created disabled and imported outbound routes have no trunk attached, so nothing can route real calls until you review and enable them.
1. Choose a backup file
Up to 250MB. SIP passwords/trunk secrets are never shown on screen.
2. Choose what to import
Everything is checked by default. Uncheck anything you don't want created — e.g. a trunk you don't recognize, or a route that conflicts with something already configured.
3. Results
High availability
Active/standby clustering across two RingStack nodes sharing a floating IP — automatic failover if the active node goes down. A call in progress at the moment of failover drops (mid-call state isn't preserved); everything else — config, registrations, the database — recovers on the standby.
Local network (the default) uses keepalived's own Layer-2 ARP takeover for the floating IP below — free, but only works when both nodes share a private L2 network (on-prem, Proxmox, VMware). A public cloud provider blocks that takeover by design, so failover there has to move a floating IP through the provider's own API instead. Configure this BEFORE enabling HA below if you're on a public cloud.
Enable HA on this node
Turns this node into the FIRST node of a pair — it claims the floating IP alone (no peer yet). Do this on one node, then either generate a join token below for a second node, or — if you're setting up the second node — paste a token generated on the first one.
Using your cloud provider's own floating IP API for failover (see Failover method above) — no separate VIP needed here.
Pair a second node
Generate a one-time token here, then paste it into the second node's own HA page (under "Join an existing pair"). Expires in 15 minutes, one use only.
Join an existing pair
Paste a join token generated on the FIRST node's HA page. This will overwrite this node's local database and secrets to match the pair — only do this on a fresh node, not one already holding real data.
Manage this pair
Failover is automatic (keepalived watches this node's own Asterisk reachability). Manual override below is for planned maintenance — e.g. taking the active node down for an OS update without waiting on a health-check timeout.
Support access
Ad hoc, time-limited shell access for vendor support — nothing is ever standing. Starting a session opens an outbound-only connection (no inbound firewall change needed) and grants access only to RingStack's own support key, only until it ends or expires.
Multi-tenant Beta
Run several separate companies on one install, each with their own extensions, trunks, routes, and branding — same UI and features as a standard install, fully isolated from each other. A global admin can swap between tenants without separate logins.
--multi-tenant (an existing install can't convert in place yet). Go to Settings → Licensing.
Tenants
| Company | Extensions | Trunks | Status | |
|---|---|---|---|---|
| Acme Corp | 24 | 2 | Active | |
| Widgets Inc | 8 | 1 | Active | |
| Northgate Dental | 15 | 1 | Active | |
| Riverside Logistics | 42 | 3 | Active | |
| Fairview Realty Group | 6 | 1 | Suspended |
Security
Who's trying to get in, and who's been blocked. Backed by real fail2ban jails watching SIP registration and admin panel logins — bans are real UFW firewall rules, not just a database flag.
Currently blocked
—| Loading… | ||||
Ban settings
Repeat offenders
Call security
Firewall
Real UFW status — the actual rules currently enforcing on this box, plus trusted sources: known carrier trunks and paired systems get scoped firewall access and are excluded from fail2ban's auto-ban, so they're never caught by the same dynamic banning that protects everything else.
Blocked today — by source
Almost always ordinary internet background scanning against any publicly-reachable port (SSH, SIP, HTTPS) — not evidence of anything targeted at this box specifically. If you recognize an IP as legitimate (e.g. your own office), add it as a trusted source so it stops getting dropped. A row marked GeoIP was dropped by the country-block feature instead — use Unblock there to let that one IP through regardless of its country.
| Source IP | Blocked by | Hits | Port(s) probed | Protocol(s) | Last seen (server time) | |
|---|---|---|---|---|---|---|
| Loading… | ||||||
Banned IPs (fail2ban)
—| Loading… | ||||
Standing IP/subnet blocks
ufw deny — the "Block a source" button above already covers a single IP (via fail2ban, permanent); this is the one place to block a whole range (CIDR) at once, or to deny outright independent of fail2ban entirely. Applied ahead of every other rule on this box — a block here always wins, even against a trusted source or a normally wide-open port, so double-check the range before saving.| Host | Port | Protocol | Note | Added | |
|---|---|---|---|---|---|
| Loading… | |||||
Rules
| Action | Protocol | Port | Source | Comment | |
|---|---|---|---|---|---|
| Loading… | |||||
New trusted source
Trusted sources
| Source | Type | Host | Resolved IP | Port | Status | |
|---|---|---|---|---|---|---|
| Loading… | ||||||
Advanced: restrict SIP port to trusted sources
—GeoIP country blocking
—Exceptions
An IP here is let through the country block regardless of which country it's in — it stays subject to every other firewall rule, this only exempts it from the GeoIP check specifically. The same action is also reachable directly from a blocked-IP row on the Firewall or Security page.
| IP address | Why | Added by | Added | |
|---|---|---|---|---|
| Loading… | ||||
GeoIP blocks today
Real, live confirmation the rule is actually dropping traffic — not just configured. Most recent first, capped to the last 50.
| IP address | Country | Time (server time) |
|---|---|---|
| Loading… | ||
Settings
Company details, who can sign in, and the system underneath it all.
General
White label
Users
| Name | Role | 2FA | Last sign-in | |
|---|---|---|---|---|
| Loading… | ||||
Currently signed in
Real, live sessions — not the "Last sign-in" history below. "Signed in" is approximate (sessions don't track live activity, only when they'll time out) and "Expires" is when this session stops working on its own if nobody signs it out sooner.
| User | Role | Signed in | Expires | |
|---|---|---|---|---|
| Loading… | ||||
Two-factor sign-in — your account
This protects your own sign-in only — set it up separately for each user from their own account (Portal → Account for extension-holders, here for admins).
We'll send a 6-digit code to your account email.
Single sign-on (SSO)
Uses YOUR OWN Google Workspace or Microsoft 365 app registration — RingStack doesn't ship with either provider pre-configured. SSO only signs in an email that already has a RingStack user account; it never creates one.
Notifications
Notification channels
{{event}} {{subject}} {{message}} {{timestamp}} — each is substituted as a JSON-safe string, so the result just needs to be valid JSON once filled in. Use Slack/Mattermost format
Routing
| Event |
|---|
Email delivery
Not configuredVariables
{customer_system} is always available and resolves automatically from your company name (Settings → General) — add your own on top of it for anything else you reference across templates, like a support phone number.
Templates
AI integration
Beta Not configuredText-to-speech (ElevenLabs)
Not configuredMobile push
Beta Not configuredSystem
Recording policy
System logging
SSL/TLS
—Licensing
—RingStack is free and open source — unlimited extensions, up to 2 simultaneous calls, no license needed. A license raises that concurrent-call ceiling and unlocks paid features (marked "PRO" throughout the app, like High availability). Signed and locked to this specific machine (see below), so a license file only ever works on the machine it was actually issued for.
At the limit
When a call arrives and this box is already at its concurrent-call limit, it's rejected with a plain busy signal by default — no audio, since the call is never answered. Pick a clip below to play a real spoken announcement (e.g. "All circuits are busy, please try again later") instead. That means the call gets briefly answered for real before hanging up — a normal, harmless difference from a plain busy signal, but worth knowing since it'll show as "answered" for a moment in call logs and on the caller's own phone.
About
Time conditions
Route calls differently depending on the day and time — one time window per condition, with a destination for inside it and a destination for outside it.
—
New time condition
Call flows
A manual override switch between two destinations — dial the control number from any phone to flip it (day/night, open/closed), or flip it here. Point an inbound route, IVR option, time condition, or feature code at a call flow the same way you'd point it at an extension.
—
—New call flow
Flow modules
A single named, reusable routing step — build it once, point as many time conditions, IVR menus, ring groups, or anything else with a destination at it as you want. Editing a module changes it everywhere it's used at once. A module can even point at another module, to chain a few steps together under one name.
e.g. "This call may be recorded for quality assurance." Plays once, then continues on to the destination above — leave this on "No clip" to keep this module exactly as it is today.
| Name | Destination | |
|---|---|---|
| Loading… | ||
Webhooks
A webhook fires an outbound HTTP POST (caller ID, DID, a timestamp) mid-call, then keeps going to its own next destination — pick "Fire webhook: <name>" anywhere a destination is chosen (inbound routes, IVR options/timeout, time conditions, ring group/queue no-answer fallback, call flows, custom feature codes, flow modules). The request never blocks the call either way, and is refused (with a reason logged) against private/loopback/link-local addresses or this box's own IPs.
Available: {callerIdNum} {callerIdName} {didNumber} {uniqueid} {timestamp} {webhookActionId} {webhookActionName}. Must still be valid JSON once filled in.
| Name | URL | Auth | Then route to | |
|---|---|---|---|---|
| Loading… | ||||
Conference rooms
Shared dial-in bridges anyone can join with a PIN — no per-call scheduling needed.
—
New conference room
Call parking
Put a call on hold in a shared slot so anyone can pick it up from a different phone. Asterisk's own built-in default lot (dial 700, slots 701-720) always exists — the lots below are additional ones you manage.
—
| Space | Status | Caller | Parked for | Rings back in |
|---|---|---|---|---|
| Loading… | ||||
New parking lot
Patches
Pending updates for Asterisk, PJSIP, and the rest of this system's real stack — read directly from apt's local package cache, refreshed by the OS's normal automatic update timer.
Available updates
| Package | Installed | Available | Source | |
|---|---|---|---|---|
| Loading… | ||||
RingStack itself
Audio library
Upload once, use anywhere — an IVR greeting, a queue's hold music, or a mailbox's voicemail greeting. Anything you upload is converted to the format Asterisk actually plays.
System default hold music
Upload audio
| Name | Type | Duration | Used by | ||
|---|---|---|---|---|---|
| Loading… | |||||
Reports
How your phone system is performing over time — call volume, queue performance, and where calls actually go.
Call volume
last 30 daysBusiest times
Extension activity
| Ext | Name | Calls | Avg talk | Missed |
|---|---|---|---|---|
| Loading… | ||||
Ring group performance
| Group | Name | Calls | Answered | Abandoned | Avg talk | Avg ring |
|---|---|---|---|---|---|---|
| Loading… | ||||||
Queue performance
last 30 days| Queue | Name | Offered | Answered | Abandoned | Avg wait | SLA % |
|---|---|---|---|---|---|---|
| Loading… | ||||||
Missed calls
last 30 days| When | From | To | Rang for |
|---|---|---|---|
| Loading… | |||
Voicemail
last 30 days| When | Mailbox | Caller | Duration |
|---|---|---|---|
| Loading… | |||
Feature usage
last 30 days| Feature | Calls |
|---|---|
| Loading… | |
SMS activity
last 30 days| Number | Messages |
|---|---|
| Loading… | |
Recording usage
last 30 days| Source | Recordings |
|---|---|
| Loading… | |
Audit trail
last 30 days| When | Who | Action | Detail |
|---|---|---|---|
| Loading… | |||
Security activity
last 30 days| Fraud alert type | Count | Auto-suspended |
|---|---|---|
| Loading… | ||
My reports
saved questions — each re-runs fresh against current data, never a cached answerAsk a question
the AI picks which real report(s) to pull from — never raw database accessCall direction over time
last 30 daysTop inbound callers
last 30 days| Number | Calls | Answered | Total talk time |
|---|---|---|---|
| Loading… | |||
Top outbound destinations
last 30 days| Number | Calls | Answered | Total talk time |
|---|---|---|---|
| Loading… | |||
Duration distribution
Trunk usage
last 30 days| Trunk | Provider | Inbound | In. answered | Outbound | Out. answered | Total talk time |
|---|---|---|---|---|---|---|
| Loading… | ||||||
Call volume by DID
last 30 days| Number | Name | Calls | Answered | Total talk time |
|---|---|---|---|---|
| Loading… | ||||
Agent performance
last 30 days| Agent | Extension | Calls handled | Total talk time | Avg talk time |
|---|---|---|---|---|
| Loading… | ||||
Repeat callers
last 30 days| Number | Calls | First call | Last call | Closest gap |
|---|---|---|---|---|
| Loading… | ||||
Daily peaks
last 30 days| Day | Peak simultaneous calls |
|---|---|
| Loading… | |
IVR containment
last 30 daysSoftphones
Which extensions can take calls in a browser, and who is signed in right now. Turn browser calling on or off and email a one-tap setup link — with a QR code attached — right from this list.
| Ext | Name | Browser calling | Status | Registered from | Setup |
|---|---|---|---|---|---|
| Loading… | |||||
Messages
Real text messages over SIP (RFC 3428 MESSAGE) through your trunks — no separate carrier API or webhook, the same connection that carries your calls. Your trunk provider needs to actually support SMS-over-SIP for delivery to work; this sends/receives whatever the trunk is willing to carry.
Conversations
Paired systems
Real inter-PBX SIP trunking — dial a prefix + their extension to reach another RingStack install directly. Same PJSIP building blocks as Trunks, verified end-to-end (a real call round-trip through the peer and back) before this page was built. Manual mutual setup for now: enter the same shared secret on both systems — no invite-code exchange yet.
—
Phone models
Turn on the vendors and models you actually use — enabled models show up in Phones → Add a phone. Auto-provisioning config is generated for Yealink, Grandstream, and Cisco; Poly can be tracked here but won't get a config file yet. Cisco is shelved for now (old SPA-series hardware, not commonly used) — existing entries below can still be re-enabled here even though Cisco isn't offered when adding a new phone/model.
New phone model
Programmable keys
| Vendor | Model | Type | Status | |
|---|---|---|---|---|
| Loading… | ||||
New sidecar model
Sidecar / expansion modules
| Vendor | Model | Keys | Status | |
|---|---|---|---|---|
| Loading… | ||||
Provisioning
Global settings for auto-provisioning phones — TFTP and HTTPS both serve from the same generated files. Per-model key templates live in Phone models → Keys; this page is everything that applies fleet-wide instead.
Server info for DHCP / manual setup
Global provisioning settings
HTTPS provisioning authentication
Feature codes
Star codes any phone can dial — no extra setup on the phone itself needed. Turn any of these off if you'd rather that code stay free for something else, and change the code itself if it collides with a carrier feature code you already use.
| Code | Feature | On |
|---|---|---|
| Loading… | ||
Custom feature codes
| Code | Name | Destination | Status | |
|---|---|---|---|---|
| Loading… | ||||