
A fresh VPS is not locked down by default. The moment an instance switches on and gets a public IP address, bots start scanning it. I have watched failed login attempts show up in a server’s auth log within minutes of it going live, long before I had gotten around to naming the thing.
This guide covers every step to take on a new VPS before trusting it with anything, in the order to take them. It’s built around three tiers:
- What to set up before doing anything else
- What to finish in the first week
- And what to add once the server carries production traffic or anything sensitive
I used a Hostinger VPS while working through the security steps in this guide. The commands and settings apply to any Linux VPS regardless of the hosting provider, only the control panel and where you find certain settings may differ.
If you don’t have a VPS yet, browse the current Hostinger VPS hosting plans directly. If you want to see how Hostinger’s VPS plans actually perform, our full Hostinger VPS hosting review covers the benchmarks and support testing.
Before You Start: What You Need
- Root or sudo access to the VPS over SSH
- A terminal on your own computer (Terminal on macOS/Linux, or PuTTY/Windows Terminal on Windows)
- The VPS provider’s control panel login, for the parts of this guide that live outside the server itself
At checkout, most providers only ask for a plan, an operating system, and a data center location. Everything below happens after that, inside the provider’s panel and over SSH.

Tier 1: Do This Before Anything Else
These five steps close the gaps that automated attacks go after first. Do these within the first hour of provisioning a server, before installing anything else.
1. Update the system
New images ship with whatever packages were current when the image was built, which can be weeks or months old. Patch the system before doing anything else.
On Ubuntu or Debian:
sudo apt update sudo apt upgrade -y
On AlmaLinux, Rocky Linux, or other RHEL-based systems:
sudo dnf upgrade -y
Run this again periodically. Tier 3 covers automating it.
2. Generate and add an SSH key
Password logins over SSH are the first thing a bot tries to brute force. A key pair replaces the password with a private key that never leaves your computer and a public key that sits on the server. Guessing it is not practical.
Generate a key pair on your own machine, not on the server:
ssh-keygen -t ed25519
Press Enter to accept the default file location, and set a passphrase on the key itself for an added layer of protection. This creates two files: a private key to keep and a public key to upload to the server.
Most providers have a spot in the panel to paste the public key so it lands in the right place automatically.
In the Hostinger dashboard, that is under VPS > Settings > SSH keys.


If the provider doesn’t offer this, copy the key manually with ssh-copy-id user@your-server-ip, or paste the contents of the .pub file into ~/.ssh/authorized_keys on the server.
Test the key works before touching anything else:
ssh -i ~/.ssh/id_ed25519 user@your-server-ip
Once the key logs in, move to the next step.
3. Turn off password authentication
Adding a key is not enough on its own. If password login is still turned on, a bot can still try to brute-force it alongside the key. Turn passwords off entirely once the key works.
Edit the SSH daemon configuration:
sudo nano /etc/ssh/sshd_config
Find these lines and set them as shown, removing the # if the line is commented out:
PasswordAuthentication no PubkeyAuthentication yes
Restart SSH to apply the change:
sudo systemctl restart sshd
On Ubuntu 24.04 and later, SSH is managed through ssh.socket rather than the older service file. Check which one applies with systemctl status ssh.socket first; if it exists, restart that instead:
sudo systemctl restart ssh.socket
Keep the existing terminal session open while testing a fresh login in a second window. If the new session fails, the first one is still there to fix the mistake instead of being locked out.
4. Block root login over SSH
Every Linux server has a root account, so it’s the one username every bot already knows to try. Force logins as a normal user and switch to root only when needed, using sudo.
In the same sshd_config file:
PermitRootLogin no
Restart SSH again. This step only works once there’s a non-root user with sudo rights to log in as, which is the next step in Tier 2. Hold off on this line until that user exists.
5. Turn on a default-deny firewall
A firewall decides what network traffic reaches the server. Set the default policy to deny everything, then open only the ports actually in use.
On Ubuntu and Debian, ufw is the simplest option:
sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow OpenSSH sudo ufw enable
If the SSH port has already been changed (covered in Tier 2), allow that port number instead of OpenSSH.
Many providers also offer a firewall inside the control panel that filters traffic before it reaches the server at all. Add this as a second layer alongside the server’s own firewall rather than relying on either one alone.
In the Hostinger dashboard, this lives under VPS > Security > Firewall.


Name the configuration something that describes what it does (web server, SSH only, block all traffic), add rules for the needed ports, and switch it on. From the same screen’s menu, you can edit or delete a configuration later.

Test What You Built
Before moving on, confirm the intended ports are reachable and the blocked ones actually are not.
Check this manually with a tool like nmap from another machine (nmap -p 22,80,443 your-server-ip), or see what’s actually listening on the server itself with sudo ss -tulnp.
Hostinger has also built an AI agent into the Hostinger dashboard that inspects and tests a firewall configuration conversationally. I asked it to verify a firewall I’d just set up, and it caught something I’d missed: the firewall group existed but had never been attached to the VPS, so none of its rules were actually being enforced.
It also confirmed SSH was reachable and flagged that no web server was listening on ports 80 or 443 yet, which explained why those ports weren’t responding.

That’s the kind of check that’s easy to skip and easy to get wrong by eye, and something that inspects the running configuration rather than just reading a rule list is a genuine step up from digging through iptables -L output by hand.
If using an agent for this, ask it to check three things: that the intended ports are reachable, that everything else is blocked, and that the firewall configuration is actually attached to the right server. That last check matters more than it sounds. A firewall that exists but isn’t applied gives no protection at all while looking, at a glance, like it does.
Tier 2: Handle This in Your First Week
These steps close the gaps that Tier 1 leaves open. None are urgent in the first hour, but a server isn’t production-ready until they’re done.
6. Change the default SSH port
Port 22 is the first port every scanning bot checks. Moving SSH to a non-standard port won’t stop a targeted attacker, but it removes the server from the pile of results that mass scanners return, which cuts down on log noise and low-effort attempts substantially.
Before changing anything, keep the current SSH session open. In sshd_config, find the port line and set a new number between 49152 and 65535:
Port 49152
If a firewall is active, allow the new port before restarting SSH, or this locks you out:
sudo ufw allow 49152/tcp sudo systemctl restart sshd
Test the new port in a second terminal window before closing the first:
ssh -i ~/.ssh/id_ed25519 -p 49152 user@your-server-ip
Once that works, remove the old port 22 rule from the firewall and update any saved connection profiles.
7. Create a restricted user for daily work
Running everything as root means one mistake, or one compromised process, has full control of the system. Create a separate account for daily tasks and reserve root access for when it’s actually needed.
sudo adduser yourusername sudo usermod -aG sudo yourusername
Copy the SSH key to the new user to log in the same way as root:
rsync --archive --chown=yourusername:yourusername ~/.ssh /home/yourusername
Log in as this user going forward, and use sudo for anything that needs elevated rights. This is also the point to apply the PermitRootLogin no line from Tier 1 if it was held off earlier.
8. Install Fail2ban
Fail2ban watches the logs for repeated failed login attempts and temporarily blocks the offending IP address. It catches brute-force attempts a firewall alone won’t, since a firewall doesn’t care how many times someone gets the password wrong on an open port.
sudo apt install fail2ban sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local sudo nano /etc/fail2ban/jail.local
Under the [sshd] section, set:
[sshd] enabled = true port = 49152 maxretry = 3 findtime = 5m bantime = 30m
Use whatever port SSH is set to from Tier 2. This configuration blocks an IP address for 30 minutes after three failed attempts within five minutes. Restart the service to apply it:
sudo systemctl restart fail2ban
Check it’s running with sudo fail2ban-client status sshd.
9. Turn on your host’s network-level firewall
The ufw firewall from Tier 1 runs on the server itself, which means malicious traffic still reaches the network interface before being dropped.
A firewall at the provider’s network edge blocks it before it arrives at all, reducing load on the server during an attack and adding a layer that keeps working even if something on the server gets misconfigured.
This is the same Hostinger dashboard firewall covered in Tier 1’s step 5. Circle back and finish it if it isn’t set up yet.
10. Bind internal services to localhost
A firewall protects the ports it manages, but plenty of services listen on the public network interface by default even though nothing outside the server should ever reach them. MySQL, PostgreSQL, Redis, and most admin dashboards fall into this category.
An open firewall does nothing if the service itself is listening on 0.0.0.0 and a rule accidentally allows the port.
Check what’s listening publicly:
sudo ss -tulnp
For a database like MySQL, restrict it to localhost in its config file (/etc/mysql/mysql.conf.d/mysqld.cnf on Ubuntu):
bind-address = 127.0.0.1
Restart the service after the change and confirm it no longer shows up bound to the public interface in ss -tulnp. If something on another server needs to reach the database, use a private network between the two instances instead of exposing it publicly.
11. Set up automated backups
A firewall protects against intrusion. It does nothing if a bad update, a failed migration, or a plain mistake wipes out data. Back up before it’s needed, not after.
Most providers offer scheduled snapshots and on-demand ones. In the Hostinger dashboard, both live under VPS > Backups & Monitoring > Snapshots & Backups.

Take a manual snapshot before any change that isn’t fully certain (an OS upgrade, a major configuration change, or installing something untested). Restoring from a snapshot takes minutes, and it beats rebuilding a server from nothing.
Tier 3: For Production Workloads and Sensitive Data
Everything above covers a server running personal projects or low-stakes work. If the VPS handles customer data, processes payments, or runs anything that can’t tolerate downtime, add these.
12. Add two-factor authentication to your hosting account
Everything so far protects the server. None of it matters if someone gets into the account that controls the server, since from there they can reset the root password, spin up new instances, or delete backups outright.
Turn on two-factor authentication on the hosting account itself, not just the server.
In the Hostinger dashboard, this is under the account menu > Security > Two-Factor Authentication.

Use an authenticator app over email-based codes where there’s a choice. An app-generated code can’t be intercepted via a compromised inbox.
13. Automate security updates
Manually running apt upgrade works until the week it gets forgotten, and that’s usually the week a patched vulnerability gets exploited in the wild. Automate the parts that matter.
On Ubuntu and Debian:
sudo apt install unattended-upgrades sudo dpkg-reconfigure --priority=low unattended-upgrades
On AlmaLinux and Rocky Linux:
sudo dnf install dnf-automatic sudo systemctl enable --now dnf-automatic.timer
This handles security patches on its own. A manual update pass once a month still catches anything outside that scope.
14. Sync the clock and log what sudo does
Every log this guide has generated so far, from fail2ban bans to auth attempts, is only as useful as its timestamp. Server clocks drift over time, especially on smaller VPS plans, and a drifted clock makes correlating an incident across multiple log files close to impossible. Install a time sync service if one isn’t already running:
sudo apt install chrony sudo systemctl enable --now chrony
Separately, know what happens under sudo on the server, not just who logged in. By default, every sudo command already gets logged to /var/log/auth.log (or /var/log/secure on RHEL-based systems). Check it periodically:
sudo grep sudo /var/log/auth.log
For anything running multiple admin users, a dedicated tool like auditd gives a searchable record instead of grepping raw logs by hand.
15. Monitor logs and scan for rootkits
By this stage the server is reasonably locked down against opportunistic attacks. Monitoring catches the ones that get through anyway, and gives a record for investigating later.
A lightweight setup:
sudo apt install logwatch rkhunter sudo rkhunter --propupd sudo rkhunter --check
logwatch gives a daily summary of what happened on the server instead of raw log files that would otherwise go unread. rkhunter scans for signs of rootkits and known exploits. Neither replaces active monitoring on a server carrying anything sensitive, but both catch problems a firewall alone will miss.
Turn on a built-in scanner, too, if the provider includes one. The Hostinger dashboard has one built into every VPS plan, under VPS > Security > Malware Scanner, and it can quarantine or clean infected files automatically once activated.

16. Cut the attack surface
Every running service is a potential way in. Check what’s actually listening on the server and remove anything unused.
sudo ss -tulnp
Anything in that list that isn’t recognized or actively needed should be investigated and, if unused, uninstalled. The same goes for pre-installed software that shipped with the OS image. A smaller footprint means fewer things to patch and fewer things that can go wrong.
17. Harden the kernel with sysctl
Beyond the firewall, the Linux kernel itself has settings that affect how the server responds to certain network conditions and attack patterns. A short set of sysctl values closes off some default behavior that most servers never need. Add these to /etc/sysctl.d/99-hardening.conf:
net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.all.send_redirects = 0 net.ipv4.tcp_syncookies = 1 net.ipv4.conf.all.rp_filter = 1
Apply them with:
sudo sysctl --system
These settings ignore ICMP redirect attacks, protect against IP spoofing through reverse-path filtering, and enable SYN cookies to absorb certain flood attempts without exhausting server resources.
18. Add TLS if the server serves anything public
If the VPS runs a website, API, or any service reachable over HTTP, encrypt that traffic. A free certificate through Let’s Encrypt, issued and renewed automatically with a tool like Certbot, covers most setups:
sudo apt install certbot sudo certbot --nginx
Swap –nginx for –apache depending on the web server in use. This step depends on a web server actually being installed and configured, which is a separate setup from anything in this guide, but it belongs on this list because an otherwise hardened server serving plain HTTP still exposes every request in transit.
19. Run a hardening audit
Once everything above is in place, run a full audit rather than trusting that everything got covered. Lynis checks system configuration against a long list of hardening standards and gives a score along with specific fixes.
sudo apt install lynis sudo lynis audit system
Run it after any major change to the server, not just once. Configuration drifts over time, and an audit tool catches what manual review misses.
Common Mistakes That Undo All of This
- Adding an SSH key without disabling passwords. The key does nothing for security if a bot can still try passwords on the same account.
- Opening a firewall port to debug something, then forgetting to close it. This is one of the most common ways a hardened server quietly stops being hardened.
- Setting up a firewall configuration that is never attached to the actual server. The AI agent test earlier in this guide caught exactly this. A firewall rule set that exists somewhere in the panel but isn’t applied to the VPS protects nothing.
- Leaving a database bound to the public interface. A firewall rule that gets accidentally opened, or a hosting migration that resets network settings, turns an exposed database into an open door.
- Skipping backups because nothing has gone wrong yet. The point of a backup is not knowing in advance which week it will be needed.
- Treating account-level security as separate from server security. A hardened server behind a compromised hosting account login isn’t hardened at all.
- Never re-running an audit after the initial setup. Configuration changes over the life of a server. What passed a hardening check on day one can silently regress by month six.
What to Do If You Get Locked Out
If disabling password authentication or changing the SSH port goes wrong, most providers offer a way back in that doesn’t involve reinstalling from scratch.
A browser-based console, reachable from the panel without needing SSH at all, allows a direct login to fix a broken configuration file. In the Hostinger dashboard, this is the Web console button on the VPS overview page.


Some panels also offer one-click resets for exactly this situation, separate from the console. Hostinger’s dashboard has dedicated reset buttons for both the firewall and SSH configuration under VPS > Settings > Main settings, putting either back to its default state without touching the rest of the server.

Keep this in mind before making any changes to SSH or firewall rules. Knowing the way back in ahead of time turns a lockout from an emergency into a two-minute fix.
Recap Checklist
Tier 1, before anything else:
- System updated
- SSH key generated and added
- Password authentication disabled
- Root login over SSH disabled
- Default-deny firewall enabled and tested
Tier 2, first week:
- SSH moved off port 22
- Restricted non-root user created for daily use
- Fail2ban installed and configured
- Network-level firewall enabled at the provider
- Databases and internal services bound to localhost
- Automated backups scheduled, with a manual snapshot before major changes
Tier 3, production and sensitive workloads:
- Two-factor authentication on the hosting account
- Automatic security updates configured
- Time sync running and sudo activity reviewed periodically
- Log monitoring and rootkit scanning in place
- Unused services and packages removed
- Kernel network settings hardened via sysctl
- TLS added to any public-facing service
- Hardening audit run and re-run after changes

