Get your free server today! View Plans →
Home Plans Blog About Contact Panel Join Discord
Security

SSH keys and firewalls: locking down a Linux server

Swap password logins for SSH keys and set up a basic ufw firewall, step by step, without accidentally locking yourself out of your own server.

SSH keys and firewalls: locking down a Linux server

If you have a fresh Linux server, two changes will do more for its security than almost anything else. Swap password logins for SSH keys, and put a firewall in front of it that only opens the ports you actually use. This guide walks through both, step by step, and shows you how to do it without accidentally locking yourself out, which is the thing everyone is secretly worried about.

Why password logins are the weak spot

The moment your server is online, bots start trying to log in. They guess common usernames like root, admin and ubuntu, and they throw millions of passwords at the SSH port. Most of it is automated and constant. You will see it the first time you read your auth logs and it can be a bit alarming.

A password is one secret. If it leaks, gets guessed, or you reused it somewhere that got breached, that is the whole door. An SSH key is a different and much stronger setup. So let's start there.

How SSH keys actually work

An SSH key comes in two halves that are made together as a pair. There is a private key, which stays on your own computer and never leaves it, and a public key, which you copy onto any server you want to log into.

The public key is fine to share. It cannot be used to log in on its own. When you connect, the server uses the public key to send your machine a little challenge that only the matching private key can answer. Your computer answers it quietly in the background, the server is satisfied, and you are in. No password travels across the network at any point.

Think of the public key as a lock you bolt onto the server's door, and the private key as the only key that opens it. You can hand out copies of the lock all day. As long as you are the only one holding the key, you are the only one getting in.

A quick warning: protect that private key. If someone copies it off your laptop, they get the same access you have. This is why you put a passphrase on it, which we will do in a second.

Generating a key with ssh-keygen

On your own machine, not the server, open a terminal and run this. Mac and Linux have it built in, and Windows 10 and 11 ship with it too.

ssh-keygen -t ed25519 -C "[email protected]"

The -t ed25519 part picks a modern key type that is small and strong. If you are on something old that does not support it, use ssh-keygen -t rsa -b 4096 instead. The -C bit is just a comment so you can tell your keys apart later.

It will ask where to save the key. Press Enter to accept the default, which puts it in your .ssh folder. Then it asks for a passphrase. Set one. I know it is one more thing to type, but if your laptop ever gets stolen, that passphrase is the difference between a minor headache and a stranger logging into all your servers. You can use ssh-agent so you only type it once per session.

When it finishes you will have two files. The private key has no extension, and the public key ends in .pub. The one ending in .pub is the one that goes on the server. Never share or upload the other one.

Getting the public key onto the server

The easy way is ssh-copy-id. From your machine, while you can still log in with a password, run this with your own user and server address.

ssh-copy-id [email protected]

It logs in, creates the right folder, and adds your public key to a file called authorized_keys with the correct permissions. That is the whole job.

If ssh-copy-id is not available, you can do it by hand. Print your public key, copy the whole line, then on the server paste it into ~/.ssh/authorized_keys. The manual version looks like this.

mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "paste-your-public-key-line-here" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Those permission numbers matter more than they look. SSH is fussy on purpose. If the .ssh folder or the authorized_keys file is readable by other users, SSH will quietly refuse to use the key and fall back to asking for a password. So if your key is not working, check the permissions first.

Test the key before you change anything else

Do not skip this. Open a new terminal and try to log in.

ssh [email protected]

If it lets you in without asking for your account password, and only asks for your key passphrase, the key works. Good. Keep that terminal open and logged in. We are about to turn off password logins, and having a working session already open is your safety net.

Turning off password logins safely

Once your key works, you can tell SSH to stop accepting passwords at all. The bots can keep guessing forever and it will not matter, because there is no password to guess anymore.

On the server, open the SSH config file with a text editor. You will need sudo.

sudo nano /etc/ssh/sshd_config

Find these lines, uncomment them if they have a # in front, and set them like this.

PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin prohibit-password

That last one means root can still be reached with a key if you really need it, but never with a password. Honestly, on most setups you should be logging in as a normal user and using sudo, not as root at all, but that is a topic for another day.

Save the file, then reload SSH so it picks up the change.

sudo systemctl restart ssh

Now here is the careful part. Do not close that first terminal. Open a brand new one and try to connect again. If the new connection works with your key, you are golden. If something is wrong, your old session is still open so you can fix the config and try again. Only once the fresh login works should you relax. This habit of testing in a second terminal has saved us more times than I can count.

Adding a firewall with ufw

Keys handle who can log in. A firewall handles what can be reached at all. The cleanest approach is simple. Block everything by default, then open only the few ports you genuinely use.

On Ubuntu and Debian the friendly tool for this is ufw, which stands for uncomplicated firewall. It is a nicer front end over the messy rules underneath.

Before you do anything, allow SSH. This is the one rule you absolutely cannot forget, because if you enable the firewall without it, you will lock yourself out of your own server. If your SSH runs on the standard port 22, this works.

sudo ufw allow OpenSSH

If you moved SSH to a custom port, allow that number instead, for example sudo ufw allow 2222/tcp. Then set the default behaviour and turn it on.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable

It will warn you that enabling may disrupt existing connections. Since you allowed SSH first, your session stays up. Check what is allowed with sudo ufw status and you will see a short list of open ports.

Only open ports you actually use

This is where people go wrong. They open a pile of ports just in case, and every open port is one more thing an attacker can poke at. Keep the list short and honest. Open a port only when something real is listening on it.

Here are the common ones, just so you know what you are looking at.

PortWhat it is for
22SSH, your login
80Web traffic over HTTP
443Web traffic over HTTPS
25565A Minecraft server

So if you are running a website, you would add the web ports like this.

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

If you run a Discord bot with discord.py or discord.js, you usually do not need to open anything at all, because the bot connects out to Discord rather than waiting for connections in. Outgoing traffic is already allowed, so it just works. When you stop using a service, remove its rule with sudo ufw delete allow 80/tcp so the door does not sit open for no reason.

One thing worth saying plainly. A firewall on the server is not the same as DDoS protection. A firewall decides which ports answer. It does not stop someone from flooding your line with junk traffic. That is a separate layer, and on our own game and VPS plans the network level protection sits in front of the box for exactly that reason. Your ufw rules and that protection are doing different jobs, and you want both.

Putting it together

So the whole flow, start to finish, is short. Make a key pair on your own machine. Copy the public half to the server. Test that the key logs you in. Turn off password logins. Add ufw, allow SSH first, deny the rest, and open only the ports you really need. Test once more from a fresh terminal.

None of these steps are hard on their own. The thing that trips people up is rushing the order and locking themselves out, which is why testing in a second terminal keeps coming up. Take it slow the first time. Do it once carefully and it becomes muscle memory, and every server you set up after this will be tighter from the very first hour.

Common questions

What is the difference between the public and private SSH key?

The private key stays on your own computer and never leaves it. The public key gets copied onto any server you want to log into. The public one is safe to share because it cannot be used to log in by itself. Only the matching private key can answer the server's challenge, so guard the private key carefully.

Will turning off password logins lock me out?

Not if you test first. Generate your key, copy the public half to the server, and confirm the key logs you in before you disable passwords. Keep your working session open, change the setting, then test from a fresh terminal. If anything breaks, your open session lets you undo it.

Which ports should I open in ufw?

Only the ones something is actually using. Always allow SSH first, usually port 22, or it will lock you out. Add port 80 and 443 for a website, or 25565 for a Minecraft server. Leave everything else closed and remove rules when you stop using a service.

Does a firewall protect me from DDoS attacks?

No. A firewall like ufw decides which ports answer and which stay closed. It does not stop someone flooding your connection with junk traffic. DDoS protection is a separate network level layer that sits in front of the server, and you want both.

My SSH key is not working, what should I check?

Check the permissions first. SSH refuses to use a key if the.ssh folder or the authorized_keys file can be read by other users. Set the folder to 700 and the file to 600. If the permissions are wrong, SSH quietly falls back to asking for a password instead of using your key.

DO
Daniel Okafor
Web Developer at Bytte.cloud

Part of the Bytte.cloud team. We run game servers, bots and websites for a living, and we write these guides from what we see day to day in support and on our own servers.

Want to try this on real hardware?

Bytte.cloud has free plans for game servers, bots and websites. No credit card, set up in seconds.

Start for free See the plans