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:
- Make sure you have physical access, console access, or another recovery method.
- Keep one working SSH session open while changing settings.
- Create an Ed25519 SSH key with a passphrase.
- Copy the public key to the server.
- Test key-based login from a second terminal.
- Disable direct root SSH login.
- Disable SSH password login after key login works.
- Disable keyboard-interactive authentication if you are not using it.
- Restrict SSH to your LAN, management machine, or VPN with UFW.
- Add Fail2ban if SSH is exposed, noisy, or reachable by more than a few trusted devices.
- Review local users and old keys.
- Check logs occasionally.
- 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 nostops direct root login over SSH.PubkeyAuthentication yesallows SSH key authentication.PasswordAuthentication nodisables normal SSH password login.KbdInteractiveAuthentication nodisables keyboard-interactive login, which can behave like password login on many PAM-based systems.PermitEmptyPasswords nomakes the obvious bad idea explicitly bad.X11Forwarding nodisables X11 forwarding, which most headless home servers do not need.MaxAuthTries 3reduces repeated authentication attempts per connection.LoginGraceTime 30sgives 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:
- SSH keys only.
- No direct root login.
- No password or keyboard-interactive login.
- UFW restrictions by source IP if your admin IP is stable.
- Fail2ban for brute-force noise.
- Automatic security updates or a disciplined update routine.
- Logs you actually check.
- 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:
- Keys first.
- No root login.
- No password login.
- Firewall restrictions.
- Fail2ban if reachable or noisy.
- 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:
- Use the Linux Home Server Security Checklist to understand the whole machine.
- Use this SSH guide to secure remote access.
- Use UFW Firewall Rules for Home Servers to control what can connect.
- Use Fail2ban for Beginners to reduce brute-force noise.
- Use Lynis to audit the result.
- If the server runs containers, read Docker Security for Homelab Beginners.
- If the server runs Docker services you care about, set up Docker container backups.
- 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:
- Linux Home Server Security Guide: Secure Your Homelab Without Enterprise Nonsense
- Linux Home Server Security Checklist: Hardening a Cheap Homelab Without Going Crazy
- UFW Firewall Rules for Home Servers: Simple Rules That Actually Make Sense
- Fail2ban for Beginners: Protect SSH on a Linux Home Server
- Lynis Hardening Checklist: What to Fix First on a Linux Home Server
- Docker Security for Homelab Beginners: Stop Exposing Random Containers
- Backing Up Docker Containers: The Homelab Disaster You Can Avoid
- Uptime Kuma for Home Servers: Simple Self-Hosted Monitoring That Actually Helps
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
Post a Comment