Tools: How to Protect Your New Vps (2026)

Tools: How to Protect Your New Vps (2026)

SSH vulnerabilities

Bot protection

Cloudflare

fail2ban

Firewall

Maybe not so scary after all I was very intimitaded about using a VPS outside a VPC my web apps. I had never used a stand alone VPS without some kind of walled garden around it. At work everything is usually behind a VPC. And I have always worked with awesome security people to double check things! I don't have to worry so much about bots or people constantly trying to exploit my service (of course we follow guidence from our excellent security colleagues). But when you turn on your new VPS it immediately can be discovered and bots will immediately try to exploit vulnerabilities. Recently I launched wishlistpalace.com which is running on a Hetzner VPS and I have come to find out that things are not quite a dire or dangerous as I had thought. One flavor of exploit that bots try against your VPS is to try a bunch of passwords to try to be able to ssh into your new VPS and do whatever (maybe start mining bitcoin or installing malware). Thankfully, VPS providers don't just spin up your box with weak passwords and call it a day. In fact it's even better than that on Hetzner. They let you explicit disable ssh password authentication so this exploit simply won't happen to your new box. But then you might ask, how do I get into my box then? With the key of course. By default the setup wizard on the Hetzner site for new VPS asks you to provide a public ssh key. You can use to generate a public and private key pair. Then during the setup flow you upload the PUBLIC key. Later once your box is up you will be able to get the IP for the VPS. Shelling into your box can be made super simple by setting up your ssh config. Add an entry to ~/.ssh/config so SSH uses it automatically: Just replace the place holder values above of course! Another probably unfounded fear was that as soon as I turned on my VPS there would be a DDoS or some other overwhelm attack. That I thought this probably means I think a little too highly of myself sure there will be pokes at the new IP but probably not a DDoS right out of the gate. Never-the-less I learned about a few bot protection measures. This is probably obvious to most, but if you are really worried about bots, the cloudflare is the way the go. And they have a free tier. I won't list the full instructions on how to setup here, but there are lots of good tutorials I found on line, and Claude was helpful in getting this setup. I chose also to use nginx in front of my app so I needed to configure the handshake between cloudflare and nginx. Something you can run on the new VPS is fail2ban which monitors login attempts and temporarily bans IPs that fail too many times. It's kind of fun to use because after a few days you can the thousands of failed attempts to get into your machine from bots. The VPS I set up is using Ubuntu 24.04 LTS and setting up fail2ban is as simple as After about a week after I started the VPS here's what I see when I check in on fail2ban with sudo fail2ban-client status sshd to check attacks against ssh. Wow! I'm so thankful bots wanted to try to shell into my VPS! Ubuntu has a firewall utility called ufw and is a quick way to help protect the service you want to run on the VPS. After all I wanted to host wishlist palace the application on the VPS that was the whole point. I chose Elixir's Phoenix framework as the web service part of the app and it exposes the port 4000. But as soon as I spin it up it is possible for people to try some exploit against this port. But with a firewall and using cloudflare and nginx we can really lock down direct access to the app. The desired state would ensure that the only traffic to the app has to travel through our protective layer above, i.e., cloudflare and nginx. To achieve this we can setup the firewall to limit to only the ports we need for this desired access pattern. With a few invocations of ufw you can lock access down. But it is important to leave the ssh port open so you can get back in. This basically sets up an allow list then locks every other port down. That's all I did in the first week of having my VPS and so far it hasn't crashed so maybe I was wrong to be worried. I have no doubt there are other important security techniques I need to learn about but I wanted to share this setup. I think I might follow up with more details about the cloudflare nginx setup in another post. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Command

Copy

$ ssh-keygen -t ed25519 -f ~/.ssh/name_of_key -C "your new hetzner box" ssh-keygen -t ed25519 -f ~/.ssh/name_of_key -C "your new hetzner box" ssh-keygen -t ed25519 -f ~/.ssh/name_of_key -C "your new hetzner box" Host someNameOfYourBox HostName <your-vps-ip> User root IdentityFile ~/.ssh/name_of_key Host someNameOfYourBox HostName <your-vps-ip> User root IdentityFile ~/.ssh/name_of_key Host someNameOfYourBox HostName <your-vps-ip> User root IdentityFile ~/.ssh/name_of_key -weight: 500;">apt -weight: 500;">install fail2ban -weight: 500;">apt -weight: 500;">install fail2ban -weight: 500;">apt -weight: 500;">install fail2ban Status for the jail: sshd |- Filter | |- Currently failed: 1 | |- Total failed: 3487 | `- Journal matches: _SYSTEMD_UNIT=sshd.-weight: 500;">service + _COMM=sshd `- Actions |- Currently banned: 0 |- Total banned: 164 `- Banned IP list: Status for the jail: sshd |- Filter | |- Currently failed: 1 | |- Total failed: 3487 | `- Journal matches: _SYSTEMD_UNIT=sshd.-weight: 500;">service + _COMM=sshd `- Actions |- Currently banned: 0 |- Total banned: 164 `- Banned IP list: Status for the jail: sshd |- Filter | |- Currently failed: 1 | |- Total failed: 3487 | `- Journal matches: _SYSTEMD_UNIT=sshd.-weight: 500;">service + _COMM=sshd `- Actions |- Currently banned: 0 |- Total banned: 164 `- Banned IP list: graph LR User -->|":443 HTTPS"| Cloudflare Cloudflare -->|":443 HTTPS"| nginx nginx -->|":4000 HTTP"| Phoenix nginx -->|":80 HTTP redirect"| Cloudflare graph LR User -->|":443 HTTPS"| Cloudflare Cloudflare -->|":443 HTTPS"| nginx nginx -->|":4000 HTTP"| Phoenix nginx -->|":80 HTTP redirect"| Cloudflare graph LR User -->|":443 HTTPS"| Cloudflare Cloudflare -->|":443 HTTPS"| nginx nginx -->|":4000 HTTP"| Phoenix nginx -->|":80 HTTP redirect"| Cloudflare ufw allow 22 # SSH — do this FIRST or you'll lock yourself out ufw allow 80 # HTTP — needed for Certbot's verification step ufw allow 443 # HTTPS — your app's public port ufw -weight: 500;">enable ufw -weight: 500;">status # confirm rules are active ufw allow 22 # SSH — do this FIRST or you'll lock yourself out ufw allow 80 # HTTP — needed for Certbot's verification step ufw allow 443 # HTTPS — your app's public port ufw -weight: 500;">enable ufw -weight: 500;">status # confirm rules are active ufw allow 22 # SSH — do this FIRST or you'll lock yourself out ufw allow 80 # HTTP — needed for Certbot's verification step ufw allow 443 # HTTPS — your app's public port ufw -weight: 500;">enable ufw -weight: 500;">status # confirm rules are active