Server security doesn't have to be complicated. This guide covers five essential steps to protect your cloud server from common threats and attacks. We'll walk through setting up firewalls, implementing fail2ban, configuring backups, and more.
I will use a Hetzner server for this tutorial, but the steps are similar for other providers. If you do not have a Hetzner Account yet, feel free to sign up with my referral link to get 20€ credits for free.
Let's make sure that you will not land in the news for being hacked! 😤
1. Firewall
The first thing you should always do when creating a new cloud server is creating a firewall. A firewall controls incoming and outgoing network requests to/from your server. For example, a firewall could be configured in such a way that your server has no access to the internet or that only a specific IP Address can reach your server.
The actual configuration of the firewall depends on the applications that you are running on your server. If you are running a simple website you usually have these requirements:
- Everyone can reach the website through HTTP or HTTPS
- The Server has full access to the internet
The first requirement is about "incoming" (or inbound) traffic. In other words, any IP address (IPv4 or IPv6) can reach your server at the ports 80 (http) and 443 (https).
In the Hetzner Dashboard it would look something like this:
Note: You would probably also want to allow SSH connections from only your IP. For this, figure out your IP address and then add an incoming rule for only this IP to TCP/22!
Our second requirement, that the server can access anything, is usually the default. In Hetzner you would not need to change anything:
2. Fail2Ban
Fail2ban is like a security guard for your server. It watches for anyone trying to break into your system by guessing passwords over and over. When it sees too many wrong guesses from a particular place, it locks them out for a while to keep your computer safe from hackers. But of course, there is no free lunch. If you need to guess your own password, you might just lock yourself out!
Anyway, you can install fail2ban very easily like this:
sudo apt-get install fail2ban
Now you could optimize the setup further, but this is already going to be enough and keep most automated attempts giving up pretty fast!
3. Backups
I knoow, I know. No one likes to think or especially pay for backups. And if we are honest, sometimes you can live dangerously and ignore them, for example, if you only want to run a temporary dev server.
While there are many ways to do backups, the easiest one is usually just using the snapshot backups of your cloud provider. Most providers take 20% of your server price to make daily backups. If you destroy your server, simply restore it from the previous day and you should be good to go again! 🥳
Again, this is a specific feature from Hetzner with similar ones available from Hosts such as DigitalOcean!
4. UFW
Another firewall! 🔥
UFW, which stands for Uncomplicated Firewall, is a simple tool that helps you control and manage the firewall on your computer. The same as the first firewall, it lets you decide which traffic is allowed to reach your server. The difference is that it is not part of your cloud provider's infrastructure but instead is running on your server. If you forget to enable your cloud provider's firewall (or if they do not have one), UFW will still keep your unwanted traffic out. This might sound redundant, but Defense in depth is a very important concept and can save you from human errors. Anyway, let's see how you can use it:
First, install it.
sudo apt install ufw
We are now going to build up our firewall step by step by first denying every incoming traffic and allowing every outgoing traffic. This basically means that we can contact everyone, but no one can contact us.
sudo ufw default deny incoming
sudo ufw default allow outgoing
If we stop now, we wouldn't be able to connect to our server anymore! This is why we now allow SSH connections, as well as http and https for our webserver. If you don't host a webserver, don't execute the last two lines :)
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
And finally, we are enabling the firewall and double-check if we did everything correctly!
sudo ufw enable
sudo ufw status
5. Use SSH Keys
When creating your server you usually have 2 choices. You can either log in with a password or with an SSH key. While passwords might be the obvious choice, they are also the least secure choice! Passwords can be brute-forced, SSH keys use asymmetric encryption and (realistically) can't be brute-forced. Of course, you still need to keep your private keys safe, but that is usually a lot easier to do than with passwords! How you can use SSH keys to log in to your server depends on your Cloud Provider, here is a tutorial for Hetzner, DigitalOcean, and AWS
Conclusion
This is barely scratching the surface of security. There are many more things you can do to secure your server, but this should give you a good starting point!
If you are not doing this to learn but to get stuff done, it is maybe worth to consider other options like managed container services that take care of all the security aspects for you. I'm the Founder of Sliplane, a PaaS specifically designed for Docker. You can get started in less than 2 minutes and the first 48 hours are free, then only 7 Euros per month for an unlimited number of Docker containers :)
Deploy Docker Apps in 2 Minutes 🚀
Cheers,
Jonas
Top comments (10)
Yeah idk. All the steps will not increase the security of your server by any means.
Step 1 and 4 are both firewalls. Allow http/https traffic and ssh and allow ALL outbound traffic.
So you have a web application running which is vulnerable to RCE and an attacker will spawn a reverse shell. Firewall useless.
Step 2 and 5: Use fail2ban to prevent bruteforce and use ssh keys. So if I have ssh keys and disabled password login, why do I need fail2ban?
If you really want to secure your server you should follow best practices like CIS / NIST.
Sorry, this argument doesnt make sense. My house explodes because a nuke is dropped on it, so the fire extinguisher is useless? Of course a firewall doesnt fix if your web application is vulnerable to RCE lol. Doesnt make the firewall less useful.
Defense in depth. Multiple firewalls are good.
You still get the benefits of banning malicious login tries? Thats worth it imo.
Of course. I am clearly not saying that this list is exhaustive or would protect you from everything. We are on a beginner friendly blogging platform here, these are just basic first steps.
If you don't control and monitor outbound traffic it is kinda useless. And tends to be more snake oil style of advice. What does the firewall protect you from? What is the potential fire, that you need an extinguisher for? Feel free to give an example.
I totally understand this. But this steps are so shallow that they do more harm then good. People will think installing fail2ban and ufw will protect them in any way.
The only advice that is really increasing the security is using ssh keys.
If you don't have any services that you need to protect from the internet you simply do not need a firewall. Better then this would the the advice to create a low priv user, disable root login, don't run things as root, enable unattented-upgrades, have good logging (auditd)
I would argue that most people host web applications on VPS and have that exact use case. Especially if you for example use Docker. See this as example: x.com/rameerez/status/184884215777... , the Hetzner Firewall would've caught that.
I agree on your other points, but this firewall argument I dont get. You need a firewall.
If you have your small website hosted on a vps with nginx or a small node app, which runs on 80 /443 there is no need for a firewall imo. You don't have any other services running that need to be protected from the internet. If you have more complex services, with internal apis etc. yeah a firewall could make sense, so does a load balancer.
It's been a minute since I used docker, but as far as I remember you have to explicitly expose container ports, no? And you can create networks for containers. So your web app exposing port 80/443 and connecting to the db container, but the db container does not need to make it port public?
Can't fully follow the example on x, because I don't know kamal and the whole setup there. But the tldr part would be, the AI generated script exposed remote control port of docker? Well a firewall might have caught that, but the user could also have then exposed it in the firewall, if the deploy tool would not work, because it needs that port?
In general I am also not saying never use a firewall. There are certain scenarios where it makes sense. But the general statement use a firewall = your safe is simply not true. If you say, use a firewall to prevent misconfiguration of your services and accidentally exposed ports... yeah that might be a point.
99% of web setups are reverse proxy on 80/443 and then redirecting to your actual service though. Thats my whole point, for this you 100% want a firewall.
Step 6: Steal a good hardening script from the internet to take care about the finetuning (but make sure to read and understand it first 🤠)
i like the thrill of just running random scripts without checking them out first
Is there anything you think I missed? LMK here!