All free tools Generated in your browser

sshd Hardening Generator

Choose a hardening level, review the risks it flags, and generate an OpenSSH server configuration you can drop into /etc/ssh/sshd_config.d/.

Harden an OpenSSH server

sshd_config

A wrong sshd_config can lock you out of your own server. Keep your current SSH session open while you apply and test the new file, and open a second session to check that logging in still works before you close the first one. Make sure you still have console, VNC or recovery access through your provider's panel, and never set PasswordAuthentication no until you have confirmed a working key login with ssh -i ~/.ssh/your_key user@server.

Choosing a level fills in the settings below. Everything stays editable, and changing any value switches the level to Custom.
Access and authentication
1 to 65535. A non-standard port cuts noise in the logs, but it is obscurity rather than security. Open the new port in the firewall first. On Ubuntu 22.10 and newer with socket activation, the listening port comes from ssh.socket, not from this file.
Failed attempts allowed per connection, 1 to 20. Each key your agent offers counts as an attempt.
Sessions allowed inside one network connection, 1 to 100.
no blocks root entirely, prohibit-password allows root with a key only, and yes allows root with a password and is flagged as risky.
How long an unauthenticated connection may stay open, 0 to 600. A value of 0 removes the limit and is not recommended.
Allow lists and listeners
The account you log in with today. It is not written into the file; it is used only to warn you if an allow list would shut you out.
Optional. Separate names with spaces or commas. Only these accounts may log in. Patterns such as [email protected].* are allowed.
Optional. Check your own membership with id -nG yourname before applying, because both lists must pass.
Optional, one IPv4 or IPv6 address per line. Leave empty to listen on every address. Under systemd socket activation this setting is ignored.
Forwarding and features
Set to no if nobody tunnels through this server. It does not stop a shell user from installing their own forwarder.
Layer 2 or layer 3 tun device forwarding. Almost nothing needs it.
Whether a remote forward may listen on a public address rather than loopback only.
OpenSSH treats a second Subsystem sftp definition as a fatal error. If you set one here, comment out the existing Subsystem sftp line in /etc/ssh/sshd_config first, or sshd -t will report that it is already defined.
Optional file shown before authentication. Use none to turn a banner off explicitly.
Keepalives
0 to 3600. The server sends a check to an idle client this often. 0 disables the check.
0 to 100. Unanswered checks before the server closes the session. Interval multiplied by this value is the idle timeout.
Cryptography policy
Modern adds the post-quantum hybrid key exchange [email protected], which needs OpenSSH 8.5 or newer on both ends. Compatible drops it and keeps the same ciphers and MACs. Leaving the distribution defaults is a reasonable choice on current Ubuntu and Debian, whose shipped lists are already free of the weak algorithms.
Match blocks (optional)

A Match line ends the general part of the file: everything after it applies only to that block. Match blocks are always written last for that reason.

We do not store your data. The review and the configuration file are produced entirely in your browser and never sent to VPSLake. No password, key or other secret is requested anywhere on this page.

Harden in four steps

Work on a server where you already have a second way in, such as the provider console, before you change anything.

  1. 1

    Pick a level and adjust it

    Balanced suits a normal internet-facing server. Strict tightens the limits and switches off forwarding. Either preset stays editable, and the level changes to Custom as soon as you edit a value.

  2. 2

    Name your admin account

    Type the account you actually log in with. If an allow list would exclude it, the review flags that before you deploy the file rather than after.

  3. 3

    Read the review, then the file

    The review explains what each risky choice means and what to change. The generated file below it is what you deploy.

  4. 4

    Deploy it with a session still open

    Save it as /etc/ssh/sshd_config.d/99-hardening.conf, run sudo sshd -t to check the syntax, then sudo systemctl reload ssh. Leave your current session connected and open a second one to confirm you can still log in. To roll back, delete the file and reload again.

How the drop-in file works

Current Debian and Ubuntu ship an /etc/ssh/sshd_config whose first effective line is Include /etc/ssh/sshd_config.d/*.conf. Files in that directory are read at that point, before the rest of the main file.

That ordering matters, because for most keywords sshd keeps the first value it reads. A drop-in only wins because it is included near the top; a file appended to the bottom of sshd_config would lose to the values above it. Naming the file with a number prefix, such as 99-hardening.conf, controls its order relative to other drop-ins your distribution or your cloud image may already have installed.

Everything after a Match line belongs to that block, so the generated file always places Match blocks at the very end.

What the review checks

The review is a plain reading of the settings you chose. It does not connect to your server, scan it, or know anything about it beyond what you typed, so it cannot confirm that a key is installed or that a group exists.

  • Password, keyboard-interactive and public key authentication
  • Root login policy and empty-password handling
  • Missing allow lists, and allow lists that exclude your own account
  • Forwarding, tunnelling and gateway ports
  • Attempt limits, grace time and idle timeouts
  • Match block overrides that loosen the general policy

Treat this as a reviewed starting point, not an audit

The generated file is a sensible baseline for a general-purpose Linux server. It has not been audited against any compliance standard, and it cannot be guaranteed safe for your environment. Test it on one machine before rolling it out, keep console or recovery access available, and remember that hardening sshd is only part of the job: you still need current packages, a firewall, restricted sudo, and a rate limiter such as fail2ban or sshguard.

sshd Hardening Generator FAQ

On Ubuntu 20.04 and newer, Debian 11 and newer, and most current distributions, save it as /etc/ssh/sshd_config.d/99-hardening.conf owned by root with mode 644. Confirm that /etc/ssh/sshd_config contains Include /etc/ssh/sshd_config.d/*.conf; if it does not, add that line as the first line of the file, because sshd keeps the first value it reads for each keyword. On an older system with no include support, merge the directives into /etc/ssh/sshd_config by hand, replacing rather than duplicating existing keywords.
Run sudo sshd -t first; it prints nothing when the configuration parses. Then run sudo systemctl reload ssh on Debian and Ubuntu, or sudo systemctl reload sshd on RHEL, Rocky and AlmaLinux. Reloading does not disturb existing sessions, so keep the session you are in open, then open a second terminal and log in again. Only close the first session once the second one works. If it does not, use the still-open session to run sudo rm /etc/ssh/sshd_config.d/99-hardening.conf and reload again.
Ubuntu 22.10 and newer start sshd through systemd socket activation, so the listening port comes from ssh.socket and the Port and ListenAddress directives are ignored. Check with systemctl is-enabled ssh.socket. To change the port there, create /etc/systemd/system/ssh.socket.d/port.conf containing [Socket], an empty ListenStream= line to clear the default, and ListenStream=2222, then run sudo systemctl daemon-reload && sudo systemctl restart ssh.socket. Also open the new port in your firewall and in any provider-level security group before you disconnect.
OpenSSH refuses to accept the same subsystem twice, and Debian and Ubuntu already set Subsystem sftp /usr/lib/openssh/sftp-server in the main sshd_config. If you asked this tool to emit a Subsystem line, comment out the existing one in /etc/ssh/sshd_config and validate again. If you do not need to change SFTP, leave the option on the distribution default and no Subsystem line is written at all.
If every client is OpenSSH 8.5 or newer, Modern is a good choice: it puts the hybrid post-quantum key exchange [email protected] first and keeps only ChaCha20-Poly1305, AES-GCM, AES-CTR and encrypt-then-MAC MACs. Compatible removes the post-quantum exchange so OpenSSH 7.x clients and older network appliances can still connect. If you are unsure, leave the distribution defaults: the lists shipped by current Ubuntu and Debian are already free of the genuinely weak algorithms, and a hand-written list that is too narrow is a common cause of "no matching key exchange method found".
Once AllowUsers exists, every account not listed is refused, and the list is case-sensitive. If you also set AllowGroups, an account must satisfy both lists, not either one. Check group membership with id -nG name. Root is a normal account for these lists: if you set PermitRootLogin prohibit-password but do not list root, root still cannot log in.
That keyword replaced ChallengeResponseAuthentication in OpenSSH 8.7. On an older server, change the line to ChallengeResponseAuthentication with the same value. Check your version with sshd -V or ssh -V. Note that with PAM in use, turning this off is what actually stops PAM from prompting for a password even when PasswordAuthentication no is set.
No. Validation, the review and the file are all produced by JavaScript running in your browser, and the page makes no network requests with your input. The admin account name is used only for the allow-list warning and is never written into the generated file. The tool never asks for a password, private key or server credential.
It does not generate or install host keys, edit PAM, configure a firewall, set up fail2ban, apply two-factor authentication, or touch your server in any way. It also leaves out directives it cannot validate confidently, so treat the output as a base and add anything else after checking it in man sshd_config.