Securing Your Web Server on a VPS: A Step-by-Step Guide

This post is free for all to read thanks to the investment Mindsers Courses members have made in our independent publication. If this work is meaningful to you, I invite you to join our courses today.

There are several reasons why a developer would want to manage their own servers. Servers, especially VPS (Virtual Private Server), have become very affordable resources. They allow us to test, build, host our projects and do many other things.

Whatever use you make of a server, it must be protected, because an intrusion could have serious repercussions. In this article, I explain how to secure a VPS simply in 5 simple steps.

☝️
I assume that you have just purchased your VPS and that you have never connected to it before. But, most of the steps are feasible on an already running server.

1/ Update your system

This may sound basic to you, but one of the primary reasons for finding flaws in web servers is system obsolescence. Not updating your systems regularly is a real danger for your business.

Even if you have just requested the installation of your VPS from your host, you will benefit from updating your system before moving on to the rest of this article. Indeed, hosts often use backups or snapshots to create new servers. So, there is a good chance that the packages on your system need updates.

Run the following commands:

$ sudo apt update
$ sudo apt upgrade -y

2/ Change root password

I'm not sure it's worth explaining. Change your root password.

$ sudo su
$ passwd
New password: 
Retype new password: 
passwd: password updated successfully
$ exit

The root account is the “super-administrator” account. He has all the rights. If there is an account that we refuse to leave in the hands of hackers, it is this one.

But changing the root account password is not enough. You will see that a little further in the rest of the article.

3/ Create a new user

Another tip to avoid problems on your server: don't use root. I see at least two reasons for this:

  • everyone has a root user on their machine by default. It's easy for a hacker to guess
  • root has all rights on the machine. If a person finds the root account password, he can do anything on the machine
☝️
Some hosts, to limit this problem, change the name of the root account. Don't think you're protected, though! As explained above, because of the automation of their process, they often give the same names to all customers. It is therefore enough to know who your host is to know how it works, and therefore to know how to attack your machine.

The best solution to prevent this problem is to use a different account to manage your machine. To do this, use the following command:

$ adduser nameOfTheUser
Adding user `nameOfTheUser' ...
Adding new group `nameOfTheUser' (1001) ...
Adding new user `nameOfTheUser' (1001) with group `nameOfTheUser' ...
Creating home directory `/home/nameOfTheUser' ...
Copying files from `/etc/skel' ...
New password: 
Retype new password: 
passwd: password updated successfully
Changing the user information for nameOfTheUser
Enter the new value, or press ENTER for the default
        Full Name []:
        Room Number []: 
        Work Phone []: 
        Home Phone []: 
        Other []:
Is the information correct? [Y/n]

After answering all the questions of the utility, let's tell the system that this new user will be able to perform actions usually dedicated to the superuser without being one.

The idea is to be able to say “I'm not a superuser, give me no rights” but temporarily, when the situation requires it, tell the system “in fact, I'm the superuser, let me do this one-time action”.

$ adduser nameOfTheUser sudo
sudo adduser nameOfTheUser sudo
Adding user `nameOfTheUser' to group `sudo' ...
Adding user nameOfTheUser to group sudo
Done.

Now you will be able to type the sudo command from your new user account without receiving a system denial. You can also connect in SSH directly with this user.

4/ Change SSH access

Now that only you know the password for the root account, and you no longer use it to connect to the server, it's time to go a little further.

What are the problems we might encounter? Brute force attack. You no longer use the root account, but it is still usable. Using randomly generated passwords until one works is a method that still works today.

The method would also work on the second account that we created above.

To remedy this, we'll modify the SSH configuration somewhat to log in using an RSA key rather than a password. To be able to log in with a key, you first need... a key.

So let's generate ours on our local computer (not the server).

$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
  • -t allows you to indicate the type of key you want to create. We want an RSA key.
  • -b specifies the size of the key. I usually put 4096 so that it is twice as long, complex and solid as the default 2048 bites. But, you can put the size you want. Just tell yourself that depending on the power of your computer, the more you ask for a long key, the longer it will take to generate (and use?) it.
  • -C allows you to add a comment to facilitate your organization.

The command will ask you for a passphrase. It is a sentence that must be indicated to use the key. A kind of password to protect the key. You can leave it out, but it is strongly recommended that you do put one.

Once the key is generated, you will find two new files on your local machine.

$ ls ~/.ssh
id_rsa    id_rsa.pub
  • id_rsa is your private key. Not to be communicated under any circumstances. It must not leave your machine and allows you to decrypt the data that is sent to you.
  • id_rsa.pub is the public version of your key. To communicate to those with whom you wish to communicate. It does not make it possible to decrypt the data, but only to encrypt them. In other words, it allows people to write messages that only your private key can decrypt.

As I just said, the private key will not move from your machine. However, to be able to communicate with the server, the server must have your public key. So, we have to send it to him.

No need to open the file and copy-paste anything, there's a command for that:

$ ssh-copy-id -i ~/.ssh/id_rsa nameOfTheUser@ipOfTheServer

This command will create the ~/.ssh folder in your user's account on the server. Then, it will create the file ~/ssh/authorized_keys in which it will add the public key linked to the private key id_rsa.

Normally, this command sends all public keys from your local machine to the server. To avoid this, we use -i to tell it which key to send.

You can now connect without passwords to the server by doing ssh nameOfTheUser@ipOfTheServer. Only the passphrase will be requested if you have specified one.

Since it is possible to log in without passwords, all we have to do is disable the login with passwords. Thus, the risk of brute force will be eliminated. To do this, on the server, edit the following lines in the /etc/ssh/sshd_config file to have these values:

PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no

With these settings, it will be impossible to log in with the root account whether you know the password or not. All other accounts will be inaccessible with a password, but accessible if you have the correct RSA key.

Last detail, the standard port used by SSH is 22. It means that everyone knows this port. To make the access a little more complicated, a good practice is to change this port to a value between 1024 and 6665.

In the same /etc/ssh/sshd_config file, modify the following line with the value of your choice:

Port 5489

To validate these changes, restart the SSH agent as follows:

$ sudo systemctl restart ssh

Your server now looks a bit more like a fortress. ssh nameOfTheUser@ipOfTheServer will no longer work. You will need, in addition to the user and the IP, to indicate the port that you have chosen previously. The password will not be requested, you will need the RSA key to be able to connect.

$ ssh nameOfTheUser@ipOfTheServer -p 2345 -i ~/.ssh/id_rsa 
Enter passphrase for key '~/.ssh/id_rsa':
☝️
I agree that for greater security, we have largely sacrificed the simplicity and usability of this command. But, it is possible to simplify it again thanks to the file ~/.ssh/config.

5/ Enable a firewall

The firewall allows you to control who can connect to your server and how. The idea is to avoid leaving windows open in our fortress. We will therefore explicitly specify what we allow as a connection to our server.

Most Linux distributions have iptables and ufw installed by default. I use UFW. I will therefore explain to you the basic rules that I apply for the security of my servers. To learn more about how this tool works, I recommend this article from DigitalOcean.

We start by disabling the firewall while we make our changes:

$ sudo ufw disable

Next, I change the default rules so that all incoming connections are denied, and all outgoing connections are allowed:

$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing

Next, we'll allow SSH connections. Otherwise, we will no longer have a way to connect to the server.

$ sudo ufw allow 2345/tcp

Change 2345 to the port you chose for SSH in the previous step.

⚠️
UFW knows the default ports for services and offers helpers like ufw allow ssh. But don't use it for SSH precisely, because you no longer use the default port 22. You risk blocking all SSH connections since SSH no longer listens to port 22.

Now we can activate the firewall.

$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

As we no longer use the default SSH port, if you still have connections using port 22 (on another terminal, for example), UFW warns you that you may lose your connection.

☝️
You can verify that your rules are correct before activating the firewall using the ufw status verbose command.

Now you have all the basics to secure your servers. There are of course many other things that one can implement to secure a server, but with the 5 steps in this article, you will have a server that is much less vulnerable to attacks.

I have also prepared for those who wish it a print which includes all the commands of this article, a glossary and an explanation of the changes of the sshd_config file. Nothing more than what is in this article, but the idea is to have a cheat sheet to quickly secure your server.

If you are a premium member of the club, log in and download it there. Otherwise, you can find “VPS/server security cheatsheet” on the store to buy it without becoming a member :

The French version of the PDF can be found on the shop or at the bottom of the French article.

Join 250+ developers and get notified every month about new content on the blog.

No spam ever. Unsubscribe in a single click at any time.

If you have any questions or advices, please create a comment below! I'll be really glad to read you. Also if you like this post, don't forget to share it with your friends. It helps a lot!