The Perfect Server - Debian 9 (Stretch) with Apache, BIND, Dovecot, PureFTPD and ISPConfig 3.1 - Page 2

10 Install Apache2, PHP, FCGI, suExec, Pear, phpMyAdmin, and mcrypt

Apache2, PHP5, phpMyAdmin, FCGI, suExec, Pear, and mcrypt can be installed as follows:

apt-get -y install apache2 apache2-doc apache2-utils libapache2-mod-php php7.0 php7.0-common php7.0-gd php7.0-mysql php7.0-imap phpmyadmin php7.0-cli php7.0-cgi libapache2-mod-fcgid apache2-suexec-pristine php-pear php7.0-mcrypt mcrypt  imagemagick libruby libapache2-mod-python php7.0-curl php7.0-intl php7.0-pspell php7.0-recode php7.0-sqlite3 php7.0-tidy php7.0-xmlrpc php7.0-xsl memcached php-memcache php-imagick php-gettext php7.0-zip php7.0-mbstring memcached libapache2-mod-passenger php7.0-soap

You will see the following questions:

Web server to reconfigure automatically: <- apache2
Configure database for phpmyadmin with dbconfig-common? <- yes
Enter the phpmyadmin application password? <-  Just press enter

Then run the following command to enable the Apache modules suexec, rewrite, ssl, actions, and include (plus dav, dav_fs, and auth_digest if you want to use WebDAV):

a2enmod suexec rewrite ssl actions include dav_fs dav auth_digest cgi headers

To ensure that the server can not be attacked trough the HTTPOXY vulnerability, we will disable the HTTP_PROXY header in apache globally by adding the configuration file /etc/apache2/conf-available/httpoxy.conf.

nano /etc/apache2/conf-available/httpoxy.conf

Paste the following content to the file:

<IfModule mod_headers.c>
    RequestHeader unset Proxy early

And enable the module by running:

a2enconf httpoxy
service apache2 restart

10.1 Install HHVM (HipHop Virtual Machine)

There are no HHVM packages for Debian 9 available yet. HHVM is an optional PHP mode, so your server will work without it, you just can't use PHP mode HHVM for websites.

10.2 SuPHP

SuPHP is not available anymore for Debian 9, the SuPHP functions are outdated and will get removed from ISPConfig as well. Use the available PHP modes PHP-FPM or PHP-FCGI together with suexec instead of SuPHP.

11 Install Let's Encrypt

ISPConfig 3.1  has support for the free SSL Certificate authority Let's encrypt. The Let's Encrypt function allows you to create free SSL certificates for your website from within ISPConfig.

Now we will add support for Let's encrypt.

cd /usr/local/bin
chmod a+x certbot-auto
./certbot-auto --install-only

There are no further steps required than installing LE. The website SSL certificates are created by ISPConfig when you add the web sites.

12 Install PHP-FPM

To use PHP-FPM with Apache, we need the mod_proxy_fcgi Apache module, which is installed by default and needs just be enabled. We can install PHP-FPM and as follows:

apt-get -y install php7.0-fpm

Make sure you enable the modules and restart Apache:

a2enmod actions proxy_fcgi alias 
service apache2 restart

12.2 Install PHP Opcode Cache (optional)

Opcache is a free PHP opcode cacher for caching and optimizing PHP intermediate code. APCu is a compatibility module which provides APC compatible functions for Opcache which is used by many CMS caching systems.  It is recommended to have these PHP extensions installed to speed up your PHP page.

APCu can be installed as follows:

apt-get -y install php7.0-opcache php-apcu

Now restart Apache:

service apache2 restart

13 Install Mailman

ISPConfig allows you to manage (create/modify/delete) Mailman mailing lists. If you want to make use of this feature, install Mailman as follows:

apt-get install mailman

Select at least one language, e.g.:

Languages to support: <-- en (English)
Missing site list <-- Ok

Before we can start Mailman, a first mailing list called mailman must be created:

newlist mailman
[email protected]:~# newlist mailman
Enter the email of the person running the list: <-- admin email address, e.g. [email protected]
Initial mailman password: <-- admin password for the mailman list
To finish creating your mailing list, you must edit your /etc/aliases (or
equivalent) file by adding the following lines, and possibly running the
`newaliases' program:

## mailman mailing list
mailman:              "|/var/lib/mailman/mail/mailman post mailman"
mailman-admin:        "|/var/lib/mailman/mail/mailman admin mailman"
mailman-bounces:      "|/var/lib/mailman/mail/mailman bounces mailman"
mailman-confirm:      "|/var/lib/mailman/mail/mailman confirm mailman"
mailman-join:         "|/var/lib/mailman/mail/mailman join mailman"
mailman-leave:        "|/var/lib/mailman/mail/mailman leave mailman"
mailman-owner:        "|/var/lib/mailman/mail/mailman owner mailman"
mailman-request:      "|/var/lib/mailman/mail/mailman request mailman"
mailman-subscribe:    "|/var/lib/mailman/mail/mailman subscribe mailman"
mailman-unsubscribe:  "|/var/lib/mailman/mail/mailman unsubscribe mailman"

Hit enter to notify mailman owner... <-- ENTER

[email protected]:~#

Open /etc/aliases afterwards...

nano /etc/aliases

... and add the following lines:

## mailman mailing list
mailman:              "|/var/lib/mailman/mail/mailman post mailman"
mailman-admin:        "|/var/lib/mailman/mail/mailman admin mailman"
mailman-bounces:      "|/var/lib/mailman/mail/mailman bounces mailman"
mailman-confirm:      "|/var/lib/mailman/mail/mailman confirm mailman"
mailman-join:         "|/var/lib/mailman/mail/mailman join mailman"
mailman-leave:        "|/var/lib/mailman/mail/mailman leave mailman"
mailman-owner:        "|/var/lib/mailman/mail/mailman owner mailman"
mailman-request:      "|/var/lib/mailman/mail/mailman request mailman"
mailman-subscribe:    "|/var/lib/mailman/mail/mailman subscribe mailman"
mailman-unsubscribe:  "|/var/lib/mailman/mail/mailman unsubscribe mailman"



and restart Postfix:

service postfix restart

Finally, we must enable the Mailman Apache configuration:

ln -s /etc/mailman/apache.conf /etc/apache2/conf-enabled/mailman.conf

This defines the alias /cgi-bin/mailman/ for all Apache vhosts, which means you can access the Mailman admin interface for a list at, and the web page for users of a mailing list can be found at

Under you can find the mailing list archives.

Restart Apache afterwards:

service apache2 restart

Then start the Mailman daemon:

service mailman start

14 Install PureFTPd and Quota

PureFTPd and quota can be installed with the following command:

apt-get install pure-ftpd-common pure-ftpd-mysql quota quotatool

Create the dhparam file for pure-ftpd:

openssl dhparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 2048

Edit the file /etc/default/pure-ftpd-common...

nano /etc/default/pure-ftpd-common

... and make sure that the start mode is set to standalone and set VIRTUALCHROOT=true:


Now we configure PureFTPd to allow FTP and TLS sessions. FTP is a very insecure protocol because all passwords and all data are transferred in clear text. By using TLS, the whole communication can be encrypted, thus making FTP much more secure.

If you want to allow FTP and TLS sessions, run

echo 1 > /etc/pure-ftpd/conf/TLS

In order to use TLS, we must create an SSL certificate. I create it in /etc/ssl/private/, therefore I create that directory first:

mkdir -p /etc/ssl/private/

Afterwards, we can generate the SSL certificate as follows:

openssl req -x509 -nodes -days 7300 -newkey rsa:2048 -keyout /etc/ssl/private/pure-ftpd.pem -out /etc/ssl/private/pure-ftpd.pem
Country Name (2 letter code) [AU]: <-- Enter your Country Name (e.g., "DE").
State or Province Name (full name) [Some-State]: <-- Enter your State or Province Name.
Locality Name (eg, city) []: <-- Enter your City.
Organization Name (eg, company) [Internet Widgits Pty Ltd]: <-- Enter your Organization Name (e.g., the name of your company).
Organizational Unit Name (eg, section) []: <-- Enter your Organizational Unit Name (e.g. "IT Department").
Common Name (eg, YOUR name) []: <-- Enter the Fully Qualified Domain Name of the system (e.g. "").
Email Address []: <-- Enter your Email Address.

Change the permissions of the SSL certificate:

chmod 600 /etc/ssl/private/pure-ftpd.pem

Then restart PureFTPd:

service pure-ftpd-mysql restart

Edit /etc/fstab. Mine looks like this (I added ,usrjquota=quota.user,,jqfmt=vfsv0 to the partition with the mount point /):

nano /etc/fstab
# /etc/fstab: static file system information.
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
# <file system> <mount point> <type> <options> <dump> <pass>
# / was on /dev/sda1 during installation
UUID=f539c5cb-624f-4c27-a149-1446a251a453 / ext4 errors=remount-ro,usrjquota=quota.user,,jqfmt=vfsv0 0 1
# swap was on /dev/sda5 during installation
UUID=8d3194e7-edb5-4492-937d-d066b4994baf none swap sw 0 0
/dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0

To enable quota, run these commands:

mount -o remount /
quotacheck -avugm
quotaon -avug

15 Install BIND DNS Server

BIND can be installed as follows:

apt-get install bind9 dnsutils

 If your server is a virtual machine, then it is highly recommended to install the haveged daemon to get a higher entropy for DNSSEC signing. You can install haveged on nonvirtual servers as well, it should not hurt.

apt-get install haveged

An explanation on that topic can be found here.

16 Install Webalizer and AWStats

Webalizer and AWStats can be installed as follows:

apt-get install webalizer awstats geoip-database libclass-dbi-mysql-perl libtimedate-perl

Open /etc/cron.d/awstats afterwards...

nano /etc/cron.d/awstats

... and comment out everything in that file:


#*/10 * * * * www-data [ -x /usr/share/awstats/tools/ ] && /usr/share/awstats/tools/

# Generate static reports:
#10 03 * * * www-data [ -x /usr/share/awstats/tools/ ] && /usr/share/awstats/tools/

17 Install Jailkit

Jailkit is needed only if you want to chroot SSH users. It can be installed as follows:

apt-get install build-essential autoconf automake libtool flex bison debhelper binutils
cd /tmp
tar xvfz jailkit-2.20.tar.gz
cd jailkit-2.20
echo 5 > debian/compat
./debian/rules binary

You can now install the Jailkit .deb package as follows:

cd ..
dpkg -i jailkit_2.20-1_*.deb
rm -rf jailkit-2.20*

18 Install fail2ban and UFW Firewall

This is optional but recommended, because the ISPConfig monitor tries to show the log:

apt-get install fail2ban

To make fail2ban monitor PureFTPd and Dovecot, create the file /etc/fail2ban/jail.local:

nano /etc/fail2ban/jail.local

And add the following configuration to it.

enabled = true
port = ftp
filter = pure-ftpd
logpath = /var/log/syslog
maxretry = 3

enabled = true
filter = dovecot
logpath = /var/log/mail.log
maxretry = 5

enabled = true
port = smtp
filter = postfix-sasl
logpath = /var/log/mail.log
maxretry = 3

Restart fail2ban afterwards:

service fail2ban restart

To install the UFW firewall, run this apt command:

apt-get install ufw
Share this page:

Suggested articles

24 Comment(s)

Add comment


By: tucuta

In step 10 I did not see Enter the password of the administrative user.

It is normal...???

As additional information I did not install mariadb, I installed mysql

By: till

MariaDB requests a password, MySQL does not do that. When you do not follow the tutorial closely or install different software, then you won't get the same questions from the installers.

By: r_s

I did install MariaDB exactly as in step 8, and it did not request a password, too.

Also question no. 3 is slightly different:

'MySQL application password for phpmyadmin:'


NB: latest Debian 9 as of today.


By: tucuta

Ok, thanks till...


By: tucuta

A thousand apologies because I can not reply.One more question, does this affect the tutorial ...?

By: till

It should work with MySQL as well, but I haven't tested that. At least you will have to set the sql-mode in a different file then.

By: tucuta

I will follow the tutorial to see if it works.Many thanks till.Very friendly.

By: Greenhorn2013

Is there nothing to do with ufw and fail2ban? Doesnt think that fail2ban works by default with ufw.

By: till

UFW and Fail2ban both use iptables internally, so Fail2ban does not have to use UFW as it uses iptables directly.

By: anerty

Work fine, except :

1 - the SSL certificate is not working, my connection is not secured and not "secured but unknown authority".

2 - This is a Major problem, email works only in internal hosted email boxes, and only for sending to outside, can't receive any email from outside emails (like gmail).

Thank you so far, I need to mention that I have been using an AWS EC2 instance with elastic IP and Route 53.

By: till

1) These are self-signed SSL certs, that's why you get this message. The messages do not indicate an error, just accept the self-signed cert once in the client. If you want to get an officially signed cert e.g. from lets encrypt, then you can find instructions in the forum for that.

2) That's a problem of the hosting provider that you have chosen and not the tutorial. AWS closes the mail ports to disallow you to use your instance as mail server. You will probably have to use an external relay server for mail if you want to stay at amazon or go to a provider like linode or digitalocean, that allow mail server hosting.

By: Gary Pearce

installing on a raspberry pi today this tutorial fails during step 10


Determining localhost credentials from /etc/mysql/debian.cnf: succeeded.

dbconfig-common: writing config to /etc/dbconfig-common/phpmyadmin.conf


Creating config file /etc/dbconfig-common/phpmyadmin.conf with new version


Creating config file /etc/phpmyadmin/config-db.php with new version

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES).

unable to connect to mysql server.

error encountered creating user:

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

dbconfig-common: phpmyadmin configure: trying again.

Determining localhost credentials from /etc/mysql/debian.cnf: succeeded.

dbconfig-common: writing config to /etc/dbconfig-common/phpmyadmin.conf

Replacing config file /etc/dbconfig-common/phpmyadmin.conf with new version

Replacing config file /etc/phpmyadmin/config-db.php with new version

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES).

unable to connect to mysql server.

error encountered creating user:

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)


dbconfig-common: phpmyadmin configure: ignoring errors from here forwards


Any suggestions ?

By: till

The MySQL root password that you have set in the file /etc/mysql/debian.cnf seems to be wrong.

By: Gary Pearce

DOH ! silly me. 


By: Gary Pearce

This command 

quotacheck -avugm

reported that it could not find /dev/root 

a soft link:

ln -s /dev/sda /dev/root


appears to be the solution but




quotaon -avug



quotaon: using // on /dev/root [/]: No such process

quotaon: Quota format not supported in kernel.

quotaon: using //quota.user on /dev/root [/]: No such process


quotaon: Quota format not supported in kernel.


fstab looks like this:

proc            /proc           proc    defaults          0       0

# root on usb drive

/dev/sda1       /               ext4    usrjquota=quota.user,,jqfmt=vfsv0  0       1

# SDcard 

PARTUUID=f010533b-01  /boot           vfat    defaults          0       2

# PARTUUID=f010533b-02  /               ext4    defaults,noatime  0       1

# a swapfile is not a swap partition, no line here


#   use  dphys-swapfile swap[on|off]  for that

Any thoughts ?

By: Gary Pearce

 Well a reboot fixed the quotaon -avug issue 

no real idea why a reboot was required

but the symlink of /dev/sda to /dev/root did not survive the reboot as /dev is created dynamically. To fix this I needed to create this file "/etc/udev/rules.d/10-local.rules" 

this needed to contain a single line:

KERNEL=="sda" SYMLINK="root"


the only side effect is that running quotacheck with quotas turned on now returns:


quotacheck: Quota for users is enabled on mountpoint / so quotacheck might damage the file.


Please turn quotas off or use -f to force checking.


turning quotas off prior to running quotacheck behaves normally however. 


Is this a problem ?



By: peri0603

HHVM is now available for Debain Strech:

By: sftp


i'm on a fresh Debian 9 (.3) installation and I followed every step of this tutorial but it seems to me the phpmyadmin part has changed.

I don't get the questions mentioned in this tutorial:

Web server to reconfigure automatically: <- apache2 Configure database for phpmyadmin with dbconfig-common? <- yesEnter the phpmyadmin application password? <-  Just press enterEnter the password of the administrative user? <- yourrootmysqlpassword

I get the fist two questions in the dialog, but not the last two questions. The wording of the last two is different of whats written in this tutorial.

The question of the phpmyadmin applications password is different, but gives me the option to just press enter to generate a random password. If I just press enter, the config dialog says the passwords dont match and the whole config dialog stops.

If I retry it with dpkg-reconfigure phpmyadmin I get a bunch of other questions, like how I want to connect, but unix socket or tcp-ip.

Has this changed? How is the correct way to "restart" the config dialog for phpmyadmin. My root-pw in the debian.cnf is correct, I copy&pasted it from keepass. Do I have to put it in ticks (' or ") when it contains special characters like .,/ etc.?

Thanks in advance! And thank you for the awesome ispconfig! :)

By: till

This has not been changed, but it might be that your apt-setup is set to an advanced mode. Just accept the defaults for other questions that might appear. To reconfigure phpmyadmin run:


dpkg-reconfigure phpmyadmin

By: FredZinsli

Section 10:

Web server to reconfigure automatically: <- apache2Configure database for phpmyadmin with dbconfig-common? <- yesEnter the phpmyadmin application password? <-  Just press enterEnter the password of the administrative user? <- yourrootmysqlpassword The admin password question did not show after I just pressed enter for the application password. How does this affect the rest of the install?

Yes I am using copy/paste for all instructions.


Yes this is a virgin install





By: PVasileff

Here is HHVM instalation for debian 9:

Please update the article

By: till

HHVM decided to stop supporting PHP code which makes it useless as PHP mode option in ISPConfig, therefore it got removed from ISPConfig master branch already. So better not install HHVM.

By: casinad

My fstab file is empty !  i have only this line:  # UNCONFIGURED FSTAB FOR BASE SYSTEM

can you help me ? 

By: arnold61

Part 10:

memcached seems to be 2 times in the list to install