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.
1. Structure of a .sopm
Section titled “1. Structure of a .sopm”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.
2. Files & Directory Structure
Section titled “2. Files & Directory Structure”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.
3. Building & Installing the Package
Section titled “3. Building & Installing the Package”3.1 Creating the OPM
Section titled “3.1 Creating the OPM”Use the CLI tool to build an OPM from your SOPM:
cd /path/to/MyExtensionbin/otobo.Console.pl Dev::Package::Build \ --sopm-file MyExtension.sopm \ --output /tmp/MyExtension.opm3.2 Installation
Section titled “3.2 Installation”Admin UI: Upload the package under Admin → Settings → Package Manager. Console:
bin/otobo.Console.pl Admin::Package::Install /tmp/MyExtension.opmTo uninstall or upgrade:
bin/otobo.Console.pl Admin::Package::Uninstall /tmp/MyExtension.opmbin/otobo.Console.pl Admin::Package::Upgrade /tmp/MyExtension.opm4. Extension Points
Section titled “4. Extension Points”4.1 Dynamic Fields
Section titled “4.1 Dynamic Fields”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.
4.2 Event Handler
Section titled “4.2 Event Handler”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).
4.3 Output Filter
Section titled “4.3 Output Filter”<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.
5. Deployment & OTOpar
Section titled “5. Deployment & OTOpar”-
Repository Index: Generate
Packages.xmlfor 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.
6. Example: MyCalendar Package
Section titled “6. Example: MyCalendar Package”- Create SOPM with the name
MyCalendar. - DB script
sql/create_calendar.sqlfor tablecalendar_events. - Config XML defines a new ticket field “Appointment”.
- Core module
Kernel/System/CalendarEvent.pmwith CRUD methods. - Frontend module
Kernel/Modules/AgentCalendar.pm, templateAgentCalendar.tt. - Build package and upload to OTOpar.
7. Tips & Best Practices
Section titled “7. Tips & Best Practices”- 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_*.pmanden_*.pm.
With this, you have a solid foundation to develop, distribute, and maintain your own OTOBO plugins in customer projects. Have fun!
Frequently asked questions
What is a SOPM file in OTOBO plugin development?
The SOPM file (*.sopm) holds package metadata such as name, version, framework compatibility, vendor, license, changelog, and the file list installed with the package.
How do I build an OPM package for OTOBO?
Use bin/otobo.Console.pl Dev::Package::Build with --sopm-file and --output to create an .opm from your SOPM and Kernel files.
Where are OTOBO plugins installed?
OPM packages are installed through the OTOBO package manager (Admin → Package Manager) or related console commands, which copy the listed files into the system.