VPS Hardening
This guide provides essential practices and tools that VPS operators can use to secure their Linux servers, particularly in exposed or high-risk environments.
Last updated
Was this helpful?
This guide provides essential practices and tools that VPS operators can use to secure their Linux servers, particularly in exposed or high-risk environments.
Last updated
Was this helpful?
It focuses on practical, executable steps, including system hardening, SSH security, firewall configuration, intrusion prevention, and monitoring. All instructions are tested on Debian-based systems (e.g., Ubuntu), with emphasis on clarity and maintainability.
For Advanced Hardening in an automated script, take a look at: script created by a dedicated member of the Anyone Community.
Keeping your system fully updated ensures your protection against known vulnerabilities and that all installed packages operate with the latest security patches.
Reducing your system's attack surface starts with turning off services that aren't needed. Unused services may expose ports or run vulnerable software unnecessarily.
Audit running services and disable those not in use:
Then disable with this command:
Service
Purpose
packagekit.service
Manages automatic updates graphically; not needed for headless CLI-based VPS.
snapd.service
Snap uses additional background daemons and mounts. It’s often unwanted bloat on servers. (Remember to sudo apt purge snapd
)
snap.canonical-livepatch.canonical-livepatchd.service
Livepatching isn’t typically used on minimal or ephemeral servers. (It's usually removed by purging snapd)
multipathd.service
Multipath is for SAN and storage setups. Not needed on cloud VPS or simple disk configs.
Service
Purpose
dbus.service
Required by some utilities and desktop components. Harmless and often needed by other services.
getty@tty1.service
Provides login on local TTY; not harmful, but optional to disable in headless environments.
networkd-dispatcher.service
Helps with DHCP Netplan events; required on Netplan-managed systems.
polkit.service
Used for user privilege escalation. Needed if you use desktop tools or sudo based GUI operations; may be safe to disable on hardened CLI-only systems.
ssh.service
Keep for remote access.
systemd-networkd.service
Manages network interfaces; critical for connectivity on minimal systems.
systemd-resolved.service
Handles DNS; often required unless using custom resolvers or DNS tools.
systemd-timesyncd.service
Keeps system clock accurate (important for anon).
systemd-journald.service
System logging; required!
systemd-logind.service
Handles user logins and sessions; usually fine to leave.
systemd-udevd.service
Manages device nodes; needed.
user@1000.service
Your user session; leave it alone.
SSH is the lifeline of remote management, securing it is critical.
Changing the SSH port from the default 22
to a custom value (e.g., 52231
) helps reduce exposure to automated scans and brute-force attacks. While not truly secure, it adds a layer of obscurity that can reduce low-effort intrusion attempts.
Edit sshd_config
Look for #Port 22
and change it to to anything else, and for the sake of this example we just randomly selected 52231
:
Then restart the SSH service.
Login banners warn users that the system is monitored and restricted. These messages can serve legal or policy purposes by clearly stating that unauthorized access is prohibited.
Edit /etc/issue.net
with a warning message.
Replace the contents and save it with something like:
Edit /etc/ssh/sshd_config
and look for the banner option.
Set it to the updated issue.net
file.
Restart the SSH Service.
Disabling direct root login via SSH helps prevent attackers from brute-forcing the root account. Instead, users should authenticate with non-root accounts and escalate privileges securely using sudo
.
If you've followed the guide so far you already know how to edit /etc/ssh/sshd_config
.
Set:
SSH key authentication replaces passwords with cryptographic key pairs, significantly reducing the risk of brute-force attacks. It’s a foundational best practice for secure remote access.
Generate key pair (on a local machine):
Generating public/private ed25519 key pair.
Enter file in which to save the key (/root/.ssh/id_ed25519): [Press ENTER]
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): [Press ENTER]
Enter same passphrase again: [Press ENTER]
Your identification has been saved in /root/.ssh/id_ed25519
Your public key has been saved in /root/.ssh/id_ed25519.pub
Copy public key to the server:
INFO: Source of key(s) to be installed: "/root/.ssh/id_ed25519.pub" The authenticity of host 'server_ip (server_ip)' can't be established. ECDSA key fingerprint is SHA256:<redacted>. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes INFO: attempting to log in with the new key(s), to filter out any that are already installed The authenticity of host 'server_ip (server_ip)' can't be established. ECDSA key fingerprint is SHA256:<redacted>. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys ALERT! You are entering a secured area! Your IP, Login Time, and Username have been noted and have been sent to the server administrator! This service is restricted to authorized users only. All activities on this system are logged. Unauthorized access will be fully investigated and reported to the appropriate law enforcement agencies. user@server_ip's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh -p '52231' 'user@server_ip'" and check to make sure that only the key(s) you wanted were added.
Try to log in to the server from your local machin with the new key:
On the server, disable password authentication in sshd_config
:
Set:
UFW (Uncomplicated Firewall) makes it easy to manage iptables and control which services are exposed to the internet. Setting a default-deny policy and allowing only essential ports helps contain threats and limit exposure.
Enable the service.
To check the status of UFW:
Automated protection against brute-force and scanning behavior.
Fail2Ban monitors system logs for failed login attempts or suspicious behavior, then bans the source IP using firewall rules. It's highly effective for deterring brute-force attacks against SSH and other services.
Instead of modifying the default jail.conf
, create a local configuration.
In the [DEFAULT]
section, adjust the following parameters as needed:
Ensure the [sshd]
jail is enabled.
If you've changed the SSH port (e.g., to 52231), update the port
value accordingly.
Monitor Fail2Ban Status
Check the status of Fail2Ban and its jails.
To unban an IP, use the set
function:
Basic system monitoring helps detect when something is wrong; like resources, failed services, or suspicious activity. Before it becomes a full outage or compromise.
Configure /etc/watchdog.conf
for system checks like disk, memory, or network loss.
Suggestion provided on AskUbuntu.com:
Read more about typical SSH Key Scanning at:
When running the , UFW is offered as an option to enable access for SSH and ORPort. Read more about UFW on the official Ubuntu documentation:
See Ubuntu Man pages for detailed description on how to modify the configuration file for Watchdog: