Plugins
Plugins are optional add-ons that extend what your eIOU node does. This page covers what plugins are, what they can and cannot reach, how to install and enable them, and how signature verification works. The CLI commands for plugin management live in System & Advanced; the full technical reference (manifest schema, permission catalog, plugin-authoring contract) lives in Reference › Plugins.
Setting up MCP inference? Follow the MCP Passthrough documentation for node access, providers, client configuration, and a first test call.
Overview
A plugin is an optional add-on that extends what the eIOU node software can do without modifying the core. Each plugin lives in its own directory under /etc/eiou/plugins/, ships with a manifest that declares everything it wants to contribute, and runs in an isolated sandbox separate from the wallet (see The sandbox).
Plugins can contribute Web GUI sections, CLI subcommands, REST API endpoints, payback-method rail types (for example, Bitcoin, PayPal, Bizum), event subscribers, and additional services that run alongside the node inside the container.
Plugins are disabled by default. A freshly-installed plugin will not run until you explicitly enable it through the GUI or the CLI and restart the node. This opt-in posture exists so a buggy or untrusted plugin cannot crash the node on its first boot.
Bundled vs third-party plugins
Every plugin on your node falls into one of two categories.
Bundled plugins are authored by eIOU and ship inside the official eiou-docker image. They are seeded into your node's plugin directory on first boot, can be auto-upgraded when a newer image ships an updated version (with your enabled or disabled state preserved), and are open-source verifiable in the eiou-docker repository. Today the only bundled plugin is hello-eiou, a sample plugin used to demonstrate the plugin surface.
Third-party plugins are anything not authored by eIOU and not shipped in the official image. eIOU does not author, audit, or vouch for third-party plugins, regardless of whether they are signed by a publisher whose key you have chosen to trust (see Signature verification). Each third-party plugin is between you and the publisher.
Bundled and third-party plugins share the same install, enable, and sandbox model. The difference is who wrote them, and therefore whether you can trust the publisher.
The sandbox
The node software enforces a mandatory sandbox on every plugin. The installer refuses to accept any plugin that does not opt into the sandbox in its manifest, and the loader refuses to enable or boot one even if it somehow slipped through. Every plugin runs in its own process pool, as its own Unix user, with a restricted filesystem view and shell-out and eval disabled.
What the sandbox blocks
Under those rules, a sandboxed plugin cannot:
- Read wallet private keys, the BIP39 seed phrase, the master encryption key, or any other wallet secret on the filesystem
- Read API key plaintext (only hashed identifiers are exposed)
- Run direct SQL against core tables:
contacts,transactions,api_keys,balances,payback_methods, and others are completely invisible to the plugin's database user - Read or modify other plugins' tables
- Persist state anywhere except its own directory and its own database tables
- Crash the node: a plugin that throws during discovery, registration, or boot is caught, marked
failed, and logged, while the rest of the node continues - Run shell commands, evaluate arbitrary code through
eval, or invoke other restricted PHP functions
What the sandbox does NOT block
The sandbox isolates wallet data; it is not a full PHP execution sandbox. A malicious plugin still runs arbitrary PHP inside its own pool and can:
- Make outbound network requests within the limits of the container's network access
- Transmit any data the operator has authorized it to read (see What a plugin can see)
- Behave maliciously after passing signature verification: signatures attest to the publisher's identity, not to the plugin's behavior
For genuinely hostile plugins, the mitigations are upstream of the sandbox: signature verification, vetted install sources, code review, and the operator's choice not to grant permissions a plugin does not need.
What a plugin can see
Within the sandbox, a plugin reaches core data only through a controlled, read-only set of queries that it declares up front in its manifest. The manifest specifies two things, and both are visible to you at install time so you can review what the plugin is asking for before enabling it.
core_services is an allow-list of <Service>.<method> calls the plugin will make. The host gateway rejects any call outside this list, even if the method exists on the host.
permissions is a louder-consent grant required by certain higher-impact methods (for example, listing every contact, reading the full transaction history, or sending funds on the wallet's behalf). The installer refuses any manifest that asks for unknown permission keys.
The data categories a plugin can reach with the right declarations include contact lookups (and, with the louder-consent enumeration permission, the full address book), transaction records (by id, by memo, or full history with the enumeration permission), wallet balance, payment requests, and payback-method capability metadata. The most consequential permission is wallet_outbound_send: a plugin that holds it can spend funds from the wallet within the rate cap, the same way the eiou send command does.
The full permission catalog (which is expected to grow as the plugin system evolves) is documented in Reference › Plugins › Permissions. Reviewing it before approving a third-party plugin is the cheapest way to understand what you are agreeing to.
What is deliberately not reachable
- Plaintext payback-method account identifiers (for example, bank account numbers, Lightning addresses) are not exposed; only capability metadata is
- API key plaintext is never exposed; only hashed identifiers
- Wallet keys and the BIP39 seed phrase are not exposed by any service, with or without permissions
Installing a plugin
There are three ways a plugin can arrive on a node.
Bundled with the image
Plugins authored by eIOU ship inside the official Docker image. On first boot, the startup process seeds them into your plugin directory without overwriting existing operator state. If a later image ships a newer version of a bundled plugin, the auto-upgrade flow installs the newer copy at boot while preserving your enabled or disabled state.
Upload a .zip through the GUI or CLI
The most common path for third-party plugins. From the GUI, navigate to Settings › Plugins and use the upload control. From the CLI:
docker cp my-plugin.zip alice:/tmp/my-plugin.zipdocker exec alice eiou plugin install /tmp/my-plugin.zipEither path runs the same validation pipeline: zip integrity, no path traversal, allow-listed file types, a single top-level plugin directory, the manifest parses and matches the directory, and (when signature verification is set to require) the plugin is signed by a trusted key.
Install does not enable the plugin. Newly installed plugins land disabled until you explicitly enable them (see Enabling and disabling).
Manual drop-in
If you have shell access to the container, you can copy a plugin directory directly into /etc/eiou/plugins/. The next time the node discovers plugins (at boot or on demand) it will pick it up, disabled by default, subject to the same signature checks as upload installs.
Enabling and disabling
Plugins are disabled by default. To turn one on, use the GUI (Settings › Plugins) or the CLI:
eiou plugin enable hello-eiouThe enabled flag is persisted in /etc/eiou/config/plugins.json. The plugin's own process pool starts immediately, but most plugin surfaces (event subscriptions, filter hooks, render hooks) only bind during boot. You need to restart the node for those to take effect:
eiou restartDisabling a plugin is the same flow in reverse:
eiou plugin disable hello-eiouDisabling stops the plugin's process pool immediately and prevents its event subscriptions from binding on the next boot. The plugin's directory, manifest, and database tables remain intact in case you re-enable it later. To remove a plugin entirely, see Upgrading and uninstalling.
The full set of plugin CLI commands, including eiou plugin list for inspecting installed plugins, lives in System & Advanced › Plugins.
Signature verification
The node software supports Ed25519 signature verification for plugins. The verifier answers exactly one question: "was this plugin signed by a publisher I have chosen to trust?" Nothing more. Signatures attest to who signed the plugin, not to whether the plugin behaves well.
Two layers of trusted keys
The node looks for trusted public keys in two directories.
Baked-in (first-party): /app/eiou/plugins/trusted-keys/ holds eIOU-official keys that ship with every node. Read-only inside the container.
Operator-managed (third-party): /etc/eiou/plugins/trusted-keys/ holds keys you have deliberately added because you trust the publisher to ship plugins for your node. Lives on your config volume.
Adding a key to the operator-managed directory is a meaningful security decision. A trusted key lets the holder ship plugins your node will accept; make sure you actually trust the publisher and have a way to revoke if you change your mind.
Three enforcement modes
Signature checking has three modes, controlled by the PLUGIN_SIGNATURE_MODE environment variable.
off: the verifier does not run. Every plugin loads regardless of signature state. Use this only when you deliberately want to disable signature verification.
warn (default): the verifier runs, signature status is recorded and surfaced in the plugin list, but the plugin still loads even if verification fails. Useful for seeing which plugins would fail under require without breaking anything.
require: the verifier runs and refuses to load any plugin whose signature is missing, malformed, untrusted, or invalid. Recommended for production once every plugin you want to keep running has been signed by a trusted key.
A reasonable rollout is to use the default warn mode to see which of your plugins would fail, sign or re-source whatever needs signing, then switch to require.
The full signature workflow (generating keys, signing plugins, distributing public keys, and what each signature status means) lives in Reference › Plugins › Plugin Signatures.
Upgrading and uninstalling
The upgrade flow installs a newer version of an already-installed plugin: extract the new zip, run the plugin's onUpgrade hook (which may migrate database tables), and atomically replace the directory. A backup of the previous version is kept for 30 days so you can roll back if a migration goes wrong.
Uninstalling runs the reverse: the plugin's onUninstall hook runs first, then its tables and database user are dropped, its credentials file is removed, and finally its files are deleted. A plugin must be disabled before it can be uninstalled.
eiou plugin uninstall hello-eiouFull upgrade and uninstall command details live in System & Advanced › Plugins. The contract for plugin authors writing onUpgrade and onUninstall hooks lives in Reference › Plugins.