Skip to main content

Accounts and extensions

An account is a credential a phone registers with. An extension is a number inside a tenant. An account names the extension it belongs to, and several accounts may name the same one.

Each account is its own document, and metadata.name is the SIP username:

configVersion: lyno/v1
kind: Account
metadata:
name: alice
tenant: acme
spec:
password: "change-me"
extension: "100"
displayName: Alice
---
configVersion: lyno/v1
kind: Account
metadata:
name: alice-mobile
tenant: acme
spec:
password: "change-me-too"
extension: "100" # same extension: both devices ring
---
configVersion: lyno/v1
kind: Account
metadata:
name: bob
tenant: acme
spec:
password: "and-me"
extension: "101"
FieldRequiredPurpose
metadata.nameyesThe SIP username, unique within the tenant.
passwordyesDigest password, stored in plain text in the file.
extensionyesThe extension number this account belongs to.
displayNamenoCaller name shown on internal calls.
recordnoOverrides the recording mode for calls this account answers or places. Unset follows the tenant.

Registration

Phones register to the tenant's SIP domain with the PBX as their outbound proxy:

FieldValue
Usernamethe account username
Domain / SIP serverthe tenant domain, e.g. acme.pbx.example.com
Outbound proxythe PBX address, e.g. 192.0.2.10:5060

The domain in the request selects the tenant and becomes the digest realm. A registration whose domain matches no tenant is refused with a log line naming the domain it offered.

Bindings are keyed tenant/extension, so nothing that looks up "extension 100" without a tenant can ever be right.

Expiry

The requested expiry comes from the Contact expires parameter, or from the Expires header, and is clamped:

Value
Minimum60s
Default when the phone asks for nothing300s
Maximum3600s

A REGISTER with Expires: 0 removes the binding; Contact: * with Expires: 0 removes every binding for that account. The 200 OK echoes the current bindings with their remaining lifetime.

NAT

Endpoints are dialled at the source address observed during REGISTER, not the address advertised in the Contact header, because NAT clients advertise private addresses. Nothing needs configuring for the phone side of NAT.

If the PBX itself is behind NAT, set sip.externalHost and media.externalIp — see Running behind NAT.

Several devices on one extension

Every registered device for an extension rings in parallel. The first to answer wins and the others are cancelled. This is how a desk phone and a softphone share extension 100 without any group configuration.

Extensions with runtime state

Two things can change what happens when an extension is rung, without any change to these files:

  • Do-not-disturb makes the extension contribute no ring targets, which looks exactly like a phone that is not registered.
  • Call forwarding sends the call somewhere else.

Both are set by the endpoint itself through feature codes, and both are kept in the data directory rather than written back into the configuration. An extension whose calls are vanishing and whose phone is registered is the usual sign of one of them being set.

A mailbox is also keyed by account extension — see Voicemail.

Extensions without an account

An extension number does not need an account. Extension 200 in the quick start is a dialplan entry point reached from a DID: it plays a greeting and rings other extensions, but nothing registers as "200". This is the normal shape for hunt groups, out-of-hours announcements and IVR-style entry points.

Conversely, an account needs no Extension document to be reachable. A colleague dialling 100 gets the phone directly, and a ring group or follow-me stage can name 100 as a target, because those resolve against the account roster.

What a plan adds is everything past ringing: a fallback to voicemail, a greeting, a time condition. Two places also require one — an InboundRoute or an IVR option of type extension must name a dialplan, not a bare account — so give any number you deliver a DID to a plan, even if it holds one dial step:

configVersion: lyno/v1
kind: Extension
metadata:
name: "100"
tenant: acme
spec:
description: Alice
steps:
- id: ring
type: dial
timeout: 30s
target:
kind: endpoint
endpoint: "100"
- id: box # what the plan is really for
type: voicemail

Naming a plan after an account extension is not a clash: the plan wins, for internal callers as much as external ones, which is exactly how that extension gets voicemail on no answer.

Passwords

Passwords are stored in plain text; digest authentication needs them. Lyno writes configuration files with mode 0600 and the container image runs as a non-root user, but the operational rule is simple: treat every file holding these documents as a secret, and keep it out of any public repository.

A placeholder like change-me is a real credential the moment the PBX is reachable, and the guard bans a wrong password rather than a right one. Give every account a long random password — including one that exists only to own a shared mailbox and that no handset ever registers as.