SSH Hardening

Practical SSH server hardening guidance for Linux systems in homelab and self-hosted environments

created: Sat Mar 14 2026 00:00:00 GMT+0000 (Coordinated Universal Time) updated: Sat Mar 14 2026 00:00:00 GMT+0000 (Coordinated Universal Time) #security#ssh#linux

Introduction

SSH is the primary administrative entry point for many Linux systems. Hardening it reduces the likelihood of credential attacks, accidental privilege exposure, and overly broad remote access.

Purpose

This guide focuses on making SSH safer by:

  • Disabling weak authentication paths
  • Reducing exposure to brute-force attacks
  • Limiting which users can log in
  • Preserving maintainability by relying on modern OpenSSH defaults where possible

Architecture Overview

SSH hardening has three layers:

  • Transport and daemon configuration
  • Network exposure and firewall policy
  • Operational practices such as key handling and logging

For most self-hosted systems, the best model is:

Admin workstation -> VPN or trusted network -> SSH server

Step-by-Step Guide

1. Use key-based authentication

Generate a key on the client and copy the public key to the server:

ssh-keygen -t ed25519 -C "admin@example.com"
ssh-copy-id admin@server.example

2. Harden sshd_config

Baseline example:

PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
AllowUsers admin

If you need port forwarding for a specific workflow, enable it deliberately instead of leaving it broadly available.

3. Validate the configuration

sudo sshd -t

4. Reload safely

Keep an existing SSH session open while reloading:

sudo systemctl reload sshd

Distribution-specific service names may be ssh or sshd.

5. Restrict network exposure

  • Prefer VPN-only or management-VLAN-only access
  • Allow SSH from trusted subnets only
  • Do not expose SSH publicly unless it is necessary and monitored

Configuration Example

Example host firewall intent:

Allow TCP 22 from 192.168.10.0/24
Allow TCP 22 from Tailscale tailnet range
Deny TCP 22 from all other sources

Troubleshooting Tips

Locked out after config change

  • Keep the original session open until a new login succeeds
  • Validate the daemon config with sshd -t
  • Check the service name and logs with journalctl -u sshd or journalctl -u ssh

Key authentication fails

  • Check file permissions on ~/.ssh and authorized_keys
  • Confirm the server allows public key authentication
  • Verify the client is offering the intended key with ssh -v

Automation jobs break

  • Review whether the workload depended on password auth, port forwarding, or agent forwarding
  • Create narrowly scoped exceptions rather than reverting the whole hardening change

Best Practices

  • Rely on current OpenSSH defaults for ciphers and algorithms unless you have a specific compliance need
  • Disable password-based interactive logins on internet-reachable systems
  • Use individual user accounts and sudo instead of direct root SSH
  • Combine SSH hardening with network-level restrictions
  • Review SSH logs regularly on administrative systems

References