Hello again, tech enthusiasts! 👋
You rented a small cloud server for a report script or a website. Great! But within minutes, robots on the internet start trying to log in. They guess passwords day and night.
The good news: a few simple steps stop almost all of these attacks. Today we lock the front door (SSH keys), build a fence (firewall), and keep the walls fresh (automatic updates). The examples use Ubuntu, but other Linux systems are very similar.
What you need
- A Linux server (Ubuntu 22.04 or 24.04) and a user with
sudorights - A terminal on your own computer (Windows, Mac and Linux all have
sshbuilt in)
In the examples, the server is server.example.com and the user is admin. Change them to yours.
Step 1: Create an SSH key and copy it to the server
SSH is how you log in to the server from far away. A password is like a door code that anyone can guess. An SSH key is like a real metal key: there are two parts, a private key that stays on your computer and a public key that you give to the server.
Run this on your own computer, not on the server:
# Create a modern key. Choose a passphrase when it asks (recommended).
ssh-keygen -t ed25519 -C "my-laptop"
# Copy the public key to the server (it asks for your password one last time)
ssh-copy-id admin@server.example.com
# Test: this should log you in without the server password
ssh admin@server.example.com
On Windows without ssh-copy-id, copy the line from .ssh\id_ed25519.pub into ~/.ssh/authorized_keys on the server.
Step 2: Turn off password login
Now that the key works, we tell the server to stop accepting passwords. On the server, create a small settings file:
sudo nano /etc/ssh/sshd_config.d/00-hardening.conf
Put these lines in it:
# Only keys, no passwords
PasswordAuthentication no
KbdInteractiveAuthentication no
# root may log in with a key only, never with a password
PermitRootLogin prohibit-password
Why the name 00-? The SSH server uses the first value it reads. Files in this folder are read in name order, and some cloud images add a file like 50-cloud-init.conf that turns passwords back on. A name starting with 00- is read first, so your choice wins.
Check the settings, then restart the service:
sudo sshd -t # no output means no errors
sudo systemctl restart ssh
sudo sshd -T | grep -Ei 'passwordauthentication|permitrootlogin'
Step 3: Test in a second window before you close anything
This is the most important step. Keep your current SSH window open. Open a new terminal and log in again:
ssh admin@server.example.com
If it works, great. If not, use the first window to fix the problem. If you close both, you could lock yourself out!
Step 4: Turn on the firewall
A firewall is like a guard at the gate. It only lets visitors in through the doors you name. Ubuntu includes a simple one called ufw.
sudo ufw default deny incoming # block everything coming in...
sudo ufw default allow outgoing # ...but let the server reach out
sudo ufw allow OpenSSH # IMPORTANT: allow SSH before enabling
sudo ufw allow 80/tcp # only if you run a website
sudo ufw allow 443/tcp # only if you run a website (HTTPS)
sudo ufw enable
sudo ufw status verbose
Only open the ports you really use. A database port should usually stay closed.
Step 5: Automatic security updates
Most attacks use old, known bugs. Updates fix them. Let the server install security updates by itself:
sudo apt update
sudo apt install unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades # choose "Yes"
# Check that it works (this only tests, it changes nothing)
sudo unattended-upgrade --dry-run --debug
Some updates need a restart. If the file /var/run/reboot-required exists, plan one at a quiet time.
Bonus: fail2ban
Even with keys only, the robots keep knocking. fail2ban watches the log and blocks an address for a while after too many failed tries.
sudo apt install fail2ban
sudo nano /etc/fail2ban/jail.local
[sshd]
enabled = true
maxretry = 5
findtime = 10m
bantime = 1h
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
Common problems
- “Permission denied (publickey)” after Step 2. The key was not copied correctly. Use your still-open first window and check
~/.ssh/authorized_keys. The folder~/.sshshould have permission700and the file600. - Passwords still work. Another file sets
PasswordAuthentication yes. Runsudo grep -ri password /etc/ssh/sshd_config.d/and check the file names. - The website stopped working after ufw. You forgot to allow 80 or 443. Add them with
sudo ufw allow. - fail2ban does not start. Some systems have no
/var/log/auth.log. Addbackend = systemdunder[sshd]and restart.
Wrap-up
With keys, a firewall, automatic updates and fail2ban, your server is now much safer than many servers on the internet.
Next idea: set up a daily backup of your server to another place. A backup protects you from everything else, including your own mistakes. 🙂