SSH hardening should be staged, not rushed. The safe pattern is to keep your current session open, add a second verified login path, test configuration syntax, and only then disable weaker access.
This guide is Astro-ready but should be treated as a verification draft until the commands are run on the exact Ubuntu 24.04 server environment you plan to document. Do not close your existing SSH session while changing authentication or firewall rules.
Before you change anything
Open a second terminal and confirm you can log in independently. If you are connected to a VPS, also confirm you have provider console or rescue access before touching SSH settings.
Minimum safety checks:
- one current SSH session stays open;
- one separate SSH login succeeds;
- you know the server’s public IP or private Tailscale/WireGuard address;
- you have console/rescue access from the VPS provider;
- you know how to revert the file you are editing.
If any of those are missing, fix that first.
Step 1: Create or confirm a non-root sudo user
Use a non-root admin user for daily access. Root login should not be the normal path.
Run these on Ubuntu 24.04 as root or with sudo:
adduser kasimba
usermod -aG sudo kasimba
If the user already exists, confirm group membership instead:
id kasimba
Expected result: the user should belong to the sudo group.
Verification needed: run this on the target server and paste the redacted
idoutput into the final draft if we publish it as tested.
Step 2: Add SSH key authentication before disabling passwords
Do not disable password login until key login works from a fresh terminal.
From your local machine, copy your public key:
ssh-copy-id kasimba@SERVER_ADDRESS
Or manually place the public key in:
/home/kasimba/.ssh/authorized_keys
Then test a fresh login:
ssh kasimba@SERVER_ADDRESS
If this fails, stop. Do not edit password settings yet.
Step 3: Put SSH hardening in a drop-in file
On modern Ubuntu, it is often cleaner to place local overrides in /etc/ssh/sshd_config.d/ instead of editing the whole main config file.
Create a local hardening file:
sudo nano /etc/ssh/sshd_config.d/99-local-hardening.conf
Start with conservative settings:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
KbdInteractiveAuthentication no
X11Forwarding no
These settings assume key login already works. If key login has not been verified, do not apply them.
Step 4: Test SSH configuration before restarting
Always test syntax before reloading or restarting SSH.
sudo sshd -t
No output usually means the syntax check passed. If there is an error, fix it before restarting anything.
Then reload SSH:
sudo systemctl reload ssh
On Ubuntu, the service is commonly named ssh. Confirm before changing automation around it:
systemctl status ssh --no-pager
Verification needed: confirm service name and
sshd -tbehavior on the target Ubuntu 24.04 host.
Step 5: Test a new login before closing the old one
Keep your original SSH session open. In a new terminal, try logging in again:
ssh kasimba@SERVER_ADDRESS
Then confirm sudo works:
sudo -v
Only close the old session after the new session works.
Step 6: Limit where SSH is reachable
SSH key login is good. Private reachability is better.
For small servers, consider one of these patterns:
- SSH only over Tailscale;
- SSH only over WireGuard;
- SSH allowed only from trusted source IPs;
- SSH behind a temporary access path during maintenance.
If using UFW, be careful. Allow your safe SSH path before enabling or tightening the firewall:
sudo ufw allow OpenSSH
sudo ufw status verbose
If SSH should only be reached over a private interface, test that path first and document exactly what is allowed.
Step 7: Keep a rollback path
Before hardening, save the current effective configuration and the file you changed.
sudo cp /etc/ssh/sshd_config /root/sshd_config.backup.$(date +%F)
If you used a drop-in file, you can temporarily move it away from console access:
sudo mv /etc/ssh/sshd_config.d/99-local-hardening.conf /root/99-local-hardening.conf.disabled
sudo systemctl reload ssh
Do not rely on memory during a lockout. Write the rollback path down before changing access.
A safer minimum baseline
A reasonable first SSH baseline is:
- non-root sudo user;
- key-based login verified from a fresh terminal;
- root SSH login disabled;
- password SSH login disabled only after key login works;
- SSH config syntax tested before reload;
- firewall rules reviewed before activation;
- provider console/rescue access confirmed;
- private access path planned for admin work.
That baseline is not exotic. It is just careful.
Common lockout causes
Disabling passwords before testing keys
This is the classic mistake. A public key in the wrong user’s home directory will not save you after password login is disabled.
Restarting SSH after a syntax error
Run sudo sshd -t before reloads. Syntax checks are cheap; lockouts are expensive.
Enabling UFW before allowing the active SSH path
A firewall can lock you out even if SSH itself is configured correctly.
Closing the only working session
Keep the old session open until a new one works.
Internal links
- Secure Remote Access for a Linux Server
- How to Decide What Should Be Public on a Linux Server
- Tailscale vs WireGuard vs Cloudflare Tunnel
Before you apply this on a production server
Keep your current SSH session open, test each change in a second terminal, and confirm your VPS provider console or rescue mode works before touching firewall or SSH settings.
Use read-only checks such as sshd -t, systemctl status ssh --no-pager, and ufw status verbose before and after changes. Do not close the working session until key-based login, SSH reload, and firewall status have all been checked.
Bottom line
SSH hardening is not about one clever setting. It is about changing access without losing access.
Keep a working session open, verify key login, test syntax, reload carefully, and only then remove weaker paths.