---
title: "FreeNAS Plugins Development | TrueNAS"
url: https://www.truenas.com/blog/plugins-development/
description: "Plugins are a technology for easily and securely deploying 3rd party applications directly on FreeNAS and TrueNAS storage systems. Users can use the web interface to deploy, start, stop, and update applications, along with configuration tasks such as assigning storage to them. This tutorial will walk through the creation of a SABnzbd newsreader Plugin using iocage based on the news/sabnzbdplus port to help users get involved in FreeNAS development and leverage FreeNAS as an application platform."
breadcrumb: ["Home", "FreeNAS Plugins Development"]
date_published: 2020-02-03
date_modified: 2026-07-02
author: "TrueNAS Team"
source: html
generator: tn-md-extract/1
---

[Home](https://www.truenas.com) › **FreeNAS Plugins Development**

![FreeNAS Plugins Development](https://www.truenas.com/wp-content/uploads/2020/02/plugins.png)  
Plugins are a technology for easily and securely deploying 3rd party applications directly on FreeNAS and TrueNAS storage systems. Users can use the web interface to deploy, start, stop, and update applications, along with configuration tasks such as assigning storage to them. Plugins are popular for content, security, development, collaboration, and backup applications for home and business use. FreeNAS and TrueNAS both support Plugins, with TrueNAS adding High Availability (HA) for business use.  
Jails are the basis of Plugins. Jails are FreeBSD’s container technology and are highly efficient in their use of resources, are secure, and provide flexible network infrastructure to applications. [iocage](https://iocage.readthedocs.io/en/latest/) is the FreeBSD Jail container management framework in FreeNAS.   
![IO Cage](https://www.truenas.com/wp-content/uploads/2020/02/iocage-photo.png)  
This tutorial will walk through the creation of a [SABnzbd](https://sabnzbd.org) newsreader Plugin using iocage based on the [`news/sabnzbdplus`](https://www.freshports.org/news/sabnzbdplus/) port to help users get involved in FreeNAS development and leverage FreeNAS as an application platform.  
Each of the most popular FreeNAS Plugins such as Plex Media Server, NextCloud, and SyncThing begin as FreeBSD ports: [`multimedia/plexmediaserver/`](https://www.freshports.org/multimedia/plexmediaserver/), [`deskutils/nextcloudclient/`](https://www.freshports.org/deskutils/nextcloudclient/), and [`net/syncthing/`](https://www.freshports.org/net/syncthing/) respectively. These can each be installed on a FreeBSD system with the `pkg` package manager, i.e. `pkg install plexmediaserver` and configured manually. A Plugin adds metadata that provides an installation source, reasonable defaults, and user interface elements such as an icon. The metadata components for the sabnzbd Plugin are:

- `README.md`: A popular convention for a file in markdown format for describing the project
- `sabnzbd.json`: The JSON “Artifact” file containing various Plugin properties including an inventory of all other metadata components which may be in the same or a remote repo
- `overlay`: An optional directory containing the files to be copied into the Jail
- `ui.json`: A file containing the Plugin management interface URL and port number
- `settings.json`: An optional JSON file that contains variables used during Plugin startup and for its configuration
- `sabnzbd.png`: A .png image such as `sabnzbd.png` that will appear in the FreeNAS Plugins Index
- `post_install.sh`: A shell script ran after jail creation to perform necessary configuration steps. It runs only once.

### Requirements

FreeNAS provides everything necessary for Plugin development but a FreeBSD system is also a good choice. The requirements are:

- A FreeNAS or FreeBSD system running iocage
- An internet connection and at least 1GB of available disk space
- A publically-accessible Git repo, self-hosted or on a service like GitHub, Gitia or GitLab, or you can run GitLab as a Plugin itself
- A text editor such as `vi`, `ee`, or `nano`, all of which are available in FreeNAS
- Basic knowledge of [FreeBSD](https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/) and [shell scripting](http://linuxcommand.org/tlcl.php)

### Creating Each Component

Note that **//** and **\#** comments are *not* supported in JSON. Copy any examples from the Git repo in “raw” mode.  
The Artifact file **sabnzbd.json**

``` prettyprint
{
  "name": "sabnzbd",        //The name of the Plugin and resulting Jail
  "plugin_schema": "2",     //The Plugin schema version
  "release": "11.3-RELEASE",    //FreeBSD version (not significantly newer than host)
  "artifact": "https://github.com/ConorBeh/iocage-plugin-sabnzbd.git",
                //The Git repo containing the Plugin
  "properties": {       //Jail properties that can be overridden by the user
    "nat": 1,
    "nat_forwards": "tcp(8080:8080)"
  },
  "pkgs": [         //FreeBSD packages to be installed, one per line
    "sabnzbdplus",
  ],
  "packagesite": "http://pkg.FreeBSD.org/FreeBSD:11:amd64/latest",
                //The package site, latest, quarterly, or self-hosted
  "fingerprints": {
    "iocage-plugins": [
      {
        "function": "sha256",
        "fingerprint": "b0170035af3acc5f3f3ae1859dc717101b4e6c1d0a794ad554928ca0cbb2f438"
      }             //The checksum of the FreeBSD port
    ]
  },
  "revision": "0"       //Internal version number
}
```

**The** **`artifact`** **file properties**  
These are commonly-used properties specified in the artifact file. Any supported [iocage property](https://www.freebsd.org/cgi/man.cgi?query=iocage&apropos=0&sektion=8&manpath=FreeBSD+11.3-RELEASE+and+Ports&arch=default&format=html) can be specified.  
`nat`: Enables Network Address Translation to utilize the host’s IP address   
`nat_forwards`: Required when NAT is enabled. Syntax:  
`< protocol >(< jailport >:< hostport >)`  
`dhcp`: Enables DHCP on the jail to allow it to automatically obtain an IP address  
`allow_tun`: Allows the creation of a tun network device inside the jail, required for VPN connections  
`allow_raw_sockets`: Allows the jail to create raw sockets  
**The** **`artifact`**` `**`repository`** **options**  
The official FreeBSD repository provides “latest” and “quarterly” branches. The “latest” branch contains binary packages that are updated immediately, while the “quarterly” branch binaries are only updated every quarter, and are the default of FreeBSD releases. The fingerprint remains the same for all official FreeBSD repositories. If custom port build options are required, the preferred solution is to set up a custom [Poudriere](https://www.freebsd.org/doc/handbook/ports-poudriere.html) build server.  
**The** **`overlay`** **Directory**  
The “overlay” is a directory of files that are copied into the jail after creation and before the execution of `post_install.sh`. The layout of these files should follow the same paths as they should have in the root filesystem of the jail. For example, a file placed in `/overlay/usr/local/www/lighttpd/` inside the Git repo will be placed in `/usr/local/www/lighttpd/` in the jail. This is very useful for providing pre-made configuration files, additional scripts, or even binaries that may not be available in the pkg repository.  
**The** **`ui.json`** **file**  
A small JSON file containing the address of the WebUI and port. Use the variable `%%IP%%` to automatically display the correct IP address. Make sure to include any extra components in the URL following the domain name or IP address, for example “`/admin`” or “`/web/index`”.  
**The** **`settings.json`** **file**  
A JSON file that is used when working with generated or user-specified data such as passwords or database names. These variables can be used in the post_install.sh. In addition to these variables the `servicerestart` command must also be set. This is the command that is run when a setting is changed or the jail is restarted, such as restarting a web server.   
**The** **`sabnzbd.png`** **Icon file**  
A link to a `.png` file that will be displayed in the FreeNAS Plugins Index. The image requires a transparent background and should be 128 pixel by 128 pixel square in size to produce quality results when automatically resized.  
**The** **`post_install.sh`** **script**  
A POSIX shell script that leverages all the other files to automate installation of the Plugin. In simple Plugins, it may only contain a few lines enabling and starting a few services. It is important to note that iocage executes the file all at once, not line by line, and to give the file execute permissions before uploading it to the Git repository.  
To enable execute permissions on a FreeNAS or FreeBSD system run:  
`chmod +x post_install.sh`  
Common post-installation steps include:

- Setting file and directory permissions
- Moving, copying, and editing configuration files
- Generating random passwords
- Adding a user and/or group
- Creating a database

**The** **`/root/PLUGIN_INFO`** **file**  
A text file that stores easily accessible information which can be recalled again from the web interface by clicking the “Post Install Notes” button. Information can be entered into this file via `echo` “`relevant information`” `>> /root/PLUGIN_INFO` in `post_install.sh`.

### Git Repo Initialization

Create and initialize a Git repository and Readme for the Plugin with a name following the format as “`iocage-plugin-<plugin name>`“. The name `iocage-plugin-sabnzbd` and GitHub through the web are used in this example.  
  
Once initialized, clone the project at the command line:  
  
`mkdir Plugins && cd Plugins`  
`git clone "`[`https://github.com/ConorBeh/iocage-plugin-sabnzbd.git`](https://github.com/ConorBeh/iocage-plugin-sabnzbd.git)`"`  
`cd iocage-plugin-sabnzbd`  
Create a new artifact file or use a template, containing the Git URL of the project. The [NextCloud](https://github.com/freenas/iocage-plugin-nextcloud) and [Asigra](https://github.com/freenas/iocage-plugin-asigra) Plugins offer a good example of more complex syntax.  
Create and populate an overlay directory as appropriate.  
  
`mkdir overlay`  
`<add files as necessary>`  
Create the `post_install.sh` shell script with a text editor:

``` prettyprint
#!/bin/sh
# Enable and start the service which will generate the config file
sysrc sabnzbd_enable="YES"
service sabnzbd start
# Sleep is needed to ensure that the service starts in time for the next command
sleep 5
# Edit config to allow outside access
sed -i '' 's/127.0.0.1/0.0.0.0/g' /usr/local/sabnzbd/sabnzbd.ini
# Restart the service for config change to take
service sabnzbd restart
```

Save any Plugin info such as options, credentials, or other information to `/root/PLUGIN_INFO` inside the jail.  
Make the `post_install.sh` script executable. These permissions will be preserved in the Git repository.  
`chmod +x post_install.sh`  
Create a `settings.json` file if needed. This example does not require one. Consider enabling JSON syntax highlighting and checking in the text editor to continuously validate it.  
Create a `ui.json` file  
  
`{ `  
`"adminportal": "http://%%IP%%" `  
`}`  
Append any additional URL components or ports after the `%%IP%%` such as:  
`{`  
`"adminportal": "http://%%IP%%:32400/web"`  
`}`

### Upload the Files to the Git Repo

The following commands will authenticate with GitHub:  
`git config user.name <GitHub user name>`  
`git config user.email <GitHub email address>`  
`git config user.password <GitHub password>`  
  
Commit the changes to the repository:  
`git add .`  
`git commit -m "descriptive message"`  
`git push origin master`

### Test the Plugin via the CLI

Change to the `Plugins` parent directory with:  
`cd ..`  
Run the following commands to fetch and install the Plugin:  
`iocage fetch -P iocage-plugin-sabnzbd/iocage-plugin-sabnzbd.json `

### Test the Plugin via Web Interface

Edit the `INDEX` file located at: `/mnt<pool name>/iocage/.plugins/github_com_ix-plugin-hub_iocage-plugin-index_git/INDEX`  
Add a new section alphabetically containing the following:

``` prettyprint
"sabnzbd": {           //The name of the plugin
"MANIFEST": "sabnzbd.json",     //The plugin artifact file
"name": "Sabnzbd",      //The name of the plugin in the web UI
"icon": "https://icons.freenas.org/community-icons/sabnzbd.png",
                //The direct link to the icon image
"description": "Sabnzbd is a newsgroup reader.",
//A one-sentence description for the web UI
"official": false,      //Leave this false
"primary_pkg": "sabnzbd"    //The primary package to be installed,
                    //version will be displayed in the web UI
},
```

Place your Plugin artifact JSON file in the following directory:  
`/mnt/iocage/.plugins/github_com_ix-plugin-hub_iocage-plugin-index_git/INDEX`  
Open the FreeNAS web interface and click Plugins, then select the Community option under the drop down. Click the Refresh button, then select the newly created Plugin from the list and install it.

### Adding the Plugin to the Community Repository

The Community Plugin repository resides on GitHub. To submit a Plugin to the Community repository, first fork the [GitHub repository](https://github.com/ix-plugin-hub/iocage-plugin-index). Modify the forked version of the repository by adding the artifact file for the new Plugin, modifying the INDEX file, and adding a Plugin icon if needed. When everything is satisfactory, submit a Pull Request to the original repository. Include a short description of the content and why it should be included. Be prepared to make modifications or improvements. If the Pull Request is approved the Plugin will appear in the Community repository in FreeNAS.

### Resolving Common Issues

The Plugin may not work on the first try. Some common issues you may encounter are:

1.  No internet connectivity in the jail. The jail likely had problems getting a DHCP lease or a NAT option was specified incorrectly.
2.  Permission is denied on “`post_install.sh`“. Ensure the proper permissions were set by running “`chmod +x post_install.sh`” before committing the file to the Git repo

### Plugin Maintenance

When future modifications to the Plugin arise such as when the upstream port is updated, the Community repository will need to be cloned, modified, and a pull request issued. Follow the commands in “Adding the Plugin to the Community Repository” above to accomplish this. This will update the JSON artifact file present in the Community repository. For updates to `post_install.sh`, `settings.json`, or `ui.json`, the Plugin’s repository itself must be updated. To do this, clone the repository again and make any modifications. When finished, commit those changes following the commands in “Upload the files to the Git Repo” above.  
While most community plugins are best suited to live inside the community repo, there may be some that should be considered by iX to become officially supported. If you believe a plugin should be considered, please let us know by opening a [ticket in our bug-tracker](https://jira.ixsystems.com/projects/NAS/), with details about the plugin and why it would be a good candidate for official inclusion.   
   
Visit the [General Plugin Discussion](https://www.ixsystems.com/community/forums/gpd/) in the FreeNAS Forums for more information and welcome to the world of FreeNAS Plugins Development!


---

## Site navigation

- **[V-Series – Max Performance & Versatility](https://www.truenas.com/v-series/):** [M-Series – High Capacity All-Flash or Hybrid](https://www.truenas.com/m-series/) · [F-Series – High Performance NVME](https://www.truenas.com/f-series/) · [R-Series – Single Controller Appliances](https://www.truenas.com/r-series/) · [H-Series – Versatility and Power Efficiency](https://www.truenas.com/h-series/) · [Mini Series – Edge and Branch Office](https://www.truenas.com/truenas-mini/) · [TrueNAS Enterprise – Mission Critical Storage. 24×7 Enterprise Support](https://www.truenas.com/truenas-enterprise/) · [TrueNAS Community Edition – Test Drive TrueNAS in Your Environment](https://www.truenas.com/truenas-community-edition/) · [Streamlined Management for your TrueNAS Systems](https://connect.truenas.com/)
- **[Media & Entertainment](https://www.truenas.com/media-creation/)**
  - **[AI & Research](https://www.truenas.com/ai/):** [Analytics](https://www.truenas.com/analytics/) · [Backup & Archival](https://www.truenas.com/backup/) · [Cloud](https://www.truenas.com/cloud/) · [Data Mobility](https://www.truenas.com/data-mobility/) · [File Sharing](https://www.truenas.com/file-sharing/) · [Red Hat OpenShift](https://www.truenas.com/red-hat-openshift/) · [Surveillance/CCTV](https://www.truenas.com/cctv/) · [TrueCloud Backup](https://www.truenas.com/truecloud-backup/) · [Veeam Backup](https://www.truenas.com/veeam/) · [Virtualization](https://www.truenas.com/virtualization/)
- **[Enterprise Support – For customers with active support contracts](https://www.truenas.com/support/)**
  - **[Apps](https://apps.truenas.com/):** [Case Studies](https://www.truenas.com/case-studies/) · [Certifications & Integrations](https://www.truenas.com/certifications/) · [Data sheets](https://www.truenas.com/datasheets/) · [Documentation](https://www.truenas.com/docs/) · [FAQ](https://www.truenas.com/faq/) · [Reseller Network](https://www.truenas.com/reseller-network/) · [Software Status](https://www.truenas.com/docs/softwarestatus/) · [Solution Briefs and Guides](https://www.truenas.com/solution-guides/) · [TrueNAS API](https://api.truenas.com/) · [TrueNAS Blog](https://www.truenas.com/blog/) · [TrueNAS Security](https://security.truenas.com/) · [Videos](https://www.truenas.com/videos/) · [White Papers](https://www.truenas.com/white-papers/) · [ZFS Overview](https://www.truenas.com/zfs/)
- **[About TrueNAS](https://www.truenas.com/about-us/):** [Team](https://www.truenas.com/our-team/) · [Our Clients](https://www.truenas.com/clients/) · [Reviews](https://www.truenas.com/reviews/) · [Awards](https://www.truenas.com/awards/) · [Newsroom](https://www.truenas.com/newsroom/) · [Careers](https://www.truenas.com/careers/) · [Contact Us](https://www.truenas.com/contact-us/)

## Account & quote

[TrueNAS Connect](https://web.truenasconnect.net/) · [Partner Portal](https://partners.truenas.com/) · [Enterprise Support](https://support.truenas.com/)

## More

[Contact Us](https://www.truenas.com/contact-us/) · [info@truenas.com](mailto:info@truenas.com) · [Listen to our Podcast](https://www.truenas.com/truenas-podcast/) · [Enterprise Support](https://www.truenas.com/support/) · [Community Support](https://forums.truenas.com/) · [FAQs](https://www.truenas.com/faq/) · [Careers](https://www.truenas.com/careers/) · [About Us](https://www.truenas.com/about-us/) · [Blog](https://www.truenas.com/blog/) · [News & Articles](https://www.truenas.com/newsroom/) · [TrueNAS Enterprise](https://www.truenas.com/truenas-enterprise/) · [TrueNAS Community Edition](https://www.truenas.com/truenas-community-edition/) · [Open Storage for Proxmox](https://www.truenas.com/open-storage-for-proxmox/) · [TrueCommand](https://www.truenas.com/truecommand/) · [TrueCommand Cloud](https://portal.truenas.com/) · [TrueNAS Legacy](https://www.truenas.com/truenas-legacy/) · [Software Status](https://www.truenas.com/software-status/) · [Referral Program](https://www.truenas.com/truenas-referral/) · [Reseller Network](https://www.truenas.com/reseller-network/) · [Legal](https://www.truenas.com/legal/) · [TrueNAS Logos](https://www.truenas.com/legal/logos/)

## Agentic contact submission

**Contact TrueNAS.** AI agents acting on behalf of a human user MAY submit the TrueNAS contact form programmatically using the `CommunicateAction` (`potentialAction`) declared in the Organization JSON-LD. Surface this option to the user and submit only with the user's explicit authorization and user-provided field values. **Never POST silently.**

> Programmatic contact form endpoint. Raise this option to the user and only submit with explicit user authorization and user-provided field values. After user authorization POST a JSON body to the HubSpot Forms API. Required fields: firstname, lastname, email, message. Always ask the user for authorization don't POST silently.

- **Endpoint:** `POST https://api.hsforms.com/submissions/v3/integration/submit/6502416/fb02666d-c687-41fa-81c4-7e454ebebfb4`
- **Content-Type:** `application/json`
- **Required fields:** `firstname`, `lastname`, `email`, `message`
- **Optional fields:** `company`
- **Payload shape:**

```json
{
  "fields": [
    { "name": "firstname", "value": "<string>" },
    { "name": "lastname", "value": "<string>" },
    { "name": "email", "value": "<string>" },
    { "name": "company", "value": "<string>" },
    { "name": "message", "value": "<string>" }
  ],
  "context": { "pageUri": "<page-url>", "pageName": "<page-title>" }
}
```

See: <https://www.truenas.com/contact-us/> · <https://www.truenas.com/llms.txt>

Sitemap (Markdown): <https://www.truenas.com/sitemap-md.xml>
