Set-up a hardened Linux server
by Alex Arica

In this blog post we are going to go through the minimum steps to set-up a hardened linux server.

Configure the root user

Once the server is installed, we can define a password for the root user, as follows:

sudo passwd

Then become root:

su -

Disable the root user's bash history:

echo "HISTFILESIZE=0" >> ~/.bashrc
source ~/.bashrc
history -c

Configure timezone

timedatectl set-timezone Europe/London

Update packages

apt-get update
apt-get dist-upgrade
apt autoremove

If any package was installed as a result of the command "dist-upgrade", it is usually required to reboot the server.

Create a custom user

It is not recommended to directly use the root user. We are going to create a custom user named "alex" and assign to it the sudo permission (sudoer) so that it can escalates as root only when required.

Create user "alex":

adduser alex

Add user as sudoer:

usermod -aG sudo alex

Check the user is a sudoer. The following should display “sudo” among the groups:

groups alex

Test sudo works:

su - alex
sudo apt-get update

If the above works, exit and login via SSH as "alex" to test this user can login via SSH:

ssh alex@[server ip]

Disable the bash history for alex:

echo "HISTFILESIZE=0" >> ~/.bashrc
source ~/.bashrc
history -c

User created by the hosting provider

When a server is installed by a hosting company, they may create a custom user allowing to login the first time. For example, the hosting company OVH creates a user based on the installed linux distribution (e.g. user "ubuntu"). Now we have created our own custom user ("alex"), we can remove the user created by the hosting company.

sudo deluser [username created by hosting company] --remove-home

Note: On Debian the option "--remove-home" does not work without perl. In that case, if we do not want to install perl, please delete the user's home folder manually:

sudo rm -fr /home/[username created by hosting company]

Check the home folder was deleted for [username created by hosting company]:

ls -al /home/

Login to the server using a SSH key

First, exit the server:


If we do not have a SSH key, we are going to create it on the client computer (your laptop or desktop computer). When creating it, it is highly recommended to set a passphrase for additional security.

Create a SSH key on the client computer:

ssh-keygen -t rsa

The generated key should be in the folder “~/.ssh/”

Copy the created SSH public key from the client computer to the server:

ssh-copy-id -i ~/.ssh/ alex@[server ip]

Login to the server to check it is working:

ssh alex@[server ip]

If it works, it should not ask for a password. If you have set a passphrase when creating the SSH key then it will ask for it.

Disable SSH login with password

We assume that you are logged to the server as a custom user (e.g. "alex").


sudo vi /etc/ssh/sshd_config

Set the following options’ values to “no”:

  • PasswordAuthentication: no
  • ChallengeResponseAuthentication: no
  • PermitRootLogin: no
  • UsePAM: no

Add this line to only allow a custom user (e.g. "alex") to login via SSH:

AllowUsers alex

Save the file.

Check all values:

cat /etc/ssh/sshd_config | grep PasswordAuthentication
cat /etc/ssh/sshd_config | grep ChallengeResponseAuthentication
cat /etc/ssh/sshd_config | grep PermitRootLogin
cat /etc/ssh/sshd_config | grep UsePAM
cat /etc/ssh/sshd_config | grep AllowUsers

Restart SSHD daemon

sudo systemctl restart sshd

In case of there is an issue with the config changes, do not close the current terminal window. Open a new terminal window and try connecting, as follows:

ssh alex@[server ip]

If it is working, we can close the old terminal window. If it does not work, then use the old terminal window to check the contents of the file "/etc/ssh/sshd_config" in order to identify where the error could be.

Enable auto-updates of packages

Auto-updates allow keeping a server's packages automatically up-to-date. Please follow the instructions here.

Remove known insecure packages

Remove insecure services like Mail service, Telnet service, RSH service, NIS service, TFTP service and TALK service:

sudo apt-get --purge remove xinetd nis yp-tools tftpd atftpd tftpd-hpa telnetd rsh-server rsh-redone-server

Check ports listened by internal services with "lsof"

On Debian you may have to install lsof, as follows:

sudo apt-get install lsof

List the ports listened by internal services:

sudo lsof -i | grep LISTEN

The output should only show the SSHD daemon listening to external traffic on port 22. If there are other ports opened, and if they are unwanted, please remove the packages the services(s) depend on.

For example, with the command "lsof" we noticed that on a Debian distro the SMTP service "Exim" is installed and running by default and it is listening on port 25. If we want to remove this service, we need to find the list of packages it is depending on:

dpkg -l | grep exim

Output example:

exim4-base            4.94-15    amd64        support files for all Exim MTA (v4) packages
exim4-config          4.94-15    all          configuration for the Exim MTA (v4)
exim4-daemon-light    4.94-15    amd64        lightweight Exim MTA (v4) daemon

Let's remove those packages:

sudo apt-get purge exim4-base exim4-config exim4-daemon-light

Once completed, we can also remove the obsolete packages which were installed with the removed packages above:

sudo apt-get autoremove


Once all sections above are completed, you have a minimum hardened set-up for a Linux server.

Additional actions to consider

Disabling Root Cron Jobs

List cron jobs:

sudo ls /etc/cron*

Then go to the listed file(s) to remove the app which is unwanted. For example, we can remove "bsdmainutils":

sudo apt-get purge bsdmainutils

List services and stop the ones we do not want to use

List services:

sudo service --status-all
sudo systemctl list-unit-files --state=enabled

Get info about a service:

sudo systemctl status sendmail

Disable a service

sudo systemctl disable sendmail