The Perfect Server - Debian 10 (Buster) with Apache, BIND, Dovecot, PureFTPD and ISPConfig 3.2
This tutorial shows how to prepare a Debian 10 server (with Apache2, BIND, Dovecot) for the installation of ISPConfig 3.2, and how to install ISPConfig. The web hosting control panel ISPConfig 3 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, MySQL, BIND or MyDNS nameserver, PureFTPd, SpamAssassin, ClamAV, and many more. This setup covers Apache (instead of nginx), BIND, and Dovecot.
1 Preliminary Note
In this tutorial, I will use the hostname server1.example.com with the IP address 192.168.0.100 and the gateway 192.168.0.1. These settings might differ for you, so you have to replace them where appropriate. Before proceeding further you need to have a minimal installation of Debian 10. This might be a Debian minimal image from your Hosting provider or you use the Minimal Debian Server tutorial to set up the base system.
All commands below are run as root user. Either log in as root user directly or log in as your normal user and then use the command
su -
to become root user on your server before you proceed. IMPORTANT: You must use 'su -' and not just 'su', otherwise your PATH variable is set wrong by Debian.
2 Install the SSH server (Optional)
If you did not install the OpenSSH server during the system installation, you can do it now:
apt-get install ssh openssh-server
From now on you can use an SSH client such as PuTTY and connect from your workstation to your Debian 9 server and follow the remaining steps from this tutorial.
3 Install a shell text editor (Optional)
We will use nano text editor in this tutorial. Some users prefer the classic vi editor, therefore we will install both editors here. The default vi program has some strange behavior on Debian and Ubuntu; to fix this, we install vim-nox:
apt-get install nano vim-nox
If vi is your favorite editor, then replace nano with vi in the following commands to edit files.
4 Configure the Hostname
The hostname of your server should be a subdomain like "server1.example.com". Do not use a domain name without subdomain part like "example.com" as hostname as this will cause problems later with your mail setup. First, you should check the hostname in /etc/hosts and change it when necessary. The line should be: "IP Address - space - full hostname incl. domain - space - subdomain part". For our hostname server1.example.com, the file shall look like this:
nano /etc/hosts
127.0.0.1 localhost.localdomain localhost 192.168.0.100 server1.example.com server1 # The following lines are desirable for IPv6 capable hosts ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters
Then edit the /etc/hostname file:
nano /etc/hostname
It shall contain only the subdomain part, in our case:
server1
Finally, reboot the server to apply the change:
systemctl reboot
Log in again and check if the hostname is correct now with these commands:
hostname
hostname -f
The output shall be like this:
root@server1:/tmp# hostname
server1
root@server1:/tmp# hostname -f
server1.example.com
5 Update your Debian Installation
First, make sure that your /etc/apt/sources.list contains the buster/updates repository (this makes sure you always get the newest security updates), and that the contrib and non-free repositories are enabled as some required packages are not in the main repository.
nano /etc/apt/sources.list
deb http://deb.debian.org/debian/ buster main contrib non-free
deb-src http://deb.debian.org/debian/ buster main contrib non-free
deb http://security.debian.org/debian-security buster/updates main contrib non-free
deb-src http://security.debian.org/debian-security buster/updates main contrib non-free
Run:
apt-get update
To update the apt package database
apt-get upgrade
and to install the latest updates (if there are any).
6. 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.
7 Synchronize the System Clock
It is a good idea to synchronize the system clock with an NTP (network time protocol) server over the Internet. Simply run
apt-get -y install ntp
and your system time will always be in sync.
8 Install Postfix, Dovecot, MariaDB, rkhunter, and Binutils
We can install Postfix, Dovecot, MariaDB as MySQL alternative, 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 dovecot-lmtpd sudo curl
You will be asked the following questions:
General type of mail configuration: <-- Internet Site
System mail name: <-- server1.example.com
To secure the MariaDB installation and to disable the test database, run this command:
mysql_secure_installation
Answer the questions as follows:
Change the root password? [Y/n] <-- y
New password: <-- Enter a new MariaDB root password
Re-enter new password: <-- Repeat the MariaDB root password
Remove anonymous users? [Y/n] <-- y
Disallow root login remotely? [Y/n] <-- y
Remove test database and access to it? [Y/n] <-- y
Reload privilege tables now? [Y/n] <-- y
Next, open the TLS/SSL and submission ports in Postfix:
nano /etc/postfix/master.cf
Uncomment the submission and smtps sections as follows and add lines where necessary so that this section of the master.cf file looks exactly like the one below. IMPORTANT: Remove the # in front of the lines that start with smtps and submission too and not just from the -o lines after these lines!
[...] submission inet n - - - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-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=
# -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
smtps inet n - - - - 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=
# -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING [...]
Restart Postfix afterwards:
systemctl restart postfix
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 = 127.0.0.1 by adding a # in front of it.
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 = 127.0.0.1
[...]
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 the word 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".
# Automatically generated for Debian scripts. DO NOT TOUCH!
[client]
host = localhost
user = root
password = howtoforge
socket = /var/run/mysqld/mysqld.sock
[mysql_upgrade]
host = localhost
user = root
password = howtoforge
socket = /var/run/mysqld/mysqld.sock
basedir = /usr
To prevent the error 'Error in accept: Too many open files' we will set higher open file limits for MariaDB now.
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 -p /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:
[Service]
LimitNOFILE=infinity
Save the file and close the nano editor.
Then we reload systemd and restart MariaDB:
systemctl daemon-reload
systemctl restart mariadb
Now check that networking is enabled. Run
netstat -tap | grep mysql
The output should look like this:
root@server1:/home/administrator# netstat -tap | grep mysql
tcp6 0 0 [::]:mysql [::]:* LISTEN 16623/mysqld
9 Install Amavisd-new, SpamAssassin, and ClamAV
To install amavisd-new, SpamAssassin and ClamAV, we run
apt-get install amavisd-new spamassassin clamav clamav-daemon unzip bzip2 arj nomarch lzop cabextract p7zip p7zip-full unrar lrzip 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 libdbd-mysql-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:
systemctl stop spamassassin
systemctl disable spamassassin
10 Install Apache Web Server and PHP
Apache2, PHP, FCGI, suExec, Pear, and mcrypt can be installed as follows:
apt-get -y install apache2 apache2-doc apache2-utils libapache2-mod-php php7.3 php7.3-common php7.3-gd php7.3-mysql php7.3-imap php7.3-cli php7.3-cgi libapache2-mod-fcgid apache2-suexec-pristine php-pear mcrypt imagemagick libruby libapache2-mod-python php7.3-curl php7.3-intl php7.3-pspell php7.3-recode php7.3-sqlite3 php7.3-tidy php7.3-xmlrpc php7.3-xsl memcached php-memcache php-imagick php-gettext php7.3-zip php7.3-mbstring memcached libapache2-mod-passenger php7.3-soap php7.3-fpm php7.3-opcache php-apcu libapache2-reload-perl
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 actions proxy_fcgi alias
To ensure that the server cannot be attacked through the HTTPOXY vulnerability, we will disable the HTTP_PROXY header in apache globally by adding the configuration file /etc/apache2/conf-available/httpoxy.conf.
Note: The vulnerability is named httpoxy (without 'r') and therefore the file where we add the config to prevent it is named httpoxy.conf and not httproxy.conf, so there is no 'r' missing in the filename.
nano /etc/apache2/conf-available/httpoxy.conf
Paste the following content to the file:
<IfModule mod_headers.c>
RequestHeader unset Proxy early
</IfModule>
And enable the module by running:
a2enconf httpoxy
systemctl restart apache2
11 Install Let's Encrypt
ISPConfig is using acme.sh now as Let's Encrypt client. Install acme.sh using the following command:
curl https://get.acme.sh | sh -s
12 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
root@server1:~# 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
root@server1:~#
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"
Run:
newaliases
and restart Postfix:
systemctl restart postfix
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 http://server1.example.com/cgi-bin/mailman/admin/, and the web page for users of a mailing list can be found at http://server1.example.com/cgi-bin/mailman/listinfo/.
Under http://server1.example.com/pipermail you can find the mailing list archives.
Restart Apache afterwards:
systemctl restart apache2
Then start the Mailman daemon:
systemctl restart mailman
13 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:
[...] STANDALONE_OR_INETD=standalone [...] VIRTUALCHROOT=true [...]
Now we configure PureFTPd to allow FTP and TLS sessions. FTP is a very insecu