Installing Horde Groupware


(Michael Träumner) #1

Installation of Horde at Nethserver 7

Changes at 10 July 2017

  • Don’t copy prefs.php, create a new one.
  • Added installation and configuration of mail (imp and ingo)
    Changes at 19 July 2017
  • Added installation and configuration of calendar-modul (kronolith)
    **Changes at 3 August 2017
  • Enabled TLS, because some people became an error “Strong(er) authentication required”

For my steps I looked at the following documentation (and google):

First we have to install the following packages:

  1. php-horde-horde (Basic Horde Installation)
  2. php-pecl-imagick (Manipulating graphics)
  3. aspell-en (english spell-checking; for other languages you possibly have to install other repositories)
    # yum install php-horde-horde php-pecl-imagick aspell-en

Also you have to install MariaDB and Mailserver from Nethserver-Softwarecenter.

Now we have to change values in the php.ini file (my favorite to do it is nano, which you can install with yum install nano)

# nano /etc/php.ini

Attachment size for sending mail:

; Maximum size of POST data that PHP will accept.
; Its value may be 0 to disable the limit. It is ignored if POST data reading
; is disabled through enable_post_data_reading.
; default: post_max_size = 8M
post_max_size = 100M
; File Uploads ;

; Whether to allow HTTP file uploads.
file_uploads = On

; Temporary directory for HTTP uploaded files (will use system default if not
; specified).
;upload_tmp_dir =

; Maximum allowed size for uploaded files.
; default: upload_max_filesize = 2M
upload_max_filesize = 20M

; Maximum number of files that can be uploaded via a single request
max_file_uploads = 20

Say Garbage Collection to work not so often for better performance:

; Defines the probability that the 'garbage collection' process is started on every
; session initialization. The probability is calculated by using the following equation:
; gc_probability/gc_divisor. Where session.gc_probability is the numerator and
; session.gc_divisor is the denominator in the equation. Setting this value to 1
; when the session.gc_divisor value is 100 will give you approximately a 1% chance
; the gc will run on any give request. Increasing this value to 1000 will give you
; a 0.1% chance the gc will run on any give request. For high volume production servers,
; this is a more efficient approach.
; Default Value: 100
; Development Value: 1000
; Production Value: 1000
; default: session.gc_divisor = 1000
session.gc_divisor = 10000

Give users less information about php-version and horde-groupware, and forbid them to change global data:

; Miscellaneous ;

; Decides whether PHP may expose the fact that it is installed on the server
; (e.g. by adding its signature to the Web server header).  It is no security
; threat in any way, but it makes it possible to determine whether you use PHP
; on your server or not.
; default: expose_php = On
expose_php = Off

Configure timezone:

; Module Settings ;

[CLI Server]
; Whether the CLI web server uses ANSI color coding in its terminal output.
cli_server.color = On

; Defines the default timezone used by the date functions
; default: ;date.timezone =
date.timezone = 'Europe/Berlin'

To reach the configuration you have to make some changes to the php-horde-horde.conf
Open it with:

# nano /etc/httpd/conf.d/php-horde-horde.conf

Add Require ip IP to IfModule mod_authz_core.c section and add an Allow from IP to IfModule !mod_authz_core.c section as shown below:
IP = IP of the device which should connect to the server to administrate it

 <IfModule mod_authz_core.c>
     # Apache 2.4
     Require ip X.X.X.X
   <IfModule !mod_authz_core.c>
     # Apache 2.2
     Order Deny,Allow
     Deny from All
     Allow from
     Allow from ::1
     Allow from X.X.X.X

After that reload your webserver:

# systemctl reload httpd.service

Now we have to create a database:

# mysql

mysql> create database horde5;
Query OK, 1 row affected (0.00 sec)

mysql> CREATE USER 'hordeuser'@'FQDN of your Horde-Server' IDENTIFIED BY 'Your Password';
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

 Query OK, 0 rows affected (0.00 sec)


Now we can test our new user:

# mysql -D horde5 -h FQDN of your Horde-Server -u hordeuser -p

Enter password:  Your Password
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 217265
Server version: 5.1.73 Source distribution

Copyright (c) 2000, 2014, Oracle, Monty Program Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [horde5]>
The connection is ok, now we list the databases

MySQL [horde5]> show databases; 
| Database           |
| information_schema |
| horde5             |
2 rows in set (0.01 sec)

MySQL [horde5]> quit

After that you can open your web-browser and navigate to X.X.X.X/horde/admin/config
click on gear-wheel, administration and configuration
click on Horde link at the table
click on Preferences tab and change the following

* $conf[prefs][maxsize] 65535
* $conf[prefs][driver] PHP Session

Click on the Database tab and change the following

* $conf[sql][phptype] MySQL (mysqli)
* $conf[sql][username] hordeuser 
* $conf[sql][password] Your Password
* $conf[sql][protocol] TCP/IP 
* $conf[sql][hostspec] FQDN of your Horde Server 
* $conf[sql][port] 3306
* $conf[sql][database] horde5 
* $conf[sql][charset] utf-8 
* $conf[sql][ssl] [ ] 
* $conf[sql][ca] 
* $conf[sql][splitread] Disabled

press the button 'Generate Horde Configuration’
Don’t be afraid, there could come a lot of problem reports, but after the next step everything would work great.

Back to terminal you can create the database tables with an existent script:

# /usr/bin/horde-db-migrate

After that go back to the configuration at your browser. It should look like this:

Now you can change back the value at preferences tab from PHP Session to SQL Database:

* $conf[prefs][maxsize]	65535
* $conf[prefs][driver] SQL Database
* $conf[prefs][params][driverconfig] Horde Defaults	
* $conf[prefs][params][table]

press the button ‘Generate Horde Configuration’ to save the changes.

At this time we have installed the basic system of horde.

Binding to Nethserver’s Samba Account Provider

Documentation in the Internet I found at:

Thanks as well to @flatspin and @dnutan for their help to find the correct configuration.

For binding Horde to our Samba Active Directory we have to add and change some values at the configuration. Most of the values you get at Domain Accounts at your web-interface and at the terminal with:

account-provider-test dump

For configuration navigate to X.X.X.X/horde/admin/config where X.X.X.X is the IP-Adress of your server
click on gear-wheel, administration and configuration
click on Horde link at the table
click on LDAP tab and change the following:

$conf[ldap][useldap] yes
$conf[ldap][hostspec] IP of Samba Container
$conf[ldap][port] 389
$conf[ldap][tls] true
$conf[ldap][timeout] 5
$conf[ldap][version] 3
$conf[ldap][bindas] Bind with administrative/system credentials
$conf[ldap][binddn] your bindDN
$conf[ldap][bindpw] your bindPassword
$conf[ldap][user][basedn] cn=users,your baseDN
$conf[ldap][user][uid] samaccountname
$conf[ldap][user][filter_type] LDAP filter string
$conf[ldap][user][filter] (objectClass=user)

Now we have to go to the Authentication tab and do the following settings:

$conf[auth][admins] admin
$conf[auth][checkip] true
$conf[auth][checkbrowser] true
$conf[auth][resetpassword] yes
$conf[auth][resetpassword_from] leave it blank
$conf[auth][alternate_login] false
$conf[auth][redirect_on_logout] false
$conf[auth][list_users] show a dropdown list
$conf[auth][driver] LDAP authentication
$conf[auth][params][driverconfig] Horde defaults
$conf[auth][params][basedn] cn=users,your BaseDN
$conf[auth][params][scope] Subtree search
$conf[auth][params][sizelimit] leave it blank
$conf[auth][params][ad] true
$conf[auth][params][uid] samaccountname
$conf[auth][params][encryption] ssha
$conf[auth][params][newuser_objectclass] shadowAccount, inetOrgPerson
$conf[auth][params][filter] (objectclass=Person)
$conf[auth][params][password_expiration] no
$conf[auth][params][count_bad_logins] false
$conf[auth][params][login_block] false
$conf[auth][params][login_block_count] 5
$conf[auth][params][login_block_time] 5

At last we go to the Groups tab and enter the following values:

$conf[group][driver] LDAP
$conf[group][params][driverconfig] Horde defaults
$conf[group][params][basedn] cn=users,your BaseDN
$conf[group][params][scope] Subtree search
$conf[group][params][gid] cn
$conf[group][params][memberuid] member
$conf[group][params][attrisdn] yes
$conf[group][params][user][basedn] cn=users,your BaseDN
$conf[group][params][user][uid] samaccountname
$conf[group][params][user][filter_type] LDAP filter string
$conf[group][params][user][filter] (objectCategory=group)(objectClass=user)
$conf[group][params][newgroup_objectclass] posixGroup, hordeGroup
$conf[group][params][writedn] your bindDN
$conf[group][params][writepw] your bindPassword
$conf[group][params][search][filter_type] A complete LDAP filter expression
$conf[group][params][search][filter] (objectClass=group)

Now press the the button to generate the Horde configuration.
From now on you can login with your Samba users.

For getting full name and mail address from Samba Active Directory you have to build a hook.

Create a prefs.local.php file

> nano /etc/horde/prefs.local.php

and add the following:

// If you lock this preference, you must specify a value or a hook for it in
// horde/config/hooks.php.
$_prefs['fullname'] = array(
    'locked' => 'false',
    'value' => '',
    'hook' => 'true',
    'type' => 'text',
    'desc' => _("Your full name:")
// If you lock this preference, you must specify a value or a hook for it in
// horde/config/hooks.php.
$_prefs['from_addr'] =  array(
    'locked' => 'false',
    'value' => '',
    'hook' => 'true',
    'type' => 'text',
    'desc' =>  _("The default e-mail address to use with this identity:")

After that you have to build the hook-file.

nano /etc/horde/hooks.local.php
class Horde_Hooks
    public function prefs_init($pref, $value, $username, $scope_ob)
        // LDAP connection parameters
        $ldapServer = '192.168.x.x'; //Adress of Samba Container
        $ldapPort = 389;
        $searchBase = 'cn=users,dc=MyDomain,dc=de';
        $binddn = 'MyBindDN';
        $bindpw = 'MyBindPW';

        switch ($pref)  {

            case 'from_addr':

                if (is_null($username)) {
                    return $value;

                $ds = @ldap_connect($ldapServer, $ldapPort);
                if (ldap_start_tls($ds)) {
                   if (@ldap_bind($ds, $binddn, $bindpw)) {
                      $searchResult = @ldap_search($ds, $searchBase, 'samaccountname=' . $username);
                      $information = @ldap_get_entries($ds, $searchResult);
                      if (($information === false) || ($information['count'] == 0)) {
                          $user = $username . '';
                      } else {
                          $user = ($information[0]['userprincipalname'][0] != '')
                          ? $information[0]['userprincipalname'][0]
                          : $information[0]['mail'][0];

                return empty($user) ? $username : $user;

            case 'fullname':

                if (is_null($username)) {
                    return $value;
                $ds = @ldap_connect($ldapServer, $ldapPort);

                if (ldap_start_tls($ds)) {
                  if (@ldap_bind($ds, $binddn, $bindpw)) {
                      $searchResult = @ldap_search($ds, $searchBase, 'samaccountname=' . $username);
                      $information = @ldap_get_entries($ds, $searchResult);
                      if (($information === false) || ($information['count'] == 0)) {
                          $name = '';
                      } else {
                          $name = ($information[0]['displayname'][0] != '')
                          ? $information[0]['displayname'][0]
                          : $information[0]['givenname'][0];
                return empty($name) ? $username : $name;

Now we have to change the prefs.local.php and hooks.local.php ownership to apache.

chown apache:apache /etc/horde/prefs.local.php
chown apache:apache /etc/horde/hooks.local.php

Next step is to change user rights of hooks.local.php

chmod 640 /etc/horde/hooks.local.php

To check if everything works fine, login with admin user and go to configuration again. At the left side you can switch between users and groups, have a look if you see your users and groups here. If you click a user, you should see the username, the full name and the mail address.

Installation and configuration of webmail by using our local mailserver

Please install mailserver from softwarecenter. After that you have to install imp for webmail and ingo for filtering mails in terminal

yum install php-horde-imp
yum install php-horde-ingo

After installation go back to X.X.X.X/horde/admin/config at your browser and click on horde.
Possible messages about DB Shemas you can ignore at this time.
Go to mail tab and setup the following values:

$conf[mailer][type] SMTP server (HIGHLY RECOMMENDED)
$conf[mailer][params][host] smtp.YourDomain
$conf[mailer][params][port] 587
$conf[mailer][params][secure] tls
$conf[mailer][params][localhost] YourDomain
$conf[mailer][params][auth] Yes
$conf[mailer][params][username] admin@yourDomain
$conf[mailer][params][username_auth] true
$conf[mailer][params][password] YourPassword
$conf[mailer][params][password_auth] true
$conf[mailer][params][lmtp] false

Now we can go to IMAP Server tab and set the following values

$conf[imap][enabled] Enabled
$conf[imap][server] imap.YourDomain
$conf[imap][port] 143
$conf[imap][secure] tls
$conf[imap][maildomain] YourDomain
$conf[imap][cache_folders] true

Now press the button to generate the Horde configuration again.

We have to create a webmail configuration now, click at Webmail (imp). If you want you can change some values here.
If you have finished, click on generate Webmail-Configuration.

After that you have to Update All DB Schemas.
For that you have to click “Update All DB Schemas” at X.X.X.X/horde/admin/config.

Now you can use the mailsystem. Your mail-adress is the one from active directory.

Installation an configuration of calendar-module

Please install kronolith from terminal

yum install php-horde-kronolith

If finished go to X.X.X.X/horde/admin/config an click on calendar (kronolith).
Here the following values have to been set:

$conf[calendar][driver] = SQL
$conf[calendar][params][driverconfig] = Horde defaults
$conf[calendar][params][table] = kronolith_events
$conf[calendar][params][utc] = true
$conf[storage][default_domain] = YourDomain
$conf[storage][driver] = SQL
$conf[storage][params][driverconfig] = Horde defaults
$conf[storage][params][table] = kronolith_storage
$conf[calendars][driver] = Default
$conf[resource][driver] = SQL
$conf[resource][params][driverconfig] = Horde defaults
$conf[resource][params][table] = kronolith_resources
$conf[resource][params][utc] = true
$conf[reminder][server_name] =  FQDN of your Horde-Server
$conf[reminder][from_addr] = admin@YourDomain (or another mail-adress)
$conf[autoshare][shareperms] = None (no sharing)
$conf[share][notify] = true

$conf[holidays][enable] = true

$conf[menu][import_export] = true
$conf[maps][driver] = No inline map support (If you want, of course you can activate the map support)

Now press the button to generate the calendar configuration
At this time you can work with your calendar software.
CalDav support is implemented in Horde 5.
For synchronizing with Outlook you can work with CalDav Synchronizer

I had to disable using proxy-settings of system in CalDav-Synchronizer. If you create a synchronization profile click on advanced options, Network settings and deactivate „Use system default proxy“.

Password for LDAP bind
Horde Groupware
Join QNAP-NAS to NethServer LDAP Directory?
Password for LDAP bind
(Giacomo Sanchietti) #2

Awesome! :clap:

(Alessio Fattorini) #3

You really deserve this one: :joy:

(Michael Träumner) #4

Thank you all. Especially to @dnutan and @flatspin for helping me so much and to @stephdl for creating and sharing a phpldapadmin package for nethserver which helps a lot to find the right values for configuration.

Next I will install some modules, instructions will follow.

PS: For all people who wants to help stephdl for his great work, have a look at:

Stephdl needs our love :heart:

(Marc) #5

First of all, kudos to Michael :thumbsup:
He invested many time an effort to test and write down an easy-to-follow howto.

@m.traeumner, I hit some problems on a new pristine NethServer 7 up to date:

Had to set $conf[ldap][tls] true, otherwise was greeted with a fatal error (Bind failed: Strong(er) authentication required).

Also had to:

chown apache:apache /etc/horde/prefs.local.php
chown apache:apache /etc/horde/hooks.local.php
chmod 640 /etc/horde/hooks.local.php

And due to TLS requirement the hooks file didn’t work. Had to wrap each ldap_bind call within:

if (ldap_start_tls($ds)) {
    // ldap_bind code here

Can anyone reproduce it to see if we need to update the howto?

P.S. The prefs.php file warns about…

IMPORTANT: DO NOT EDIT THIS FILE! DO NOT COPY prefs.php TO prefs.local.php!
Local overrides ONLY MUST be placed in prefs.local.php or prefs.d/.


 * Example configuration file that locks a preference, sets a different default
 * value for another, and enables a preference hook for a third one:
 * <code>
 * <?php
 * $_prefs['theme']['locked'] = true;
 * $_prefs['initial_application']['value'] = 'imp';
 * $_prefs['from_addr']['hook'] = true;
 * </code>

(Michael Träumner) #6

Hi Marc,
I’ve done all updates at my mashine, that works fine without TLS and root:root as the user of prefs.local.php and hooks.local.php.

Perhaps somebody else could try with a new installed nethserver.
/cc: @gerald_FS Would you try this, we will help you.

Thanks for the hint, I’ve changed my HowTo.

(Michael Träumner) #7

Added webmail installation and configuration to my HowTo

(Michael Träumner) #8

I’ve found some other themes for horde at the web:

(Gerald) #9

just wow!

Thank you, I believe we have made a big step - that there is a complete alternative for Sogo.

If we were to make the intregration in NS as a module, the next great milestone would have been achieved.

I fall into a few large package creator a … @stephdl @dnutan @giacomo to name a few! :wink:



(Michael Träumner) #10

Did somebody installed kronolith and tried to sync with outlook per CalDav Sxnchronizer.
I get the error, that I don’t have permission to


(Michael Träumner) #11

I managed it myself, in CalDav Synchronizer I had to disable using proxy settings from Internetexplorer.

Howto for Kronolith is following

(Michael Träumner) #12

Installation and configuration of kronolith (calendar-module) is added.

(Alessio Fattorini) #13

Thanks for constantly improving the howto, I appreciate it and not only me.

(Ralph) #14

After filling in the forms for Ldap, Authentication and Groups the horde configuration fails with the error message “Horde Bind failed: Strong(er) authentication required.” I repeated it serveral times, no success. The LDAP server is a Univention Active Directory controller.
Joining NS to the domain was no problem.
In which way can phpldapadmin help here?

(Marc) #15

Have you tried setting $conf[ldap][tls] to true?

(Ralph) #16

That did the trick. I can login now.
At first I saw no groups. In the groups section of your Howto it should say “cn=groups, BindDN” instead of “cn=users”.
How about Horde Gollem? Is that available too?
And is ActiveSync enabled?

(Michael Träumner) #17

Hi Marc because we had another test now that only works wit tls enabled I’ve changed my HowTo according to your instructions to enabled tls support. Could you have a look at it please

Could you say which setting you mean

$conf[group][params][basedn] cn=users,your BaseDN


$conf[group][params][user][basedn] cn=users,your BaseDN

For me it works with users, did you use nethserver samba ad or another?

(Ralph) #18

I meant this one
$conf[group][params][basedn] cn=users,your BaseDN

My AD controller is from Univention.

(Michael Träumner) #19

I think this is the reason, your AD could be configured different from the nethserver one.

(Michael Träumner) #20

It sounds interesting, I’ll test it, but not yet, I think in September.

At this moment it’s disabled, but I try next to enable and to sync Outlook 2013 with ActiveSync.