Skip to main content

SSH Hardening for Home Servers: Keys, Firewall Rules and Safe Remote Access

Last updated: June 12, 2026

SSH is usually the front door of a Linux home server.

It is the thing you use when the web dashboard is broken, when Docker is misbehaving, when a service refuses to start, or when you need to fix something from another room with a laptop balanced on your knees.

That also means SSH deserves more attention than most people give it.

A home server does not need enterprise paranoia. It does not need a ten-page access policy, a hardware security module, and a dashboard full of red lights. But it does need a sensible SSH setup: key-based login, no direct root login, no password login when practical, firewall rules that limit who can connect, and a recovery plan so you do not lock yourself out of your own machine.

This guide is the SSH hardening article I would follow for a small Linux home server, cheap homelab box, old workstation, mini PC, laptop server, or self-hosting machine running Docker services at home.

If you are building the whole security stack from scratch, start with the broader Linux Home Server Security Guide and the practical Linux Home Server Security Checklist. This post goes deeper on the SSH part.

Good SSH hardening is boring. You should still be able to log in. Bots should not. That is the goal.

Quick SSH hardening checklist

If you only want the short version, this is the order I would follow on a Linux home server:

  1. Make sure you have physical access, console access, or another recovery method.
  2. Keep one working SSH session open while changing settings.
  3. Create an Ed25519 SSH key with a passphrase.
  4. Copy the public key to the server.
  5. Test key-based login from a second terminal.
  6. Disable direct root SSH login.
  7. Disable SSH password login after key login works.
  8. Disable keyboard-interactive authentication if you are not using it.
  9. Restrict SSH to your LAN, management machine, or VPN with UFW.
  10. Add Fail2ban if SSH is exposed, noisy, or reachable by more than a few trusted devices.
  11. Review local users and old keys.
  12. Check logs occasionally.
  13. Document what you changed.

Do not skip the testing steps. The internet is full of “SSH hardening” snippets that are technically fine and practically dangerous because they forget the human sitting at the keyboard.

Before you touch SSH

Before changing SSH, answer one boring but important question:

How will I get back in if I break this?

For a home server, the answer might be:

  • a monitor and keyboard plugged into the machine;
  • a laptop nearby with an existing SSH session open;
  • Proxmox, VirtualBox, IPMI, iLO, iDRAC, or another console;
  • physical access to the server so you can undo the change locally;
  • a recent backup of the SSH configuration.

If the server is a cheap desktop under your desk, recovery is easy. If it is a VPS in another country, recovery depends on your provider’s console. If it is a machine you only reach over SSH, one bad line can turn a five-minute hardening task into a support ticket.

Make a quick copy of the current SSH config before changing anything:

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup.$(date +%F)

If your system uses SSH drop-in files, also list them:

ls -la /etc/ssh/sshd_config.d/

On Ubuntu and Debian-style systems, I prefer using a separate drop-in file instead of editing the main file directly. It keeps your changes visible and easier to remove later.

Check how SSH is exposed right now

Before hardening SSH, check what is actually listening.

sudo ss -tulpn | grep ssh

You may see something like:

tcp   LISTEN 0  128  0.0.0.0:22    0.0.0.0:*    users:(("sshd",pid=1234,fd=3))
tcp   LISTEN 0  128  [::]:22       [::]:*       users:(("sshd",pid=1234,fd=4))

That means SSH is listening on all IPv4 interfaces and all IPv6 interfaces. That is normal, but it also means firewall rules matter.

Now check whether the machine has a global IPv6 address:

ip -6 addr show scope global

This matters because many home users think “my router protects me” because they are used to IPv4 NAT. IPv6 can be different. If your server has a globally reachable IPv6 address and your router/firewall allows traffic, SSH may be more reachable than you think.

Also check the current firewall state:

sudo ufw status verbose

If UFW is inactive, do not panic. Just do not assume anything is protected by the host firewall yet. I cover UFW in more detail in UFW Firewall Rules for Home Servers.

Create a proper SSH key

For a normal home server today, I would use an Ed25519 key unless you need compatibility with something ancient.

On your laptop or desktop, generate a key:

ssh-keygen -t ed25519 -a 100 -C "yourname@homelab"

Use a passphrase. Yes, it is slightly less convenient. That is the point. If your laptop is stolen, a passphrase gives you an extra layer of protection before that private key becomes useful to someone else.

You should end up with two files:

~/.ssh/id_ed25519
~/.ssh/id_ed25519.pub

The private key is the one without .pub. Do not copy it to random servers. Do not paste it into web apps. Do not keep it in an unencrypted notes file called “server stuff”. The public key is the one you install on the server.

Check the files:

ls -la ~/.ssh/id_ed25519*

The private key should be readable only by you. If you have copied keys between machines and permissions look too open, fix them:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

Copy the key and test it

Copy the public key to the server:

ssh-copy-id -i ~/.ssh/id_ed25519.pub youruser@server-ip

Example:

ssh-copy-id -i ~/.ssh/id_ed25519.pub ms@192.168.1.20

Now test normal login:

ssh youruser@server-ip

Do not disable password login yet.

First, open a second terminal and test again. Keep the first session open. That old session is your safety rope.

If you want to confirm the server is accepting your key, use verbose mode:

ssh -v youruser@server-ip

You should see lines showing that a public key was offered and accepted.

On the server, the public key is stored here:

~/.ssh/authorized_keys

Check permissions on the server:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

For a single-admin home server, this is usually enough. For multiple people, do not share one account. Create separate users and give each person their own key.

Harden the SSH server config

Now create a dedicated SSH hardening file on the server:

sudo nano /etc/ssh/sshd_config.d/99-homelab-hardening.conf

Paste this:

# Homelab SSH hardening
# Keep this small, understandable and easy to roll back.

PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitEmptyPasswords no

X11Forwarding no
MaxAuthTries 3
LoginGraceTime 30s

That is a practical baseline for most home servers.

What these settings do:

  • PermitRootLogin no stops direct root login over SSH.
  • PubkeyAuthentication yes allows SSH key authentication.
  • PasswordAuthentication no disables normal SSH password login.
  • KbdInteractiveAuthentication no disables keyboard-interactive login, which can behave like password login on many PAM-based systems.
  • PermitEmptyPasswords no makes the obvious bad idea explicitly bad.
  • X11Forwarding no disables X11 forwarding, which most headless home servers do not need.
  • MaxAuthTries 3 reduces repeated authentication attempts per connection.
  • LoginGraceTime 30s gives unauthenticated clients less time to sit around.

Notice what I did not include yet:

AllowUsers youruser

AllowUsers is useful, but it is also an easy way to lock yourself out if you type the wrong username, forget a second admin account, or later create automation that needs SSH. Add it only after the basic setup works.

If you want to add it later, use your real username:

AllowUsers ms

For multiple admin users:

AllowUsers ms admin backupuser

Another option is to use a dedicated group:

AllowGroups ssh-users

Then create the group and add allowed users:

sudo groupadd ssh-users
sudo usermod -aG ssh-users youruser

But again: keep the first hardening pass simple. A readable config you understand is better than a hardened-looking config you are afraid to touch.

Test before reloading SSH

Always test the SSH server configuration before applying it:

sudo sshd -t

If there is no output, the syntax is valid.

If there is an error, stop and fix it. Do not reload SSH with a broken config.

Now check the active settings that SSH will use:

sudo sshd -T | grep -E '^(port|permitrootlogin|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|permitemptypasswords|x11forwarding|maxauthtries|logingracetime|allowusers|allowgroups)'

You should see values like:

permitrootlogin no
pubkeyauthentication yes
passwordauthentication no
kbdinteractiveauthentication no
permitemptypasswords no
x11forwarding no
maxauthtries 3
logingracetime 30

Reload SSH:

sudo systemctl reload ssh.service

If your distribution uses sshd.service instead:

sudo systemctl reload sshd.service

Now test from a new terminal:

ssh youruser@server-ip

Do not close the original working session until the new login works.

Finally, test that password-only login fails:

ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no youruser@server-ip

If password authentication is disabled correctly, that should fail.

Restrict SSH with UFW

SSH keys are good. Firewall restrictions are better.

If SSH only needs to be reachable from your home network, do not allow it from everywhere.

Find your LAN range. It is often something like:

192.168.1.0/24
192.168.0.0/24
10.0.0.0/24

If your server IP is 192.168.1.20 and your LAN is 192.168.1.0/24, allow SSH only from the LAN:

sudo ufw allow from 192.168.1.0/24 to any port 22 proto tcp comment 'SSH from LAN'

Set sane defaults:

sudo ufw default deny incoming
sudo ufw default allow outgoing

Enable UFW:

sudo ufw enable

Check it:

sudo ufw status verbose
sudo ufw status numbered

If you only manage the server from one workstation, you can be stricter:

sudo ufw allow from 192.168.1.10 to any port 22 proto tcp comment 'SSH from admin laptop'

That is better than allowing the whole LAN, but only if your admin machine has a stable IP or DHCP reservation.

If you use a VPN interface such as Tailscale, you may prefer SSH over the VPN only:

sudo ufw allow in on tailscale0 to any port 22 proto tcp comment 'SSH over Tailscale'

The exact interface name depends on your VPN. Check with:

ip link

For deeper firewall examples, see UFW Firewall Rules for Home Servers.

What if SSH is exposed to the internet?

My default answer for home servers is simple:

Do not expose SSH directly to the internet unless you have a real reason.

Use a VPN if possible. WireGuard, Tailscale, ZeroTier, or another private access method is usually a better fit for a homelab than forwarding port 22 from your router to a box under your desk.

If you absolutely need public SSH, use layers:

  1. SSH keys only.
  2. No direct root login.
  3. No password or keyboard-interactive login.
  4. UFW restrictions by source IP if your admin IP is stable.
  5. Fail2ban for brute-force noise.
  6. Automatic security updates or a disciplined update routine.
  7. Logs you actually check.
  8. Backups, because security includes recovery.

A public SSH service with password login is asking for noise. A public SSH service with key-only login, no root login, Fail2ban, and source restrictions is much more reasonable. Still, for a home server, VPN-only access is usually the cleaner design.

If the server also runs Docker services, remember that Docker port publishing and firewall behavior can get confusing. I wrote more about that in Docker Security for Homelab Beginners.

Should you change the SSH port?

Changing the SSH port is not real hardening by itself.

It can reduce log noise from bots that only scan port 22. That is useful, but it is not a substitute for SSH keys, firewall rules, and disabling password login.

For a LAN-only home server, I usually keep SSH on port 22 and restrict who can reach it.

For a public-facing server, using a non-standard port can reduce background noise, but do not let it create a false sense of security. Anyone scanning all ports can still find it.

There is also a practical reason not to make port changes the first step: on some newer Ubuntu setups, SSH may be managed through systemd socket activation, so changing the port can require extra care. If you change the port and SSH still listens on 22, check whether ssh.socket is involved:

systemctl status ssh.socket

For most home servers, this is my order of importance:

  1. Keys first.
  2. No root login.
  3. No password login.
  4. Firewall restrictions.
  5. Fail2ban if reachable or noisy.
  6. Port change only if you still want less noise.

Port changes are seasoning, not the meal.

Where Fail2ban fits

Fail2ban is not the lock on the door. It is the person who stops someone from trying the handle 500 times.

It watches logs, counts failed attempts, and bans IP addresses that cross a threshold.

Install it:

sudo apt update
sudo apt install fail2ban

Create a small SSH jail:

sudo nano /etc/fail2ban/jail.d/sshd.local

Paste:

[sshd]
enabled = true
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h

Restart Fail2ban:

sudo systemctl restart fail2ban

Check status:

sudo fail2ban-client status
sudo fail2ban-client status sshd

If SSH is LAN-only and your LAN is quiet, Fail2ban may never ban anything. That is fine. Boring is good.

If SSH is public, Fail2ban will probably start earning its keep quickly.

For a full beginner walkthrough, see Fail2ban for Beginners: Protect SSH on a Linux Home Server.

Clean up users and old keys

SSH hardening is not only about sshd_config.

Old users and forgotten keys are just as important.

List local users:

cut -d: -f1 /etc/passwd

Check sudo users:

getent group sudo

On some distributions, the admin group may be wheel instead:

getent group wheel

Review your own authorized keys:

nl -ba ~/.ssh/authorized_keys

If you see a key from an old laptop, a temporary VM, or a test machine you no longer use, remove it.

For every admin account, ask:

  • Does this user still need SSH?
  • Does this user need sudo?
  • Do I recognize every key in authorized_keys?
  • Does each key have a useful comment?
  • Is this a shared account that should be split into real users?

To lock an old account without deleting its files:

sudo usermod -L olduser

To remove a user:

sudo deluser olduser

Do not remove accounts blindly. Check ownership of files and services first.

Password hygiene still matters even when SSH passwords are disabled. Your sudo password, web dashboards, password manager, and recovery accounts still need strong unique passwords. I covered that in Strong, Unique Passwords Without Losing Your Mind.

Optional hardening that can break workflows

There are more SSH settings you can tighten, but not every setting belongs in a beginner baseline.

For example:

AllowAgentForwarding no
AllowTcpForwarding no
PermitTunnel no
PermitUserEnvironment no

These can be useful, but they may break things you actually use:

  • SSH tunnels;
  • remote development tools;
  • some backup workflows;
  • jump-host workflows;
  • automation that expects forwarding.

If you do not use forwarding, disabling it can reduce the damage from a compromised account. But test carefully.

A more restrictive optional block might look like this:

# Optional restrictions. Test before keeping.
AllowAgentForwarding no
AllowTcpForwarding no
PermitTunnel no
PermitUserEnvironment no

I would not paste that into every home server automatically. I would add it only after confirming I do not rely on those features.

One setting I would avoid changing casually is UsePAM. Some hardening lists tell people to disable PAM without explaining the side effects. On Ubuntu and Debian systems, PAM is part of normal account and session handling. Turning it off can break behavior you did not expect.

Hardening should reduce risk without turning your server into a puzzle box.

Logs and monthly maintenance

Once SSH is hardened, check the logs occasionally.

On systemd-based systems:

sudo journalctl -u ssh.service --since "24 hours ago" --no-pager

If your service is named sshd:

sudo journalctl -u sshd.service --since "24 hours ago" --no-pager

On Ubuntu/Debian systems, you may also have authentication logs:

sudo grep sshd /var/log/auth.log | tail -n 50

Useful checks:

last
sudo lastb

last shows successful logins. lastb shows bad login attempts if the system records them.

For a monthly home server routine, I would check:

  • Is SSH still key-only?
  • Is root login still disabled?
  • Is UFW active?
  • Is SSH still limited to LAN, VPN, or trusted IPs?
  • Are there unknown users?
  • Are there old keys in authorized_keys?
  • Is Fail2ban running?
  • Are updates installed?
  • Do backups still work?

This is also where Lynis Hardening Checklist: What to Fix First on a Linux Home Server fits nicely. Lynis will often point at SSH, firewall, users, updates and permissions. Just remember: do not blindly fix every warning in one evening.

How to recover if you lock yourself out

If you followed the earlier advice and kept a working session open, recovery is usually easy.

Undo the hardening file:

sudo mv /etc/ssh/sshd_config.d/99-homelab-hardening.conf /root/99-homelab-hardening.conf.disabled

Test config:

sudo sshd -t

Reload or restart SSH:

sudo systemctl reload ssh.service

If reload fails, restart:

sudo systemctl restart ssh.service

If the problem is UFW, check the rules:

sudo ufw status numbered

Add a rule for your current machine:

sudo ufw allow from 192.168.1.10 to any port 22 proto tcp

Or, from local console only, temporarily disable UFW:

sudo ufw disable

Do not leave it disabled forever. Fix the rule, test, and enable it again.

sudo ufw enable
sudo ufw status verbose

If you lost the only key and password login is disabled, you need local console access, provider console access, or a backup admin path. That is not a bug in SSH hardening. That is the tradeoff you created.

This is why I do not disable password login until I have tested key login from a second terminal.

My recommended home server SSH setup

For most home servers, this is the setup I like:

  • SSH listens on port 22.
  • SSH is reachable only from LAN or VPN.
  • Admin login uses Ed25519 keys with passphrases.
  • Root login is disabled.
  • Password login is disabled.
  • Keyboard-interactive login is disabled.
  • UFW denies incoming traffic by default.
  • Fail2ban protects SSH if the service is exposed or noisy.
  • Old users and old keys are reviewed occasionally.
  • Backups exist before making big changes.

That is not fancy. That is why I like it.

It is understandable, recoverable and strong enough for the kind of Linux home server most people actually run.

If you want to place SSH hardening in the bigger homelab picture, this is the order I would follow:

  1. Use the Linux Home Server Security Checklist to understand the whole machine.
  2. Use this SSH guide to secure remote access.
  3. Use UFW Firewall Rules for Home Servers to control what can connect.
  4. Use Fail2ban for Beginners to reduce brute-force noise.
  5. Use Lynis to audit the result.
  6. If the server runs containers, read Docker Security for Homelab Beginners.
  7. If the server runs Docker services you care about, set up Docker container backups.
  8. Then monitor the basics with Uptime Kuma for Home Servers.

Security is not one magic setting. It is a stack of boring decisions that make the server harder to abuse and easier to recover.

SSH is a good place to start because it is the door you use most often.

Make the door boring.


FAQ

What is SSH hardening?

SSH hardening means configuring the SSH server so remote access is safer. For a home server, that usually means using SSH keys, disabling direct root login, disabling password login when practical, restricting SSH with a firewall, and monitoring failed login attempts.

Should I disable SSH password login on a home server?

Yes, if SSH key login is working and you have a recovery method. Do not disable password login until you have tested key login from another terminal. If you lose the only key and have no console access, you can lock yourself out.

Is changing the SSH port enough to secure SSH?

No. Changing the SSH port can reduce automated bot noise, but it is not real protection by itself. SSH keys, no root login, no password login, firewall restrictions and updates matter much more.

Should SSH be exposed to the internet?

Usually no for a home server. A VPN-only setup is normally safer and cleaner. If you must expose SSH publicly, use key-only login, disable root and password login, restrict source IPs where possible, and run Fail2ban.

Do I still need Fail2ban if password login is disabled?

Maybe. If SSH is LAN-only, Fail2ban may not do much. If SSH is public or noisy, Fail2ban is still useful because it reduces repeated authentication attempts and log spam.

Is root SSH login dangerous?

Direct root SSH login is unnecessary for most home servers. Use a normal user and elevate with sudo. That gives you a named account, better logs, and one less obvious login target.

What SSH key type should I use?

For modern Linux systems, Ed25519 is a good default. Use RSA only when you need compatibility with older systems. Always protect private keys carefully and use a passphrase for keys that unlock important servers.

Can UFW lock me out of SSH?

Yes. If you enable UFW before allowing SSH from your current network, you can block yourself. Add the SSH allow rule first, keep a working session open, then enable UFW and test from another terminal.

Does Docker affect SSH hardening?

Docker does not normally change host SSH settings, but Docker port publishing can complicate firewall expectations for container services. Harden SSH separately, then review Docker exposure separately.


References used while writing this guide


Related posts:

Written by MS

MS is a Linux homelab and cybersecurity enthusiast who documents practical experiments with home servers, Docker, firewalls, backups, Lynis, Fail2ban, honeypots and old hardware. The guides on IT Random Stuff are based on hands-on testing, real configurations and lessons learned from running Linux systems at home.

Comments

Popular posts from this blog

OpenCanary Honeypot on Ubuntu: 2026 Home Lab Setup Guide

I first wrote about OpenCanary years ago, and that old version badly needed an update. The tool is still useful, but the way I would deploy it in a home lab today is different: newer Ubuntu versions, Python 3, Docker as an option, cleaner logging, and no copy-pasted example credentials that look like something someone might actually reuse. This guide is the updated version: how I would set up an OpenCanary honeypot on Ubuntu in 2026 for a small home network or homelab. The goal is not to trap random people on the internet. The goal is to create a quiet internal warning system: a fake service that should never be touched, so any connection to it deserves attention. Important: this is a defensive security guide. Run OpenCanary only on systems and networks you own or have permission to monitor. Do not expose a honeypot to the public internet unless you understand the logging, legal, abuse and maintenance implications. If you are building a Linux home server security setup fro...

Lenovo ThinkPad X250 on Linux: Tweaks, Undervolting, Battery Life and 2026 Update

I wanted a cheap, small, serviceable Linux laptop. Something light enough to carry, easy enough to repair, and inexpensive enough that upgrades would still make sense. The Lenovo ThinkPad X250 was a good candidate because it has a 12.5-inch form factor, a proper ThinkPad keyboard, SSD upgrade options, replaceable parts, Ethernet, docking support and generally good Linux compatibility. I found one on eBay for around 130€ : an Intel Core i5-5300U model with 8GB RAM , a 128GB SSD , two batteries and an HD screen with a small bruise. The plan was simple: clean it, repaste it, upgrade the SSD, install Linux Mint, undervolt it and see how useful it could still be. This post started as my original 2019 notes about tweaking the Lenovo X250 in Linux. I have now updated it with a 2026 perspective, cleaner instructions, better internal links and a more realistic look at whether this old ThinkPad is still worth using. Related posts: Linux Home Server Security Checklist Docker Secu...

Strong, Unique Passwords Without Losing Your Mind

Last updated: May 27, 2026 Password Security in 2026: Password Managers, Passkeys & 2FA for Real People Password Security in 2026: Password Managers, Passkeys & 2FA That Actually Work Most people do not have a weak-password problem. They have a reused-password problem. You can invent the cleverest password in the world, but if you use it on twenty websites and one of them gets breached, you suddenly have twenty compromised accounts. That is how most real-world account takeovers happen in 2026. Not elite hackers brute-forcing your login from a dark room somewhere. Just automated credential stuffing using databases leaked years ago from services you forgot existed. One old forum breach becomes access to your email, cloud storage, streaming services, VPN account, and eventually your homelab dashboard because the same password got reused everywhere. This guide explains how to handle passwords properly today: without paranoia, without enterprise co...