Mutara

Files, logs and API

This page lists the files of a Mutara install, the log, the command-line flags and the web routes that are documented for other programs.

Files of an install #

PathWhat it holds
/etc/mutara/mutara.yamlThe configuration. A save keeps the old file as .bak.
/etc/mutara/modules.d/One file for each node after the first.
/opt/mutara/bin/The programs. The old program stays as mutara.prev after an upgrade.
/var/lib/mutara/The state folder of the service.
/var/lib/mutara-upgrade/resultThe result of the last upgrade job.

The installer links mutara and mutara-switch into /usr/local/bin and /usr/local/sbin.

The state folder #

The state folder holds:

  • mutara-tls/: the self-signed certificate
  • mutara-certs/: the Let's Encrypt cache
  • chat/: the chat messages and files
  • recordings/: the recorded clips. A clip with a transcript also has <clip>.stt.json.
  • bundles/: the bundles. Each bundle has a folder bundles/<id>/ with bundle.json, the clips in clips/ (hard links or copies), and the joined audio audio.opus and audio.m4a. Read Storage and clean-up.
  • voice-cache/: the copies of voice server answers
  • The recent nodes, the calls that stay up through a restart, and the weather alerts
  • scan-priority.json: the own scan priority of each user
  • scan-list.json: the own scan list of each user (In my scan)
  • user-prefs.json: the dashboard theme, the DMR ID and the M17 callsign of each user
  • sessions.json: the dashboard sign-ins, as hashes of the tokens. Older versions kept it next to the configuration file; the node moves it here at start.
  • install-id: the ID of the install for the transcoder server. Do not delete or change it.

Mutara finds the state folder with the first rule that applies:

  1. MUTARA_STATE_DIR, if it is set.
  2. STATE_DIRECTORY, which systemd sets: /var/lib/mutara for the service.
  3. The working folder, if it already holds state and the folder of the configuration file does not.
  4. The working folder, if it is /var/lib/mutara, as in the Docker image.
  5. The folder of the configuration file.

Each node after the first keeps its recent nodes, clips, bundles, chat and favorites in modules/<node>/. A room keeps its clips, bundles and chat in modules/<id>/. A removed node moves to modules/.removed/<node>-<date>-<time>/. Mutara does not delete those files.

Logs and the journal #

  • Follow the log of the service: journalctl -u mutara -f
  • Read the log of an upgrade: journalctl -u mutara -u mutara-upgrade
  • log.level is debug, info, warn or error. log.format is text or json.
  • The diagnostics file from Settings has the recent logs, the version, the status and the settings without passwords.

Useful messages: "allstar registration failed" with the reason, and an ERROR with the stack when a node stops on an internal error.

Command-line flags #

FlagWhat it does
-config fileThe configuration file. The default is ./mutara.yaml, then /etc/mutara/mutara.yaml.
-versionPrint the version.
-example-configPrint a commented example configuration.
-check-configCheck the configuration and the module files.
-hash-passwordRead a password and print a bcrypt hash for password_hash.
-list-radiosList the USB radio interfaces.
-find-radio-moduleLook for radio modules on the USB serial ports. -ports selects the ports.
-program-radio-moduleWrite radio.module to the module, only when the radio is quiet.
-import-asl3 folderMake the configuration from an ASL3 setup. Read The ASL3 importer.
-verify-release fileCheck the signature and checksum of a release file.
-healthcheckCheck that the dashboard of the running node answers.
-cpuprofile fileWrite a CPU profile of the running node. -cpuprofile-seconds sets the time, 60 by default.

The ASL3 importer #

mutara -import-asl3 /etc/asterisk -dry-run
sudo mutara -import-asl3 /etc/asterisk -config /etc/mutara/mutara.yaml

The importer reads rpt.conf, iax.conf and the USB channel files. It copies these items:

  • the node number and password, the callsign and the timers
  • the courtesy tone, the DTMF functions, the macros and the schedule
  • the permanent links of startup_macro and the [nodes] entries
  • the simpleusb or usbradio channel and the IAX app logins

It prints what it copied and what it skipped. It does not change the ASL3 files.

  • -dry-run shows the result and writes nothing.
  • -force replaces a configuration and keeps its dashboard accounts.
  • -asl3-node selects the node for mutara.yaml when the setup has several nodes.
  • The importer writes the node with the USB radio, or the node of -asl3-node, to mutara.yaml. It writes each other node to modules.d/<node>.yaml.

sudo mutara-switch asl3 stops Mutara and starts ASL3. sudo mutara-switch mutara does the opposite. The first time, it copies the ASL3 settings. To copy a different node, add its number: sudo mutara-switch mutara 2101. If Mutara does not start, it starts ASL3 again.

Web API #

These routes are documented for other programs. Other routes are for the dashboard and can change.

RouteWhat it does
GET /api/recordingsThe list of clips, newest first, with id, start, duration_ms, talker, label, kind, size, type and url.
GET /api/recordings/{id}/audioThe clip, with HTTP Range support. format=m4a sends Opus in MP4. download=1 asks the browser to save it.
DELETE /api/recordings/{id}Delete a clip. Admins only.
/api/wsThe event stream. It sends a recording message when a clip is added or deleted. Each user, or each address of a visitor who is not signed in, can have at most 32 of these connections, and the node accepts 1024 in total. A connection over a limit closes with code 1013 and a reason.
GET /api/meThe signed-in user and the rights. modules lists the nodes that the user may view, also when there is one, and can of each node has the twelve actions, bundles included, for example {"talk":true,"download":false}. The fields for the whole install (can_transmit, can_operate, can_chat and the others) are true when the user may do it on any node, for older apps. can_admin is an admin of the install. An older node sends only those fields, and modules only with more than one node, without can. "no_modules": true when the user has no node of the install. "theme" is the saved dashboard theme of the user, "dmr_id" the DMR ID and "callsign" the M17 callsign of the user.
PUT /api/me/prefsSave the preferences of the signed-in user, for example {"theme":"dark"}. The theme is system, light or dark. dmr_id (7 digits) and callsign (the M17 callsign) are optional. Signed-in users only.
GET /api/statusThe status of the first node.
GET /api/modulesThe nodes that the user can use, with their status.
/api/m/{node}/…Each dashboard route for one node, for example /api/m/2101/status. Another node of a limited user returns 403. A change to a stopped node returns 503.
POST /api/modules/{node}/restartRestart one node. Admins only.
POST /api/modulesAdd a module, for example {"type":"allstar","node":"2200"} or {"type":"ysf","id":"ysf-club","reflector":"host:port","local_number":"2350","link_module":"2100"}, or a DMR module with "type":"dmr", id, master, password, dmr_id, essid, timeslot, talkgroup, local_number and link_module. Admins only.
DELETE /api/modules/{id}Remove a module. Mutara keeps its state folder in modules/.removed/. You cannot remove the first module. Admins only.
GET /api/lastheardThe last talkers and the activity of each module, for the module bar. ?module={id} gives the talkers of one module. ?scope=all gives one row for each callsign.
GET /api/activityThe recent events of all the modules that you may see, newest first, up to 150. Each event has module and module_type. Add ?module= and a module ID for the events of one module.
GET /api/scan/priorityThe scan priority of each module that you may listen to, for example {"2101":{"default":90,"user":null,"effective":90}}. user is null when you use the default.
PUT /api/scan/priority{"module":"2101","user":20} sets your own value. "user":null removes it. An admin sends {"module":"2101","default":90} to set the default. The value is from 0 to 99.
/api/m/{node}/bundlesThe bundles of a node: list, make, change and delete them, get the audio and the zip, and make public links. /api/bundles is the same for the first node. A bundle gives can_edit, can_delete, can_links and can_download for the user. The zip needs download. Read Bundles and transcripts.
POST /api/m/{node}/recordings/{id}/transcribeSend one clip to speech to text. It needs bundles. The answer is 202. The recording event with op: "transcript" comes when the text is ready.
GET /api/m/{node}/recordings/{id}/transcriptThe transcript of a clip, with its parts and a confidence for each part. It needs clips. 404 means that the clip has no transcript.
GET /api/share/{token}A bundle as the holder of a public link sees it, with no account. Account names show as callsigns. /share/{token} is the web page. A link that ended or was revoked gives 404.
/api/scan/audioThe scan stream, a WebSocket. It plays the active node of all the nodes of the user. Read The scan stream.

A user with clips on the module can list and play its clips. Saving a clip (download=1 or format=m4a) needs download. The list says can_download and can_delete for the user, so a client shows only the buttons that work. An older node does not send can_download: take it as true. Other requests get 403. A client must play url with the media type in type, and must not make the URL itself.

The scan stream

Open /api/scan/audio?codec=opus or ?codec=ulaw as a WebSocket. You must be signed in with listen permission. hang= (2 to 30 seconds), skip_ids=1 and list=1 are optional start values. list=1 is Scan my list; without it, the scan is Scan all. The scan and the audio of a module count in the same limit: at most 8 audio connections for each user, and 256 in total. A connection over a limit closes with code 1013 and a reason.

  • The audio frames, and the ptt and agc messages, are the same as on the audio stream of one node.
  • The first message is hello, with "where":"scan", "protocol":1, mode (all or list) and the list of nodes.
  • A scan message comes when the scan changes. It gives module, state, active, skipped, waiting, priority, port_id, list (the modules of the scan now) and left_out (the rooms of the list that the scan left out, with the reason full or removed). The state is idle, active, hang or talk.
  • priority gives the priority of each module for this user. waiting lists the active modules with a higher priority that wait because you talk back, the best first.
  • A change of priority or of the scan list applies to an open scan at once. The scan does not connect again.
  • port_id is the port of the scan in the status of that node. It is empty when the scan is idle.
  • To control the scan, send scan (with hang_s or skip_ids), skip or unskip.

PTT talks on the node that the scan plays. If the node refuses PTT, a ptt message gives the reason: scan_idle, scan_no_tx, scan_gone, limit or busy, and in a room stopped, interrupt or threshold. On a YSF module that is busy, busy comes with "where":"reflector" and the talker of the reflector. The README of the project has the full list of messages.