Skip to content

Using plugins

This page covers operating plugins on a running server: where the host looks for them, how configuration keys are namespaced, how to verify that a plugin loaded correctly, and a tour of the plugins that ship with the official Docker image.

The host scans two directories at startup:

PathPurpose
/usr/lib/mumble-server/pluginsPlugins baked into the image.
/etc/mumble/pluginsOperator-supplied plugins (mount your own).

Both are scanned on boot. Any file matching the platform’s shared library extension (*.so on Linux, *.dylib on macOS, *.dll on Windows) is considered a candidate. Files that fail to load (wrong ABI version, missing symbols, panic in on_load, …) are logged and skipped; the server continues to boot.

To override the search path, set the plugins_dir server config key (comma-separated for multiple directories).

Every plugin gets its own configuration namespace under plugin.<name>.* in mumble-server.ini, where <name> is the value returned by the plugin’s MumblePlugin::name() method.

# Enable the live-doc plugin and bind its WebSocket on port 64740
plugin.fancy-live-doc.enabled=true
plugin.fancy-live-doc.port=64740
plugin.fancy-live-doc.state_path=/data/fancy-live-doc
# Enable the file server and pin its storage directory
plugin.fancy-file-server.enabled=true
plugin.fancy-file-server.storagePath=/data/file-server-storage
plugin.fancy-file-server.port=64739

Inside the plugin, these are read via PluginContext::get_config("port") - the host strips the plugin.<name>. prefix automatically, so plugins never have to know their own name to read their own config.

Every Fancy plugin defaults to disabled. The plugin host scans the plugin directories and discovers every cdylib it finds, but it only calls a plugin’s on_load hook after reading plugin.<name>.enabled from mumble-server.ini and confirming the value is true, 1, yes, or on (case-insensitive, leading/trailing whitespace ignored). Disabled plugins:

  • never run on_load, so they bind no ports and start no background tasks;
  • do not appear in the PluginRegistry broadcast (wire ID 201), so clients do not advertise capabilities for them;
  • do not receive any lifecycle events (on_client_connected, on_client_disconnected, on_plugin_data, on_plugin_message).

The check lives entirely in the host — individual plugins do not (and should not) inspect enabled themselves. To turn a plugin off without removing the cdylib:

  1. Set plugin.<name>.enabled=false in mumble-server.ini (or simply remove the line; absent counts as disabled).
  2. Send SIGHUP to murmurd (or restart the container) to reload the configuration.
  3. Confirm the plugin’s “plugin loaded” log line is replaced by a “plugin discovered but not enabled” line.

When a disabled plugin is discovered the host logs:

INFO mumble_plugin_host::host: plugin discovered but not enabled; set plugin.fancy-live-doc.enabled=true to load plugin=fancy-live-doc

On startup the host logs each plugin it tries to load:

INFO mumble_plugin_host::host: plugin host initialising dir_count=2 dirs=["/usr/lib/mumble-server/plugins", "/etc/mumble/plugins"]
INFO mumble_plugin_host::host: plugin loaded plugin=fancy-live-doc version=0.1.0 path=/usr/lib/mumble-server/plugins/libmumble_live_doc.so
INFO mumble_plugin_host::host: plugin loaded plugin=fancy-file-server version=0.1.0 path=/usr/lib/mumble-server/plugins/libmumble_file_server.so
INFO mumble_plugin_host::host: plugin host ready loaded=2

After a successful boot you can also inspect the registry from any connected client. Open the Server Info dialog (toolbar -> “i” icon) and switch to the Developer tab. The “Plugins” panel lists every entry from the PluginRegistry envelope along with the debug_rows each plugin advertises (listening ports, snapshot intervals, queue depths, …).

The official fancy-mumble/mumble-server Docker image ships with two plugins out of the box.

A self-contained HTTP file server that backs avatars, message attachments, and live-doc snapshots. Listens on port 64739 by default. Storage lives at plugin.fancy-file-server.storagePath, which must be a writable mount if you want files to survive container restarts.

See File server for the full configuration reference and storage layout.

To run a plugin you built yourself (or grabbed from a third party):

  1. Copy the *.so file to a host directory you control, e.g. ./my-plugins/libmy_plugin.so.

  2. Mount that directory into the container at /etc/mumble/plugins:

    services:
    mumble:
    image: fancy-mumble/mumble-server:latest
    volumes:
    - ./mumble-server.ini:/data/mumble-server.ini:ro
    - ./my-plugins:/etc/mumble/plugins:ro
  3. Add a plugin.<name>.enabled=true line to mumble-server.ini along with whatever else your plugin’s from_context parser expects.

  4. Restart the container and watch the boot log for plugin loaded plugin=<name>.

Inbound PluginMessage envelopes from clients are subject to the same per-user rate limit as any other Mumble control message. The server stamps sender_session and sender_name before handing the message to the target plugin; the plugin cannot spoof either.

Each plugin can additionally check whether the sender has a specific permission on a channel via PluginContext::has_permission - useful for gating administrative operations on standard Mumble ACL flags (Write, Move, Kick, …). The flag values are defined in the mumble_plugin_api::permissions module.

  • Server Plugins (admin panel) — enable, disable, and uninstall plugins from the Fancy Mumble client UI without editing config files.
  • Marketplace — install community plugins with one click from the built-in marketplace.
  • Plugins (user view) — how end users grant or revoke trust for plugin UI surfaces (slash commands, modals, components).