Generate and manage your reports from your own servers.
It provides the same API as the Carbone Cloud API, except that you are unlimited in usage, details:
The license price of Carbone On-premise depends on your company revenues and all subsidiaries. The license is valid only for one project or one product.
To get more information about the pricing, or get a trial license, reach us on the chat or by email: contact@carbone.io.
Carbone On-Premise works the same way as Carbone Cloud API,
To generate a document, you have to:
POST /template
to get a template ID
. The template is stored in your file system into the directory template
. It is possible to store templates into a custom storage system (s3, object storage)POST /render/:templateId
from the template ID
and a JSON data-set
, then the request returns a unique usable render ID
.GET /render/:renderId
thanks to the render ID
.POST /template
=> Return a unique templateId
.POST /render/:templateId
=> Return a unique renderId
GET /render/:renderId
GET /template/:templateId
DELETE /template/:templateId
GET /status
SDKs are available to integrate the Carbone Cloud API into your service/application in a few lines of code:
To test the Cloud API in a few minutes, load a pre-made API specification into:
Learn more on the Cloud API specification, all API endpoint are details to create your HTTP client on your own language.
Carbone On-premise can be installed in different ways:
chmod +x carbone-ee
in order to execute the binary.CARBONE_EE_LICENSE
with the license key as the value--license
followed by the license key as the value when you start the server (step 5) ./carbone webserver --port 4000 --workdir .
If an error appears during the start up, you must verify:
Carbone On-Premise contains automatic installation scripts to daemonize with systemd. It has been carefully configured to provide a high level of security. The Systemd installation is working only for Ubuntu or Debian.
# Generate installation scripts
./carbone install
# Execute installation scripts and follow instructions
sudo ./install.sh
The service is configured to run with "carbone" user (automatically created) in the "/var/www/carbone-ee" directory.
It is possible to overwrite values through environment variables CARBONE_USER
and CARBONE_WORKDIR
.
You must install LibreOffice to generate PDF documents, read instructions.
A pre-built image of Carbone is available on Docker Hub.
On your terminal, start a Carbone container with the following command line:
$ export CARBONE_EE_LICENSE=`MY_CARBONE_LICENSE`
$ docker run -t -i --rm --platform linux/amd64 -p 4000:4000 -e CARBONE_EE_LICENSE carbone/carbone-ee
To change server options, set environment variable options.
A pre-built image of Carbone is available on Docker Hub.
Example of docker-compose.yml
to run a Carbone container:
version: "3.9"
services:
carbone:
image: carbone-ee
platform: linux/amd64
ports:
- "4000:4000"
secrets:
- source: carbone-license
target: /app/config/prod.carbone-license
environment:
- CARBONE_EE_STUDIO=true
secrets:
carbone-license:
file: your_license.carbone-license
Contact the support if you want to build your own image of Carbone, we will provide you the Dockerfile
.
Build the image with the command:
$ docker build --platform "linux/amd64" -t carbone-ee:latest .
Then start the container:
$ docker container run --name carbone-ee -p 4000:4000 --platform linux/amd64 --volume=/var/tmp/key:/key --env CARBONE_EE_LICENSEDIR=/key --entrypoint ./carbone-ee-linux carbone-ee:latest webserver
## For background mode, add the -d option
The server is listening by default on http://localhost:4000
. To change configuration, add CLI options at the end of the command.
Stop the container:
$ docker stop carbone-ee
Remove the container:
$ docker container rm carbone-ee
Contact the support if you want to build your own image of Carbone, we will provide you the Dockerfile
.
Open a terminal where the Dockerfile
and the docker-compose.yml
are located.
Start the server with the command:
$ docker-compose up
## For background mode, add the -d option
The server is listening by default on http://localhost:4000
. To change configuration, add CLI options on the docker-compose.xml
.
Command to stop the container without removing it:
$ docker-compose stop
Command to stop the container and removes the container, networks, volumes, and images created by up:
$ docker-compose down
Discover more commands by reading the docker-compose CLI overview.
Carbone uses efficiently LibreOffice to convert documents. Among all tested solutions, it is the most reliable and stable one in production for now. Behind the scene, Carbone server does:
Installing Carbone On-premise with docker doesn't need LibreOffice to be installed, it is already included on the Docker image.
Install for:
# remove all old version of LibreOffice
sudo apt remove --purge libreoffice*
sudo apt autoremove --purge
# Download LibreOffice debian package. Select the right one (64-bit or 32-bit) for your OS.
# Get the latest from http://download.documentfoundation.org/libreoffice/stable
# or download the version currently "carbone-tested":
wget https://downloadarchive.documentfoundation.org/libreoffice/old/7.4.1.1/deb/x86_64/LibreOffice_7.4.1.1_Linux_x86-64_deb.tar.gz
# Install required dependencies on ubuntu server for LibreOffice 7.0+
sudo apt update
sudo apt install libxinerama1 libfontconfig1 libdbus-glib-1-2 libcairo2 libcups2 libglu1-mesa libsm6 libnss3
# Uncompress package
tar -zxvf LibreOffice_7.4.1.1_Linux_x86-64_deb.tar.gz
cd LibreOffice_7.4.1.1_Linux_x86-64_deb/DEBS
# Install LibreOffice
sudo dpkg -i *.deb
# If you want to use Microsoft fonts in reports, you must install the fonts
# Andale Mono, Arial Black, Arial, Comic Sans MS, Courier New, Georgia, Impact,
# Times New Roman, Trebuchet, Verdana,Webdings)
sudo apt install ttf-mscorefonts-installer
# If you want to use special characters, such as chinese ideograms, you must install a font that support them
# For example:
sudo apt install fonts-wqy-zenhei
Carbone default parameters can be overwritten through:
If an option is reported in different places, CLI options are picked in priority, then environment variables in second place, and finally the configuration file.
Options | Default Values | Description | CLI options | ENV |
---|---|---|---|---|
port | 4000 | Service PORT | --port / -p | CARBONE_EE_PORT |
workdir | Actual directory | Define the place to store elements, it creates 6 directories: - template : where carbone keeps templates (cache)- render : temp directory where report are generated,- asset : internal used only, - config : config, licenses and ES512 keys for authentication,- logs : [NOT IMPLEMENTED YET] formatted output logs, and- plugin : where to put custom plugin |
--workdir / -w | CARBONE_EE_WORKDIR |
licenseDir | "config/" | Absolute directory path to licenses | --licenseDir / -L | CARBONE_EE_LICENSEDIR |
license | License as a string, if the option is used, licenseDir option is skipped |
--license / -l | CARBONE_EE_LICENSE | |
factories | 1 | Multithread parameter, number of LibreOffice converter | --factories / -f | CARBONE_EE_FACTORIES |
attempts | 1 | If LibreOffice fails to convert one document, attempts options set the number of re-try |
--attemps / -a | CARBONE_EE_ATTEMPTS |
authentication | false | Authentification documentation at the following link | --authentication / -A | CARBONE_EE_AUTHENTICATION |
studio | false | Web interface to preview reports. Learn more. | --studio / -s | CARBONE_EE_STUDIO |
studioUser | admin:pass | If the authentication option is enabled, the browser requests an authentication to access the web page. Credentials have to be formated, such as: [username]:[password] . |
--studioUser / -S | CARBONE_EE_STUDIOUSER |
maxDataSize | 60MB | Maximum JSON data size accepted when rendering a report, the value must be bytes. Calcul example: 100 * 1024 * 1024 = 100MB | --maxDataSize / -mds | CARBONE_EE_MAXDATASIZE |
maxTemplateSize | 20MB | The file size limit when uploading a new template through the request POST /template , the value must be bytes. Calcul example: 30 * 1024 * 1024 = 30MB |
CARBONE_EE_MAXTEMPLATESIZE | |
templatePathRetention | 0 | Template path retention in days. 0 means infinite retention. | --templatePathRetention / -r | CARBONE_EE_TEMPLATEPATHRETENTION |
lang | en | Locale language used by Carbone | --lang / -l | CARBONE_EE_EN |
timezone | Europe/Paris | Timezone for managing dates | --timezone / -t | CARBONE_EE_TIMEZONE |
currencySource | Currency source for money conversion. If empty, it depends on the locale. | --currencySource / -cs | CARBONE_EE_CURRENCYSOURCE | |
currencyTarget | Currency target for money conversion. If empty, it depends on the locale. | --currencyTarget / -ct | CARBONE_EE_CURRENCYTARGET | |
currencyRates | { EUR : 1, USD : 1.14, ... } |
Currency rates, it is based on EUR which should be equals to "1". The option can only be set on the config/config.json file. |
||
translations | {} |
Translation object loaded at startup. It can be overwritten by rendering requests. The option can only be set on the config/config.json file. |
||
converterFactoryTimeout | 60000 | Maximum conversion/socket timeout for one render (unit: ms) | CARBONE_EE_CONVERTERFACTORYTIMEOUT | |
xlsmEnabled | false | Accept xlsm export | --xlsmEnabled / -xe | CARBONE_EE_XLSMENABLED |
To list available options, run the help command, such as:
./carbone webserver --help
Here is an example of passing options to the service:
./carbone webserver --port 4001 --factories 4 --workdir /var/www/carbone --attemps 2 --authentication --studio
To use a configuration file, config.json
must be created in the config
folder. Here is an example of a configuration:
{
"port": 4001,
"bind": "127.0.0.1",
"factories": 4,
"attempts": 2,
"authentication": true,
"studio" : true,
"studioUser" : "admin:pass" // login:password if authentication is active
}
Environment variables can be used to define options, the name has to be uppercased and has to start with the prefix "CARBONE_EE_
", such as:
export CARBONE_EE_PORT=3600
export CARBONE_EE_BIND=127.0.0.1
export CARBONE_EE_FACTORIES=4
export CARBONE_EE_WORKDIR=/var/www/carbone
export CARBONE_EE_ATTEMPTS=2
export CARBONE_EE_AUTHENTICATION=true
By default, all API endpoints are reachable without authentication, and all requests are authorized.
An authentication system is available to restrict the access. When activated, all API endpoints are protected by authentication except GET /render/:renderId
and GET /status
.
Reasons why GET /render/:renderId
is not protected:
:renderId
contains the custom report name in base64, concatenated with a 22-characters-long cryptographically random numbers with unbiased tranformation. It is somehow a unique password for each rendered report. It is better than any authentication mechanism.:renderId
is ephemeral, the resource becomes inaccessible once the file is downloaded.Three solutions to enable authentication:
--authentication
"authentication" : true
CARBONE_EE_AUTHENTICATION=true
Then the header Authorization
must be passed to all requests, with a ES512
JWT token as value. To generate a token, you can:
./carbone generate-token
generates 40-years valid tokensconfig/key.pub
(ES512). Tokens must contain at least the following payload:{
"iss": "your-carbone-user",
"aud": "carbone-ee",
"exp": 2864189447
}
Carbone Studio Light is a web interface to preview reports with a JSON editor. It is a "light" version of https://studio.carbone.io without files and version management. To enable the Carbone Studio Light:
--studio
to the binary, such as: ./carbone webserver --studio
CARBONE_EE_STUDIO
to true
"studio": true
.Then visit the URL http://127.0.0.1:4000
and enjoy!
If the authentication option is enabled, the browser requests an authentication to access the web page.
Carbone On-premise gives the possibility to override functions at specific moments to add custom features, such as adding analytics, store data on a specific storage provider, custom authentication, etc... It is possible through:
requirement plugins and middlewares can be only written using NodeJS.
For a better understanding, here is the Carbone On-premise lifecycle:
Following actions can be customized:
It is recommended to create a separate NodeJS repository:
# 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). Custom plugins MUST be inserted in the plugin
folder.
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 requesttemplateId
: Unique template ID as a sha256 hashtemplatePathTemp
: Absolute path of the uploaded templatecallback
: callback functionAdditional file informations are available 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 bytesconst 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
}
To override template reading, the file storage.js
in the plugin
folder has to be created. The function to explort is readTemplate
which is described as follow:
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.
To override template deletion, add the function deleteTemplate
in the storage.js
file in the plugin
folder and export it, for instance:
// 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
}
To override render writing, add the function afterRender
in the storage.js
file in the plugin
folder and export it.
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 on Buckets, or it is also possible to change the response object:
res.send({
success: true,
data: {
newField: reportName
}
});
The statistics
argument return an object with:
{
"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"
}
The function readRender
has to be exported in the storage.js
located in the plugin
folder.
function readRender (req, res, renderName, next) {
// Return the directly render or a local path
}
This function can be used to return directly the file using res
, it is also possible to return the new render name, or return a path from the afterRender
function.
// 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')
}
Before or after 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.
function beforeRender (req, res, carboneData, carboneOptions, next) {
// add a prefix to rendered filename
carboneOptions.renderPrefix = 'myPrefix';
next(null);
}
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 follow:
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
}
Middlewares can be added before or after 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:
function beforeMiddleware (req, res, next) {
console.log('I am executed before all route')
return next()
}
function afterMiddleware (req, res, next) {
console.log('I am executed after all route')
}
module.exports = {
before: [beforeMiddleware], // Middlewares in this array will be executed before routes
after: [afterMiddleware] // Middlewares in this array will be executed after routes
}
When the Carbone server receives SIGTERM signal, (what we call "SOFT STOP")
GET /status
API request returns HTTP status 503
instead of 200
. It can be used as a trigger (liveness, readiness probes) for a load balancer, reverse-proxy, or kubernetes.