hardening a $5 hetzner vps with sst and ansible.
I’ve been going down the $5 VPS rabbit hole for a while now, and have been using SST to deploy my applications to Hetzner. But being a recovering serverless addict, the concept of “hardening” your server was foreign to me, so my servers were just sitting ducks for bad actors. For all the idiots like myself out there, hardening is essentially securing a system by minimising its vulnerabilities — this involves disabling unnecessary services, removing unused software, and configuring the system to be as secure as possible.
With security being such a hot topic on X right now, I thought this would be a good time to share how I’m using SST and Ansible to automate the process of hardening my servers.
The firewall
Section titled: The firewallFirst things first, we need to set up a firewall. Most people will set this up using ufw
(Uncomplicated Firewall) but since I’m using Hetzner and SST, we can easily do this with some code like so:
This code sets up a firewall that allows SSH, HTTP, and HTTPS traffic, and allows all outgoing TCP and UDP traffic. This is a good starting point, but you should adjust the rules to suit your needs.
Creating a new user
Section titled: Creating a new userNow we’ve set up our fireall, we can log into our server and create a new user. This is important because the default root
user has full access to the server, which makes it a prime target for bad actors. By creating a new user with limited privileges, you can reduce the risk of a successful attack.
This code creates a new user called amos
and gives them sudo privileges. It also copies the authorized_keys
file from the root
user to the new user’s .ssh
directory, so you can log in with your SSH key.
The hardening
Section titled: The hardeningNow that we have set up our fireall and created a new user, we need to harden the server. This is where Ansible comes in. Ansible is an open-source automation tool that allows you to automate the configuration of servers. We can use Ansible to automate the process of hardening our server by creating a playbook that does everything for us.
Of course we aren’t going to create one ourselves, because there’s already a great collection out there called devsec.hardening. We’ll be using the ones for hardening SSH and the operating system.
This code installs the devsec.hardening
collection, creates an Ansible playbook that hardens the server, and then runs the playbook. The playbook hardens the operating system and SSH service, and ensures that the SSH service is enabled and running.
Fail2Ban (Optional)
Section titled: Fail2Ban (Optional)Finally, we can set up Fail2Ban to protect our server from brute-force attacks. Fail2Ban is an open-source intrusion prevention tool that scans log files for malicious activity and bans IP addresses that show signs of malicious activity.
To do this, we can update the playbook to the following:
This sets up Fail2Ban to monitor the SSH service and ban IP addresses that show signs of malicious activity. The maxretry
parameter specifies the number of failed login attempts before an IP address is banned, and the bantime
parameter specifies the duration of the ban in seconds.
Conclusion
Section titled: ConclusionAnd that’s it! We’ve set up a firewall, created a new user, hardened the server, and set up Fail2Ban to protect our server from bad actors.
There are probably loads more things you can do (such as changing the default SSH port, for example), but I think this is a good starting point, that is totally automated. If you know of any other good practices that I missed, please let me know on 𝕏. I’ll also definitely be writing more about my experience with $5 VPSs in the future, so while you’re there, consider giving me a follow.