Skip to main content
    VPS

    How to Secure a VPS: The First-Hour Hardening Checklist

    September 13, 2026
    20 min read
    How to Secure a VPS: The First-Hour Hardening Checklist

    Short version: create a non-root user with sudo, log in with an SSH key, disable root login and password authentication, turn on a default-deny firewall, install Fail2ban, and enable automatic security updates. That is roughly twenty minutes of work, and it removes the overwhelming majority of what actually reaches a fresh VPS.

    The rest of this guide is the complete checklist for how to secure a VPS, in the order you should run it, with commands for both Debian/Ubuntu and the RHEL family (RHEL, Rocky Linux, AlmaLinux). One thing worth saying before anything else: Devoster VPS plans are unmanaged with full root access. Every item below is your job, not ours. You cannot secure a server you quietly assume somebody else is securing.

    Key Takeaways

    • Order matters more than any individual setting. Test key-based login in a second terminal before you disable password authentication, and open the firewall port before you make SSH listen on it. Almost every lockout story is a sequencing mistake, not a config mistake.
    • Key-based SSH with password authentication off is the highest-value change on the list. It ends password brute force against your server instead of merely slowing it down.
    • Moving SSH off port 22 cuts log noise dramatically, but it is obscurity, not security. Do it after keys and a firewall, never instead of them.
    • Debian 12 and later no longer install rsyslog by default, so /var/log/auth.log may not exist. Fail2ban's sshd jail needs the systemd backend or it will refuse to start.
    • A VPS with no swap lets the kernel OOM killer terminate your database under memory pressure. Configuring swap costs nothing and prevents a whole category of 3 a.m. outages.
    • A backup on the same VPS is not a backup, and a backup you have never restored is a hypothesis. Book a restore drill.

    The First Hour, in Order

    New servers get scanned within minutes of the IP going live. That is not a scare statistic, it is just how the internet works: automated tools walk address ranges continuously looking for port 22 answering with password authentication, exposed database ports, and default credentials. None of it is targeted at you. All of it will find you.

    These are the first steps after buying a VPS, in the order that keeps you from locking yourself out. Work through the table below top to bottom. This VPS hardening sequence is deliberate, and skipping ahead is how people lock themselves out of a box they provisioned four minutes ago. If you are new to Linux server hardening, resist the urge to jump straight to the interesting parts.

    # Task Why it sits here Time
    1 Patch everything The image you booted was built weeks or months ago. Patch before you expose services. 2-5 min
    2 Create a non-root sudo user You need a working alternative login before you take root's away. 2 min
    3 Install your SSH key and test it Must succeed before step 4. Test in a new terminal, not the one you are already in. 3 min
    4 Harden sshd, restart, verify Only safe once you have proven key login works. 5 min
    5 Firewall: default deny inbound Do this before installing web or database software, not after. 3 min
    6 Fail2ban Needs a working log source, so it comes after SSH is settled. 5 min
    7 Automatic security updates The one control that keeps working while you are asleep. 5 min
    8 Time sync and swap Boring, unglamorous, and the reason your logs and your database survive. 5 min
    9 TLS, headers, banners Only once a web server actually exists. 10 min
    10 Database lockdown Same: after installation, before the app goes live. 10 min
    11 Off-box backups plus a restore drill Last on the list, first thing you will want when something goes wrong. 20 min

    Before you start, open two SSH sessions and keep the first one alive for the whole exercise. If you break authentication in session two, session one is your way back in. This single habit prevents most emergency console tickets.

    Step 1: Patch the Base Image

    Provider images are snapshots. On Debian or Ubuntu run sudo apt update && sudo apt upgrade -y. On the RHEL family run sudo dnf upgrade -y. If the kernel was updated, reboot now while nothing is running on the box. Rebooting a fresh VPS is free; rebooting a production one at 2 p.m. is not.

    Step 2: Create a Non-Root Sudo User

    Working as root full time means every typo is potentially unrecoverable and every compromised process runs with total authority. Create a normal account and escalate deliberately.

    Debian and Ubuntu: sudo adduser yourname then sudo usermod -aG sudo yourname.

    RHEL family: sudo adduser yourname, sudo passwd yourname, then sudo usermod -aG wheel yourname. The privileged group is wheel, not sudo — using the wrong one is a common cross-distro slip that produces a user who cannot escalate at all.

    Verify before moving on. Open a second terminal, log in as the new user, and run sudo whoami. If it prints root, you are clear.

    Should sudo require a password?

    Yes, in almost every case. Passwordless sudo turns any code execution bug in anything the user runs into instant root. The exception is a dedicated deploy or automation account that runs a small, explicitly listed set of commands — and that belongs in a file under /etc/sudoers.d/ naming those commands, not a blanket NOPASSWD entry. Always edit sudo rules with sudo visudo -f /etc/sudoers.d/deploy so syntax errors are caught before they lock out sudo entirely.

    Step 3: Secure SSH on a VPS With Keys, Not Passwords

    This is the step that matters most. A password can be guessed at machine speed from a botnet; a 256-bit key cannot.

    On your own laptop, not the server, generate a key: ssh-keygen -t ed25519 -C "laptop-2026". Ed25519 is the sensible modern default — short, fast, and supported everywhere OpenSSH is current. Use a passphrase. A stolen laptop with a passphrase-free key is a stolen server.

    Copy the public key to the new account with ssh-copy-id yourname@your.server.ip. If ssh-copy-id is not available on your machine, append the contents of your .pub file to ~/.ssh/authorized_keys on the server, then fix permissions: chmod 700 ~/.ssh and chmod 600 ~/.ssh/authorized_keys. SSH silently refuses keys in world-writable directories, and this is the most common reason a correctly copied key still does not work.

    Now test. Open a fresh terminal and run ssh yourname@your.server.ip. You should get in without typing an account password. Only when that works do you continue.

    Editing the SSH daemon config

    Ubuntu and Debian place Include /etc/ssh/sshd_config.d/*.conf at the very top of /etc/ssh/sshd_config, and OpenSSH uses the first value it obtains for most directives. That means anything in a drop-in file wins over what you edit lower down in the main file. Provider and cloud-init images frequently ship a drop-in that re-enables password authentication.

    So look first: ls -l /etc/ssh/sshd_config.d/ and read whatever is there. Then put your own settings in a drop-in that sorts early, for example /etc/ssh/sshd_config.d/00-hardening.conf, containing:

    • PermitRootLogin no — the OpenSSH default is prohibit-password, not no, so this is a real change rather than a formality.
    • PasswordAuthentication no
    • KbdInteractiveAuthentication no — disabling password auth alone can leave a PAM-driven keyboard-interactive path open. Turning both off is what actually closes the door.
    • PubkeyAuthentication yes
    • MaxAuthTries 3 — the default is 6.
    • AllowUsers yourname — an allowlist beats a blocklist. Every other account, including any service account created later, is refused SSH outright.

    Validate the configuration before restarting: sudo sshd -t. Silence means it parsed. Then sudo systemctl restart ssh on Debian and Ubuntu, or sudo systemctl restart sshd on the RHEL family. Keep your original session open and confirm a brand-new login works.

    Changing the SSH port: honest framing

    Moving SSH from 22 to something like 2222 will drop your failed-login log volume enormously, because the bulk of that traffic is untargeted scanning of port 22 only. That is a genuine operational benefit: quieter logs mean you notice the events that matter.

    It is not security. Anyone running a full port scan finds your service in seconds, and the banner tells them what it is. A non-standard port protects you from nobody who has decided to look at your specific IP. Treat it as noise reduction, and never as a reason to relax about keys or the firewall.

    If you do it, order is critical:

    1. Open the new port in the firewall first.
    2. On the RHEL family, label the port for SELinux, or sshd will not be permitted to bind it: sudo semanage port -a -t ssh_port_t -p tcp 2222. The semanage tool comes from policycoreutils-python-utils. Skipping this produces a service that fails to start with a permission error that looks nothing like a SELinux problem.
    3. Change the port, restart, and test from a new terminal before closing port 22.

    One modern trap: Ubuntu 22.10 and later start sshd through systemd socket activation (ssh.socket), so the listening port is owned by systemd rather than by sshd. On 22.10 through 23.10 the port was migrated into /etc/systemd/system/ssh.socket.d/, and editing Port in sshd_config alone does nothing. On 24.04 LTS the port is pulled dynamically from the sshd configuration by a systemd generator, so an edit works — but only after sudo systemctl daemon-reload. Check which mode you are in with systemctl is-enabled ssh.socket, and always confirm the result with sudo ss -tlnp | grep ssh rather than assuming.

    Step 4: A Default-Deny Firewall

    The rule is simple: deny all inbound traffic, then open exactly the ports a real service listens on. Not "the ports I might need later". Later is when you open them.

    On Ubuntu and Debian, ufw is the path of least resistance:

    • sudo ufw default deny incoming
    • sudo ufw default allow outgoing
    • sudo ufw allow OpenSSH (or sudo ufw allow 2222/tcp if you moved the port)
    • sudo ufw allow 80/tcp and sudo ufw allow 443/tcp if this box serves web traffic
    • sudo ufw enable then sudo ufw status verbose

    On the RHEL family, firewalld is already running:

    • sudo firewall-cmd --permanent --add-service=ssh
    • sudo firewall-cmd --permanent --add-service=http --add-service=https
    • sudo firewall-cmd --reload then sudo firewall-cmd --list-all

    Then audit what is actually listening: sudo ss -tulpn. Every line binding 0.0.0.0 or [::] is reachable from the internet if the firewall permits it. A database, a cache, or a metrics exporter on a public interface is the classic way a hardened SSH setup gets bypassed entirely.

    The Docker exception nobody warns you about

    If you install Docker, ufw stops protecting your published container ports. Docker's own documentation is explicit: traffic to published ports is diverted in the nat table before it reaches the INPUT chain ufw uses, so your firewall rules are effectively ignored. Run a container with -p 8080:80 and port 8080 is on the public internet no matter what ufw status claims.

    The straightforward fix is to bind published ports to loopback — -p 127.0.0.1:8080:80 — and put a reverse proxy in front. Check your assumptions from outside the box with nmap from another machine, because ss run locally will not tell you what the firewall is doing.

    Need more power? Move up to a VPS

    Dedicated resources, full root access, and NVMe storage. From $3.49/mo, ready in minutes.

    Compare VPS plans

    Step 5: Fail2ban

    Fail2ban watches authentication logs and temporarily bans IPs that fail repeatedly. With password authentication already disabled it is not stopping a break-in so much as stopping the resource drain and log spam of thousands of daily attempts. That is still worth having.

    Install it (sudo apt install fail2ban, or sudo dnf install fail2ban after enabling EPEL on the RHEL family), then never edit jail.conf — package upgrades overwrite it. Create /etc/fail2ban/jail.local instead, with a [DEFAULT] section setting bantime = 1h, findtime = 10m and maxretry = 3, and an [sshd] section with enabled = true. The shipped defaults are a 10 minute ban and 5 retries, which is gentler than most people want.

    Here is the part that trips people up on modern Debian. From Debian 12 onward rsyslog is no longer installed by default, so /var/log/auth.log may not exist at all and logs live only in the systemd journal. Fail2ban's default backend = auto can then fail to find a log source and the sshd jail will not start. Add backend = systemd to your [DEFAULT] block and it reads the journal directly.

    Then confirm it is genuinely running, because a Fail2ban that failed silently is worse than none — it produces false confidence. Run sudo systemctl restart fail2ban, then sudo fail2ban-client status to list active jails and sudo fail2ban-client status sshd to see the ban counters. If the jail is missing from that list, it did not start, regardless of what the service status says.

    Add your office or home IP to ignoreip if it is static. Banning yourself during a bad-password afternoon is a rite of passage you can skip.

    Step 6: Automatic Security Updates

    Most servers that get compromised are not victims of anything clever. They are running a package with a fix that shipped months earlier. Automating security patching is the one control that keeps working while you are on holiday.

    Debian and Ubuntu. Install unattended-upgrades, then run sudo dpkg-reconfigure --priority=low unattended-upgrades and answer yes. That writes /etc/apt/apt.conf.d/20auto-upgrades containing APT::Periodic::Update-Package-Lists "1"; and APT::Periodic::Unattended-Upgrade "1";. Confirm with apt-config dump APT::Periodic::Unattended-Upgrade.

    By default only the security pocket is applied, which is the behaviour you want on a production box. Review /etc/apt/apt.conf.d/50unattended-upgrades to see the enabled origins and to decide on unattended reboots. If you enable Unattended-Upgrade::Automatic-Reboot "true", pair it with Automatic-Reboot-Time so kernel updates do not restart your server mid-afternoon.

    RHEL family. Install dnf-automatic and edit /etc/dnf/automatic.conf. Set upgrade_type = security to restrict it to security advisories and apply_updates = yes to actually install rather than merely notify. Then enable the timer: sudo systemctl enable --now dnf-automatic.timer, which follows your config file. There are also purpose-built timers — dnf-automatic-notifyonly.timer, dnf-automatic-download.timer and dnf-automatic-install.timer — if you prefer the behaviour fixed by the unit rather than by config. Enable exactly one. Verify with systemctl list-timers | grep dnf. On very recent releases built on DNF 5, check whether your distribution ships the automatic plugin under a different package name before assuming.

    Automation does not cover everything. Application dependencies — your Composer packages, npm modules, WordPress plugins — are outside the OS package manager and stay your responsibility.

    Step 7: Time Sync and Swap

    Two unglamorous items that quietly decide whether the rest of your work holds up.

    Time synchronisation

    Clock drift breaks TLS certificate validation, invalidates TOTP two-factor codes, corrupts the ordering of your logs during an investigation, and causes mysterious authentication failures against external APIs. Check with timedatectl and look for "System clock synchronized: yes". Ubuntu has historically used systemd-timesyncd, with chrony shipping as the default client from Ubuntu 25.10; the RHEL family uses chrony. On a chrony system, chronyc tracking and chronyc sources show you the real picture. Set the timezone explicitly with sudo timedatectl set-timezone UTC — UTC on servers saves you from daylight-saving log confusion later.

    Swap, and why its absence kills MySQL

    Many VPS images ship with no swap at all. Here is what that means in practice. When Linux runs out of memory and has nowhere to page out to, the kernel OOM killer chooses a process to terminate. Its scoring heuristic favours killing the process using the most memory — which, on a typical web server, is your database. MySQL or MariaDB disappears, your site starts throwing connection errors, and nothing in the database log explains why, because the process never got a chance to log anything. The evidence is in dmesg or journalctl -k, where you will find a line naming the killed process.

    A modest swap file gives the kernel somewhere to put cold pages during a spike, so a brief burst causes a slow minute instead of a dead database. On a small VPS, roughly one to two times RAM is a reasonable starting point, capped by how much disk you can spare — on a 25 GB plan, 2 GB of swap is sensible, not 16 GB.

    • sudo fallocate -l 2G /swapfile
    • sudo chmod 600 /swapfile
    • sudo mkswap /swapfile
    • sudo swapon /swapfile
    • Add /swapfile none swap sw 0 0 to /etc/fstab so it survives reboot
    • sudo sysctl vm.swappiness=10, and persist it in /etc/sysctl.d/99-swappiness.conf

    A low swappiness value tells the kernel to prefer RAM and use swap as an emergency buffer rather than a routine tier — which is exactly the role you want it in on NVMe-backed storage. Confirm with free -h and swapon --show.

    Swap is a stopgap, not a capacity plan. If you are swapping constantly, you need more RAM, and our breakdown of what cheap VPS plans actually deliver covers how to size one honestly.

    Step 8: The Web Layer

    TLS with automatic renewal

    Certbot's own recommendation on most systems is the snap package: sudo snap install --classic certbot followed by sudo ln -s /snap/bin/certbot /usr/local/bin/certbot. Where snap is not appropriate, the EFF documents a pip-in-a-virtualenv install under /opt/certbot/. Distribution packages exist too and are fine, they just lag upstream.

    Issue with sudo certbot --nginx or sudo certbot --apache and let it edit the vhost. The critical step is the one people skip: sudo certbot renew --dry-run. Certbot installs a systemd timer or cron job that renews automatically, but the dry run is what proves the renewal path actually works — with your current firewall rules, your current vhost, and your current DNS. An expired certificate on a Sunday morning is nearly always a renewal that had been silently failing for two months.

    Security headers

    Following Mozilla's web security guidance, a reasonable baseline is Strict-Transport-Security: max-age=63072000; includeSubDomains, X-Content-Type-Options: nosniff, X-Frame-Options: DENY (or SAMEORIGIN if you legitimately frame your own pages), and Referrer-Policy: strict-origin-when-cross-origin. A Content-Security-Policy is more valuable than all of those combined and considerably harder to get right — deploy it in report-only mode first, or you will break your own site.

    One warning on HSTS: the preload directive is genuinely hard to reverse. Do not add it until you are certain every subdomain will serve HTTPS indefinitely.

    Stop advertising your version numbers

    Set server_tokens off; in the http block on nginx — the documented effect is that nginx stops emitting its version on error pages and in the Server response header. On Apache, set ServerTokens Prod and ServerSignature Off. For PHP, set expose_php = Off in php.ini to drop the X-Powered-By header.

    Be clear-eyed about the value: this is fingerprinting resistance, not protection. It removes the free lookup that lets a scanner match your exact version against a list of known issues, which meaningfully reduces automated targeting. It does nothing against anyone willing to probe behaviour. Patch anyway.

    Step 9: Database Hardening

    An exposed database is the shortest path from "someone scanned my IP" to "someone has my customer table".

    Start by binding to loopback. In your MySQL or MariaDB config, set bind-address = 127.0.0.1; for PostgreSQL, listen_addresses = 'localhost'; for Redis, bind 127.0.0.1 plus requirepass. If the app runs on the same VPS, the database has no business listening on a public interface at all. Confirm with sudo ss -tulpn | grep 3306 and check that it shows 127.0.0.1:3306, not 0.0.0.0:3306.

    Then run the guided cleanup: sudo mysql_secure_installation (MariaDB ships the same tool as mariadb-secure-installation). It sets a root password, removes anonymous accounts, disallows remote root login, and drops the test database — which by default is accessible to every user, including anonymous ones.

    Finally, least privilege for the application account. Your app does not need ALL PRIVILEGES and it certainly does not need GRANT OPTION. Create a dedicated user scoped to one database and one host, along the lines of granting SELECT, INSERT, UPDATE, DELETE on appdb.* to a user identified as 'appuser'@'localhost'. When an SQL injection bug eventually appears in your code, the difference between that grant and ALL PRIVILEGES is the difference between a data leak and a total server compromise.

    If your database must accept remote connections, do not open port 3306 to the world. Use an SSH tunnel, a private network, or a firewall rule restricted to one source IP.

    Step 10: Backups You Have Actually Restored

    Say it plainly: a backup stored on the same VPS is not a backup. It shares a fate with the thing it is protecting. Disk corruption, a compromised root account, an accidental rm in the wrong directory, or a billing lapse takes both. Ransomware operators specifically look for and delete local backups before they encrypt.

    Aim for the familiar 3-2-1 shape: three copies, on two kinds of media or services, one of them off-site. On a VPS that realistically means the live data, a provider snapshot, and an encrypted copy pushed to object storage somewhere else entirely.

    Practical notes that matter more than the tooling choice:

    • Dump databases properly rather than copying raw data files from a running server. mysqldump --single-transaction gives you a consistent snapshot of InnoDB tables without locking the site.
    • Encrypt before upload if the destination is third-party storage. Tools like restic and BorgBackup handle encryption and deduplication for you.
    • Use append-only or write-once credentials for the backup target where the provider supports it. If the VPS is compromised and holds delete permissions, so does the attacker.
    • Keep more than one generation. Corruption discovered on Thursday is useless if Wednesday already overwrote the last good copy.
    • Monitor the backup job itself. A cron job that has failed silently for six weeks is the single most common backup failure mode there is.

    The restore drill

    Put this in your calendar quarterly. Provision a second VPS — the smallest plan is fine, and you can destroy it an hour later. Restore the most recent backup to it. Bring the application up. Load the front page and log in. Note how long the whole thing took, and write down every step you had to improvise.

    The first drill almost always surfaces something: a missing web server config that was never in the backup set, an environment file with credentials that only ever existed on the original box, a database dump that restores but is missing a table, a DNS assumption nobody documented. Finding that during a drill costs you an hour. Finding it during an actual outage costs you the weekend.

    Ongoing: Monitoring and Log Review

    Hardening is a state you leave, not a state you reach. Treat this VPS security checklist as a recurring routine rather than a one-time task, and a short weekly pass keeps it honest.

    Weekly, take five minutes to check: sudo fail2ban-client status sshd for ban counts, lastb | head -20 for failed logins, last | head -20 for successful ones (any login you cannot account for is an incident), df -h for disk headroom, and sudo ss -tulpn to catch any new listener you did not intend. On the RHEL family, sudo journalctl -u sshd --since "7 days ago" | grep -i "accepted" gives you the accepted-login picture quickly.

    Monthly, verify that unattended upgrades are still applying (grep -i upgrade /var/log/unattended-upgrades/unattended-upgrades.log on Debian and Ubuntu), confirm your certificate renewal dry run still passes, and confirm the last backup actually completed.

    Set up external uptime monitoring as well. Monitoring that runs on the server cannot alert you when the server is down, which is the only time you truly need it.

    DDoS protection is not host hardening

    Devoster VPS plans include DDoS protection at the network edge. That is real and useful: it absorbs volumetric floods before they saturate your link, which is a problem you cannot solve from inside a 1 Gbps guest no matter how well configured it is.

    It is also a completely different layer from everything in this article. Edge filtering does not care whether your SSH password is admin123, whether MySQL is bound to 0.0.0.0, or whether your WordPress install is two years out of date. Those attacks arrive as legitimate-looking traffic on ports you deliberately opened. Network protection and host hardening solve non-overlapping problems, and you need both. Our VPS hosting plans give you the network side; this checklist is the other half.

    If You Think You Are Compromised: Rebuild, Do Not Clean

    This is the section most hosting blogs get wrong, so here it is bluntly: if a server has been rooted, you rebuild it. You do not clean it.

    Once an attacker has had root, you cannot trust anything the machine tells you. ps can be replaced to hide a process. ls can be replaced to hide a file. A kernel module can hide both from every tool you run. Removing the webshell you found tells you nothing about the cron job, the added SSH key, the modified systemd unit, or the second webshell you did not find. "I cleaned it and it seems fine" is how the same server gets compromised again three weeks later.

    A workable sequence:

    1. Isolate. Take the box off the network, or firewall it down to your own IP. Do not power it off if you intend to investigate — you lose memory state.
    2. Snapshot. Take a full image for forensics and evidence before you change anything.
    3. Rotate every credential. Database passwords, API keys, SSH keys, mail credentials, payment tokens, anything that ever sat in an environment file or a config on that machine. Assume all of it is public.
    4. Rebuild from a clean OS image. Not from a snapshot taken after the intrusion — you would be restoring the intrusion.
    5. Restore data, not binaries. Bring back database dumps and user uploads. Reinstall applications from source control or official packages. Inspect uploaded files for anything executable.
    6. Work out how they got in before you go live again, or you will simply be re-exploited. Usually it is an unpatched application, a leaked credential, or an exposed service — not a kernel zero-day.

    The good news is that if you have done step 10 properly, rebuilding is a couple of hours of unpleasant but predictable work rather than a business-ending event. That is the real reason to run restore drills.

    Distro Command Reference

    Task Debian / Ubuntu RHEL / Rocky / AlmaLinux
    Update all packages sudo apt update && sudo apt upgrade sudo dnf upgrade
    Admin group sudo wheel
    SSH service name ssh (plus ssh.socket on 22.10+) sshd
    Firewall ufw firewalld
    Open HTTPS sudo ufw allow 443/tcp sudo firewall-cmd --permanent --add-service=https
    Auto security updates unattended-upgrades dnf-automatic + timer
    Fail2ban source Main repo EPEL
    Mandatory access control AppArmor SELinux
    Non-standard SSH port needs Firewall rule (+ socket unit awareness) Firewall rule + semanage port
    Time sync systemd-timesyncd (chrony from 25.10) chrony

    When a VPS Is the Wrong Choice

    Everything above is perhaps ninety minutes the first time and fifteen minutes a month afterwards. That is genuinely not much. But it is not zero, and it never becomes zero.

    Skip the VPS if any of these describe you. You are running a single brochure site or small WordPress install and have no interest in system administration — shared hosting handles OS patching, firewalling and TLS for you, and does it competently. You need someone accountable at 3 a.m. when the database will not start; unmanaged means the console is yours and so is the outage, whereas managed hosting puts a human on the other side. Or your team simply has no Linux experience — a badly maintained VPS is considerably less secure than well-run shared hosting, and the price difference does not begin to cover a breach.

    Take the VPS if you need root for a specific reason: custom software stacks, particular PHP or Node versions, background workers, containers, staging environments, or predictable dedicated resources. Root access is the product, and knowing how to secure a VPS is what makes that access an asset rather than a liability. This checklist is what root access costs.

    If you are unsure which side of that line you are on, ask us before you buy. We would rather put you on the right plan than sell you a server you will not maintain.

    Have questions? Get in touch

    Not sure which plan fits or how crypto billing works for you? We're here to help.

    Contact us

    Frequently Asked Questions

    How long does it take to secure a new VPS?

    The core items — sudo user, SSH keys, hardened sshd, default-deny firewall, Fail2ban and automatic updates — take about thirty minutes if you are comfortable at a terminal, and an hour or two the first time. The web, database and backup layers add another hour. Budget fifteen minutes a month afterwards for log review and verification.

    Is changing the SSH port actually worth doing?

    For log noise, yes: the vast majority of automated SSH scanning only ever touches port 22, so moving off it makes your authentication logs readable. For security, no. A port scan finds the new port immediately. Do it after keys, firewall and Fail2ban are in place, and never treat it as a replacement for any of them.

    Do I still need Fail2ban if I disabled password authentication?

    It is optional at that point, but still useful. Key-only authentication means brute force cannot succeed, yet thousands of daily attempts still consume CPU, fill logs and hide real events. Fail2ban also protects other services — web application login endpoints, mail, FTP — where passwords are unavoidable. Low cost, real benefit.

    What happens if I lock myself out of my VPS?

    Most providers offer console or VNC access that bypasses SSH entirely, letting you log in as if you were at a keyboard and undo the change. Find that feature in your control panel before you need it. Failing that, rescue mode or a rebuild is the fallback — which is another argument for tested off-box backups.

    Does Devoster secure my VPS for me?

    No. Devoster VPS plans are unmanaged with full root access, so the operating system, firewall, updates and application security are yours. We provide the KVM virtualisation, NVMe storage, network, DDoS protection at the edge and free migration. If you want the operating system managed for you, look at managed or shared hosting instead.

    Is a root password ever acceptable if it is very strong?

    It is defensible but strictly worse than keys. A strong password is still guessable in principle, is replayable if phished or keylogged, and can leak through a compromised client. SSH keys are not guessable, and a passphrase-protected key remains useless to anyone who copies the file. There is no practical scenario where passwords beat keys for server login.

    How much swap should a small VPS have?

    Roughly one to two times RAM is a sensible starting point on small plans, bounded by available disk — 2 GB of swap on a 25 GB volume, not 16 GB. Pair it with vm.swappiness=10 so the kernel treats swap as an emergency buffer. If the box swaps continuously rather than occasionally, buy more RAM; swap is a safety net, not capacity.

    Ready to Experience Devoster?

    Join thousands of satisfied customers with transparent pricing and lightning-fast hosting.

    We value your privacy

    We use essential cookies to make our site work, and optional analytics cookies to understand how you use Devoster and improve our services. You can accept all cookies, or adjust your preferences.

    Read more in our Cookie Policy and Privacy Policy. You can change your choices at any time.