A short and practical cheat sheet for a reasonably secure SSH setup, both on the server and on the client.
This is not a complete hardening guide. It is a simple baseline that is easy to use, easy to read, and good enough for many small servers.
Server: sshd_config
Port 22
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
AllowUsers youruser
MaxAuthTries 3
X11Forwarding no
# Optional hardening:
# LoginGraceTime 30
# AllowAgentForwarding no
# AllowTcpForwarding no
# ClientAliveInterval 300
# ClientAliveCountMax 2
# Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
# KexAlgorithms sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,curve25519-sha256
# MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.comClient: ~/.ssh/config
Host *
HashKnownHosts yes
ServerAliveInterval 60
ServerAliveCountMax 3
# Optional hardening:
# ForwardAgent no
# Compression no
# StrictHostKeyChecking ask
# UpdateHostKeys yes
# AddKeysToAgent yes
Host my-server
HostName example.com
User youruser
Port 22
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yesExplanation: server
Port 22
Listen on the standard port. Changing it can reduce log noise, but it does not replace real security.
PermitRootLogin no
Block direct login as root. Log in as a normal user and use sudo when needed.
PasswordAuthentication no
Disable password login so only SSH keys work.
PubkeyAuthentication yes
Allow login with SSH keys. This is the foundation when passwords are disabled.
KbdInteractiveAuthentication no
Disable interactive authentication to reduce the chance of password-based flows sneaking back in.
X11Forwarding no
Disable X11 forwarding unless you explicitly need it.
Optional hardening
The following lines are useful when you want a stricter setup, but they are not required for every server.
AllowAgentForwarding no
Disable agent forwarding unless you explicitly need it. It is convenient, but it also expands the trust boundary.
AllowTcpForwarding no
Disable port forwarding unless the server is actually meant to be used as a jump host, tunnel endpoint, or similar.
AllowUsers youruser
Restrict which accounts are allowed to even try logging in over SSH.
MaxAuthTries 3
Reduce the number of allowed attempts per connection.
LoginGraceTime 30
Do not leave half-open login attempts hanging around for too long. Thirty seconds is enough for most normal logins.
ClientAliveInterval 300
Have the server check whether the client is still alive every five minutes.
ClientAliveCountMax 2
Drop dead sessions after a couple of missed replies instead of keeping them forever.
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
Restrict encryption to modern ciphers. This is optional, since OpenSSH already has good defaults, but it can be useful if you want a stricter baseline.
KexAlgorithms sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,curve25519-sha256
Restrict key exchange to modern algorithms. Again, this is optional hardening more than a strict requirement.
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
Restrict message authentication to strong Encrypt-then-MAC variants for older non-AEAD cipher cases.
Explanation: client
Host *
Apply the following settings to every host, unless a more specific host block overrides them.
Host my-server
A short alias so you can type ssh my-server.
HostName example.com
The actual hostname or IP address to connect to.
User youruser
Which user the client should log in as by default.
Port 22
Which port the client should use for this specific host.
IdentityFile ~/.ssh/id_ed25519
Which private key should be used.
IdentitiesOnly yes
Force the client to try only the key you specify here, instead of everything that happens to be loaded.
HashKnownHosts yes
Store hostnames in hashed form in known_hosts so the file leaks less information if it is exposed.
ServerAliveInterval 60
Send a keepalive every 60 seconds so long-running sessions are less likely to die behind NAT or firewalls.
ServerAliveCountMax 3
Close the connection after a few missed keepalives instead of hanging forever.
Optional hardening
The following lines are helpful if you want stricter client behavior by default.
ForwardAgent no
Do not forward your local SSH agent unless you explicitly need it.
Compression no
Leave compression off unless you have a very specific reason to enable it.
StrictHostKeyChecking ask
Warn before trusting an unknown host key. This is safer than blindly accepting everything.
UpdateHostKeys yes
Allow the client to learn better host keys from a server it already trusts.
AddKeysToAgent yes
Add keys to your local agent when you use them. This is mostly a convenience setting.
A simple rule of thumb
- Use SSH keys, not passwords
- Do not allow direct root login
- Keep forwarding features off unless you need them
- Treat cipher and KEX pinning as optional hardening, not mandatory for every system
- Prefer a short config you understand over a long config you copied blindly