The Perfect Server - Ubuntu 20.04 with Apache, PHP, MariaDB, PureFTPD, BIND, Postfix, Dovecot and ISPConfig 3.2 (Beta)

This tutorial shows the installation of an Ubuntu 20.04 (Focal Fossa) web hosting server with Apache 2.4, Postfix, Dovecot, Bind, and PureFTPD to prepare it for the installation of ISPConfig 3.2. The resulting system will provide a Web, Mail, Mailinglist, DNS, and FTP Server.

ISPConfig is a web hosting control panel that allows you to configure the following services through a web browser: Apache or Nginx web server, Postfix mail server, Courier or Dovecot IMAP/POP3 server, MariaDB as MySQL replacement, BIND or MyDNS nameserver, PureFTPd, SpamAssassin, ClamAV, and many more. This setup covers the installation of Apache (instead of Nginx), BIND (instead of MyDNS), and Dovecot (instead of Courier).

1. Preliminary Note

In this tutorial, I use the hostname with the IP address and the gateway  These settings might differ for you, so you have to replace them where appropriate.  Before proceeding further you need to have a basic minimal installation of Ubuntu 20.04 as explained in the tutorial.

The commands in this tutorial have to be run with root permissions. To avoid adding sudo in front of each command, you'll have to become root user by running:

sudo -s

before you proceed.

2. Edit /etc/apt/sources.list and Update your Linux Installation

Edit /etc/apt/sources.list. Comment out or remove the installation CD from the file and make sure that the universe and multiverse repositories are enabled. It should look like this afterwards:

nano /etc/apt/sources.list
# See for how to upgrade to
# newer versions of the distribution.
deb focal main restricted
# deb-src focal main restricted

## Major bug fix updates produced after the final release of the
## distribution.
deb focal-updates main restricted
# deb-src focal-updates main restricted

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team. Also, please note that software in universe WILL NOT receive any
## review or updates from the Ubuntu security team.
deb focal universe
# deb-src focal universe
deb focal-updates universe
# deb-src focal-updates universe

## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## multiverse WILL NOT receive any review or updates from the Ubuntu
## security team.
deb focal multiverse
# deb-src focal multiverse
deb focal-updates multiverse
# deb-src focal-updates multiverse

## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
deb focal-backports main restricted universe multiverse
# deb-src focal-backports main restricted universe multiverse

## Uncomment the following two lines to add software from Canonical's
## 'partner' repository.
## This software is not part of Ubuntu, but is offered by Canonical and the
## respective vendors as a service to Ubuntu users.
# deb focal partner
# deb-src focal partner

deb focal-security main restricted
# deb-src focal-security main restricted
deb focal-security universe
# deb-src focal-security universe
deb focal-security multiverse
# deb-src focal-security multiverse

Then run

apt-get update

to update the apt package database and

apt-get upgrade

to install the latest updates (if there are any). If you see that a new kernel gets installed as part of the updates, you should reboot the system afterwards:


3. Change the Default Shell

/bin/sh is a symlink to /bin/dash, however we need /bin/bash, not /bin/dash. Therefore, we do this:

dpkg-reconfigure dash

Use dash as the default system shell (/bin/sh)? <-- No

If you don't do this, the ISPConfig installation will fail.

4. Disable AppArmor

AppArmor is a security extension (similar to SELinux) that should provide extended security. In my opinion, you don't need it to configure a secure system, and it usually causes more problems than advantages (think of it after you have done a week of troubleshooting because some service wasn't working as expected, and then you find out that everything was ok, only AppArmor was causing the problem). Therefore, I disable it (this is a must if you want to install ISPConfig later on).

We can disable it like this:

service apparmor stop
update-rc.d -f apparmor remove
apt-get remove apparmor apparmor-utils

5. Synchronize the System Clock

It is a good idea to synchronize the system clock with an NTP (network time protocol) server over the Internet when you run a physical server. In case you run a virtual server then you should skip this step. Just run

apt-get -y install ntp

and your system time will always be in sync.

6. Install Postfix, Dovecot, MariaDB, rkhunter, and binutils

For installing postfix, we need to ensure that sendmail is not installed and running. To stop and remove sendmail run this command:

service sendmail stop; update-rc.d -f sendmail remove

The error message:

Failed to stop sendmail.service: Unit sendmail.service not loaded.

Is ok, it just means that sendmail was not installed, so there was nothing to be removed.

Now we can install Postfix, Dovecot, MariaDB (as MySQL replacement), rkhunter, and binutils with a single command:

apt-get -y install postfix postfix-mysql postfix-doc mariadb-client mariadb-server openssl getmail4 rkhunter binutils dovecot-imapd dovecot-pop3d dovecot-mysql dovecot-sieve sudo patch

You will be asked the following questions:

General type of mail configuration: <-- Internet Site
System mail name: <--

It is important that you use a subdomain as "system mail name" like or and not a domain that you want to use as email domain (e.g. yourdomain.tld) later.

Next, open the TLS/SSL and submission ports in Postfix:

nano /etc/postfix/

Uncomment the submission and smtps sections as follows - add the line -o smtpd_client_restrictions=permit_sasl_authenticated,reject to both sections and leave everything thereafter commented:

submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
-o smtpd_tls_auth_only=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject # -o smtpd_reject_unlisted_recipient=no # -o smtpd_client_restrictions=$mua_client_restrictions # -o smtpd_helo_restrictions=$mua_helo_restrictions # -o smtpd_sender_restrictions=$mua_sender_restrictions # -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject # -o milter_macro_daemon_name=ORIGINATING smtps inet n - y - - smtpd -o syslog_name=postfix/smtps -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject # -o smtpd_reject_unlisted_recipient=no # -o smtpd_client_restrictions=$mua_client_restrictions # -o smtpd_helo_restrictions=$mua_helo_restrictions # -o smtpd_sender_restrictions=$mua_sender_restrictions # -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject # -o milter_macro_daemon_name=ORIGINATING [...]

NOTE: The whitespaces in front of the "-o .... " lines are important!

Restart Postfix afterward:

service postfix restart

We want MySQL to listen on all interfaces, not just localhost. Therefore, we edit /etc/mysql/mariadb.conf.d/50-server.cnf and comment out the line bind-address =

nano /etc/mysql/mariadb.conf.d/50-server.cnf
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
#bind-address           =


Now we set a root password in MariaDB. Run:


You will be asked these questions:

Enter current password for root (enter for none): <-- press enter
Set root password? [Y/n] <-- y
New password: <-- Enter the new MariaDB root password here
Re-enter new password: <-- Repeat the password
Remove anonymous users? [Y/n] <-- y
Disallow root login remotely? [Y/n] <-- y
Reload privilege tables now? [Y/n] <-- y

Set the password authentication method in MariaDB to native so we can use PHPMyAdmin later to connect as root user:

echo "update mysql.user set plugin = 'mysql_native_password' where user='root';" | mysql -u root

Edit the file /etc/mysql/debian.cnf and set the MYSQL / MariaDB root password there twice in the rows that start with password.

nano /etc/mysql/debian.cnf

The MySQL root password that needs to be added is shown in red. In this example, the password is "howtoforge". Replace the word "howtoforge" with the password that you have set for the MySQL root user with the mysql_secure_installation command.

# Automatically generated for Debian scripts. DO NOT TOUCH!
host = localhost
user = root
password = howtoforge
socket = /var/run/mysqld/mysqld.sock
host = localhost
user = root
password = howtoforge
socket = /var/run/mysqld/mysqld.sock
basedir = /usr

Open the file /etc/security/limits.conf with an editor:

nano /etc/security/limits.conf

and add these lines at the end of the file.

mysql soft nofile 65535
mysql hard nofile 65535

Next, create a new directory /etc/systemd/system/mysql.service.d/ with the mkdir command.

mkdir /etc/systemd/system/mysql.service.d/

and add a new file inside:

nano /etc/systemd/system/mysql.service.d/limits.conf

paste the following lines into that file:


Save the file and close the nano editor.

Then we reload systemd and restart MariaDB:

systemctl daemon-reload
service mariadb restart

Now check that networking is enabled. Run

netstat -tap | grep mysql

The output should look like this:

[email protected]:~# netstat -tap | grep mysql
tcp6       0      0 [::]:mysql              [::]:*                  LISTEN      51836/mysqld
[email protected]:~#

7. Install Amavisd-new, SpamAssassin, and Clamav

To install amavisd-new, SpamAssassin, and ClamAV, we run

apt-get -y install amavisd-new spamassassin clamav clamav-daemon unzip bzip2 arj nomarch lzop cabextract apt-listchanges libnet-ldap-perl libauthen-sasl-perl clamav-docs daemon libio-string-perl libio-socket-ssl-perl libnet-ident-perl zip libnet-dns-perl postgrey

The ISPConfig 3 setup uses amavisd which loads the SpamAssassin filter library internally, so we can stop SpamAssassin to free up some RAM:

service spamassassin stop
update-rc.d -f spamassassin remove

To start ClamAV use:

service clamav-daemon start

The following error can be ignored on the first run of freshclam.

ERROR: /var/log/clamav/freshclam.log is locked by another process
ERROR: Problem with internal logger (UpdateLogFile = /var/log/clamav/freshclam.log).

8. Install Apache, PHP, phpMyAdmin, FCGI, SuExec, Pear

Apache 2.4, PHP 7.4, phpMyAdmin, FCGI, suExec, and Pear can be installed as follows:

apt-get -y install apache2 apache2-doc apache2-utils libapache2-mod-php php7.4 php7.4-common php7.4-gd php7.4-mysql php7.4-imap phpmyadmin php7.4-cli php7.4-cgi libapache2-mod-fcgid apache2-suexec-pristine php-pear libruby libapache2-mod-python php7.4-curl php7.4-intl php7.4-pspell php7.4-sqlite3 php7.4-tidy php7.4-xmlrpc php7.4-xsl memcached php-memcache php-imagick php7.4-zip php7.4-mbstring php-soap php7.4-soap php7.4-opcache php-apcu php7.4-fpm libapache2-reload-perl

You will see the following question:

Web server to reconfigure automatically: <-- apache2

Enable PHPMyAdmin in Apache2

Configure database for phpmyadmin with dbconfig-common? <-- Yes
DBConfig Common

MySQL application password for phpmyadmin: <-- Press enter

MySQL application password

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 cgi alias proxy_fcgi
a2enmod dav_fs dav auth_digest headers

To ensure that the server cannot be attacked through the HTTPOXY vulnerability, I will disable the HTTP_PROXY header in apache globally. Create a new httpoxy.conf file with nano:

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

Paste this content into the file:

<IfModule mod_headers.c>
    RequestHeader unset Proxy early

Enable the config file by running:

a2enconf httpoxy

Restart Apache afterward:

service apache2 restart

If you want to host Ruby files with the extension .rb on your websites created through ISPConfig, you must comment out the line application/x-ruby rb in /etc/mime.types:

nano /etc/mime.types
#application/x-ruby                             rb

(This is needed only for .rb files; Ruby files with the extension .rbx work out of the box.)

Restart Apache afterwards:

service apache2 restart

9. Install Let's Encrypt

ISPConfig 3.2 has built-in 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 in ISPConfig.

Now we will add support for Let's encrypt.

apt-get install certbot

10. 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 -y install mailman

Select at least one language, e.g.:

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

The error 'Job for mailman.service failed because the control process exited with error code.' can be ignored for now.

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"



afterward and restart Postfix:

service postfix restart

Finally, we must enable the Mailman Apache configuration:

ln -s /etc/mailman/apache.conf /etc/apache2/conf-available/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 http://<vhost>/cgi-bin/mailman/admin/<listname>, and the web page for users of a mailing list can be found at http://<vhost>/cgi-bin/mailman/listinfo/<listname>.

Under http://<vhost>/pipermail you can find the mailing list archives.

Activate the configuration with:

a2enconf mailman

Restart Apache afterward:

service apache2 restart

Then start the Mailman daemon:

service mailman start

11. Install PureFTPd and Quota

PureFTPd and quota can be installed with the following command:

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

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>
/dev/mapper/server1--vg-root / ext4 errors=remount-ro,usrjquota=quota.user,,jqfmt=vfsv0 0 1
/dev/mapper/server1--vg-swap_1 none swap sw 0 0
/dev/fd0 /media/floppy0 auto rw,user,noauto,exec,utf8 0 0

To enable quota, run these commands:

mount -o remount /
quotacheck -avugm
quotaon -avug

 Which will show the following output:

[email protected]:/tmp# quotacheck -avugm
quotacheck: Scanning /dev/mapper/server1--vg-root [/] done
quotacheck: Cannot stat old user quota file //quota.user: No such file or directory. Usage will not be subtracted.
quotacheck: Cannot stat old group quota file // No such file or directory. Usage will not be subtracted.
quotacheck: Cannot stat old user quota file //quota.user: No such file or directory. Usage will not be subtracted.
quotacheck: Cannot stat old group quota file // No such file or directory. Usage will not be subtracted.
quotacheck: Checked 13602 directories and 96597 files
quotacheck: Old file not found.
quotacheck: Old file not found.
[email protected]:/tmp# quotaon -avug
/dev/mapper/server1--vg-root [/]: group quotas turned on
/dev/mapper/server1--vg-root [/]: user quotas turned on

12. Install BIND DNS Server

BIND can be installed as follows:

apt-get -y install bind9 dnsutils haveged

Enable and start the haveged Daemon:

systemctl enable haveged
systemctl start haveged

13. Install Vlogger, Webalizer, AWStats and GoAccess

Vlogger, Webalizer, and AWStats can be installed as follows:

apt-get -y install vlogger webalizer awstats geoip-database libclass-dbi-mysql-perl goaccess

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/

14. Install Jailkit

Jailkit is used to jailed shell users and cronjobs in ISPConfig. Install jailkit with apt:

apt-get -y install jailkit

15. Install fail2ban and UFW

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

apt-get -y install fail2ban

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

nano /etc/fail2ban/jail.local
enabled  = true
port     = ftp
filter   = pure-ftpd
logpath  = /var/log/syslog
maxretry = 3

enabled = true
filter = dovecot
action = iptables-multiport[name=dovecot-pop3imap, port="pop3,pop3s,imap,imaps", protocol=tcp]
logpath = /var/log/mail.log
maxretry = 5

enabled  = true
port     = smtp
filter   = postfix
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

16. Install Roundcube Webmail

To install Roundcube Webmail, run:

apt-get -y install roundcube roundcube-core roundcube-mysql roundcube-plugins roundcube-plugins-extra javascript-common libjs-jquery-mousewheel php-net-sieve tinymce

The installer might ask the following questions:

Configure database for roundcube with dbconfig-common? <-- Yes
MySQL application password for roundcube: <-- Press enter

Don't worry if you do not get these questions and a warning about the ucf script, that's ok.

The ucf warning that you will get on the shell can be ignored, it has no negative impact on the installation.

Then edit the RoundCube apache configuration file.

nano /etc/apache2/conf-enabled/roundcube.conf

and remove the # in front of the Alias line, then add the second Alias line for /webmail and add the line "AddType application/x-httpd-php .php" right after the "<Directory /var/lib/roundcube>" line:

# Those aliases do not work properly with several hosts on your apache server
# Uncomment them to use it or adapt them to your configuration
Alias /roundcube /var/lib/roundcube
Alias /webmail /var/lib/roundcube [...] <Directory /var/lib/roundcube> AddType application/x-httpd-php .php [...]

And restart apache

service apache2 restart

Then edit the RoundCube configuration file:

nano /etc/roundcube/

and change the default host to localhost:

$config['default_host'] = 'localhost';

This prevents that Roundcube will show server name input field in the login form.

17. Install ISPConfig 3.2

We will use the ISPConfig 3.2 nightly builds which contain ISPConfig 3.2 beta 1 at the time of publishing this guide as ISPConfig 3.2 final has not been released yet.

cd /tmp 
wget -O ispconfig.tar.gz
tar xfz ispconfig.tar.gz
cd ispconfig3*/install/

The next step is to run

php -q install.php

This will start the ISPConfig 3 installer. The installer will configure all services like Postfix, Dovecot, etc. for you.

# php -q install.php

_____ ___________ _____ __ _ ____
|_ _/ ___| ___ \ / __ \ / _(_) /__ \
| | \ `--.| |_/ / | / \/ ___ _ __ | |_ _ __ _ _/ /
| | `--. \ __/ | | / _ \| '_ \| _| |/ _` | |_ |
_| |_/\__/ / | | \__/\ (_) | | | | | | | (_| | ___\ \
\___/\____/\_| \____/\___/|_| |_|_| |_|\__, | \____/
__/ |

>> Initial configuration
Operating System: Ubuntu 20.04.1 LTS (Focal Fossa)
Following will be a few questions for primary configuration so be careful.
Default values are in [brackets] and can be accepted with <ENTER>.
Tap in "quit" (without the quotes) to stop the installer.

Select language (en,de) [en]: <-- Hit Enter
Installation mode (standard,expert) [standard]: <-- Hit Enter
Full qualified hostname (FQDN) of the server, eg server1.domain.tld []: <-- Hit Enter
MySQL server hostname [localhost]: <-- Hit Enter
MySQL server port [3306]: <-- Hit Enter
MySQL root username [root]: <-- Hit Enter
MySQL root password []: <-- Enter your MySQL root password
MySQL database to create [dbispconfig]: <-- Hit Enter
MySQL charset [utf8]: <-- Hit Enter
Configuring Postgrey
Configuring Postfix
Generating a 4096 bit RSA private key
writing new private key to 'smtpd.key'
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
Country Name (2 letter code) [AU]: <-- Enter 2 letter country code
State or Province Name (full name) [Some-State]: <-- Enter the name of the  state
Locality Name (eg, city) []: <-- Enter your city
Organization Name (eg, company) [Internet Widgits Pty Ltd]: <-- Enter company name or press enter
Organizational Unit Name (eg, section) []: <-- Hit Enter
Common Name (e.g. server FQDN or YOUR name) []: <-- Enter the server hostname, in my case:
Email Address []: <-- Hit Enter
Configuring Mailman
Configuring Dovecot
Configuring Spamassassin
Configuring Amavisd
Configuring Getmail
Configuring BIND
Configuring Jailkit
Configuring Pureftpd
Configuring Apache
Configuring vlogger
Configuring Metronome XMPP Server
writing new private key to 'localhost.key'
Country Name (2 letter code) [AU]: <-- Enter 2 letter country code
Locality Name (eg, city) []: <-- Enter your city
Organization Name (eg, company) [Internet Widgits Pty Ltd]: <-- Enter company name or press enter
Organizational Unit Name (eg, section) []: <-- Hit Enter
Common Name (e.g. server FQDN or YOUR name) []: <-- Enter the server hostname, in my case:
Email Address []: <-- Hit Enter
Configuring Ubuntu Firewall
Configuring Fail2ban
[INFO] service OpenVZ not detected
Configuring Apps vhost
Installing ISPConfig
ISPConfig Port [8080]:
Admin password [admin]:
Do you want a secure (SSL) connection to the ISPConfig web interface (y,n) [y]: <-- Hit Enter
Generating RSA private key, 4096 bit long modulus
e is 65537 (0x10001)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
Country Name (2 letter code) [AU]: <-- Enter 2 letter country code
State or Province Name (full name) [Some-State]: <-- Enter the name of the  state
Locality Name (eg, city) []: <-- Enter your city
Organization Name (eg, company) [Internet Widgits Pty Ltd]: <-- Enter company name or press enter
Organizational Unit Name (eg, section) []: <-- Hit Enter
Common Name (e.g. server FQDN or YOUR name) []: <-- Enter the server hostname, in my case:
Email Address []: <-- Hit Enter
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: <-- Hit Enter
An optional company name []: <-- Hit Enter
writing RSA key

Symlink ISPConfig LE SSL certs to postfix? (y,n) [y]:  <-- Hit Enter
Symlink ISPConfig LE SSL certs to pureftpd? Creating dhparam file takes some times. (y,n) [y]:  <-- Hit Enter
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time

Configuring DBServer
Installing ISPConfig crontab
no crontab for root
no crontab for getmail
Detect IP addresses
Restarting services ...
Installation completed.

The installer automatically configures all underlying services, so there is no manual configuration needed.

Afterward you can access ISPConfig 3 under http(s):// or http(s):// (HTTP or HTTPS depends on what you chose during installation). Log in with the username admin and the password admin (you should change the default password after your first login):

ISPConfig Login on Ubuntu 18.04 LTS

ISPConfig 3.2 dashboard

The system is now ready to be used.

18. Virtual machine image download of this tutorial

This tutorial is available as ready to use virtual machine image in ovf/ova format that is compatible with VMWare and Virtualbox. The virtual machine image uses the following login details:

SSH / Shell Login

Username: administrator
Password: howtoforge

This user has sudo rights.

ISPConfig Login

Username: admin
Password: howtoforge

MySQL Login

Username: root
Password: howtoforge

The IP of the VM is, it can be changed in the file /etc/netplan/01-netcfg.yaml. Please change all the above passwords to secure the virtual machine.

19. Links

Share this page:

Suggested articles

39 Comment(s)

Add comment


By: ustoopia at: 2020-09-10 18:27:14

Allright!! I already have a freshly installed server waiting for exactly this moment! Thanks!

By: ustoopia at: 2020-09-10 20:25:43

Perhaps an idea for you to include somewhere in the setup guide that we need to perform the command : "apt install patch" before starting the ispconfig installer. I received an error message after entering the command " php -q install.php" that said "The patch command is missing. Install patch command and start installation again." After searching the forum here I found the solution so now the installer was able to start succesfully.

By: till at: 2020-09-11 06:46:15

A separate installation of the patch command was not required on my systems. But I can add it.

By: Hammers Thor at: 2020-09-11 20:39:48

Outstanding, and I mean OUTSTANDING tutorial. I have posted to GAB and Brighteon. Social (sorry, don't do facebook or twitter).

Thank you!

By: Tom at: 2020-09-12 15:29:35

OMG this is such great tutorial. I can tell already I'm going to learn a ton just by going through the motions of setting it up. Thanks for such detailed work. 

By: Tom at: 2020-09-12 23:03:55

Am I missing something? It says there's a link to download the image, but for the life of me I can't find any download link for that.

By: till at: 2020-09-13 06:27:32

The download link is in the menu on the right side of the page, near the top. Right below the big red download Icon.

By: Zoltan Kiss at: 2020-09-14 12:16:08

Hi! The download does not work.

By: till at: 2020-09-14 14:00:13

Try the download again, it works fine now.

By: jakobdam at: 2020-09-16 11:21:20

Wow - this is an EXTREMELY well made tutorial! Thanks a lot for the time and professionalism put into this - it made able to do something I thought was much, much harder - and indeed, it would've been (for me) if not for this tutorial.


Just a few sidenotes if any future visitors should encounter the same issues as me:


1) quota setup: My fstab file didn't look remotely like yours:

/dev/mapper/server1--vg-root / ext4 errors=remount-ro,usrjquota=quota.user,,jqfmt=vfsv0

Instead, mine was mapped with UUIDs. It now says:

UUID=62a4ff85-72b8-4b49-9aaa-e66f919b4b8d / ext4 usrjquota=quota.user,,jqfmt=vfsv0 0 0


2) In my case, ispconfig3 worked fine but I couldn't log in with admin/admin. So I entered mariadb and changed the password for the admin user:

Log on to the mariadb as root, enter password when prompted:

mysql -u root -p

Then enter the ispconfig db:


use dbispconfig;

Now update admin with the password admin:

UPDATE sys_user SET passwort = md5('admin') WHERE username = 'admin';

And write "quit" to exit, and now the login admin/admin works.

By: jakobdam at: 2020-09-17 10:41:38

Additional to my earlier comment; phpmyadmin didn't work for me. This was the solution in my case:

ln -s /etc/phpmyadmin/apache.conf/etc/apache2/conf-available/phpmyadmin.conf

a2enconf phpmyadmin

service apache2 restart

By: till at: 2020-09-17 11:00:01

@jakobdam The Reason that you were not able to access phpmyadmin is that you missed to enable it during installation. See screenshots in chapter 8, you must navigate to the apache config option using tab key and enable the apache option by using the space key on your keyboard, so that the * shows up in the option field. If you miss that, then phpmyadmin will not work and you'll have to enable it later manually.


Regarding ispconfig password, the password is what you see in the installer, it is not admin, unless you enter the word admin.


The fstab file is different depending on your base setup, so it's normal that it does not look exactly as in the guide. But there are unlimited possible alterations, so only one is shown in the guide.

By: aadursun at: 2020-09-18 13:49:38

where are the downloads, can't find links??

By: till at: 2020-09-18 13:56:48

This has been answered in the comments already, here again: The download link is in the menu on the right side of the page, near the top. Right below the big red download Icon.

By: Bob White at: 2020-09-23 02:57:54

I've been getting a lot of spam lately where the body of the message is base64 encoded. Once the body is decoded, it contains URLs that contain a server (e.g., What I would like to do is discard any message containing the text "hubspotfree".

I can add it to Postfix's "body_checks" file, but that requires putting it in three times because it's base4 encoded. I tried editing the Spamassassin config files in /etc/spamassassin, but that doesn't seem to have any effect - I expect because it's using amavis, not SA. I tried entering into ISPConfig - with /hubspotfree/ as the text to match and DISCARD as the action.  Still didn't catch a test message.

How is this supposed to work? Where do I put the stuff I want filtered or flagged as spam?



By: till at: 2020-09-23 05:40:09

@Bob: Please post support questions in the ISPConfig forum here at howtoforge.

By: Kart Mitchel at: 2020-09-23 07:56:20

Everything is excellent in the manual. some details like .. quota settings were not of major importance as well Errors were encountered while processing:


E: Sub-process / usr / bin / dpkg returned an error code (1)

fix it by removing # $ myhostname = "abc.def.ghi";

# Qualified Domain Name (FQDN) and remove the # at the beginning of the line.


#$ myhostname = "abc.def.ghi";

everything worked as expected ... thanks


By: till at: 2020-09-23 08:02:14

@Kart Michael: There is no need to edit that file, if amavis fails with this error, then it means that you did not configure the server hostname properly. As a wrong server hostname setup will give you more errors later when you start using the system, I highly recommend that you undo the change you made in the amavisd config file and instead fox your /etc/hostname file and server hostname, so that the command 'hostname -f' returns the correct FQDN hostname.

By: Maik Kramer at: 2020-09-24 07:45:47

Great tutorial. Everything is working fine, but I stuck for many days now with the mailserver. I made the installiation on Alibaba Cloud in Hong Kong and I can not send emails (250 authenification fail) and I do not recieve emails; permanent error (SMTP error from remote mail server after RCPT TO:<[email protected]>:  550 5.1.1 <[email protected]>: Recipient address rejected:  User unknown in local recipient table). It is the first time I have to set up a mailserver, an I thought it was done with this tutorial, but I see now thats not. May be someone can give me some links, topics or help what I still have to do, to get the mailserver working based on this tutorial. I read many other tutorial now and even one for Alibaba Cloud (How to Setup Email Server on Ubuntu 16.04 Alibaba ECS), but they all go different ways, from what I saw in this tutorial. thank you in advance

By: till at: 2020-09-24 07:49:21

@Maik: The mail server is completely set up when you finished this guide, you just have to add your domain and mailboxes in ISPConfig. It is good that you asked for help instead of following another guide as mixing guides is a guarantee that you will mess up your setup. Please post your problem in the ISPConfig forum here at howtoforge if you need further help.

By: Maik Kramer at: 2020-09-24 09:40:43

@Till: Thank you! Can it be possible, that I have a mix up with the IP addresses? I got 2 IP addresses from Alibaba Cloud: one they call internet IP and the other privat IP. Now I saw, that in ISPConfig under Server Config the used IP address is the privat IP and also under Sites/WebDomain it showed only the privat IP, which I used then, to save that site. Now, after I added in the DNS the Internet IP I can change under Sites/Webdomain to the internet IP, with the effect, that, if I go through the webbrowser to my site, it do not show the client side, but instead the index site under /var/www/html/. My question is, do the installation have to use the internet IP address or the privat IP address. One other thing I would like to ask you, because it is irritating for me. I have DNS Settings for the Domain in Alibaba Cloud under manage DNS and I have DNS Settings in ISPConfig. Do I have to make the same DNS settings in both, or only some in Alibaba DNS and the rest in ISPConfig. I hope the questions are not to basic or worse. I just need to know, where I have to look/search and I will get it working, but in the moment I am realy in the dark. Thank you, Maik

By: till at: 2020-09-24 11:29:18

@Maik: Please use the forum to ask for help. the comments section is not a good place to discuss individual setup questions. Thanks!

By: Goedendag at: 2020-09-25 18:02:09

Hi, I get the "SMTP Error (250): Authentication failed." when trying to send a mail via roundcube. Any ideas on how to fix this?

By: till at: 2020-09-25 18:06:31

@Goedendag: Please use the forum to ask for help. the comments section is not a good place to discuss individual setup questions. Thanks!

By: Ghostshell3301 at: 2020-09-29 17:33:50

It would be nice to add the correct username and password for the OVA root:howtoforge is not working !!!

By: till at: 2020-09-30 03:09:03

@Ghostshell3301: The correct username and password is mentioned in the tutorial already. The username is 'administrator' and the password is 'howtoforge'. As you might know, you can not login as root user on Ubuntu systems, you always use the username of a user with sudo privileges, in this case, the user 'administrator' to log in, then run 'sudo -s' to become root.

By: Ghostshell3301 at: 2020-09-30 07:13:39

@Till sorry I'm a (not) the RTFM dude ... So I used the pdf file with the download link :$ One must follow orders :) For only once I did read the RTFM and I'm awarded with this :p Problem solved (BTW I'm using the Perfect server from version Debian 6 until now with great pleasure and love the docs) KUDOS !

By: agustintommasi at: 2020-09-30 16:13:40

Hello, is there any way to put APS Installer in ISPConfig 3.2? 

By: till at: 2020-09-30 17:06:33, the source of APS packages, has been discontinued in 2019. And an application installer that has no recent packages to be installed anymore makes not much sense. That's why the APS installer is hidden in the menu, the code is still there in 3.2, but it makes not much sense to activate it.

By: Mark Rhyne at: 2020-10-03 21:44:31

Hi, I get the "SMTP Error (250): Authentication failed." when trying to send a mail via roundcube. Any ideas on how to fix this?

If you ran the update script this becomes an issue. In the Roundcube config file change the port back to 25 not 587 then it works again.

Maybe its fixed now, maybe my advise is bad but it worked for me.

By: Newland Futures at: 2020-10-05 01:03:38

Been using these tutorials for 15+ years.  A very long time.  Thank you again for the great work and easy installation.  Use this for a runbook and out the large number of servers I have installed using these tutorials only once or twice have I had issues.

I was able to download the nightly build, but the tar.gz file was corrupted and several files did not extract properly.  So I simply git cloned the repository and switched the branch to the 3.2b3 branch and off to the races.  Thanks!

By: decentris at: 2020-10-06 07:09:44

Hi Till,

I have to add to the praises of my predecessors. The new tutorial is again top, as we are used to from you and your team. I just have one question: When configuring the "postfix" - file, I stumbled upon a line "#  -o smtpd_tls_auth_only=yes" in the option-settings of

submission inet n - y - - smtpd

which is not displayed in the respective config example above. Is it save to keep this commented out or could it be a security improvement to activate "smtpd_tls_aut_only"?Thanks for your valued input.Best,Johannes

By: till at: 2020-10-06 07:52:38

Hello Johannes, it might indeed be better to activate that line to prevent users from sending AUTH details on submission port without TLS at all. There are (hopefully) no mail clients anymore today which have a problem with that setting. I'll update the tutorial and add that line.

By: aplusdesigners at: 2020-10-07 19:32:30

I LOVE this tutorial. It has been a few years since I setup my own server and this is just what the doctor ordered. One question though. My ISP blocks port 25 for mail sending, so how do we specify a port in the setup to send the mail? Thanks a bunch for such a well documented process.

By: till at: 2020-10-08 10:03:27

@aplusdesigners: You cans et the relay host in ISPConfig under System > server config. Append the port like this to the relay server name:




where 123 is the port.

By: Indar at: 2020-10-14 11:23:50

Hi Till,

Nice tutorial, but I got a problem with step-7 (install amavisd-new, SpamAssassin, and ClamAV). After executing the command (apt-get -y install amavisd-new spamassassin ...), I got error messages:

Setting up amavisd-new (1:2.11.0-6.1ubuntu1) ...Creating/updating amavis user account...Job for amavis.service failed because the control process exited with error code.See "systemctl status amavis.service" and "journalctl -xe" for details....Oct 14 11:06:03 pakcarik systemd[1]: Failed to start LSB: Starts amavisd-new mailfilter.dpkg: error processing package amavisd-new (--configure):  installed amavisd-new package post-installation script subprocess returned error exit status 1 ...

Errors were encountered while processing:    amavisd-new E: Sub-process /usr/bin/dpkg returned an error code (1)

I just ignored those errors, and continue the steps. When I tried to run the ClamAV by executing: freshclam 

then I got there errors:

ERROR: /var/log/clamav/freshclam.log is locked by another processERROR: Problem with internal logger (UpdateLogFile = /var/log/clamav/freshclam.log).ERROR: initialize: libfreshclam init failed.ERROR: Initialization error!

Did I miss something? I followed your tutorial carefully after a fresh install of Ubuntu 20.04 server. My server has an Intel i9-9900K with 64GB DDR4 and 2TB SSD. Any suggestion? Many thanks!

By: phanky5 at: 2020-10-18 22:06:18

Roundcube doesn't appear to be properly configured out of the box. IMAP and SMTP hosts are both configured as localhost. This causes issues with authentication. Localhost should be replaced with the fully qualified domain name of your email server in /etc/roundcube/ $config['default_host'] = 'tls://'; $config['smtp_server'] = 'tls://'; @till maybe you want to add this to the tutorial. I see a few people already ran into the same issue.

By: leonardo.saracini at: 2020-10-22 14:14:36

In section 7 before freshclam better do a

systemctl stop clamav-freshclam.service

By: TonyG at: 2020-10-22 23:00:31

Trivial typo:

"The MySQL root password that needs to be added is shown in read"

should be red.