Appendix A: Development and advanced configuration

Importing configuration data

Although the Zentyal interface greatly eases the system administrator work, some configuration tasks through the interface can be tedious if you have to perform them repeatedly. For example, adding 100 new user accounts or enabling an e-mail account for all the Zentyal users.

These tasks can be automated easily through the Application Programming Interface (API) which is provided by Zentyal. You only need a basic knowledge of Perl [1], and to know the public methods exposed by the Zentyal modules you want to use. In fact, Zentyal web interface uses the same programming interface.

An example on how to create a small utility is shown below, using the Zentyal API. This utility automatically adds an arbitrary number of users defined in a Comma Separated Values (CSV) file:


use strict;
use warnings;

use EBox;
use EBox::Samba::User;
use File::Slurp;

my @lines = read_file('users.csv');
chomp (@lines);


my $parent = EBox::Samba::User->defaultContainer();

for my $line (@lines) {
    my ($username, $givenname, $surname, $password) = split(',', $line);
        samAccountName => $username,
        parent => $parent,
        givenName => $givenname,
        sn => $surname,
        password => $password


Save the file with the name bulkusers and grant it execution permission using the command chmod +x bulkusers.

Before running the script, you must have a file called users.csv in the same directory. The appearance of this file should be the following:


Finally, you must be in the directory where the files are placed and run:

sudo ./bulkusers

In this section you have seen a small example of task automation using the Zentyal API, but the possibilities are almost unlimited.

[1]Perl is a high-level, general-purpose, interpreted, dynamic programming language.

Advanced Service Customization

You may need to extend the functionality of Zentyal modules to suit your needs. Zentyal offers two different mechanisms for this purpose. It is possible to change or extend parts of the behavior in such a way that you can still benefit from the abstraction and automation offered by the framework.

stubs: Templates that will be used to generate the configuration files used by the daemons. Modifying or creating a stub, you can customize the behaviour of any module, for example, adding a safe port to Squid (HTTP Proxy) configuration.

hooks: Scripts that will be triggered during specific checkpoints of the life cycle of a module, for example, adding a rule that marks certain types of traffic in the firewall after establishing Zentyal’ rules.


The Zentyal modules, once configured, overwrite the original system configuration files for the services they manage. Modules do this through templates that essentially contain the structure of a configuration file for the service. Some parts of the resulting file are parametrized through variables provided by the framework.

How the configuration template system works

How the configuration template system works

Modifying the configuration files directly is incorrect, because these files will be overwritten each time the templates are processed (saving changes, for example). Zentyal’s own configuration templates can be found in /usr/share/zentyal/stubs and their names consists of the original configuration file, plus the .mas extension. For example /usr/share/zentyal/stubs/dns/named.conf.mas. Modifying these templates is not a good solution either, because they will be overwritten if the software package is updated or reinstalled.

Therefore, to make your changes persistent, you can copy the original template file to a directory in /etc/zentyal/stubs/, with the name of the module.

For example:

sudo mkdir /etc/zentyal/stubs/dns
sudo cp /usr/share/zentyal/stubs/dns/named.conf.options.mas /etc/zentyal/stubs/dns

Another advantage of copying the templates to /etc/zentyal/stubs/ is that you can keep control of the modifications that you have done over the original templates, and you will always be able to check these differences using the ‘diff’ tool. For example, for the previous case:

diff /etc/zentyal/stubs/dns/named.conf.options.mas

For the next example, let’s suppose you don’t want to allow the ‘DMZ’ network, which is internal, but not fully trusted, to perform DNS zone transfers.

You will create the directory /etc/zentyal/stubs/dns and copy the files named.conf.local.mas and named.conf.options.mas.

You add the ‘DMZ’ group containing the desired network ranges in named.conf.local.mas:

acl "DMZ" {;;

And then forbid zone transfers to this object in named.conf.options.mas:

allow-transfer { !DMZ; internal-local-nets; };

Remember to restart the module after modifying the files:

sudo zs dns restart


It is possible that you need to perform certain additional actions at some specific point of the execution state of a module. For example, when Zentyal saves changes related to the firewall, the first thing the firewall module does is to remove all existing rules, and then add the ones configured in Zentyal. If you manually add a custom iptables rule that is not covered by Zentyal interface, it will disappear when saving firewall module changes. To modify this behavior, Zentyal lets you run scripts while the saving changes process is being performed.

There are six points during the process when you may execute these scripts, also known as hooks. Two of them are general and the remaining four are module specific:

  • Before saving changes: In /etc/zentyal/pre-save directory, all scripts with running permissions are run before starting the save changes process.
  • After saving changes: Scripts with running permissions in /etc/zentyal/post-save directory are executed when the process is finished.
  • Before saving module configuration: Writing the file /etc/zentyal/hooks/<module>.presetconf, with module being the module name you want to tailor, the hook is executed prior to overwriting the configuration of this daemon.
  • After saving module configuration: /etc/zentyal/hooks/<module>.postsetconf, the script will be executed after saving the configuration of a specific module.
  • Before restarting the service: Will execute /etc/zentyal/hooks/<module>.preservice. You can use this to load Apache modules, for example.
  • After restarting the service: Will execute /etc/zentyal/hooks/<module>.postservice. In case of firewall, you can add all the extra rules here.

Let’s suppose that your server has a transparent proxy, but you wish to exclude certain network segments so that these will not be automatically redirected to the proxy. You will create the file /etc/zentyal/hooks/firewall.postservice, with the following content:

iptables -t nat -I premodules -s \
-p tcp -m tcp --dport 80 -j ACCEPT

Then, you will give execution permissions to the module and restart the service:

sudo chmod +x firewall.postservice
sudo zs firewall restart

These options have great potential and allow you to highly customize Zentyal to your specific case.

Development environment of new modules

Zentyal is designed with extensibility in mind and it is relatively easy to create new modules.

Anyone with Perl language knowledge can take advantage of the Zentyal development framework to create Web interfaces and, also, benefit from the integration with the rest of the modules and other common Zentyal features.

Zentyal design is completely object-oriented and it uses the Model-View-Controller (MVC) design pattern [2], so that the developer only needs to define those features required by the data model. The remaining parts are generated automatically by Zentyal.

You can follow the development tutorial [3] to get started with the development of a new module.

Zentyal is designed to be installed on a dedicated machine. This recommendation is also extensible to the development scheme. It is not recommended to develop on the user´s own machine. The recommended option is to use a virtualized environment, as detailed in Appendix A: Test environment with VirtualBox.

[2]MVC pattern:
[3]Zentyal Development Tutorial:

Commercial Edition Release Policy

Major versions of the Commercial Zentyal Editions (such as 7.0 or 6.0) are released every two years, when a new Ubuntu Server LTS version becomes available. Minor Commercial Zentyal Server versions (such as 7.1 or 7.2) are published between mayor releases, introducing usually new features. The Commercial Zentyal Editions are solely based on Ubuntu Server LTS.

Zentyal offers approximately 4.5 years of official support for Commercial Zentyal Editions. This ensures that since the release of a new major Zentyal Commercial Edition version, support for all security issues as well as commercial technical support and subscription services will be offered for this version during this time. After this time period, the Commercial Zentyal Edition version reaches the end of its life cycle and becomes unsupported. For further information, see the Zentyal Release Policy [4].

[4]Zentyal Release Policy:

Development Edition Release Policy

The general release cycle of the Development Edition is similar to that of the Commercial Edition: Major Zentyal Server versions (such as 7.0 or 6.0) are published every two years and minor Zentyal Server versions (such as 7.1 or 7.2) are published between mayor releases, introducing usually new features. All releases are always based on the Ubuntu Server LTS.

It is important to note that the Development Edition is the laboratory where new experimentations and features are first being deployed. Only when a new feature or a fix has been stabilized in the Development Edition, it will be back ported to the Commercial Edition. Also, only the latest Development Edition version is maintained.

Bug management policy

Zentyal uses Github [5] to manage the issues and requests for new features that the users create. These “issues” are public and any user with an account in GitHub can create and answer to any issue or request.

It is highly recommendable that before reporting a bug, you are fairly sure that your problem is really a bug and not just an expected result of the program under determined circumstances. If the bug was reported already, you can still help by confirming that you have reproduced it and giving additional details about the issue.

It is absolutely necessary to include detailed steps to reproduce the issue so that the Zentyal Development Team can fix it. If you are reporting manually, include at least the ‘/var/log/zentyal/zentyal.log‘ file or any other useful information you think it’s related with your issue. Screenshots are also welcome if you think they will help to see the problem.

[5]Zentyal Github:

Community support

Community support is provided mainly on the Internet. There are many occasions in which the community is able to support itself. That is, the users of the application selflessly help other users.

The community members are an important, even fundamental, providers of information for the product development. Users contribute by discovering hidden bugs and help developers to improve the product so it becomes more attractive to more users.

This voluntary support, logically, does not offer any guarantees. If a user asks a question, it is possible that no reply is given depending on the question format, timing or any other circumstances.

Zentyal community support channels is centered on the Official Zentyal Forum [6].

All this information is available, with further documentation, in the community section of Zentyal Wiki [7].

[6]Official Zentyal Forum:
[7]Zentyal Wiki: