Skip to main content

lyno.yaml reference

The main configuration file holds what every tenant shares. Paths in it resolve against the directory containing the file.

sip: {...}
media: {...}
moh: {...}
trunks: [...]
inbound_overrides: [...]
outbound_routes: [...]
default_trunk: carrier
tenants_dir: tenants
timezone: Europe/Amsterdam
allow_inter_tenant: false

Top level

KeyTypeDefaultPurpose
sipobjectsee belowSIP listeners and identity.
mediaobjectsee belowCodecs and RTP.
mohobjectGlobal music-on-hold classes.
trunkslistCarrier trunks.
inbound_overrideslistDID redirects that beat every tenant claim.
outbound_routeslistFallback outbound routes, tried after a tenant's.
default_trunkstringTrunk used when no route matches. The number is sent unchanged.
tenants_dirstringtenantsDirectory of tenant subdirectories.
timezonestringLocalIANA timezone for time conditions, unless a tenant or condition overrides it.
allow_inter_tenantboolfalseCeiling for inter-tenant calling.

sip

sip:
bind_host: 0.0.0.0
bind_port: 5060
transports: [udp]
external_host: 203.0.113.10
user_agent: lyno-pbx
KeyTypeDefaultNotes
bind_hoststring0.0.0.0Address to listen on.
bind_portint5060Port to listen on.
transportslist[udp]udp and/or tcp. Anything else is a validation error.
external_hoststringAddress advertised in SIP when the PBX is behind NAT.
user_agentstringlyno-pbxProduct token in User-Agent and Server headers. Also the fallback identity in From when nothing more specific applies.

media

media:
codecs: [alaw, ulaw]
rtp_port_min: 10000
rtp_port_max: 20000
external_ip: 203.0.113.10
KeyTypeDefaultNotes
codecslist[alaw, ulaw]Only alaw and ulaw are supported. Offered identically on both legs — there is no transcoding.
rtp_port_minintlibrary defaultMust be set together with rtp_port_max.
rtp_port_maxintlibrary defaultMust be greater than rtp_port_min.
external_ipstringAddress advertised in SDP when the PBX is behind NAT.

moh

moh:
default: ../sounds/moh/default.wav
classes:
jazz: ../sounds/moh/jazz.wav
KeyTypeNotes
defaultpathThe class named default.
classesmapClass name → WAV path. Tenants may add to and override this map.

All files must be 8 kHz mono 16-bit PCM WAV.

trunks[]

trunks:
- name: carrier
tenant: acme
host: sip.provider.example
port: 5060
transport: udp
auth: {username: "...", password: "..."}
registration: {enabled: true, expiry: 5m, contact_user: "..."}
inbound: {match_ips: ["198.51.100.7"], auto_ips: true}
caller_id: {number: "+31201234567", name: Acme}
KeyTypeDefaultNotes
namestringRequired, unique. Referenced by routes and default_trunk.
hoststringRequired. Hostname or IP.
tenantstringPins every inbound call on this trunk to one tenant. Must exist.
portint5060
transportstringudpudp or tcp.
auth.usernamestring
auth.passwordstring
registration.enabledboolfalseRequires auth.
registration.expiryduration5mThe re-registration period, not a retry delay.
registration.contact_userstringUser part of the Contact URI.
inbound.match_ipslistExtra source addresses, added to what DNS discovers.
inbound.auto_ipsbooltrueResolve host (A/AAAA + SIP SRV) to discover source addresses, refreshed every 5 minutes.
caller_id.numberstringFallback when the tenant has none.
caller_id.namestring

See Trunks for the behaviour behind these keys.

inbound_overrides[]

inbound_overrides:
- did: "+31201234567"
tenant: globex
destination: {type: extension, target: "900"}
KeyTypeRequiredNotes
didstringyesThe number, or * as a global catch-all.
tenantstringyesThe tenant that handles the call.
destination.typestringnoextension or ring_group.
destination.targetstringnoExtension number or ring group name.

Without a destination, only the tenant is reassigned and that tenant's own inbound routes decide the rest.

outbound_routes[]

outbound_routes:
- name: national
pattern: '^0[1-9]\d{8}$'
strip: 1
prepend: "+31"
trunk: carrier
KeyTypeRequiredNotes
namestringyesLabel used in logs.
patternstringyesGo regular expression. Must compile. Not anchored implicitly.
stripintnoDigits removed from the front, applied before prepend.
prependstringnoText put in front of what remains.
trunkstringyesMust name an existing trunk.

See Outbound routing.

Durations

Duration values are Go duration strings: 20s, 1m30s, 5m, 1h. A bare number is invalid.

Validation summary

The whole tree is checked at load, and every problem is reported:

  • media: unsupported codec; only one RTP bound set; rtp_port_maxrtp_port_min.
  • sip: unsupported transport.
  • trunks: missing name or host; duplicate name; unknown tenant; registration.enabled without auth.
  • outbound_routes: pattern that does not compile; unknown trunk.
  • Across tenants: a domain claimed twice; a DID claimed twice.
  • Per tenant: see the tenant reference.