4. Preliminary steps

by Cover Tower - Updated October 18, 2021

After you pay for the VPS or dedicated server, you will receive an email with your user (root) and your password, necessary to log in to your server via SSH. First of all, you should connect to your remote server and change the root password.

If you run Linux on your desktop/laptop (which we recommend), you can connect to the remote server using the terminal by running:

ssh root@123.123.123.123

then entering your root password (replace 123.123.123.123 with the public IP of your remote server).

Once connected to your remote server, change the root password by running:

passwd

You’ll be asked to enter the new password twice. The new password should be a mixture of about 14 characters: uppercase and lowercase letters, numbers and symbols.

4.1. Check IP reputation

Although in general, IPs of newly rented servers have good reputation, the first thing you should do after renting a server is to check its IP against the main public blacklists, by using this online tool: https://mxtoolbox.com/blacklists.aspx

You can also check if the IP of your server has been reported for malicious activities, on https://www.abuseipdb.com

If you find that your IP has been included on public blacklists or on abuseipdb.com, you should follow the steps described in the IP reputation chapter to delist your IP.

4.2. Configure the network interface

If your hosting provider offers specific information on how to configure your network interface on their official website, then follow their documentation. Otherwise, follow the steps from below.

First, update the package list and upgrade all the installed packages to their last version:

apt-get update
apt-get dist-upgrade

Then install net-tools:

apt-get install net-tools

Then run ifconfig to get the netmask and the broadcast address:

ifconfig

Sample output:

ens3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 123.123.123.123  netmask 255.255.255.0  broadcast 123.123.123.255
        inet6 fe80::5054:ff:fe95:7016  prefixlen 64  scopeid 0x20<link>
        inet6 2a04:9dc0:0:4:5054:ff:fe95:7016  prefixlen 64  scopeid 0x0<global>

Then find the default gateway:

route -n

Sample output:

Kernel IP routing table
Destination      Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0          123.123.123.1   0.0.0.0         UG    0      0        0 ens3
123.123.123.1    0.0.0.0         255.255.255.255 UH    0      0        0 ens3

The IP listed next to 0.0.0.0, namely 123.123.123.1 in this case, is the default gateway. Write down the interface name. Here it’s ens3.

Then make a backup copy of the /etc/network/interfaces file and open it for editing:

cd /etc/network
cp interfaces interfaces_orig
nano interfaces

Change the content of this file to make it look like this:

auto lo
iface lo inet loopback

auto ens3
# IPv4 configuration
iface ens3 inet static
address 123.123.123.123
netmask 255.255.255.0
gateway 123.123.123.1
broadcast 123.123.123.255

# IPv6 configuration
iface ens3 inet6 static
accept_ra 0
address 2B02:6BA0:62:250::9712
netmask 64
gateway 2B02:6BA0:62:250::1

Replace ens3 with the name of your network interface, replace 123.123.123.123 with your real IPv4 address, replace 123.123.123.1 with your real default gateway address, replace 255.255.255.0 with your netmask, replace 2B02:6BA0:62:250::9712 with your real IPv6 address.

If you have an OVH server, the /etc/network/interfaces file should look a bit different:

auto lo
iface lo inet loopback

# The primary network interface

# IPv4 configuration
auto ens3
iface ens3 inet static
address 123.123.123.123
netmask 255.255.255.255
gateway 123.123.123.1
broadcast 123.123.123.123

post-up route add 123.123.123.1 dev ens3
post-up route add default gw 123.123.123.1
post-down route del default gw 123.123.123.1
post-down route del 123.123.123.1 dev ens3

# IPv6 configuration
iface ens3 inet6 static
address 2B02:6BA0:62:250::9712
netmask 64

post-up /sbin/ip -f inet6 route add 2B05:6BD3:430:56::1 dev ens3
post-up /sbin/ip -f inet6 route add default via 2B05:6BD3:430:56::1
pre-down /sbin/ip -f inet6 route del 2B05:6BD3:430:56::1 dev ens3
pre-down /sbin/ip -f inet6 route del default via 2B05:6BD3:430:56::1

Replace ens3 with the name of your network interface, replace 123.123.123.123 with your real IPv4 address, replace 123.123.123.1 with your real default gateway address, replace 2B02:6BA0:62:250::9712 with your real IPv6 address.

If you bought an additional geolocated IP address, you should add the following lines right below the lines from above:

# Additional IP configuration
auto ens3:0
iface ens3:0 inet static
address 130.130.130.130
netmask 255.255.255.255
#broadcast 130.130.130.130

post-up /sbin/ifconfig ens3:0 130.130.130.130 netmask 255.255.255.255 broadcast 130.130.130.130
pre-down /sbin/ifconfig ens3:0 down

Change the IP addresses marked with red with your real addresses and ens3 with the real name of your network interface.

4.3. Change the network interface name if necessary

If the first line of the output of the ifconfig command looks like this:

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500

it means that your network interface name is eth0 and your server uses the old ‘persistent names’ scheme for naming network interfaces and not the new ‘predictable names’ scheme.

This article explains what are the predictable network interface names and why they were introduced.

If after upgrading certain packages and rebooting, the eth0 network interface will be renamed to ens3 or ens18 or something similar, this means that the ‘predictable network interface name’ has been applied automatically during the reboot and you will loose SSH access to your server. You’ll have to log in using the web console from your hosting admin panel and try to solve the problem. In order to prevent this from happening, you should change the network interface name in advance. First, find the new name for the eth0 interface by running the following command:

echo /sys/class/net/*

The result will look similar to this:

/sys/class/net/eth0 /sys/class/net/lo

For each device path (exept /sys/class/net/lo), ask udevadm what NET_IDs it knows, by running commands like:

udevadm test-builtin net_id /sys/class/net/eth0

The result can look like this:

Load module index
Network interface NamePolicy= disabled on kernel command line, ignoring.
Parsed configuration file /usr/lib/systemd/network/99-default.link
Created link configuration context.
Using default interface naming scheme 'v240'.
ID_NET_NAMING_SCHEME=v240
ID_NET_NAME_MAC=enx00163e819bec
ID_OUI_FROM_DATABASE=Xensource, Inc.
ID_NET_NAME_PATH=enp0s18
ID_NET_NAME_SLOT=ens18
Unload module index
Unloaded link configuration context.

In the output from above, the new network interface name will be that given by the ID_NET_NAME_SLOT parameter (in this case, ens18). So, write it down and proceed to changing eth0 to the new name, in the /etc/network/interfaces file. First make a copy of the original file:

cp /etc/network/interfaces /etc/network/interfaces_orig

Then open the file:

nano /etc/network/interfaces

Make its content look like this:

auto lo
iface lo inet loopback

auto ens18
# IPv4 configuration
iface ens18 inet static
address 123.123.123.123
netmask 255.255.255.0
gateway 123.123.123.1
broadcast 123.123.123.255

# IPv6 configuration
iface ens18 inet6 static
accept_ra 0
address 3A02:7AC0:0:2::5841
netmask 64
gateway 3A02:7AC0:0:2::1

Replace ens18 with the actual name of your interface, and all the IPv4 and IPv6 addresses with your actual IP addresses.

Although in a fresh installation it is less probable for eth0 to be hardcoded into other configuration files, if it is, it has to be changed there too. To find out where eth0 appears in configuration files, run:

rgrep eth0 /etc

If you find configuration files where eth0 appears on lines that are not commented out, you’ll have to change eth0 to the new interface name, ens18 in our example.

Next, make a copy of the /etc/default/grub file:

cp /etc/default/grub /etc/default/grub_orig

Open the /etc/default/grub file:

nano /etc/default/grub

Change this line:

GRUB_CMDLINE_LINUX="biosdevname=0 net.ifnames=0"

to this:

GRUB_CMDLINE_LINUX=""

Then update grub by running:

update-grub

Ensure that your hosting provider offers a web console that you can use to log in to your remote server in case after rebooting you won’t be able to access the server via SSH, then reboot the server:

reboot

4.4. Disable systemd networking

Since new versions of systemd have networking capabilities, it can happen that after a routine systemd upgrade followed by a reboot, you will loose SSH access to your server because of some automatic network configuration changes made by systemd. To avoid this situation, you can disable the networking capabilities of systemd, and use the ‘classic’ Debian networking. To disable systemd networking just run the following commands:

systemctl stop systemd-networkd.socket systemd-networkd systemd-networkd-wait-online
systemctl disable systemd-networkd.socket systemd-networkd systemd-networkd-wait-online
systemctl disable systemd-resolved.service

It’s recommended that you also review the /etc/resolv.conf file. First open it:

nano /etc/resolv.conf

If you have an OVH server, you will find the following content in this file:

domain openstacklocal
search openstacklocal
nameserver 213.186.33.99

If you don’t use an OVH server and the content of your /etc/resolv.conf file looks somewhat similar to that from above, you can leave it as it is. If, on the contrary, the content of your file looks like this:

nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 2001:4860:4860::8888
nameserver 2001:4860:4860::8844

you can comment out these DNS servers belonging to a well-known tech giant, by prepending the hash (#) to each line, then add the following IPs of the OpenDNS DNS servers:

nameserver 208.67.222.222
nameserver 208.67.220.220
nameserver 2620:119:35::35
nameserver 2620:119:53::53

4.5. Domain hosting strategy

You can host as many websites as you want on your server (obviously, you will have to take into consideration your server’s hardware specifications, an estimate of your website traffic, the number of users simultaneously connected to the hosted applications, when deciding how many websites you will host), but let’s say you want to host 5 websites:

www.example.com

www.secondsite.net

www.thirdsite.info

www.fourthsite.org

www.fifthsite.us

It’s recommended to choose one of the 5 websites as your main website, and its domain as your ‘main domain’. Let’s say you choose www.example.com as your main website. Thus, your main domain will be example.com . You can set mail.example.com as hostname for your server. mail.example.com will also be the fully qualified domain name (FQDN) of the server.

You can set up all the subdomains necessary to access the applications described in this guide, as subdomains of the main domain, example.com, like this:

mail.example.com as subdomain for Roundcube

lists.example.com for phpList

mailman.example.com for Mailman

doli.example.com for Dolibarr

cloud.example.com for Nextcloud

office.example.com for LibreOffice Online

roundpin.example.com for Roundpin

stats.example.com for Matomo

friendica.example.com for Friendica

forum.example.com for MyBB

4.6. Configure the hosts and the hostname

Make a copy of the original /etc/hosts file:

cp /etc/hosts /etc/hosts_orig

Open the /etc/hosts file:

nano /etc/hosts

Make it look like this:

127.0.0.1         localhost
123.123.123.123   mail.example.com

# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

were 123.123.123.123 is the public IPv4 address of your server and example.com is the main domain hosted on your server.

Also make a copy of and then open the /etc/hostname file:

cp /etc/hostname /etc/hostname_orig
nano /etc/hostname

Make it look like this:

mail.example.com

Next, regenerate the server’s default self-signed SSL certificate, so that it matches the new hostname:

apt-get install ssl-cert
make-ssl-cert generate-default-snakeoil --force-overwrite

If you use an OVH server, you will have to also edit the /etc/cloud/cloud.cfg file. First make a copy of the original file:

cp /etc/cloud/cloud.cfg /etc/cloud/cloud.cfg_orig

Then open the file:

nano /etc/cloud/cloud.cfg

Change the following two parameters to make them look like this:

preserve_hostname: true
manage_etc_hosts: false

Restart the server to make the changes take effect:

reboot

4.7. Add a new regular user to log in with, instead of root

Add a new user tom with /home/tom as home folder (replace tom with your desired name):

adduser tom

Install sudo:

apt-get install sudo

Add user tom to the sudo group:

nano /etc/sudoers

Search for the line:

root ALL=(ALL:ALL) ALL

below it add the following line:

tom ALL=(ALL:ALL) ALL

(replace tom with your chosen username)

4.8. Disable root login

First make a copy of the original /etc/ssh/sshd_config file:

cp /etc/ssh/sshd_config /etc/ssh/sshd_config_orig

Open the /etc/ssh/sshd_config file:

nano /etc/ssh/sshd_config

Change PermitRootLogin to no:

PermitRootLogin no

4.9. Change the default SSH port

While you have the /etc/ssh/sshd_config file open, change the default SSH port, which is 22 to a different port, like 6283, by editing the Port parameter like this:

Port 6283

Change the LogLevel parameter to VERBOSE, since it’s necessary for fail2ban to intercept brute-force attacks. Make it look like this:

LogLevel VERBOSE

If you want sshd to use both IPv4 and IPv6 you don’t have to do anything, because it uses both protocols by default. Yet it’s recommended to configure SSH to use only the IPv4 protocol, to increase security. To do that, edit the AddressFamily parameter as follows:

AddressFamily inet

If you had wanted to configure sshd to use only IPv6 you would have added the directive AddressFamily inet6 instead.

Reboot the server:

reboot

If you use Putty, configure it to be able to access the server on the new SSH port and with the new user, since root cannot be used to log in by SSH anymore.

Open Putty, select the saved session by clicking on it, click ‘Load’, then in the ‘Port’ field enter the custom SSH port that you have configured, 6283 in our example. Then, in the left panel click on Connection > Data and in the Auto-login username enter the name of the new user that you added, that you will use to log in by SSH, tom in our example, then click again on ‘Sessions’ and click on ‘Save’, otherwise all the settings will be lost. Then, you can click on ‘Open’ to open the session that you have just configured.

Next, install the following useful utilities:

apt-get install cron dialog apt-utils logrotate debian-keyring hdparm lshw less bzip2 zip unzip htop curl build-essential

Also install the kernel headers necessary for compiling software packages. First run the following command to see what kernel header is available for your current Linux kernel:

apt-cache search linux-headers-$(uname -r)

Sample output:

linux-headers-4.19.0-14-amd64 - Header files for Linux 4.19.0-14-amd64

Then install the kernel header that you have found:

apt-get update
apt-get install linux-headers-4.19.0-14-amd64

Check the content of the /etc/apt/sources.list file. It should look like this:

deb http://deb.debian.org/debian/ buster main
deb-src http://deb.debian.org/debian/ buster main

deb http://security.debian.org/debian-security buster/updates main
deb-src http://security.debian.org/debian-security buster/updates main

# buster-updates, previously known as 'volatile'
deb http://deb.debian.org/debian/ buster-updates main
deb-src http://deb.debian.org/debian/ buster-updates main

Then, for all the above changes to take effect, reboot:

reboot

After the reboot, log in again, this time by using the new SSH port and the newly added user with SSH access, since you can no longer log in as root.

4.10. Increase the swap space if needed

If your server has less than 4 GB of RAM, it’s recommended to have a total swap space of around 2 GB. Usually, servers with 1 GB, 2 GB, 3 GB of RAM are preconfigured by the hosting companies with a swap partition of 500 MB. This is not enough for memory hungry services like clamav-daemon. When updating the ClamAV virus definitions with the freshclam utility, clamav-daemon can get killed by the OOM (out of memory) killer, although 2 GB are enough for running all the applications described in this guide, including ClamAV. If clamav-daemon gets killed during updating the virus definitions, you will notice that you will be able to start clamav-daemon manually and it will function normally until the next update. This happens because 2 GB of RAM are enough for running ClamAV, but during updating the database of virus definitions the memory requirements increase suddenly and therefore, a swap space larger than 500 MB is needed.

You can easily create a swap file of 2 GB, which will have the same effect as a swap partition. To do so run:

fallocate -l 2G /swapfile

You can verify that the correct amount of space has been allocated by running:

ls -lh /swapfile

The output will be similar to:

-rw-r--r-- 1 root root 2.0G Oct 18 12:37 /swapfile

Set the right permissions, so that the file will be accessible to root only:

chmod 600 /swapfile

Next, mark the file as swap space by running:

mkswap /swapfile

Enable the swap file:

swapon /swapfile

Now, if you run:

swapon --show

The output will be similar to the following:

NAME      TYPE      SIZE   USED PRIO
/dev/sda2 partition 512M 256.9M   -2
/swapfile file        2G     0B   -3

So, apart from the preconfigured swap partition of 512 MB, there is a swap file of 2 GB.

To make the changes persist after reboot, you have to add the swap file to the /etc/fstab file. First make a backup copy of /etc/fstab:

cp /etc/fstab /etc/fstab_orig

Then open /etc/fstab for editing:

nano /etc/fstab

At the bottom of this file add the following line:

/swapfile swap swap defaults 0 0

Please note that /swapfile none swap defaults 0 0 will also work, because if the filesystem type is swap, the system will ignore the mountpoint field.

If you ever want to remove the swap file in order to create a larger one or for other reasons, you will have to first disable it with:

swapoff /swapfile

Then remove the file with:

rm /swapfile

Then remove the corresponding line (/swapfile swap swap defaults 0 0) from the /etc/fstab file.

4.11. Create the backups directory

You will need a directory to store all the backup archives that you will create before upgrading applications, as well as the periodic backups. Create that directory now by running:

mkdir /var/bm_archives

4.12. Adjust the server clock, if needed

To see if the server has the right time/time zone, run:

date

The right time/time zone is that of the physical location of the server. If you find a different time/time zone, or if you want it to be different, in order to match your physical location, you can change the time and time zone of the server and make the change persistent after reboot, even if the host physical machine of the VPS may have a different time/time zone than the VPS.

First, make a backup copy of /etc/localtime :

cp /etc/localtime /etc/localtime_orig

Then remove the localtime file:

rm /etc/localtime

To find the list of all the available time zone files run:

ls /usr/share/zoneinfo

Then make a symbolic link from the time zone file corresponding to your location, to the /etc/localtime file. Here it’s US, but it can be EST, CET, etc:

ln -s /usr/share/zoneinfo/US /etc/localtime

Check the current time with the date command. It should show the correct time and time zone.

If the current time is still wrong, set it to localtime with the following command:

hwclock --localtime -s

In this way the time will be adjusted from the hardware clock of the host machine, taking into consideration the time zone you have set earlier.

To test the VPS clock thoroughly, you need to poweroff the VPS and then start it again, from the web interface of your hosting provider. A simple reboot won’t be enough.

If you want to check the hardware clock of the host machine run:

hwclock --debug

If you want to set the time manually, to set the year, month and day in the format yyyy-mm-dd, run:

date -–set 2021-02-18

To set the hour, minute and second, run:

date -–set 17:32:28

To write the current time to the hardware clock, so that it will be remembered after reboot, run:

hwclock --systohc

You can also install ntp, to automatically synchronize system time with Internet time servers:

apt-get install ntp

To see the servers you are syncing with, run:

ntpq -p

4.13. Enable text color in terminal when connected to a remote Debian server

As explained before, you shouldn’t connect to a remote server via SSH as root. Nearly all the brute-force attacks will suppose the user is root. That is why the root login should be disabled. However, after you connect as a regular user, you should switch to the root user (by running su - then entering the root password), so as to have all the rights and be able to do anything you need, without loosing time writing sudo in front of every command. Good qulity Linux software is designed so that even if you install it as root, its process will run as a special user (like the user postfix for Postfix), and not as root; it will run as root only if that is really necessary. So, installing good qulity programs, such as those presented in this guide, as root, as the only user running commands on the server, won’t decrease the security of the system.

It is very useful to be able to distinguish between files and folders, and between different types of files, when seeing the content of a folder in command line. Unfortunately, a minimal installation of Debian doesn’t offer distinct colors for different types of files and for folders by default. They are all listed in the same color and you are left to wonder which are files and which are folders. To have different colors for folders and files follow these steps:

First make a copy of the original /root/.bashrc file:

cd /root
cp .bashrc .bashrc_orig

Delete all the content in this file:

cat /dev/null > .bashrc

Open the file:

nano .bashrc

Add the following content inside it:

# ~/.bashrc: executed by bash(1) for non-login shells.

# Note: PS1 and umask are already set in /etc/profile. You should not
# need this unless you want different defaults for root.
# PS1='${debian_chroot:+($debian_chroot)}\h:\w\$ '
# umask 022

# You may uncomment the following lines if you want `ls' to be colorized:
# export LS_OPTIONS='--color=auto'
# eval "`dircolors`"
# alias ls='ls $LS_OPTIONS'
# alias ll='ls $LS_OPTIONS -l'
# alias l='ls $LS_OPTIONS -lA'
#
# Some more alias to avoid making mistakes:
# alias rm='rm -i'
# alias cp='cp -i'
# alias mv='mv -i'

export PS1="\[$(tput setaf 1)\]\u\[$(tput setaf 3)\]@\[$(tput setaf 6)\]\h \[$(tput setaf 3)\]\w \[$(tput setaf 5)\]\\$ \[$(tput sgr0)\]"

umask 022

if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
    . /etc/bash_completion
fi

# You may uncomment the following lines if you want `ls' to be colorized:
export LS_OPTIONS='--color=auto'
eval `dircolors`
alias ls='ls $LS_OPTIONS'
alias ll='ls $LS_OPTIONS -l'
alias l='ls $LS_OPTIONS -la'
alias ..='cd ..'

# Some more alias to avoid making mistakes:
# alias rm='rm -i'
# alias cp='cp -i'
# alias mv='mv -i'

if ! shopt -oq posix; then
  if [ -f /usr/share/bash-completion/bash_completion ]; then
    . /usr/share/bash-completion/bash_completion
  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi

Restart the server:

reboot
You can send your questions and comments to: