<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Volyte Blog]]></title><description><![CDATA[Volyte Blog]]></description><link>https://volyte.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 27 Oct 2026 13:12:41 GMT</lastBuildDate><atom:link href="https://volyte.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Secure Your Linux VPS in 10 Minutes: 8 First Steps (Ubuntu, Debian, AlmaLinux)]]></title><description><![CDATA[The first 8 things to do on a new Linux VPS: updates, a sudo user, SSH keys, no root login, a firewall, Fail2ban, auto security updates and backups.]]></description><link>https://volyte.hashnode.dev/secure-your-linux-vps-in-10-minutes-8-first-steps-ubuntu-debian-almalinux</link><guid isPermaLink="true">https://volyte.hashnode.dev/secure-your-linux-vps-in-10-minutes-8-first-steps-ubuntu-debian-almalinux</guid><category><![CDATA[Linux]]></category><category><![CDATA[Security]]></category><category><![CDATA[Devops]]></category><category><![CDATA[vps]]></category><dc:creator><![CDATA[Volyte]]></dc:creator><pubDate>Sun, 25 Oct 2026 10:39:31 GMT</pubDate><content:encoded><![CDATA[<p>A new server with a public IP gets its first login attempts from bots within minutes. The good news: a handful of steps stop almost all of them. Do these <strong>right after your VPS is ready</strong> — it takes about 10 minutes.</p>
<p>Commands are for <strong>Ubuntu and Debian</strong>, with the <strong>AlmaLinux / Rocky Linux</strong> version where it differs. Log in as <code>root</code> with the details from your welcome email.</p>
<blockquote>
<p><strong>Golden rule:</strong> when you change SSH settings, keep your current session open and test the new login in a <em>second</em> window. If something is wrong, you can still fix it from the first one.</p>
</blockquote>
<h2>1. Update everything</h2>
<pre><code class="language-bash">apt update &amp;&amp; apt upgrade -y
</code></pre>
<p>AlmaLinux / Rocky: <code>dnf upgrade -y</code>. Reboot if the kernel was updated: <code>reboot</code>.</p>
<h2>2. Create your own user with sudo</h2>
<p>Working as <code>root</code> all the time is risky — one wrong command can damage the system. Create a normal user (replace <code>deploy</code> with your name):</p>
<pre><code class="language-bash">adduser deploy
usermod -aG sudo deploy
</code></pre>
<p>Debian says <em>sudo: command not found</em>? Install it first: <code>apt install sudo -y</code>. AlmaLinux / Rocky: <code>adduser deploy &amp;&amp; passwd deploy &amp;&amp; usermod -aG wheel deploy</code>.</p>
<h2>3. Log in with an SSH key instead of a password</h2>
<p>A key is far harder to guess than any password. On <strong>your own computer</strong> (Windows PowerShell, Mac or Linux terminal), create a key once:</p>
<pre><code class="language-bash">ssh-keygen -t ed25519
</code></pre>
<p>Press Enter to accept the defaults (adding a passphrase is a good idea). Then copy it to the server — on Mac / Linux:</p>
<pre><code class="language-bash">ssh-copy-id deploy@203.0.113.25
</code></pre>
<p>On Windows PowerShell:</p>
<pre><code class="language-powershell">type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh deploy@203.0.113.25 "mkdir -p ~/.ssh &amp;&amp; chmod 700 ~/.ssh &amp;&amp; cat &gt;&gt; ~/.ssh/authorized_keys &amp;&amp; chmod 600 ~/.ssh/authorized_keys"
</code></pre>
<p>Now open a <strong>new</strong> window and check you can log in without a password: <code>ssh deploy@203.0.113.25</code>.</p>
<h2>4. Turn off root login and password login</h2>
<p>Only after the key login works, edit the SSH settings:</p>
<pre><code class="language-bash">sudo nano /etc/ssh/sshd_config
</code></pre>
<p>Set these two lines (remove the <code>#</code> at the start if there is one):</p>
<pre><code>PermitRootLogin no
PasswordAuthentication no
</code></pre>
<p>On Ubuntu, also check the files in <code>/etc/ssh/sshd_config.d/</code> — a file such as <code>50-cloud-init.conf</code> can switch <code>PasswordAuthentication yes</code> back on. Change it to <code>no</code> there too. Then test and restart SSH:</p>
<pre><code class="language-bash">sudo sshd -t &amp;&amp; sudo systemctl restart ssh
</code></pre>
<p>AlmaLinux / Rocky: the service is called <code>sshd</code> — <code>sudo systemctl restart sshd</code>. Test the login again in a new window before closing the old one.</p>
<p><em>Optional:</em> moving SSH from port 22 to another port (for example 2222) doesn't make it unbreakable, but it cuts automated login attempts dramatically. If you do, open the new port in the firewall (Step 5) <strong>before</strong> restarting SSH. On Ubuntu 24.04, also run <code>sudo systemctl daemon-reload &amp;&amp; sudo systemctl restart ssh.socket</code>.</p>
<h2>5. Switch on the firewall</h2>
<p>Allow only what you use — SSH, and web traffic if you host websites:</p>
<pre><code class="language-bash">sudo ufw allow OpenSSH
sudo ufw allow 80,443/tcp
sudo ufw enable
sudo ufw status
</code></pre>
<p>Changed the SSH port? Use <code>sudo ufw allow 2222/tcp</code> instead of <code>OpenSSH</code>. AlmaLinux / Rocky use firewalld, which is on by default and already allows SSH:</p>
<pre><code class="language-bash">sudo firewall-cmd --permanent --add-service=http --add-service=https
sudo firewall-cmd --reload
</code></pre>
<h2>6. Block repeated login attempts with Fail2ban</h2>
<pre><code class="language-bash">sudo apt install fail2ban -y
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
</code></pre>
<p>Fail2ban bans an IP for a while after several failed logins. On Ubuntu the SSH protection is on out of the box. On Debian 12, if Fail2ban doesn't start, create <code>/etc/fail2ban/jail.local</code> with these lines and restart it — Debian 12 keeps logs in the system journal instead of <code>auth.log</code>:</p>
<pre><code class="language-ini">[sshd]
backend = systemd
</code></pre>
<p>AlmaLinux / Rocky: install it from EPEL (<code>sudo dnf install epel-release -y &amp;&amp; sudo dnf install fail2ban -y</code>) and turn on the <code>sshd</code> jail in <code>/etc/fail2ban/jail.local</code>.</p>
<h2>7. Install security updates automatically</h2>
<pre><code class="language-bash">sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades
</code></pre>
<p>Choose <strong>Yes</strong>. Security fixes now install by themselves every day. AlmaLinux / Rocky:</p>
<pre><code class="language-bash">sudo dnf install dnf-automatic -y
sudo systemctl enable --now dnf-automatic.timer
</code></pre>
<p>(Set <code>apply_updates = yes</code> in <code>/etc/dnf/automatic.conf</code> so updates are installed, not just downloaded.)</p>
<h2>8. Take a snapshot and set up backups</h2>
<p>Security also means being able to recover. Now that the server is clean and configured, take a <strong>snapshot</strong> from your hosting control panel — if anything goes wrong later, you can roll back in minutes. Turn on automatic backups too, so you always have a recent copy kept off the server.</p>
<h2>Quick check: what is listening?</h2>
<p>See which services accept connections from the internet:</p>
<pre><code class="language-bash">sudo ss -tulpn
</code></pre>
<p>Anything you don't recognise or don't need (an old database open to the world, a test app) — stop it, or allow it only from your own IP.</p>
<h2>Your checklist</h2>
<table>
<thead>
<tr>
<th>Step</th>
<th>Done when…</th>
</tr>
</thead>
<tbody><tr>
<td>Updates</td>
<td><code>apt upgrade</code> shows nothing left to install</td>
</tr>
<tr>
<td>Own sudo user</td>
<td><code>sudo whoami</code> prints <code>root</code></td>
</tr>
<tr>
<td>SSH key</td>
<td>You log in without typing the server password</td>
</tr>
<tr>
<td>No root / password login</td>
<td><code>ssh root@your-ip</code> is refused</td>
</tr>
<tr>
<td>Firewall</td>
<td><code>ufw status</code> shows <em>active</em> with only the ports you need</td>
</tr>
<tr>
<td>Fail2ban</td>
<td><code>fail2ban-client status sshd</code> shows the jail running</td>
</tr>
<tr>
<td>Auto updates</td>
<td>unattended-upgrades (or dnf-automatic) is enabled</td>
</tr>
<tr>
<td>Snapshot + backups</td>
<td>A snapshot exists and backups are on</td>
</tr>
</tbody></table>
<hr />
<p><em>Originally published on the <a href="https://volyte.com/blog/secure-linux-vps">Volyte blog</a>. Next step: <a href="https://volyte.com/blog/point-domain-to-vps">point your domain to your VPS</a>.</em></p>
]]></content:encoded></item></channel></rss>