How to edit sshd_config without locking yourself out

A safe routine for changing sshd_config over SSH: validate with sshd -t, check the effective settings for your login, and arm a timed rollback first.

On this pageThe routine1. Keep a session open2. Back up the file3. Validate, then check the effective settings4. Arm a rollback before you reload5. Reload, test, cancelThe changes that lock people outHave a way in that is not SSHThe same routine, built into the editorFAQ

Everyone who runs servers has done it once: change sshd_config, reload, close the terminal, and discover that the only door into the machine is now shut. The fix is usually a console session through a cloud provider, sometimes a drive to a data centre. The prevention is a five-step routine that takes two minutes.

The routine

  1. Keep your current session open.
  2. Back up the file.
  3. Validate the new file with sshd -t, and check what sshd will really do for your login with sshd -T.
  4. Arm a timed rollback on the server.
  5. Reload, test a fresh login from a second terminal, then cancel the rollback.

Each step guards against a different mistake.

1. Keep a session open

Reloading sshd does not disconnect sessions that are already established. They run in their own processes. Your open terminal is your way back in, so do not close it until a new login has worked.

2. Back up the file

sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

-a keeps the owner, the mode and the SELinux context.

3. Validate, then check the effective settings

A syntax check:

sudo sshd -t && echo OK

sshd -t reads the configuration and reports the first error with its line number. If it prints anything, stop. A reload usually refuses a broken file, but a restart with one leaves no daemon listening at all.

A syntax check is not enough, though. A file can be valid and still shut you out. Ask sshd what it will do for your login:

sudo sshd -T -C user=deploy,addr=203.0.113.7 | grep -iE \
  'passwordauthentication|pubkeyauthentication|permitrootlogin|allowusers|allowgroups|authenticationmethods'

-T prints the effective configuration after every Include and Match block is applied. -C supplies the connection to evaluate Match blocks for: your user and the address you connect from.

Why your edit may have no effect

sshd uses the first value it reads for each keyword. On Debian and Ubuntu the main file starts with:

Include /etc/ssh/sshd_config.d/*.conf

So a drop-in file wins over anything further down the main file. The classic case is a cloud image with /etc/ssh/sshd_config.d/50-cloud-init.conf containing PasswordAuthentication yes. You set PasswordAuthentication no in the main file, reload, and passwords still work. sshd -T shows the truth:

sudo sshd -T | grep -i passwordauthentication
grep -ri passwordauthentication /etc/ssh/sshd_config /etc/ssh/sshd_config.d/

4. Arm a rollback before you reload

This is the step most people skip. Tell the server to put the old file back in five minutes unless you say otherwise:

sudo systemd-run --on-active=5min --unit=sshd-rollback \
  /bin/sh -c 'cp -a /etc/ssh/sshd_config.bak /etc/ssh/sshd_config && systemctl reload ssh'

systemd-run creates a one-off timer that survives your session ending. On Fedora, RHEL, Arch and openSUSE the service is called sshd, not ssh.

On a system without systemd, at does the same job:

echo 'cp -a /etc/ssh/sshd_config.bak /etc/ssh/sshd_config && service ssh reload' | sudo at now + 5 minutes

5. Reload, test, cancel

Reload rather than restart:

sudo systemctl reload ssh

Now open a second terminal and log in again. If you use connection sharing, a plain ssh would reuse your existing connection and prove nothing, so switch it off for the test:

ssh -S none deploy@server

If the login works, cancel the rollback from either session:

sudo systemctl stop sshd-rollback.timer

If it does not work, you have two options, both good: fix the file in the session you kept open, or wait for the timer to restore it.

The changes that lock people out

ChangeHow it goes wrongCheck first
PasswordAuthentication noYour key was never authorised for this accountLog in with the key before you make the change
PermitRootLogin noYou log in as root and have no other account with sudoCreate and test the other account first
AllowUsers or AllowGroupsThe list leaves you out. Once it exists, everyone not on it is refusedsshd -T -C user=you
Port 2222A firewall, a security group or SELinux still allows only 22Open the new port first, and keep Port 22 as a second line until the new one works
AuthenticationMethods publickey,keyboard-interactiveThe second factor is not set up for your accountTest on a second account
AllowTcpForwarding no on a bastionEvery host that is reached through it becomes unreachableList what jumps through this host
UsePAM noAccount and session rules that PAM enforced silently changeLeave it alone unless you know why

Two notes on moving the port. With SELinux enforcing, sshd cannot bind a new port until you allow it:

sudo semanage port -a -t ssh_port_t -p tcp 2222

On Ubuntu 24.04, where sshd is socket-activated, a new port also needs the socket unit regenerated:

sudo systemctl daemon-reload && sudo systemctl restart ssh.socket

Have a way in that is not SSH

The routine above makes a lockout unlikely, not impossible. Know your out-of-band path before you need it: the serial console of your cloud provider, a hypervisor console, IPMI or iDRAC, or a rescue mode that mounts the disk. Check that it works on a quiet day.

The same routine, built into the editor

Safe Change in Gatesys SSH is this routine as a review sheet. Saving sshd_config from the SFTP browser, or from your own editor, opens it:

  • The diff of what you changed.
  • The server’s own check: sshd -t on a staged copy, so a broken file never reaches /etc/ssh.
  • Your login, before and after. It runs sshd -T -C for the login you are using and shows the effective settings side by side. An edit that sshd reads the same way, because an included file wins, is marked no effect.
  • Findings in red when the login you are using would be refused, when sshd would stop listening where you came in, or when forwarding goes off for hosts that jump through this one, by name.
  • A backup under /var/backups/gatesys, five kept per file.
  • The safety net. A systemd timer on the server restores the old file after 1, 3 or 10 minutes. Gatesys SSH then makes a fresh login with the same key and asks New login works. Keep this change? If you do nothing, the server puts the old file back.

It works the same for nginx files with nginx -t, sudoers with visudo -cf, and systemd units. The review sheet, the checks, the backup and the safety net are in the free plan. Describing the change in a sentence and letting the Farabi assistant draft it needs Pro.

FAQ

How do I test sshd_config before applying it?

Run sudo sshd -t. It validates the file and exits silently when it is correct. Then run sudo sshd -T to see the effective settings, which is the only way to catch a value overridden by an included file or a Match block.

Does restarting sshd disconnect my current session?

Normally no. Established sessions run in their own processes and survive a reload or a restart of the daemon. Prefer reload, and keep the session open until a new login has worked.

Why does my sshd_config change have no effect?

sshd uses the first value it reads for each keyword. A file in /etc/ssh/sshd_config.d/ that is included at the top of the main file overrides what comes later. Check with sudo sshd -T | grep -i keyword.

I am locked out of SSH. What now?

Use an out-of-band console: your cloud provider’s serial or web console, a hypervisor console, or rescue mode. Restore the backup of sshd_config, run sshd -t, and restart the service.

Is it “ssh” or “sshd” in systemctl?

Debian and Ubuntu name the service ssh. Fedora, RHEL, CentOS, Arch and openSUSE name it sshd.

Keep reading

All posts
Guides

SSH ProxyJump: a practical guide to jump hosts

Reach servers behind a bastion with ssh -J and ProxyJump: config examples, multi-hop chains, scp and rsync through a jump host, and bastion hardening.

5 min read

Guides

Debugging a failed ProxyJump chain, hop by hop

An SSH connection through a bastion can fail at five steps on every hop. How to read the error, find the hop that broke, and test from the hop in front of it.

6 min read

Guides

SSH port forwarding explained: -L, -R and -D

Local, remote and dynamic SSH tunnels with examples you can paste: reach a database behind a bastion, expose a local port, or run a SOCKS proxy.

5 min read

Your servers, understood.

Download Gatesys SSH free. Start Pro when you want Farabi — the first 3 months are on us.