The Problem
If you grew out of your shared hosting or you need special softwares to install sooner or later you will think about to move to a private server. With a VPS you will have all the freedom you will need. Shared hosting always has limitations and you have to make compromises. With VPS you can install any software you want but you will be responsible for your server. So you will have more freedom but you will have more job to be done. A well configured server needs less job in the future and doesn’t need daily administration.
So, let’s say you decided to buy a VPS and you have chosen your hosting provider.
In most cases if you buy a VPS you will be given an IP address, a root username and a password and that’s all. Your VPS is only protected by a password out of the box, we can say it’s not too safe.
I have a VPS
Okay, let’s try out our credentials:
ssh [username]@[ipaddress]
The command above will work on Mac and Linux. On Windows ssh is included in PowerShell. On Windows you should also try out WSL. With WSL you can install a Linux running on the top of your Windows. Alternatively you can use https://www.putty.org/[Putty] to login to your VPS.
The first you should do is to update your Ubuntu installation:
sudo apt update
sudo apt upgrade
shutdown -r now
Login with root user is absolutely against security advices. We will deny root user login later on. Let’s create a new user we will use in the future.
adduser sharpbraces
usermod -aG sudo sharpbraces
The first command will create our new user named ‘sharpbraces’. The second command will add our new user to sudoers group. It means this user will be able to use ‘sudo’ command.
Let’s try to login with our new user.
ssh sharpbraces@[ipaddress]
SSH
We have a new user but it’s not perfect because we have to use a password to login. Let’s make the security one step further. We setup an SSH key. On our machine run the command below.
ssh-keygen -t rsa -b 4096 -C "sharpbraces@sharpbraces.com"
This command has to be run on our computer not on the VPS!
What it does is to generate a new SSH key. SSH keys have a public and a private part. The public part will be on our VPS, the private part will be on our computer. In default it’s located in our user’s .ssh folder.
It will ask for a password which you can leave blank. It will also ask for a filename. Filename should be something that can identify the server. In the future if you will have more VPS you should recognize them from the filename.
So now we have our new random SSH key, let’s upload the public part to the server.
ssh-copy-id -i /home/sharpbraces/.ssh/sharpbraces.pub sharpbraces@[ipaddress]
You will be asked for your user’s password. It has to be the password of the user on the VPS!
You should see something like this:
Number of key(s) added: 1
Let’s try to login with our new SSH key.
ssh sharpbraces@[ipaddress]
If everything is fine then you could login without password.
We are close but we need some further steps to make our server more secure. First of all we will disable the root login. Next we will modify the SSH service default port (22). And finally we will disable the password authentication.
If you couldn’t login without password in the previous step then something is not right so don’t go further because you will lock out yourself from your VPS.
So, let’s edit some SSH config.
sudo nano /etc/ssh/sshd_config
The first thing is the port. The default value is 22 and that is where bots are looking for it in the first place. Let’s modify this whatever value you want. For example let it be 65222.
Next thing is to disable root login. Find the property PermitRootLogin and change it to `no`.
Okay, finally disable password authentication with setting PasswordAuthentication and PermitEmptyPasswords to `no`.
In summary we made these changes in our SSH config:
Port 65222
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
Save the file and exit `nano`. Now it’s time to make are changes to take effect.
sudo service ssh restart
Logout from your VPS and try to login again. If everything is fine then you won’t be able to login with the command used previously. The reason is we modified the default port so we have to specify our new port when connecting.
ssh sharpbraces@[ipaddress] -p 65222
This command is long and ugly, we don’t want to type every time we login. Let’s make it simple!
In your user’s folder (not on the VPS!) there should be a .ssh folder (this is the place where your public and private keys were generated to). Create a file here named ‘config’ or if it’s already exists just append to it:
Host sharpbraces-vps
Hostname [ipaddress]
User sharpbraces
Port 65222
IdentityFile ~/.ssh/sharpbraces
From now if you want to login to your server you can use sharpbraces-vps alias and no need to type all the other stuff. Just try it.
ssh sharpbraces-vps
Other advantage is when you want to use SFTP to copy files between your computer and VPS or any other program that relies on SSH connection then this alias can be used. Never need to type username, password or port again.
Our login is safe and secure now but there are other things to be done.
UFW
UFW stands for Uncomplicated Firewall. It’s the default firewall configuration tool on Ubuntu. By default firewall is turned off. If it’s not installed for some reason you can install it by
sudo apt install ufw
Next check whether IPV6 is enabled or not. Open up the configuration.
sudo nano /etc/default/ufw
If IPV6 is not enabled then just enable it.
IPV6=yes
sudo ufw status verbosesudo ufw default deny incomingsudo ufw default allow outgoingsudo ufw allow 52222/tcpsudo ufw allow 80/tcpsudo ufw allow 443/tcpsudo ufw enable
1. Check the status of the firewall. By default it should be inactive.
2. By default we deny all incoming connections.
3. We allow all outgoing connections.
4. It’s very important to enable incoming connections on our SSH port. If you forget it you will be locked out from your VPS.
5. We allow incoming connections on port 80. This port is responsible for HTTP connections by default. If you will serve web pages or web applications you will have to open this port.
6. We allow incoming connections on port 443. This is the port for HTTPS connections. Nowadays most of the webpages requires HTTPS, it should be opened.
7. After configuring the firewall we simply enable it.
Try to logout and login again.
Fail2Ban
As your SSH port is exposed to the Internet we should protect it from unattended access. Fail2Ban is a tool that will block the remote IP address after predefined number of unsuccessful login attempts.
You can simply install it using apt.
sudo apt install fail2ban
The Fail2Ban config file can be found under /etc/fail2ban/jail.conf. If you want to make any changes to this configuration it’s highly recommended to make a copy of this file and use that to override default config.
cp /etc/fail2ban/fail2ban.conf /etc/fail2ban/fail2ban.local
You can use the default config as it is. If you want you can configure after how many attempts will IP banned, for how long and you can also setup an email alert if an IP is banned. After installation just enable and start out fail2ban service.
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo systemctl status fail2ban
Automatic updates
To improve security you can enable your Ubuntu installation to update automatically. The package which will allow this is called unattended-upgrades.
sudo apt install unattended-upgrades
sudo apt install update-notifier-common
After installation the service should start automatically. You can check it.
sudo systemctl status unattended-upgrades
In the next step we will configure what packages to update automatically and which packages to skip while updating. We can configure our updates via
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
By default only security updates will be installed automatically. You can specify which packages you want to be updated and which ones are blacklisted and will be ignored in the update process. For example to prevent version change problems with mariadb you can simply ignore mariadb package.
Unattended-Upgrade::Package-Blacklist {
mariadb
If you want to receive notifications about automatic updates find and uncomment the following line.
Unattended-Upgrade::Mail "notifications@sharpbraces.com ";
After an update sometimes it’s neccessary to restart your VPS, for example kernel updates to take affect.
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-WithUsers "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";
First we enable automatic reboot. Second we enable the reboot even while users are logged in to our VPS. In the last line we specify when to perform the reboot after updates.
All configs have a great documentation in comments so you can find what you need.
After installation and configuration all we have to do is to enable automatic updates.
sudo nano /etc/apt/apt.conf.d/20auto-upgrades
The file should look like this:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
Automatically clear journal logs
The last thing we will setup is to delete all log files. This process also should be automatic so we will use “cron“ to do the job for us.
Cron is a utility to schedule jobs, let us to run scripts periodically at fixed times, dates, or intervals.
To create our first cron job type
sudo crontab -e
This will open our cron. Just append this line to the file:
@daily journalctl --vacuum-time=3d
This will remove log files older than 3 days.
Congratulations
You have your VPS configured and secured, the only thing left is to develop awesome web applications or services to show them to the world! Great job, keep it up!