Skip to main content

Files and paths

Layout

configs/
lyno.yaml # shared: listeners, media, trunks, global routing
tenants/
acme/
tenant.yaml # domains, numbers, accounts, ring groups, routing
extensions/
100.yaml # this tenant's dialplans
200.yaml
globex/
tenant.yaml
extensions/
sounds/
welcome.wav
closed.wav
moh/default.wav

lyno.yaml holds what every tenant shares. Each tenant directory is self-contained, so a tenant can be read, copied or moved on its own.

Two keys control the discovery:

KeyFileDefaultResolves against
tenants_dirlyno.yamltenantsthe directory holding lyno.yaml
extensions_dirtenant.yamlextensionsthe tenant's own directory

Every subdirectory of tenants_dir that holds a tenant file is loaded. A tenant's name defaults to its directory name when omitted.

The path rule

This is the one that bites:

  • Paths in lyno.yaml resolve against the directory holding lyno.yaml.
  • Paths in tenant.yaml and extension files resolve against the tenant directory.

So a shared sounds/ folder at the repository root is ../sounds/… from configs/lyno.yaml, but ../../../sounds/… from configs/tenants/acme/extensions/200.yaml — because it resolves relative to configs/tenants/acme/, not to the file itself.

configs/lyno.yaml
moh:
default: ../sounds/moh/default.wav # configs/ → sounds/
configs/tenants/acme/extensions/200.yaml
steps:
- type: play
file: ../../../sounds/welcome.wav # configs/tenants/acme/ → sounds/

Absolute paths are left untouched and are the safest option when the layout is not under your control.

Absolute in memory, relative on disk

Loading makes every path absolute; saving converts it back to a path relative to the configuration directory. This matters if you write configuration files with your own tooling: keep them relative, exactly as lyno -configure writes them.

Files are rewritten, not edited

lyno -configure regenerates the YAML from the parsed configuration. Comments are not preserved. If you keep the configuration in version control and maintain comments by hand, edit the files by hand too, and use the editor only for exploration.

Files are written atomically with mode 0600, because they contain SIP passwords.

Validation

./bin/lyno -config configs/lyno.yaml -validate

Validation is a whole-tree check that collects every problem instead of stopping at the first. It covers, among others:

  • unsupported codecs or transports;
  • an RTP port range where only one bound is set, or where max ≤ min;
  • trunks without a name or host, duplicate trunk names, a trunk naming an unknown tenant, and registration.enabled without auth;
  • outbound routes with a pattern that is not a valid regular expression, or naming an unknown trunk;
  • domains claimed by more than one tenant, and DIDs claimed by more than one tenant;
  • dialplan steps referencing an unknown ring group, extension or file;
  • time conditions with an invalid day, hour range, date or timezone.

Saving from the editor runs the same validation first, so the editor cannot write a file the PBX would refuse to load.