Bali, Indonesia
Insights

Restarting sshd Won't Drop Your Session, but a Bad Config Locks Out the Next Login

November 2, 2026
0:00
Plenty of admins edit sshd_config over SSH with one worry in the back of their mind: if I restart sshd now, will it kick me off the server? So they delay the restart, or run it and wait for the terminal to freeze. On a typical Linux server, restarting sshd leaves your current session alone. The real danger shows up later, when you close that session and find the new config refuses every login, including yours. That gap between "the restart went fine" and "nobody can log in anymore" is where most self-inflicted SSH lockouts come from. It is worth understanding why, because the fix is a habit, not a tool.
The SSH daemon is not one process holding every connection. There is a main sshd process that listens on the port (22 by default) and does almost nothing else. When a client connects, the listener starts a separate process for that connection, and that process handles authentication and your shell from then on. Recent OpenSSH releases make this split even more visible by running each connection under a separate sshd-session binary, but the idea is the same in older versions. When you restart the service, systemd stops the main listener and starts a new one. Whether your session processes get killed along the way depends on the unit's KillMode setting. The ssh units shipped by the common distributions typically use KillMode=process, which tells systemd to stop only the main process and leave the per-connection children running. Your shell keeps working because the process serving it was never touched. You can see this structure for yourself:
BASH
# How systemd stops the service (unit is 'ssh' on Debian/Ubuntu, 'sshd' on RHEL family)
systemctl show -p KillMode ssh

# Listener vs per-connection processes, shown as a tree
ps -ef --forest | grep '[s]shd'

# Read the unit file, including any ExecStartPre or ExecReload checks
systemctl cat ssh
There are exceptions. A reboot ends everything, obviously. A unit with KillMode=control-group would kill the whole process group. And a blunt command like pkill sshd matches the session processes too, not just the listener. But a normal systemctl restart on a stock unit is not what drops people.
A restart is a stop followed by a start. The stop always succeeds. The start only succeeds if the new sshd can parse its config and load its host keys. If you left a typo, an unknown keyword, or a bad value in the file, the new listener exits immediately and nothing is listening on the port anymore. From inside your open session, this can look completely fine. Your prompt still responds. The systemctl restart command may print an error, but it is easy to miss, and some people run it chained with other commands. Meanwhile every new connection gets refused. Your current session is now the only way into the server, and it is held together by your Wi-Fi, your laptop's sleep settings, and any idle timeout like ClientAliveInterval that you may have just configured. Some distributions guard against part of this. Their unit files run sshd -t before a start or reload, so a syntax error aborts the reload and the old listener stays up. That protection depends on the unit, so read it with systemctl cat instead of assuming. And it only helps with reload in most cases. On a restart, the old listener is already gone by the time the check fails. The second kind of broken config is harder to spot because it is perfectly valid. sshd starts, the port is open, and you still cannot get in. Common examples during hardening:
  • PasswordAuthentication no set before your public key is actually in ~/.ssh/authorized_keys with the right permissions.
  • PermitRootLogin no on a server where you only ever log in as root.
  • AllowUsers or AllowGroups added without your own account in the list.
  • A new Port value with the firewall, or SELinux on RHEL-family systems, still only allowing 22.
There is also a trap with drop-in files. Many modern distributions put Include /etc/ssh/sshd_config.d/*.conf near the top of the main file, and for most keywords sshd uses the first value it reads. A drop-in from cloud-init or a provider image can quietly override the setting you just changed further down. A common pattern in lockout and "my hardening didn't apply" tickets is exactly this: the admin edited the right line in the wrong place.
sshd -t is test mode. It parses the full config, including Include files, checks the host keys, and exits without starting anything. It prints nothing when the config is valid, so pair it with an explicit success message. Run it as root, because it needs to read the host keys. sshd -T goes further and prints the effective configuration after defaults and drop-ins are applied. That is how you catch the first-value-wins problem: you see what sshd will actually use, not what you think you wrote. Adding -C lets you evaluate Match blocks for a specific user and source address.
BASH
# Syntax and host key check; silent with exit code 0 when valid
sudo sshd -t && echo 'config OK'

# Effective values after defaults and Include files are applied
sudo sshd -T | grep -Ei '^(port|permitrootlogin|passwordauthentication|pubkeyauthentication|allowusers|allowgroups) '

# Evaluate Match blocks for a given user and client address
sudo sshd -T -C user=deploy,host=example.com,addr=203.0.113.10 | grep -i '^passwordauthentication'
When something is wrong, sshd -t points at the file and line. Illustrative output format:
TEXT
/etc/ssh/sshd_config: line 42: Bad configuration option: PermitRootLogn
/etc/ssh/sshd_config: terminating, 1 bad configuration options
Be clear about what this check cannot see. It does not know whether your key is in authorized_keys, whether the firewall allows the new port, whether SELinux labels it, or whether your username matches AllowUsers. A config can pass sshd -t and still lock you out. That is why the next step matters more.
The only real test of an SSH config is a fresh login. Your existing session is your safety line, so keep it open until a new one has succeeded. The order matters here:
  1. Keep your current session open. Ideally open a second one before you change anything, so you have a spare if the first drops.
  2. Back up the file first, for example to sshd_config.bak next to the original, so a revert is one copy away.
  3. Make the change, then run sshd -t and check the relevant values with sshd -T.
  4. Apply it. Prefer a reload if your unit supports it, since many units validate before reloading and keep the old listener on failure. Restart works too, as long as step 3 passed.
  5. From a new terminal, start a brand new SSH connection using the same user, key, and port you will rely on later. Adding -v to the ssh client shows which authentication methods the server offers and where it fails.
  6. In that new session, confirm that sudo or your root access still works. A login that succeeds but cannot escalate is still a lockout for admin work.
  7. Only after the new login works, close the old session.
If step 5 fails, do not close anything. Fix the config from the session you still have, or restore the backup, validate, and reload again. Watch out for brute-force protection like fail2ban or a firewall's login failure tracking. A few failed test logins from your own IP can get that IP blocked, which looks exactly like a broken config. Check the ban list from your open session before you change more settings. On a support desk, this is usually the first thing to establish when a customer reports a lockout after hardening: is any session still open somewhere? If yes, the fix is quick. If not, you are relying on out-of-band access: a web or serial console from the VPS platform, the noVNC or serial console on a Proxmox host, or IPMI on dedicated hardware. Find out which of these your platform provides before you need it, not during the lockout.
Stop worrying about the restart and start worrying about the next login. Restarting sshd on a standard unit leaves existing sessions running, which is exactly what gives you room to test safely. Run sshd -t to catch syntax errors, use sshd -T to see what sshd will actually enforce, and treat a successful fresh login in a second terminal as the only real confirmation. Close the original session last, never first.