# Plugin: Minimal Linux

**Audience:** Integrators registering a long-running managed plugin on Linux endpoints.

This is the Linux variant of [Plugin: Minimal Windows](/keeperpam/endpoint-privilege-manager/integrations/examples/plugin-minimal-windows.md). The plugin structure and field meanings are identical — the differences are the binary path, `supportedPlatforms`, and Linux-specific signing and permission considerations. Read the Windows page first for the full explanation of each field; this page covers only what changes on Linux.

## The Plugin JSON

```json
{
  "id": "MyBridge",
  "name": "My Bridge",
  "description": "Long-running bridge component.",
  "version": "1.0.0",

  "pluginType": "Executable",
  "executablePath": "bin/MyBridge/MyBridge",
  "supportedPlatforms": ["Linux"],

  "Subscription": {
    "Topic": "MyBridge",
    "Qos": 2,
    "CleanSession": true
  },

  "metadata": {
    "mqttRole": ["subscriber", "publisher"],
    "mqttTopics": {
      "publish": ["KeeperLogger"],
      "subscribe": ["MyBridge", "MyBridge/Commands/+"]
    }
  },

  "startupPriority": 60,
  "autoStart": true,
  "executionContext": "Service",
  "requiresMonitoring": true,
  "autoRestart": true
}
```

## What to Change

The fields are the same as the Windows variant. The only Linux-specific substitutions are:

<table data-header-hidden="false" data-header-sticky><thead><tr><th width="276.6666259765625">Field</th><th>What to Put Here</th></tr></thead><tbody><tr><td><code>id</code></td><td>A stable, unique identifier matching the filename: <code>MyBridge.json</code> for <code>"id": "MyBridge"</code>.</td></tr><tr><td><code>executablePath</code></td><td>Path to the binary relative to the agent root, with no <code>.exe</code> extension. The default Linux agent root is <code>/opt/KeeperPrivilegeManager</code> — so <code>bin/MyBridge/MyBridge</code> resolves to <code>/opt/KeeperPrivilegeManager/bin/MyBridge/MyBridge</code>. Confirm the install root with your administrator.</td></tr><tr><td><code>supportedPlatforms</code></td><td><code>["Linux"]</code> for a Linux-only plugin. Use <code>["Linux", "Windows", "macOS"]</code> if the same JSON covers multiple platforms, though separate per-platform files are usually easier to maintain.</td></tr><tr><td><code>Subscription.Topic</code></td><td>The primary MQTT topic for this plugin. By convention, use the plugin <code>id</code>.</td></tr><tr><td><code>metadata.mqttTopics.publish</code></td><td>Every topic your binary publishes to. Include <code>KeeperLogger</code> if you publish log messages.</td></tr><tr><td><code>metadata.mqttTopics.subscribe</code></td><td>Every topic your binary subscribes to beyond the primary <code>Subscription.Topic</code>.</td></tr></tbody></table>

**No `.exe` extension.** The binary name in both `executablePath` and the directory path has no extension. Binary names on Linux are conventionally lowercase — `mybridge` rather than `MyBridge` — though the agent resolves whatever name you provide.

**File permissions.** The binary must be executable by the agent service account before the orchestrator can launch it:

```bash
chmod +x /opt/KeeperPrivilegeManager/bin/MyBridge/MyBridge
```

If the agent runs as a specific non-root user, also confirm that user has read and execute permission on the binary and its parent directories.

**Signing on Linux.** Unlike Windows and macOS, there is no universal binary signing requirement enforced at the OS level on Linux. The agent's process trust mechanism relies primarily on the orchestrator having launched your binary — ensuring it is always started by the agent rather than manually is more important than a code signature. If your deployment enforces IMA or uses GPG-signed packages, align with those requirements as you would for any other component. Add your certificate thumbprint to `Settings:AlternativeSignatures` in `appsettings.json` if MQTT or Plugin Settings access must work outside an orchestrator-launched context.

**`autoRestart` and service management.** On Linux, the KEPM agent typically runs as a systemd service. If `autoRestart: true` is set and the plugin exits unexpectedly, the orchestrator restarts it — independently of systemd. Be aware that rapid restart loops can generate significant log volume and CPU load. Confirm your plugin exits cleanly under expected shutdown conditions and logs a clear message before exiting to distinguish crashes from intentional stops.

## Before You Deploy

1. Place the binary at the path resolved by `executablePath` and set executable permissions with `chmod +x`.
2. Place the JSON file at `{AgentRoot}/Plugins/MyBridge.json`. The filename must match `id`.
3. Coordinate with your administrator on the supported insertion path for your environment.
4. Restart the agent service so the orchestrator picks up the new plugin registration:

```bash
sudo systemctl restart keeperprivilegemanager
```

## Verify

After the agent restarts, check the agent logs for your plugin name to confirm it started. Then verify Plugin Settings are reachable from inside your binary at startup:

```bash
curl -s https://127.0.0.1:6889/api/PluginSettings/MyBridge \
  --cert /path/to/client.pem \
  --key /path/to/client.key \
  --cacert /path/to/ca.pem
```

This call requires Plugin-tier authentication and will return `403` if made from an arbitrary shell session rather than from a process the agent launched. Run the equivalent call from inside your plugin binary as a startup smoke test.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.keeper.io/keeperpam/endpoint-privilege-manager/integrations/examples/plugin-minimal-linux.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
