---
source: https://carbone.io/documentation/developer/on-premise-installation/plugins.html
title: "On-Premise plugins"
description: "Add plugins in your On-Premise installation"
generated_at: "2026-07-13"
---

# On-Premise plugins

Add plugins in your On-Premise installation

## Introduction

Carbone On-Premise gives the possibility to override functions at specific moments to add custom features, such as adding analytics, storing data on a specific storage provider, or handling custom authentication, etc... It is possible through:

-   Functions to manage file storage, authentication, analytics, logs, or custom behaviors.
-   Functions that are fired before or after HTTP requests. It can be useful for logging, statistics, or custom behaviors.

**Language**

Plugins and middlewares can be only written using NodeJS.

**Lifecycle**

![image](/img/doc/CarboneOnPremiseLifecycle.png)

It is recommended to create a separate NodeJS repository:

```sh
# Create a separate folder
mkdir carbone-on-premise

# Initialize a node repository
npm init

# Move the carbone binary inside this folder
mv /path/to/carbone/binary ./carbone-on-premise
```

When Carbone On-premise is executed for the first time, default folders are created automatically ([explanation here](/documentation/developer/on-premise-installation/configuration.md)). Custom plugins MUST be inserted in the `plugin` folder.

## Write template hook

To override template storage, create the file `storage.js` in the `plugin` folder. It will be possible to upload your template into an Object Storage, S3 API or other storage systems. Export a function called `writeTemplate` with 5 arguments:

-   `req`: The req object represents the HTTP request and has properties for the request query string, parameters, body, HTTP headers, and so on.
-   `res`: The res object represents the HTTP response that a server sends when it gets an HTTP request
-   `templateId`: Unique template ID as a sha256 hash
-   `templatePathTemp`: Absolute path of the uploaded template
-   `callback`: callback function

Additional file information is available in the request header:

-   `req.headers['carbone-template-extension']`: file extension (eg: 'xml')
-   `req.headers['carbone-template-mimetype']`: file mimetype (eg: 'application/xml')
-   `req.headers['carbone-template-size']`: file size in bytes

```js
const fs = require('fs');
const path = require('path');
const os = require('os');

function writeTemplate (req, res, templateId, templatePathTemp, callback) {
  fs.rename(templatePathTemp, path.join(os.tmpdir(), 'PREFIX_' + templateId), (err) => {
    if (err) {
      return callback(err);
    }
    return callback(null);
  });
}

// Export the writeTemplate function
module.exports = {
  writeTemplate
}
```

## Read template hook

To override template reading, the file `storage.js` in the `plugin` folder has to be created. The function to export is `readTemplate`, which is described as follows:

```js
function readTemplate (req, templateId, callback) {
  // Read your template and return a local path for carbone
}

module.exports = {
  readTemplate
}
```

The function must return a local path because Carbone needs to read the file from a disk.

## Delete template hook

To override template deletion, add the function `deleteTemplate` in the `storage.js` file in the `plugin` folder and export it, for instance:

```js
// You can access req and res.
// For example, if you store your template on amazon S3, you could delete it
function deleteTemplate (req, res, templateId, callback) {
  // Delete the template and either return a local path to unlink it or just use res to return a response
  return callback(null, path.join(os.tmpdir(), 'PREFIX_' + templateId));
}

module.exports = {
  deleteTemplate
}
```

## Before generation hook

The before-render plugin can be used to add pre or post rendering behavior, such as adding a prefix to the rendered filename. To do this, add a function `beforeRender` and/or `afterRender` in the `storage.js` plugin and export it. In these functions, the `req` request variable is available and options can be altered.

```js
function beforeRender (req, res, carboneData, carboneOptions, next) {
  // add a prefix to rendered filename
  carboneOptions.renderPrefix = 'myPrefix';
  next(null);
}
```

## After generation hook

To override render writing, add the function `afterRender` in the `storage.js` file in the `plugin` folder and export it.

```js
function afterRender (req, res, err, reportPath, reportName, statistics, next) {
  // Write or rename your render
  // TemplateID available: req.params.templateId
  return next(null)
}

module.exports = {
  afterRender
}
```

For example, this function can be used to move the render to buckets, or it is also possible to change the response object:

```js
res.send({
  success: true,
  data: {
    newField: reportName
  }
});
```

The `statistics` argument returns an object with:

```json
{
  "renderId"  : "",
  "template"  : "filename",
  "user"      : "if authentication enabled, the user ID is returned, it is coming from the JWT token",
  "options"   : "Rendering options as an object",
  "jsonSize"  : "size of the JSON data-set as bytes"
}
```

## Read reports hook

The function `readRender` has to be exported in the `storage.js` located in the `plugin` folder.

```js
function readRender (req, res, renderName, next) {
  // Return the directly render or a local path
}
```

This function can be used to directly return the file using `res` , it is also possible to return the new render name, or return a path from the `afterRender` function.

```js
// Return the new render name
function readRender (req, res, renderName, next) {
  return next(null, 'newRenderName')
}

// OR

// Return the new path on disk
function (req, res, renderName, next) {
  return next(null, renderName, '/new/path/on/disk')
}
```

## Authentication hook

For the authentication checking, it is possible to define a new location to store public keys. The file `authentication.js` has to be created in the `plugin` folder. Export the function `getPublicKey` described as follows:

```js
const fs = require('fs');
const path = require('path');

/**
 * @param {Object} req : Request from the request
 * @param {Object} res : Response from the request
 * @param {Object} payload : https://github.com/Ideolys/kitten-jwt#api-usage to see object details
 * @param {Function} callback : Function to call at the end
 * @return (publicKeyContent)
 */
function getPublicKey (req, res, payload, callback) {
  // Read the public key on disk or somewhere else
  fs.readFile(path.join(__dirname, '..', 'config', 'key.pub'), 'utf8', (err, content) => {
    if (err) {
      return callback(new Error('Cannot read public key ' + err.toString()));
    }

    // Return the public key content in the callback
    return callback(content)
  });
}

// Export the getPublicKey function
module.exports = {
  getPublicKey
}
```

## HTTP Request hook

Middlewares can be added before or after a route. It can be useful to log or get stats about requests. Add a `middlewares.js` file in the `plugin` folder and export two arrays:

-   before
-   after

```js
function beforeMiddleware (req, res, next) {
  console.log('I am executed before all routes')
  return next()
}

function afterMiddleware (req, res, next) {
  console.log('I am executed after all routes')
}

module.exports = {
  before: [beforeMiddleware], // Middlewares in this array will be executed before routes
  after: [afterMiddleware] // Middlewares in this array will be executed after routes
}
```

## Custom Formatters

Load custom formatters as Javascript in your Carbone instance:

1.  **Create the Formatters File**: In your Carbone directory, navigate to the **plugin** folder. Create a new file named **formatters.js**. This file will contain all your custom formatter functions.
2.  **Define Your Formatters**: Write `module.exports = { }`, then insert your Javascript function between curly brackets: One function is equal to one formatter. Example:
    
    ```js
    /**
    * Adds custom text to a tag value.
    * @param {*} d - The tag value (data to format).
    * @param {string} text - The text to append.
    * @returns {string} The formatted value.
    * @example {d.value:addText(' euro')}
    */
    function addText(d, text) {
       return d + text;
    }
    module.exports = {
       addText
    }
    ```
    
3.  **Explore Examples**: For inspiration and practical use cases, refer to the [official Carbone formatters repository](https://github.com/carboneio/carbone/tree/master/formatters).
4.  **For Docker Container** If you’re running Carbone in a Docker container, follow [this tutorial](/documentation/developer/on-premise-installation/container-customization.md#installing-your-plugins) to load your plugin

## Related topics

- [Upgrade Guide](/documentation/developer/on-premise-installation/upgrade-guide.md)
- [Template management](/documentation/developer/on-premise-installation/template-management.md)
- [On-Premise Requirements](/documentation/developer/on-premise-installation/requirements.md)
- [Metrics (OpenMetrics)](/documentation/developer/on-premise-installation/metrics.md)
- [On-Premise](/documentation/developer/on-premise-installation/introduction.md)
- [Deploy on MacOS](/documentation/developer/on-premise-installation/install-on-macos.md)
