Skip to content

Plugin Development Guide

This comprehensive guide covers how to build plugins for NetAlertX.

Tip

New to plugin development? Start with the Quick Start Guide to get a working plugin in 5 minutes.

NetAlertX comes with a plugin system to feed events from third-party scripts into the UI and then send notifications, if desired. The highlighted core functionality this plugin system supports:

  • Dynamic UI generation - Automatically create tables for discovered objects
  • Data filtering - Filter and link values in the Devices UI
  • User settings - Surface plugin configuration in the Settings UI
  • Rich display types - Color-coded badges, links, formatted text, and more
  • Database integration - Import plugin data into NetAlertX tables like CurrentScan or Devices

Note

For a high-level overview of how the config.json is used and its lifecycle, see the config.json Lifecycle Guide.

🚀 Getting Started

📚 Core Concepts

  • Data Contract - The exact output format plugins must follow (9-13 columns, pipe-delimited)
  • Data Sources - How plugins retrieve data (scripts, databases, templates)
  • Plugin Settings System - Let users configure your plugin via the UI
  • UI Components - Display plugin results with color coding, links, and more

🏗️ Architecture

🐛 Troubleshooting

🎥 Video Tutorial

Watch the video

📸 Screenshots

Screen 1 Screen 2 Screen 3
Screen 4 Screen 5

Use Cases

Plugins are infinitely flexible. Here are some examples:

  • Device Discovery - Scan networks using ARP, mDNS, DHCP leases, or custom protocols
  • Service Monitoring - Monitor web services, APIs, or network services for availability
  • Integration - Import devices from PiHole, Home Assistant, Unifi, or other systems
  • Enrichment - Add data like geolocation, threat intelligence, or asset metadata
  • Alerting - Send notifications to Slack, Discord, Telegram, email, or webhooks
  • Reporting - Generate insights from existing NetAlertX database (open ports, recent changes, etc.)
  • Custom Logic - Create fake devices, trigger automations, or implement custom heuristics

If you can imagine it and script it, you can build a plugin.

Limitations & Notes

  • Plugin data is deduplicated hourly (same Primary ID + Secondary ID + User Data = duplicate removed)
  • Currently, only CurrentScan table supports update/overwrite of existing objects
  • Plugin results must follow the strict Data Contract
  • Plugins run with the same permissions as the NetAlertX process
  • External dependencies must be installed in the container

Plugin Development Workflow

Step 1: Understand the Basics

  1. Read Quick Start Guide - 5 minute overview
  2. Study the Data Contract - Understand the output format
  3. Choose a Data Source - Where does your data come from?

Step 2: Create Your Plugin

  1. Copy the __template plugin folder (see below for structure)
  2. Update config.json with your plugin metadata
  3. Implement script.py (or configure alternative data source)
  4. Test locally in the devcontainer

Step 3: Configure & Display

  1. Define Settings for user configuration
  2. Design UI Components for result display
  3. Map to database tables if needed (for notifications, etc.)

Step 4: Deploy & Test

  1. Restart the backend
  2. Test via Settings → Plugin Settings
  3. Verify results in UI and logs
  4. Check /tmp/log/plugins/last_result.<PREFIX>.log

See Quick Start Guide for detailed step-by-step instructions.

Plugin File Structure

Every plugin lives in its own folder under /app/front/plugins/.

Important: Folder name must match the "code_name" value in config.json

/app/front/plugins/
├── __template/          # Copy this as a starting point
│   ├── config.json      # Plugin manifest (configuration)
│   ├── script.py        # Your plugin logic (optional, depends on data_source)
│   └── README.md        # Setup and usage documentation
├── my_plugin/           # Your new plugin
│   ├── config.json      # REQUIRED - Plugin manifest
│   ├── script.py        # OPTIONAL - Python script (if using script data source)
│   ├── README.md        # REQUIRED - Documentation for users
│   └── other_files...   # Your supporting files

Plugin Manifest (config.json)

The config.json file is the plugin manifest - it tells NetAlertX everything about your plugin:

  • Metadata: Plugin name, description, icon
  • Execution: When to run, what command to run, timeout
  • Settings: User-configurable options
  • Data contract: Column definitions and how to display results
  • Integration: Database mappings, notifications, filters

Example minimal config.json:

{
  "code_name": "my_plugin",
  "unique_prefix": "MYPLN",
  "display_name": [{"language_code": "en_us", "string": "My Plugin"}],
  "description": [{"language_code": "en_us", "string": "My awesome plugin"}],
  "icon": "fa-plug",
  "data_source": "script",
  "execution_order": "Layer_0",
  "settings": [
    {
      "function": "RUN",
      "type": {"dataType": "string", "elements": [{"elementType": "select", "elementOptions": [], "transformers": []}]},
      "default_value": "disabled",
      "options": ["disabled", "once", "schedule"],
      "localized": ["name"],
      "name": [{"language_code": "en_us", "string": "When to run"}]
    },
    {
      "function": "CMD",
      "type": {"dataType": "string", "elements": [{"elementType": "input", "elementOptions": [], "transformers": []}]},
      "default_value": "python3 /app/front/plugins/my_plugin/script.py",
      "localized": ["name"],
      "name": [{"language_code": "en_us", "string": "Command"}]
    }
  ],
  "database_column_definitions": []
}

For comprehensive config.json documentation, see PLUGINS_DEV_CONFIG.md

Full Reference (Below)

The sections below provide complete reference documentation for all plugin development topics. Use the quick links above to jump to specific sections, or read sequentially for a deep dive.

More on specifics below.


Data Contract & Output Format

For detailed information on plugin output format, see PLUGINS_DEV_DATA_CONTRACT.md.

Quick reference: - Format: Pipe-delimited (|) text file - Location: /tmp/log/plugins/last_result.<PREFIX>.log - Columns: 9 required + 4 optional = 13 maximum - Helper: Use plugin_helper.py for easy formatting

The 9 Mandatory Columns

Column Name Required Example
0 Object_PrimaryID YES "device_name" or "192.168.1.1"
1 Object_SecondaryID no "secondary_id" or null
2 DateTime YES "2023-01-02 15:56:30"
3 Watched_Value1 YES "online" or "200"
4 Watched_Value2 no "ip_address" or null
5 Watched_Value3 no null
6 Watched_Value4 no null
7 Extra no "additional data" or null
8 ForeignKey no "aa:bb:cc:dd:ee:ff" or null

See Data Contract for examples, validation, and debugging tips.


Config.json: Settings & Configuration

For detailed settings documentation, see PLUGINS_DEV_SETTINGS.md and PLUGINS_DEV_DATASOURCES.md.

Setting Object Structure

Every setting in your plugin has this structure:

{
  "function": "UNIQUE_CODE",
  "type": {"dataType": "string", "elements": [...]},
  "default_value": "...",
  "options": [...],
  "localized": ["name", "description"],
  "name": [{"language_code": "en_us", "string": "Display Name"}],
  "description": [{"language_code": "en_us", "string": "Help text"}]
}

Reserved Function Names

These control core plugin behavior:

Function Purpose Required Options
RUN When to execute YES disabled, once, schedule, always_after_scan, before_name_updates, on_new_device
RUN_SCHD Cron schedule If RUN=schedule Cron format: "0 * * * *"
CMD Command to run YES Shell command or script path
RUN_TIMEOUT Max execution time optional Seconds: "60"
WATCH Monitor for changes optional Column names
REPORT_ON When to notify optional new, watched-changed, watched-not-changed, missing-in-last-scan
DB_PATH External DB path If using SQLite /path/to/db.db

See PLUGINS_DEV_SETTINGS.md for full component types and examples.


Filters & Data Display

For comprehensive display configuration, see PLUGINS_DEV_UI_COMPONENTS.md.

Filters

Control which rows display in the UI:

{
  "data_filters": [
    {
      "compare_column": "Object_PrimaryID",
      "compare_operator": "==",
      "compare_field_id": "txtMacFilter",
      "compare_js_template": "'{value}'.toString()",
      "compare_use_quotes": true
    }
  ]
}

See UI Components: Filters for full documentation.


Database Mapping

To import plugin data into NetAlertX tables for device discovery or notifications:

{
  "mapped_to_table": "CurrentScan",
  "database_column_definitions": [
    {
      "column": "Object_PrimaryID",
      "mapped_to_column": "cur_MAC",
      "show": true,
      "type": "device_mac",
      "localized": ["name"],
      "name": [{"language_code": "en_us", "string": "MAC Address"}]
    }
  ]
}

See UI Components: Database Mapping for full documentation.

Static Value Mapping

To always map a static value (not read from plugin output):

{
  "column": "NameDoesntMatter",
  "mapped_to_column": "cur_ScanMethod",
  "mapped_to_column_data": {
    "value": "MYPLN"
  }
}

UI Component Types

Plugin results are displayed in the web interface using various component types. See PLUGINS_DEV_UI_COMPONENTS.md for complete documentation.

Common Display Types

Read settings in your Python script:

from helper import get_setting_value

# Read a setting by code name (prefix + function)
api_url = get_setting_value('MYPLN_API_URL')
api_key = get_setting_value('MYPLN_API_KEY')
watch_columns = get_setting_value('MYPLN_WATCH')

print(f"Connecting to {api_url}")

Pass settings as command parameters:

Define params in config to pass settings as script arguments:

{
  "params": [
    {
      "name": "api_url",
      "type": "setting",
      "value": "MYPLN_API_URL"
    }
  ]
}

Then use in CMD: python3 script.py --url={api_url}

See PLUGINS_DEV_SETTINGS.md for complete settings documentation, and PLUGINS_DEV_DATASOURCES.md for data source details.

Quick Reference: Key Concepts

Plugin Output Format

Object_PrimaryID|Object_SecondaryID|DateTime|Watched_Value1|Watched_Value2|Watched_Value3|Watched_Value4|Extra|ForeignKey
9 required columns, 4 optional helpers = 13 max

See: Data Contract

Plugin Metadata (config.json)

{
  "code_name": "my_plugin",           // Folder name
  "unique_prefix": "MYPLN",           // Settings prefix
  "display_name": [...],              // UI label
  "data_source": "script",            // Where data comes from
  "settings": [...],                  // User configurable
  "database_column_definitions": [...] // How to display
}

See: Full Guide, Settings

Reserved Settings

  • RUN - When to execute (disabled, once, schedule, always_after_scan, etc.)
  • RUN_SCHD - Cron schedule
  • CMD - Command/script to execute
  • RUN_TIMEOUT - Max execution time
  • WATCH - Monitor for changes
  • REPORT_ON - Notification trigger

See: Settings System

Display Types

label, device_mac, device_ip, url, threshold, replace, regex, textbox_save, and more.

See: UI Components


Tools & References

  • Template Plugin: /app/front/plugins/__template/ - Start here!
  • Helper Library: /app/front/plugins/plugin_helper.py - Use for output formatting
  • Settings Helper: /app/server/helper.py - Use get_setting_value() in scripts
  • Example Plugins: /app/front/plugins/*/ - Study working implementations
  • Logs: /tmp/log/plugins/ - Plugin output and execution logs
  • Backend Logs: /tmp/log/stdout.log - Core system logs