Skip to content

Plugin Development with OPM Packages

In this section, you will learn how to create, install, and distribute your own plugins as OPM packages for OTOBO.


The SOPM file (*.sopm) contains all metadata for your package:

<?xml version="1.0" encoding="utf-8"?>
<otobo_package version="1.0">
<Name>MyExtension</Name>
<Version>1.0.0</Version>
<Framework>10.0.x</Framework> <!-- Minimum OTOBO version -->
<Vendor>YourName GmbH</Vendor>
<URL>https://github.com/your-user/otobo-mypackage</URL>
<License>GPL-3.0</License>
<Description Lang="en">Extension for special functions</Description>
<ChangeLog Version="1.0.0" Date="13.06.2025 12:00:00">Initial release</ChangeLog>
<Filelist>
<File Location="Kernel/Config/Files/XML/MyExtension.xml" Permission="644"></File>
<File Location="Kernel/System/MyExtension.pm" Permission="644"></File>
<File Location="Kernel/Modules/AgentMyPage.pm" Permission="644"></File>
<File Location="Kernel/Output/HTML/Standard/AgentMyPage.tt" Permission="644"></File>
<File Location="Kernel/Language/en_MyExtension.pm" Permission="644"></File>
</Filelist>
</otobo_package>
  • Name/Version/Framework: Unique package identifier and compatible OTOBO version.
  • Filelist: All files that are copied during installation.

Create your package in its own directory, e.g., MyExtension/:

MyExtension/
├─ MyExtension.sopm
├─ Kernel/
│ ├─ Config/Files/XML/MyExtension.xml
│ ├─ System/MyExtension.pm
│ ├─ Modules/AgentMyPage.pm
│ ├─ Output/HTML/Standard/AgentMyPage.tt
│ └─ Language/en_MyExtension.pm
└─ sql/
└─ create_tables.sql # optional, for DB migrations
  • Kernel/Config/Files/XML/: Registers modules, menus, or Dynamic Fields.
  • Kernel/System/: Business logic class.
  • Kernel/Modules/: Frontend controller.
  • Templates & Language: TT files + translation .pm files.

Use the CLI tool to build an OPM from your SOPM:

Terminal window
cd /path/to/MyExtension
bin/otobo.Console.pl Dev::Package::Build \
--sopm-file MyExtension.sopm \
--output /tmp/MyExtension.opm

Admin UI: Upload the package under Admin → Settings → Package Manager. Console:

Terminal window
bin/otobo.Console.pl Admin::Package::Install /tmp/MyExtension.opm

To uninstall or upgrade:

Terminal window
bin/otobo.Console.pl Admin::Package::Uninstall /tmp/MyExtension.opm
bin/otobo.Console.pl Admin::Package::Upgrade /tmp/MyExtension.opm

In Kernel/Config/Files/XML/MyExtension.xml, you register a new Dynamic Field driver:

<Setting Name="DynamicFields::Driver###MyCustomField" Required="0" Valid="1">
<Navigation>DynamicFields::Driver</Navigation>
<Value>
<Array>
<Item><Hash>
<Item Key="DriverName">MyCustomField</Item>
<Item Key="Module">Kernel::System::DynamicField::Driver::MyCustomField</Item>
</Hash></Item>
</Array>
</Value>
</Setting>

Implement the driver in Kernel/System/DynamicField/Driver/MyCustomField.pm.

Register your event handler:

<Setting Name="Event::EventHandler###MyHandler" Required="0" Valid="1">
<Navigation>Event::EventHandler</Navigation>
<Value>
<Array>
<Item><Hash>
<Item Key="Module">Kernel::System::Event::Handler::MyHandler</Item>
</Hash></Item>
</Array>
</Value>
</Setting>

Implement the handler in Kernel/System/Event/Handler/MyHandler.pm (the Run() method).

<Setting Name="Output::Filter###MyFilter" Required="0" Valid="1">
<Navigation>Output::Filter</Navigation>
<Value>
<Array>
<Item><Hash>
<Item Key="Module">Kernel::System::Output::Filter::MyFilter</Item>
</Hash></Item>
</Array>
</Value>
</Setting>

Filter in Kernel/System/Output/Filter/MyFilter.pm.


  • Repository Index: Generate Packages.xml for your own repo:

    Terminal window
    bin/otobo.Console.pl Dev::Package::RepositoryIndex \
    --directory /var/www/otobo-packages
  • Add your repo URL under SysConfig Package::RepositoryList.

  • OTOpar: Upload your OPM to https://otopar.perl-services.de so that others can install it directly.


  1. Create SOPM with the name MyCalendar.
  2. DB script sql/create_calendar.sql for table calendar_events.
  3. Config XML defines a new ticket field “Appointment”.
  4. Core module Kernel/System/CalendarEvent.pm with CRUD methods.
  5. Frontend module Kernel/Modules/AgentCalendar.pm, template AgentCalendar.tt.
  6. Build package and upload to OTOpar.

  • Update the version number in the sopm (SemVer).
  • Version DB migrations in sql/ cleanly.
  • Create unit tests for system and module classes.
  • Include documentation in the README plus POD in Perl modules.
  • Translations in Language/de_*.pm and en_*.pm.

With this, you have a solid foundation to develop, distribute, and maintain your own OTOBO plugins in customer projects. Have fun!

Custom OTOBO module & plugin development

Need custom features or legacy package upgrades? Softoft builds maintainable, upgrade-safe Perl and frontend extensions.

Frequently asked questions

What is the purpose and structure of an OTOBO SOPM file in plugin development?

The SOPM (Softoft Package Manager) file is crucial for OTOBO plugin development as it defines all the necessary metadata and file information for an OPM (OTOBO Package Manager) package. It acts as a blueprint, telling the OTOBO system how to identify, install, and manage your plugin.

Its structure is an XML file (*.sopm) containing elements like:

  • Name: A unique identifier for the package.
  • Version: The current version of your plugin, ideally following SemVer.
  • Framework: Specifies the minimum compatible OTOBO version (e.g., 10.0.x).
  • Vendor: The name of the developer or organization.
  • URL: A link to the plugin's repository or homepage.
  • License: The licensing terms (e.g., GPL-3.0).
  • Description: A brief explanation of the plugin's functionality, often with language-specific versions.
  • ChangeLog: Records version history and changes.
  • Filelist: This critical section lists every file included in the package, along with its Location (path relative to the OTOBO root) and Permission (e.g., 644). These files are copied to their specified locations during installation.

Quellen:

How should I structure the files and directories for an OTOBO plugin?

For an OTOBO plugin, you should organize your files within a dedicated root directory, for example, MyExtension/. This root directory will contain your SOPM file and the Kernel/ subdirectory, which mirrors OTOBO's core structure.

  • SOPM File: The MyExtension.sopm file is placed directly in the plugin's root directory.
  • Kernel/ Subdirectory: This is where most of your plugin's OTOBO-specific files will go. Common subdirectories include:
    • Kernel/Config/Files/XML/: Used for registering modules, menus, Dynamic Fields, or other system configurations via XML files.
    • Kernel/System/: Contains business logic classes (e.g., MyExtension.pm).
    • Kernel/Modules/: Houses frontend controller modules (e.g., AgentMyPage.pm).
    • Kernel/Output/HTML/Standard/: Stores template files (.tt) for the frontend.
    • Kernel/Language/: Contains translation files (e.g., en_MyExtension.pm, de_MyExtension.pm).
  • Optional sql/ Directory: If your plugin requires database migrations or schema changes, you can include SQL scripts in a sql/ directory (e.g., sql/create_tables.sql). These scripts would typically be executed as part of the package installation or upgrade process, often managed by the plugin's logic or specific OTOBO console commands.

Quellen:

What are the steps to build an OTOBO plugin into an OPM package?

Building an OPM (OTOBO Package Manager) package involves using OTOBO's command-line interface (CLI) tool, bin/otobo.Console.pl, specifically the Dev::Package::Build command. This process takes your SOPM file and the associated plugin files and bundles them into a single .opm file, which is the distributable format for OTOBO plugins.

Prerequisites: Ensure you have created your plugin's directory structure and populated it with your *.sopm file and all necessary Kernel/ files as defined in your SOPM's Filelist.

Navigation: Navigate to the root directory of your plugin in the terminal, for example, cd /path/to/MyExtension.

Execution: Execute the build command:

bin/otobo.Console.pl Dev::Package::Build \
  --sopm-file MyExtension.sopm \
  --output /tmp/MyExtension.opm
  • The --sopm-file argument specifies the path to your SOPM file.
  • The --output argument defines the desired path and filename for the resulting .opm package. In this example, it will create MyExtension.opm in the /tmp/ directory.

This command processes the SOPM file, gathers all listed files from your plugin's directory, and compresses them into the .opm archive, making it ready for installation.

Quellen:

How can I install, uninstall, or upgrade an OTOBO OPM package?

OTOBO provides both a graphical user interface (GUI) and command-line interface (CLI) options for managing OPM packages.

Installation via Admin UI:

  • Log in to OTOBO as an administrator.
  • Navigate to Admin → Settings → Package Manager.
  • Use the upload functionality on this page to select and install your .opm file. The Package Manager will guide you through the installation process, verifying the package and copying files as specified in its SOPM.

Installation via Console:

  • For command-line installation, use the Admin::Package::Install command:
    bin/otobo.Console.pl Admin::Package::Install /path/to/MyExtension.opm
    
    Replace /path/to/MyExtension.opm with the actual path to your package file.

Uninstalling via Console:

  • To remove a package, use Admin::Package::Uninstall:
    bin/otobo.Console.pl Admin::Package::Uninstall MyExtension
    
    Note that for uninstall, you typically provide the package name (as defined in the SOPM), not the .opm file path.

Upgrading via Console:

  • To upgrade an existing package with a newer version, use Admin::Package::Upgrade:
    bin/otobo.Console.pl Admin::Package::Upgrade /path/to/MyExtension_v2.0.opm
    
    Similar to installation, you provide the path to the new .opm file. The package manager handles replacing old files and running any upgrade scripts.

Quellen:

What are some common extension points for OTOBO plugins, and how are they implemented?

OTOBO offers several extension points that allow plugins to integrate deeply into its functionality without modifying core code. These are typically configured via XML files placed in Kernel/Config/Files/XML/ within your package.

  • Dynamic Fields:
    • Allow you to introduce custom data fields for tickets, customers, or other objects.
    • You register a new Dynamic Field driver in your XML configuration, specifying its DriverName and the Module that implements its logic (e.g., Kernel::System::DynamicField::Driver::MyCustomField).
    • The actual driver logic is then implemented in a Perl module (e.g., Kernel/System/DynamicField/Driver/MyCustomField.pm), which handles how the field behaves, validates input, and stores data.
  • Event Handlers:
    • Enable your plugin to react to specific events within OTOBO, such as ticket creation, article updates, or user logins.
    • An event handler is registered in XML by defining its Module (e.g., Kernel::System::Event::Handler::MyHandler).
    • The corresponding Perl module (e.g., Kernel/System/Event/Handler/MyHandler.pm) must implement a Run() method, which contains the logic to be executed when the registered event occurs.
  • Output Filters:
    • Provide a mechanism to modify the output of OTOBO, often used to inject custom content or alter existing HTML before it's sent to the browser.
    • Similar to other extension points, an output filter is registered in XML with its Module (e.g., Kernel::System::Output::Filter::MyFilter).
    • The Perl module (e.g., Kernel/System/Output/Filter/MyFilter.pm) will contain the filtering logic, typically operating on the HTML content.

These extension points allow for powerful customization while maintaining upgrade compatibility, as your changes are encapsulated within your OPM package.

Quellen:

How can I distribute my OTOBO OPM package to others?

Distributing your OTOBO OPM package allows other OTOBO users and organizations to easily install and benefit from your plugin. There are a few primary methods for making your package available.

  • Direct Sharing: The simplest way is to directly share the generated .opm file. Users can then install it manually via the OTOBO Admin UI's Package Manager or using the Admin::Package::Install console command. This is suitable for private distribution or small-scale sharing.
  • Custom Package Repository: For broader distribution or managing multiple packages, you can set up your own package repository.
    • You generate a Packages.xml index file for your repository using the Dev::Package::RepositoryIndex console command, pointing it to a directory containing your .opm files (e.g., bin/otobo.Console.pl Dev::Package::RepositoryIndex --directory /var/www/otobo-packages).
    • Users then add your repository's URL to their OTOBO system configuration under SysConfig -> Package::RepositoryList. Once added, your packages will appear in their Package Manager, allowing for easy installation and updates directly from your repository.
  • OTOpar (OpenITSMHub): OTOpar (formerly OpenITSMHub) is a central platform for sharing OTOBO and Znuny packages with the community.
    • You can upload your .opm file to https://otopar.perl-services.de.
    • Once submitted and approved, your package becomes publicly available, allowing anyone to discover and install it directly through their OTOBO Package Manager if OTOpar is configured as a repository (which it often is by default). This is the recommended method for public community contributions.

Quellen:

What are the best practices for developing and maintaining OTOBO plugins?

Adhering to best practices ensures your OTOBO plugins are robust, maintainable, and compatible with future OTOBO versions.

  • Version Numbering: Always update the Version number in your *.sopm file for every release. It's highly recommended to follow Semantic Versioning (SemVer) (e.g., 1.0.0, 1.0.1, 2.0.0) to clearly communicate changes and compatibility.
  • Database Migrations: If your plugin interacts with the database, manage schema changes and data migrations cleanly. Place SQL scripts in the sql/ directory and ensure they are versioned and idempotent, allowing for smooth upgrades without data loss.
  • Unit Tests: Develop comprehensive unit tests for your system and module classes. This helps ensure the reliability of your code, catches regressions early, and simplifies future development and refactoring.
  • Documentation: Provide clear and concise documentation. Include a README file in your plugin's repository explaining its purpose, installation, configuration, and usage. Additionally, use POD (Plain Old Documentation) within your Perl modules to document functions, classes, and their parameters.
  • Translations: Make your plugin accessible to a wider audience by including translations. Create language files (e.g., Language/de_MyExtension.pm and Language/en_MyExtension.pm) for all strings displayed in the user interface.
  • Code Style: Follow OTOBO's established coding standards and Perl best practices for consistency and readability.
  • Modularity: Design your plugin with modularity in mind, separating concerns into distinct classes and modules to improve maintainability and testability.

Quellen: