Most “expert” guides on how to secure a server are just bloated collections of enterprise-grade nonsense that you’ll never actually use on a dedicated instance. They want you to buy expensive proprietary firewalls or implement complex enterprise security suites that do nothing but eat up your RAM and latency. I’ve spent enough nights watching my server logs fill up with failed SSH attempts to know that most of this advice is just marketing fluff designed to sell subscriptions. If a guide tells you that you need a massive budget to stay safe, they aren’t talking to people like us; they’re talking to corporations.
I’m not going to give you a lecture on theoretical security models or things I’ve only read about in a textbook. I’m writing this based on the specific configurations I’ve used to keep my own builds running without getting nuked. I’ve spent years hardening my own Linux environments and managing player traffic, and I’m only sharing the exact steps that I have personally tested and verified. If I haven’t manually configured the protocol or checked the port myself, you won’t find it in this guide.
Table of Contents
Why I Only Trust Ssh Key Authentication

I’ve seen too many server admins rely on passwords because they’re “easier” to remember, and frankly, it’s reckless. When I was running my survival server, I noticed the logs were constantly getting hammered by automated bots trying to guess credentials. Even with a decent password, you’re essentially leaving a door unlocked and hoping nobody has a heavy enough crowbar. Transitioning to SSH key authentication is the only way to actually stop the bleeding. Once I disabled password authentication entirely in my `sshd_config`, the constant noise in my logs from failed login attempts just… stopped.
The math is simple: a password can be brute-forced; a 4096-bit RSA key cannot. By moving to keys, you aren’t just adding a layer of complexity; you are fundamentally changing the entry requirements for your machine. It’s a core part of my server hardening checklist that I apply to every single instance I spin up. If you aren’t using keys, you aren’t actually secured—you’re just waiting for a lucky script to find your way in.
My Non Negotiable Firewall Configuration Best Practices

Most people treat their firewall like a “set it and forget it” checkbox, which is exactly how you end up with a compromised instance. I don’t do that. My approach is centered on a strict least privilege access model. If a port doesn’t have a specific, documented reason to be open, it stays closed. I don’t care if a service claims it “might” need it later; I’d rather troubleshoot a connection than deal with an open exploit vector.
When I’m setting up a new build, I follow a specific server hardening checklist that starts with dropping all incoming traffic by default. I only whitelist the bare essentials—usually just my specific IP for SSH and the necessary game ports. I’ve seen too many “easy” tutorials suggest opening wide ranges of ports for “stability,” but that’s just asking for trouble. If you aren’t actively managing your rules, you aren’t securing anything; you’re just hoping nobody notices the holes you left behind.
The Hardening Steps I Actually Use
- Disable root login immediately. I don’t care what the default config says; if someone hits your IP, the first thing they’re going to try is brute-forcing ‘root’. I use a dedicated sudo user and keep the root account locked down tight.
- Set up Fail2Ban and actually monitor the logs. It’s not enough to just install it; you need to make sure the jail levels are aggressive enough to ban IPs after three failed attempts, otherwise, you’re just watching a slow-motion car crash in your logs.
- Automate your security updates but keep a manual check on the kernel. I use unattended-upgrades for the critical patches, but I never let the system reboot itself without me verifying that the specific service dependencies for my server won’t break on startup.
- Kill off every unused port and service. If you aren’t using it, it shouldn’t be listening. I ran a netstat check on my last build and found two legacy services I forgot were running; I nuked them instantly.
- Use a non-standard SSH port if you want to reduce the noise. Moving SSH away from port 22 won’t stop a targeted attack, but it stops 99% of the mindless bot scans that clutter up my logs and eat my CPU cycles.
The Bottom Line
If you’re still using password authentication for SSH, you’re essentially leaving your front door wide open for every script kiddie on the internet.
A firewall isn’t a “set it and forget it” tool; if you haven’t manually whitelisted only the specific ports you actually use, you haven’t secured anything.
Stop following outdated tutorials from 2018; if the configuration hasn’t been tested on your specific OS build this week, it’s a liability, not a solution.
Final Hardening Steps

At the end of the day, securing a server isn’t about checking off a list of “recommended” features you found on a forum. It’s about the actual, manual work of closing doors you didn’t even know were open. I’ve spent enough hours watching logs fill up with failed login attempts to know that if you aren’t using SSH keys and a tightly scoped firewall, you’re basically just leaving your front door unlocked and hoping for the best. I’ve tested these specific configurations on my own builds, and they work because they don’t rely on some bloated, automated script—they rely on explicit, manual control over every single port and permission.
Stop looking for the “one-click” solution or the magic plugin that promises total security. It doesn’t exist. If you want a server that stays up and stays private, you have to be willing to get your hands dirty in the config files and verify every single change yourself. It’s tedious, and it’s definitely not the “fun” part of running a server, but it is the only way to actually sleep at night. Build it right, lock it down manually, and stop trusting the defaults.
Frequently Asked Questions
How do I actually set up the SSH keys without locking myself out of the root account?
Don’t touch the root account directly; it’s a rookie mistake. First, create a standard user with sudo privileges and push your public key to that user’s `.ssh/authorized_keys` file. Then, open a second, separate terminal window and attempt to log in as that new user while your original session is still active. If you can’t get in, you still have the first window open to fix the permissions. Only after testing that do you disable password auth.
Which specific ports should I leave open if I'm running a Minecraft server on this setup?
Keep it minimal. If you’re running a standard setup, you only need 25565 open for the game traffic. If you’re using RCON for remote console management, open that port too, but don’t you dare leave it on the default—change it to something random. Everything else stays shut. I’ve seen too many people leave unnecessary ports hanging open just because a generic guide told them to. If the service doesn’t need it to function, block it.
Is there a way to automate these firewall rules so they don't break every time I update the OS?
You don’t want to be manually re-typing `iptables` commands every time you run `apt upgrade`. That’s how you leave a port open by accident. I use Ansible for this. I wrote a simple playbook that defines my exact rule set and applies it to the instance. If the OS update wipes a config or resets a service, I just run the playbook and the firewall is back to my exact spec in seconds.


























