{"id":2884,"date":"2026-10-22T12:19:07","date_gmt":"2026-10-22T12:19:07","guid":{"rendered":"https:\/\/hostry.com\/blog\/?p=2884"},"modified":"2026-10-22T12:19:09","modified_gmt":"2026-10-22T12:19:09","slug":"secure-new-linux-vps-first-30-minutes","status":"publish","type":"post","link":"https:\/\/hostry.com\/blog\/secure-new-linux-vps-first-30-minutes\/","title":{"rendered":"How to Secure a New Linux VPS in the First 30 Minutes (Ubuntu 24.04)"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"892\" height=\"508\" src=\"https:\/\/hostry.com\/blog\/wp-content\/uploads\/2026\/10\/secure-new-linux-vps_main.png\" alt=\"Hostry: how to secure a new Linux VPS \u2013 terminal and security shield\" class=\"wp-image-2885\" srcset=\"https:\/\/hostry.com\/blog\/wp-content\/uploads\/2026\/10\/secure-new-linux-vps_main.png 892w, https:\/\/hostry.com\/blog\/wp-content\/uploads\/2026\/10\/secure-new-linux-vps_main-300x171.png 300w, https:\/\/hostry.com\/blog\/wp-content\/uploads\/2026\/10\/secure-new-linux-vps_main-450x256.png 450w, https:\/\/hostry.com\/blog\/wp-content\/uploads\/2026\/10\/secure-new-linux-vps_main-768x437.png 768w\" sizes=\"auto, (max-width: 892px) 100vw, 892px\" \/><\/figure>\n\n\n\n<pre class=\"wp-block-preformatted\" style=\"font-size:14px\"><em><strong>A fresh server is online for minutes before the first bot finds it. Thirty minutes of hardening decides whether that bot leaves empty-handed.<\/strong><\/em><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A new VPS is reachable from the whole internet the moment it boots. Automated scanners start probing port 22 within minutes, long before you have deployed your application. The good news: <strong>about 30 minutes of basic hardening blocks the vast majority of these attacks<\/strong>, and every step below is a copy-paste command.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide uses <strong>Ubuntu 24.04 LTS<\/strong>, the most common choice for a fresh <strong><a href=\"https:\/\/hostry.com\/products\/vps\/\">KVM VPS<\/a><\/strong>. Debian 12 works almost identically; differences are noted where they matter.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What you will set up<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Fresh packages<\/strong>: known vulnerabilities patched before anything else runs.<\/li><li><strong>A non-root sudo user<\/strong>: you stop working as <em>root<\/em> day to day.<\/li><li><strong>SSH key authentication<\/strong>: passwords can no longer be brute-forced.<\/li><li><strong>A firewall (UFW)<\/strong>: only the ports you actually use are open.<\/li><li><strong>Fail2ban<\/strong>: repeated failed logins get the source IP banned.<\/li><li><strong>Automatic security updates<\/strong>: critical patches install themselves.<\/li><\/ul>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Every service you do not run, every port you do not open and every privilege you do not grant is one less thing an attacker can use.<\/p><cite>The principle of least privilege<\/cite><\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Before you start<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You need the server IP address and the root password (or root SSH key) from your control panel, plus a terminal: <span class=\"highlighted\">Terminal<\/span> on macOS and Linux, or <span class=\"highlighted\">Windows Terminal<\/span> \/ PowerShell on Windows 10 and 11, which ship with an OpenSSH client.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Important:<\/strong> keep your first SSH session open until the very end. If a change locks you out, that session is your way back in. Most providers, Hostry included, also offer a web console (VNC) in the control panel as a last resort.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1. Update the system<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Log in as root and install all pending updates:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh root@203.0.113.10\napt update &amp;&amp; apt upgrade -y<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If the upgrade installed a new kernel, reboot with <span class=\"highlighted\">reboot<\/span> and reconnect. Replace <span class=\"highlighted\">203.0.113.10<\/span> with your own server IP throughout this guide.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2. Create a sudo user<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Working as root means a single typo or compromised session has unlimited power. Create a regular user and give it administrative rights through <em>sudo<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>adduser deploy\nusermod -aG sudo deploy<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Pick any username you like instead of <span class=\"highlighted\">deploy<\/span>, and set a strong password: you will need it for sudo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3. Switch to SSH keys<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\" style=\"font-size:14px\"><strong>Generate a key on your computer<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Run this <strong>on your local machine<\/strong>, not on the server. Ed25519 keys are short, fast and supported by every modern OpenSSH version:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh-keygen -t ed25519 -C \"you@example.com\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\" style=\"font-size:14px\"><strong>Copy the key to the server<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ssh-copy-id deploy@203.0.113.10<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On Windows, where <span class=\"highlighted\">ssh-copy-id<\/span> is not available, paste the contents of <span class=\"highlighted\">%USERPROFILE%\\.ssh\\id_ed25519.pub<\/span> into <span class=\"highlighted\">\/home\/deploy\/.ssh\/authorized_keys<\/span> on the server. Then open a <strong>new<\/strong> terminal and check that <span class=\"highlighted\">ssh deploy@203.0.113.10<\/span> logs you in without a password.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\" style=\"font-size:14px\"><strong>Disable root login and passwords<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On Ubuntu 24.04, cloud images often ship a drop-in file that re-enables password logins, so put your settings in a file that is read first:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tee \/etc\/ssh\/sshd_config.d\/00-hardening.conf &gt;\/dev\/null &lt;&lt;'EOF'\nPermitRootLogin no\nPasswordAuthentication no\nKbdInteractiveAuthentication no\nEOF\n\nsudo sshd -t &amp;&amp; sudo systemctl reload ssh<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">OpenSSH applies the <em>first<\/em> value it finds for each option, which is why the file name starts with <span class=\"highlighted\">00-<\/span>. The <span class=\"highlighted\">sshd -t<\/span> check validates the syntax before reload, so a typo cannot take SSH down. On Debian the service is called <span class=\"highlighted\">sshd<\/span> instead of <span class=\"highlighted\">ssh<\/span>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4. Turn on the UFW firewall<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">UFW is a friendly front end for the Linux firewall and comes preinstalled on Ubuntu. <strong>Allow SSH before enabling it<\/strong>, or you will cut off your own connection:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw default deny incoming\nsudo ufw default allow outgoing\nsudo ufw allow OpenSSH\nsudo ufw allow 80,443\/tcp    # only if this server hosts a website\nsudo ufw enable\nsudo ufw status verbose<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Open further ports only when a service really needs them, for example <span class=\"highlighted\">sudo ufw allow 25565\/tcp<\/span> for a Minecraft server.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5. Install Fail2ban<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Even with passwords disabled, bots will keep knocking. Fail2ban watches the SSH log and temporarily bans IP addresses that fail too many times, which also keeps your logs readable.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install -y fail2ban python3-systemd\n\nsudo tee \/etc\/fail2ban\/jail.local &gt;\/dev\/null &lt;&lt;'EOF'\n[sshd]\nenabled  = true\nbackend  = systemd\nmaxretry = 5\nfindtime = 10m\nbantime  = 1h\nEOF\n\nsudo systemctl enable --now fail2ban\nsudo fail2ban-client status sshd<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Step 6. Enable automatic security updates<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Most real-world breaches exploit vulnerabilities that already have a patch. Let the server install security updates on its own:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt install -y unattended-upgrades\nsudo dpkg-reconfigure --priority=low unattended-upgrades<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Answer <strong>Yes<\/strong> when asked. Security updates from the Ubuntu archive will now be applied daily.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 7. Verify what is exposed<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Finally, list every service listening on the network and make sure there are no surprises:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ss -tulpn<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Anything bound to <span class=\"highlighted\">0.0.0.0<\/span> or <span class=\"highlighted\">[::]<\/span> is reachable from outside unless the firewall blocks it. Databases such as MySQL or Redis should normally listen on <span class=\"highlighted\">127.0.0.1<\/span> only.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">The checklist at a glance<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Step<\/th><th>Protects against<\/th><th>Time<\/th><\/tr><\/thead><tbody><tr><td>System update<\/td><td>Known, already patched vulnerabilities<\/td><td>3\u20135 min<\/td><\/tr><tr><td>Sudo user<\/td><td>Damage from mistakes and stolen root sessions<\/td><td>2 min<\/td><\/tr><tr><td>SSH keys, no root login<\/td><td>Password brute-force attacks<\/td><td>5 min<\/td><\/tr><tr><td>UFW firewall<\/td><td>Accidentally exposed services<\/td><td>3 min<\/td><\/tr><tr><td>Fail2ban<\/td><td>Persistent scanners and log noise<\/td><td>5 min<\/td><\/tr><tr><td>Unattended upgrades<\/td><td>New vulnerabilities after launch<\/td><td>2 min<\/td><\/tr><tr><td>Port audit<\/td><td>Forgotten or misconfigured services<\/td><td>2 min<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">What to do next<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Basic hardening is the foundation, not the finish line. Depending on what the server runs, the next steps are usually:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><strong>Set up backups<\/strong> and test a restore at least once. A backup you have never restored is a hope, not a backup.<\/li><li><strong>Add TLS<\/strong> to every public website. A <strong><a href=\"https:\/\/hostry.com\/solutions\/ssl-for-free\/\">free Let&#8217;s Encrypt certificate<\/a><\/strong> takes a couple of minutes.<\/li><li><strong>Run a security audit<\/strong> with Lynis \u2013 see our guide on <strong><a href=\"https:\/\/hostry.com\/blog\/superlative-lynis-tool-for-security-on-ubuntu-22-04\/\">using Lynis on Ubuntu<\/a><\/strong>.<\/li><li><strong>Hide SSH from scanners entirely<\/strong> with <strong><a href=\"https:\/\/hostry.com\/blog\/mighty-securing-your-server-with-port-knocking\/\">port knocking<\/a><\/strong> if the server is a high-value target.<\/li><\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">FAQ<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Should I change the default SSH port?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">It reduces log noise from bots but is not real protection: a port scan finds the new port in seconds. With key-only authentication and Fail2ban in place, keeping port 22 is perfectly fine.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Do these steps work on Debian?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. On Debian 12, install UFW first with <span class=\"highlighted\">apt install ufw<\/span> and use <span class=\"highlighted\">systemctl reload sshd<\/span> for SSH. Everything else is identical.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Is a managed server a better option?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If you would rather not maintain the operating system yourself, a <strong><a href=\"https:\/\/hostry.com\/products\/dedicated-servers\/\">managed dedicated server<\/a><\/strong> or <strong><a href=\"https:\/\/hostry.com\/products\/hosting\/\">cPanel web hosting<\/a><\/strong> moves most of this work to the provider. For full control at the lowest cost, a self-managed VPS with the checklist above is hard to beat.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Ready to try it?<\/strong> <strong><a href=\"https:\/\/hostry.com\/products\/vps\/\">Deploy a KVM VPS<\/a><\/strong> with full root access in one of 18+ locations, ready in seconds, and run through this checklist on a clean server.<\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>A practical, copy-paste checklist for hardening a fresh Ubuntu 24.04 VPS: updates, a sudo user, SSH keys, firewall, Fail2ban and automatic security pa&#8230;<\/p>\n","protected":false},"author":6,"featured_media":2886,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[127,1],"tags":[],"class_list":["post-2884","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security","category-virtual-private-server"],"read_time":4,"_links":{"self":[{"href":"https:\/\/hostry.com\/blog\/wp-json\/wp\/v2\/posts\/2884","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hostry.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hostry.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hostry.com\/blog\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/hostry.com\/blog\/wp-json\/wp\/v2\/comments?post=2884"}],"version-history":[{"count":1,"href":"https:\/\/hostry.com\/blog\/wp-json\/wp\/v2\/posts\/2884\/revisions"}],"predecessor-version":[{"id":2887,"href":"https:\/\/hostry.com\/blog\/wp-json\/wp\/v2\/posts\/2884\/revisions\/2887"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hostry.com\/blog\/wp-json\/wp\/v2\/media\/2886"}],"wp:attachment":[{"href":"https:\/\/hostry.com\/blog\/wp-json\/wp\/v2\/media?parent=2884"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hostry.com\/blog\/wp-json\/wp\/v2\/categories?post=2884"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hostry.com\/blog\/wp-json\/wp\/v2\/tags?post=2884"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}