{"id":152,"date":"2026-06-06T09:02:00","date_gmt":"2026-06-06T09:02:00","guid":{"rendered":"https:\/\/blog.offshorekaka.in\/?p=152"},"modified":"2026-08-27T05:39:04","modified_gmt":"2026-08-27T05:39:04","slug":"secure-offshore-vps-server-checklist","status":"publish","type":"post","link":"https:\/\/offshorekaka.in\/blog\/secure-offshore-vps-server-checklist\/","title":{"rendered":"How to Secure an Offshore VPS Server: Practical Checklist"},"content":{"rendered":"<div class=\"ok-pro-panel\">\n<p><span class=\"ok-pro-kicker\">Server Security<\/span><\/p>\n<h2>The first hour on a new server<\/h2>\n<p>A brand new <a href=\"https:\/\/offshorekaka.in\/offshore-vps-server\/\">offshore VPS<\/a> starts getting probed within minutes of the IP going live. Not targeted at you, just automated scanners working through address ranges looking for port 22 with a password prompt on it.<\/p>\n<p>Nothing here is clever. It is five things, in order, and it takes under half an hour. Doing them in order matters, because a couple of the steps can lock you out if you do them the wrong way round.<\/p>\n<div class=\"ok-pro-grid\">\n<div class=\"ok-pro-card\"><strong>Time<\/strong><span>About 25 minutes.<\/span><\/div>\n<div class=\"ok-pro-card\"><strong>Order matters<\/strong><span>User before SSH keys. Firewall rules before enable.<\/span><\/div>\n<div class=\"ok-pro-card\"><strong>Keep open<\/strong><span>Your current SSH session, throughout.<\/span><\/div>\n<\/div>\n<\/div>\n<div class=\"ok-toc\"><strong>On this page<\/strong><a href=\"#one\">1. Patch it<\/a><a href=\"#two\">2. Stop using root<\/a><a href=\"#three\">3. Key-only SSH<\/a><a href=\"#four\">4. Firewall<\/a><a href=\"#five\">5. Fail2ban<\/a><a href=\"#after\">Worth doing after<\/a><a href=\"#faq\">FAQ<\/a><\/div>\n<h2 id=\"one\">1. Patch it<\/h2>\n<pre><code>apt update &amp;&amp; apt upgrade -y<\/code><\/pre>\n<p>Provider images are built once and reused for months, so a fresh VPS is often behind on security updates from day one. Do this before anything else.<\/p>\n<p>Then turn on automatic security patching, so this does not depend on you remembering:<\/p>\n<pre><code>apt install unattended-upgrades -y\ndpkg-reconfigure --priority=low unattended-upgrades<\/code><\/pre>\n<p>On AlmaLinux or Rocky the equivalent is <code>dnf install dnf-automatic<\/code> followed by enabling its timer.<\/p>\n<h2 id=\"two\">2. Stop using root<\/h2>\n<pre><code>adduser deployer\nusermod -aG sudo deployer<\/code><\/pre>\n<p>Two reasons this comes before the SSH work. Root is the one username every attacker already knows, so removing it as a login target removes most of their guesses. And sudo leaves a trail in the logs, so you can see what was run and when.<\/p>\n<p>Use <code>usermod -aG wheel deployer<\/code> on AlmaLinux and Rocky, where the admin group is called wheel rather than sudo.<\/p>\n<p><strong>Test that sudo works for the new user before moving on.<\/strong> Log in as <code>deployer<\/code> in a second window and run <code>sudo whoami<\/code>. If it does not print root, fix that now, while you still have a root session open.<\/p>\n<h2 id=\"three\">3. Key-only SSH<\/h2>\n<p>Now that the new user exists and can sudo, switch to keys and close password login.<\/p>\n<pre><code>ssh-keygen -t ed25519\nssh-copy-id deployer@your-server-ip<\/code><\/pre>\n<figure class=\"wp-block-image size-large ok-inline-visual\"><img decoding=\"async\" src=\"https:\/\/offshorekaka.in\/blog\/wp-content\/uploads\/2026\/08\/ok-ssh-hardening-done.webp\" alt=\"Terminal confirming root login and password authentication are both disabled and SSH is running\" loading=\"lazy\" width=\"2296\" height=\"630\"><figcaption>What you want <code>sshd -T<\/code> to say once this step is finished.<\/figcaption><\/figure>\n<p>The full walkthrough, including the override file that catches most people out, is in our <a href=\"https:\/\/offshorekaka.in\/blog\/ssh-hardening-for-offshore-vps\/\">SSH hardening guide<\/a>. The short version is that on modern Ubuntu, a file in <code>\/etc\/ssh\/sshd_config.d\/<\/code> can quietly re-enable password login after you have disabled it in the main config.<\/p>\n<h2 id=\"four\">4. Firewall<\/h2>\n<pre><code>ufw default deny incoming\nufw default allow outgoing\nufw allow OpenSSH\nufw allow 80\/tcp\nufw allow 443\/tcp\nufw enable<\/code><\/pre>\n<figure class=\"wp-block-image size-large ok-inline-visual\"><img decoding=\"async\" src=\"https:\/\/offshorekaka.in\/blog\/wp-content\/uploads\/2026\/08\/ok-firewall-ufw-status.webp\" alt=\"UFW status showing default deny incoming with only SSH, HTTP and HTTPS allowed\" loading=\"lazy\" width=\"2296\" height=\"824\"><figcaption>Three ports open, everything else denied.<\/figcaption><\/figure>\n<p>The SSH line has to come before <code>ufw enable<\/code>. There is no way around that and it is where people lock themselves out. If you moved SSH to a custom port in step 3, allow that number instead of the OpenSSH profile. More detail in the <a href=\"https:\/\/offshorekaka.in\/blog\/firewall-setup-for-offshore-vps\/\">firewall guide<\/a>.<\/p>\n<h2 id=\"five\">5. Fail2ban<\/h2>\n<pre><code>apt install fail2ban -y\nsystemctl enable --now fail2ban\nfail2ban-client status sshd<\/code><\/pre>\n<figure class=\"wp-block-image size-large ok-inline-visual\"><img decoding=\"async\" src=\"https:\/\/offshorekaka.in\/blog\/wp-content\/uploads\/2026\/08\/ok-fail2ban-status.webp\" alt=\"Fail2ban status output showing the sshd jail with banned IP addresses and total failure count\" loading=\"lazy\" width=\"2296\" height=\"866\"><figcaption>The total failed count is a good measure of how much noise you were absorbing.<\/figcaption><\/figure>\n<p>With password login already off, fail2ban has less to do, but it still cuts off the slow scanners that keep knocking. It also works on web logs, so you can use it against WordPress login attempts later.<\/p>\n<h2 id=\"after\">Worth doing after the first hour<\/h2>\n<ul>\n<li><strong>Bind the database to localhost.<\/strong> Check with <code>ss -tulpn | grep 3306<\/code>. If it says <code>0.0.0.0<\/code>, set <code>bind-address = 127.0.0.1<\/code> and restart it.<\/li>\n<li><strong>Set up backups.<\/strong> Security work assumes you can get back. Our <a href=\"https:\/\/offshorekaka.in\/blog\/backup-strategy-for-offshore-servers\/\">backup guide<\/a> covers doing it properly.<\/li>\n<li><strong>Turn on monitoring.<\/strong> You want to hear about a full disk before the site goes down. The <a href=\"https:\/\/offshorekaka.in\/blog\/offshore-server-monitoring-guide\/\">monitoring guide<\/a> has the basics.<\/li>\n<li><strong>Remove what you do not use.<\/strong> Every listening service is a way in. If the image shipped with a mail daemon and you are not sending mail, uninstall it.<\/li>\n<\/ul>\n<h2 id=\"test\">How to check it all took<\/h2>\n<ol>\n<li><code>sshd -T | grep -Ei 'permitrootlogin|passwordauth'<\/code> returns no for both.<\/li>\n<li><code>ssh root@your-server-ip<\/code> is refused.<\/li>\n<li><code>ufw status verbose<\/code> shows deny incoming and only the ports you named.<\/li>\n<li><code>fail2ban-client status sshd<\/code> reports the jail as active.<\/li>\n<li><code>ss -tulpn<\/code> shows nothing unexpected on 0.0.0.0.<\/li>\n<li><code>sudo whoami<\/code> as the new user prints root.<\/li>\n<\/ol>\n<h2 id=\"trouble\">When something breaks<\/h2>\n<table>\n<thead>\n<tr>\n<th>What you see<\/th>\n<th>Why<\/th>\n<th>Fix<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Locked out after enabling the firewall<\/td>\n<td>SSH was not allowed first<\/td>\n<td>Provider web console, <code>ufw disable<\/code>, allow SSH, enable again<\/td>\n<\/tr>\n<tr>\n<td>New user cannot sudo<\/td>\n<td>Wrong group for the distribution<\/td>\n<td>sudo on Debian and Ubuntu, wheel on RHEL family<\/td>\n<\/tr>\n<tr>\n<td>Password login still works<\/td>\n<td>Override file in <code>sshd_config.d<\/code><\/td>\n<td>Edit that file too, then restart SSH<\/td>\n<\/tr>\n<tr>\n<td>fail2ban will not start<\/td>\n<td>Log path does not exist on this distribution<\/td>\n<td>Point the jail at <code>\/var\/log\/secure<\/code> on RHEL family<\/td>\n<\/tr>\n<tr>\n<td>Everything works, then breaks after a reboot<\/td>\n<td>A service was configured but never enabled<\/td>\n<td><code>systemctl enable<\/code> each one and reboot to confirm<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"checklist\">Checklist<\/h2>\n<ul>\n<li>System fully updated, automatic security updates on.<\/li>\n<li>Non-root user created and sudo tested.<\/li>\n<li>SSH key login working before password login was disabled.<\/li>\n<li>Root login and password login both off, confirmed with <code>sshd -T<\/code>.<\/li>\n<li>Firewall on, SSH allowed before enabling.<\/li>\n<li>Fail2ban running with an active sshd jail.<\/li>\n<li>Database bound to localhost.<\/li>\n<li>Backups and monitoring scheduled.<\/li>\n<\/ul>\n<div class=\"ok-cta-box\">\n<p><strong>Starting a new server?<\/strong><\/p>\n<p>OffshoreKaka VPS plans give you full root from minute one, on KVM nodes in Amsterdam and Frankfurt, with a console in the panel for when a firewall rule goes wrong.<\/p>\n<p><a class=\"btn ok-cta-link\" href=\"https:\/\/offshorekaka.in\/offshore-vps-server\/\">See the VPS plans<\/a><\/p>\n<\/div>\n<h2 id=\"faq\">FAQ<\/h2>\n<h3>Is this enough on its own?<\/h3>\n<p>It handles the automated attacks, which is the overwhelming majority of what any small server sees. It does not protect a vulnerable application. If you run WordPress on top, that has its own maintenance to do, covered in our <a href=\"https:\/\/offshorekaka.in\/blog\/malware-scan-wordpress-offshore-hosting\/\">malware scanning guide<\/a>.<\/p>\n<h3>Do I need this if the host manages the server?<\/h3>\n<p>On shared hosting, no, the host handles it. On an unmanaged VPS, the server is yours from the moment it is created and nobody else is going to do it.<\/p>\n<h3>Will any of this improve my Google ranking?<\/h3>\n<p>Not directly. What it does is stop the thing that genuinely destroys rankings, which is getting compromised and flagged in search results.<\/p>\n<h3>How long until I see attacks in the logs?<\/h3>\n<p>Usually within an hour of the IP becoming reachable. Run <code>fail2ban-client status sshd<\/code> a day later and look at the total failed count. It is a useful reminder of what the firewall is absorbing.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You will harden login, firewall, updates and backups so basic attacks do not easily break the server.<\/p>\n","protected":false},"author":1,"featured_media":917,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-152","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-server-security"],"_links":{"self":[{"href":"https:\/\/offshorekaka.in\/blog\/wp-json\/wp\/v2\/posts\/152","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/offshorekaka.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/offshorekaka.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/offshorekaka.in\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/offshorekaka.in\/blog\/wp-json\/wp\/v2\/comments?post=152"}],"version-history":[{"count":5,"href":"https:\/\/offshorekaka.in\/blog\/wp-json\/wp\/v2\/posts\/152\/revisions"}],"predecessor-version":[{"id":958,"href":"https:\/\/offshorekaka.in\/blog\/wp-json\/wp\/v2\/posts\/152\/revisions\/958"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/offshorekaka.in\/blog\/wp-json\/wp\/v2\/media\/917"}],"wp:attachment":[{"href":"https:\/\/offshorekaka.in\/blog\/wp-json\/wp\/v2\/media?parent=152"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/offshorekaka.in\/blog\/wp-json\/wp\/v2\/categories?post=152"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/offshorekaka.in\/blog\/wp-json\/wp\/v2\/tags?post=152"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}