Lyno · an open-source PBX by telqo
A PBX you declare, not administer.
Lyno is a multi-tenant PBX in a single Go binary. Tenants, trunks, extensions, IVR menus, queues and voicemail are YAML documents — no database, no admin panel. It reads the whole set at startup, validates it, and runs what it says.
one static binary · ~19 MB image · no database · no web panel
Write it down, Lyno runs it
A tenant, a trunk, an extension, a queue — each one is a document that says what it is. Nothing gets applied in a particular order and nothing lives in a database: Lyno reads the set you point -config at, and that set is the system. Where the documents sit carries no meaning — one file, a file per tenant, or a tree something generates.
metadata.name is a resource’s identity and metadata.tenant its namespace, so a queue called support in one tenant is unrelated to one in another. Order lives in a priority rather than in file order. lyno -validate reads the whole set and either accepts it or names the document that is wrong — the PBX never starts half-configured.
configVersion: lyno/v1
kind: System
spec:
sip:
bindHost: 0.0.0.0
bindPort: 5060
transports: [udp]
defaultTrunk: carrier
timezone: Europe/Amsterdam
---
configVersion: lyno/v1
kind: Trunk
metadata:
name: carrier
spec:
host: sip.provider.example
auth:
username: "12345678"
password: "${CARRIER_PASSWORD}"
registration:
enabled: true
---
configVersion: lyno/v1
kind: OutboundRoute
metadata:
name: national # no tenant: the global fallback
spec:
priority: 20
pattern: '^0[1-9]\d{8}$'
strip: 1
prepend: "+31"
trunk: carrier
Simple to hold in your head
There is no hidden state to reason about: what the files say is what the PBX does. Everything else on this page follows from these three.
The documents are the source of truth
There is no database. Every resource is a document that says what it is, so a change is a diff you can review and revert. What the PBX writes — call logs, recordings, voicemail — goes to a separate data directory, never back into these files.
Flexible where it matters
Twelve step types compose in any order, and every step can carry a time condition. Anything set globally — recording, storage, voicemail, mail, security — can be overridden by a tenant, field by field.
Scales by adding a document
Tenants share the SIP listeners and carrier trunks but nothing else: their own domains, numbers, extensions and dialplans. Extension 100 can exist in every one of them, and the next tenant is one more document.
What Lyno does
Carrier trunks
Register with a provider or authenticate by source IP. Gateway addresses come from DNS, refreshed every five minutes.
Number routing
Outbound routes match on regex, then strip and prepend before picking a trunk. Inbound routes map a DID to an extension or ring group.
Dialplans
Twelve step types per extension, run top to bottom. A dial nobody answers falls through to the next step.
Follow-me and ring groups
Ring in stages, or everyone at once. The first answer wins and the remaining legs are cancelled.
IVR menus
Keypad menus that live on the tenant, so several plans can share one. Keys may be more than one digit, matched longest-first.
Call queues
Four strategies, static and dynamic agents, music and a periodic announcement while the caller waits.
Voicemail
Per-mailbox greetings, PIN retrieval and a message-waiting lamp. Notification by email with the recording attached.
Call recording
Stereo WAV — caller left, far end right — with a JSON sidecar. Kept on disk or uploaded to S3.
Call logs
One JSON record per call plus a per-day index, written straight to disk. Direction and outcome from a closed set.
Management API
Read call logs, recordings, voicemail, status and security over HTTP with a scoped bearer token. Off by default, loopback-bound.
Source-address guard
Packet rate limits, bans after repeated auth failures, and per-tenant ceilings on concurrency, call rate and outbound minutes.
Feature codes and transfer
Do-not-disturb and forwarding are ordinary steps, so a feature code is just an extension. Blind transfer needs no configuration.
Time conditions
Days, hour ranges that wrap midnight and holidays, in the tenant’s timezone. Any step can carry a when:.
Terminal dashboard
Calls, endpoints, trunks, security and logs in one view. Filter by tenant and every counter follows.
Configuration editor
lyno -configure walks the whole config, validates before writing, and refuses to delete anything still referenced.
Prompt generation
lyno -tts synthesises a whole prompt set from a manifest, before the PBX runs and never during a call.
One static binary
A single Go binary, or a distroless image of about 19 MB. No shell in it, no database beside it.
Run it, watch it
lyno opens a live dashboard: calls, endpoints, trunks, security and logs. Hang up a call, drop a registration or lift a ban without leaving it. Add -headless to log to stderr instead, under systemd or in a container.
┌─ Lyno PBX by Telqo ─────────────────── 0.0.0.0:5060 · 4/5 online · 1/1 trunks up · uptime 6h12m ─┐ │ Overview Calls 2 Endpoints 5 Trunks 1 Security 1 Logs tenant acme │ ├───────────────────────────────────────────────────────────────────────────────────────────────────┤ │ active calls endpoints trunks calls finished banned ips │ │ 2 4/5 1/1 148 1 │ │ in progress registered reachable 15 missed 412 rejected │ │ │ │ Tenants │ │ TENANT DOMAIN ONLINE CALLS DIDS │ │ acme acme.pbx.example.com 3/3 2 2 active │ │ globex globex.pbx.example.com 1/2 0 1 idle │ │ │ │ Recent calls │ │ TIME TENANT FROM TO STATE DURATION │ │ 14:02:11 acme +31612345678 200 answered 00:04:31 │ │ 13:58:02 acme 100 101 answered 00:00:47 │ │ 13:41:19 globex +31201112233 900 missed — │ └───────────────────────────────────────────────────────────────────────────────────────────────────┘ tab switch · t tenant · / filter · x act · ? help · q quit
Ten minutes and two softphones
That is all the quick start needs — no trunk and no carrier contract, which come later and are optional. Point -config at a path that does not exist and Lyno writes a working configuration to start from.