sshd_config linter
The server side. Paste /etc/ssh/sshd_config
or a drop-in from sshd_config.d/.
What no linter can tell you
This cannot see file order, and file order is what usually
bites. sshd reads /etc/ssh/sshd_config.d/*.conf
alphabetically and takes the first value it finds for each
keyword. Cloud images ship 50-cloud-init.conf containing
PasswordAuthentication yes — so a hardening file named
60-hardening.conf is read, parsed, and silently ignored.
The config looks right. The setting is still wrong. There is no error anywhere. Always confirm against what sshd actually resolved:
sshd -T | grep -E 'passwordauthentication|permitrootlogin|kbdinteractive|loglevel'
Never by reading the file. Not even this page's opinion of the file.
The one that catches everyone
Setting PasswordAuthentication no and leaving
KbdInteractiveAuthentication yes often changes nothing at all:
keyboard-interactive goes through PAM, and PAM asks for a password. People
disable password auth, watch a password login still succeed, and conclude the
setting does not work.
Turn off both.
A baseline to start from
Named 00- deliberately — see above. Conservative rather than
maximal, and worth revisiting on each OpenSSH upgrade: pinning algorithm
lists means you stop negotiating anything newer, including post-quantum key
exchange.
# /etc/ssh/sshd_config.d/00-hardening.conf # # Named 00- ON PURPOSE. sshd reads this directory alphabetically and takes the # FIRST value it sees for each keyword — and cloud images ship # 50-cloud-init.conf containing "PasswordAuthentication yes". A file sorting # after that one is silently ignored, which is the failure mode where the # config looks right and the setting is still wrong. # # Verify with: sshd -T | grep -E 'passwordauth|permitroot|loglevel' # Never by reading the file. # Authentication PermitRootLogin no PasswordAuthentication no KbdInteractiveAuthentication no # otherwise PAM hands passwords back PermitEmptyPasswords no PubkeyAuthentication yes MaxAuthTries 3 # Who may log in at all. Without this, every account on the host can. AllowGroups ssh-users # Log the key fingerprint used for each login. This is what lets you answer # "which key was that?" months later. LogLevel VERBOSE # Reduce what a session can do to the host and the network X11Forwarding no PermitUserEnvironment no GatewayPorts no PermitTunnel no StrictModes yes # Modern algorithms only. Revisit on each OpenSSH upgrade: pinning means you # stop negotiating anything new, including post-quantum key exchange. KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com HostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512 # Drop idle and half-open sessions ClientAliveInterval 300 ClientAliveCountMax 2 LoginGraceTime 30