The setting is PermitRootLogin in /etc/ssh/sshd_config, and on most modern distributions it already defaults to prohibit-password — meaning root can log in with a key but not a password. That default is deliberate, it is good, and the honest advice is to leave it alone.
There are real situations where you need root over SSH: a migration tool that requires it, an appliance that has no other account, a recovery path when sudo itself is what broke. Those exist. What is worth separating is the case where you genuinely need it from the far more common case where enabling it is just the fastest way past an error message, and the cost shows up later in an auth log full of automated attempts.
Table of contents
- What the four values actually mean
- Changing it, safely
- Why the default is what it is
- The setup worth having instead
- Recovering when you have locked yourself out
- When you genuinely do need root over SSH
- How this fits the rest of the stack
- FAQ
What the four values actually mean
PermitRootLogin takes more than yes and no, and the middle options are the interesting ones.
yes— root may log in by any method the server accepts, including password.prohibit-password— root may log in with a public key or another non-interactive method, but password authentication for root is refused. This is the default on Debian, Ubuntu, and most current distributions.forced-commands-only— root may authenticate with a key, but only to run a command pinned in theauthorized_keysentry. Interactive shells are refused. This is how you give a backup tool root access to exactly one command.no— root cannot log in over SSH at all, by any method.
forced-commands-only deserves more use than it gets. It is the right answer for automation that genuinely needs privilege — a backup agent, a config management pull — because it grants exactly one operation rather than a shell. Most people jump straight from no to yes without noticing the option in between that would have solved the actual problem.
Changing it, safely
The edit itself is trivial. The safety is in the order of operations.
sudo nano /etc/ssh/sshd_config
# set: PermitRootLogin prohibit-password
sudo sshd -t # validate before reloading
sudo systemctl reload sshd # or: sudo systemctl reload ssh
Run sshd -t before every reload. It parses the config and reports syntax errors without touching the running daemon. Skipping it is how people lock themselves out of a remote machine with a typo, because a config that fails to parse means sshd will not come back up.
The other half of the safety net: keep your existing SSH session open while you test. Reload does not kill established connections. Open a second terminal, confirm you can still get in, and only then close the first one. If the new config is broken, the old session is your way back.
One more trap. On Ubuntu since 22.10 and Debian 12, sshd reads drop-in files from /etc/ssh/sshd_config.d/*.conf, and the include sits near the top of the main file. Since the first occurrence of a keyword wins in sshd config, a drop-in can silently override the line you just edited. sudo sshd -T | grep -i permitrootlogin prints the effective value after all includes are resolved, which is the number that actually matters.
Cloud images add their own layer. Many ship a 99-cloud-init.conf drop-in, and some set PermitRootLogin there. Editing the main file and watching nothing change is almost always this.
Why the default is what it is
Root is the one username that exists on every Linux machine. That makes it the free half of every credential-guessing attempt — an attacker needs only the password, never the username. Put a server on a public IP with password auth enabled for root and the auth log fills with attempts within hours. Not because anyone targeted you; because the entire address space is scanned continuously.
The second reason is accountability. When four people share the root password, the log line says root and stops there. When each person has their own account and escalates with sudo, the log says who ran what and when. That difference is invisible on a good day and decisive on a bad one.
The third is blast radius. A compromised unprivileged account is a problem. A compromised root account is the end of the conversation — there is nothing left to escalate to, and no audit trail the intruder cannot edit.
None of this is theoretical or new, which is why the distributions changed the default rather than leaving it to documentation.
The setup worth having instead
Key-based login as a normal user, with sudo for privilege. It takes about five minutes and removes the whole category of problem.
# on your machine
ssh-keygen -t ed25519 -C "you@example.com"
ssh-copy-id deploy@server.example.com
# on the server
sudo adduser deploy
sudo usermod -aG sudo deploy # or wheel on Red Hat family
Then tighten the daemon. Each of these lines removes an attack surface rather than adding a feature:
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AllowUsers deploy
PasswordAuthentication no is the one that does the heavy lifting. Once no account on the box accepts a password over SSH, guessing is off the table entirely and the log noise drops to nothing. Confirm your key works before you set it, obviously — with the second-terminal habit from earlier.
Ed25519 keys over RSA, for what it is worth: shorter, faster, and no key-size decision to get wrong. Use RSA 4096 only when something in the chain genuinely cannot handle ed25519, which in 2026 is rare.
Changing the SSH port is sometimes suggested as a hardening step. It reduces log noise from broad scans and does not meaningfully improve security against anyone looking at your specific host. Do it if the quieter logs help you spot real events; do not count it as a control.
Recovering when you have locked yourself out
It happens. The routes back, roughly in order of how likely they are to be available:
- Provider console. Most hosts offer a serial or VNC console that bypasses SSH entirely. This is the normal answer and the reason to check it exists before you start editing sshd config.
- Another open session. If you kept one, fix the file and reload again. This is why the second-terminal habit matters.
- Rescue mode. Boot the provider’s rescue image, mount the root filesystem, edit
/etc/ssh/sshd_configand any drop-ins, reboot. - Snapshot rollback. If you took one before the change, restore it. If you did not, note that you should have.
The pattern across all four is that the recovery path is something you arrange beforehand. Check the console works while you can still get in the front door — a rescue procedure you have never tested is not a rescue procedure.
When you genuinely do need root over SSH
There are legitimate cases and it is worth naming them so this does not read as an absolute rule.
- A migration or imaging tool that shells in as root by design and cannot be configured otherwise.
- An appliance or embedded system where root is the only account that exists.
- Initial provisioning, before any other account has been created.
- A break-glass path for the specific failure where sudo or PAM is what broke.
In every one of those, prohibit-password plus a dedicated key gets the job done without opening password auth. Scope it further with from= restrictions in authorized_keys to pin the source address, and with forced-commands-only if the tool runs one command. And when the migration finishes, set it back — temporary changes that nobody reverts are how a fleet drifts into a state nobody intended.
How this fits the rest of the stack
Every one of these controls is something you configure, verify, and then re-verify after the next distribution upgrade quietly changes a default. That maintenance is real work, and it is work that produces no features. A managed platform moves the boundary: deployments come from a connected repository rather than an interactive shell, secrets live in environment variables instead of files someone has to remember to chmod, and access is a team permission rather than a key on somebody’s laptop. Services on RunxBuild covers how deploys, environment variables, logs, and rollback fit together. If you are weighing that against a VM you currently harden by hand, the RunxBuild hosting calculator puts the service, database, storage, and bandwidth costs side by side so the comparison includes the parts people usually forget.
Useful related references:
- What Port is SSH: 22 (Default), How to Change, and Why
- Default Port for SSH: Why 22, and When to Change It
- What Port for SSH: 22, 2222, and the Right Defaults
- Services on RunxBuild
FAQ
How do I enable root login over SSH?
Set PermitRootLogin yes in /etc/ssh/sshd_config, validate with sudo sshd -t, then sudo systemctl reload sshd. Keep your existing session open while you test the change from a second terminal. Prefer prohibit-password over yes so root can use a key but not a password.
What does prohibit-password mean in sshd_config?
Root may authenticate using a public key or another non-interactive method, but password authentication for root is refused. It is the default on most modern distributions and is almost always the right setting when root access is genuinely needed.
I changed PermitRootLogin and nothing happened. Why?
A drop-in file is probably overriding it. Modern sshd reads /etc/ssh/sshd_config.d/*.conf via an Include near the top of the main file, and the first occurrence of a keyword wins. Run sudo sshd -T | grep -i permitrootlogin to see the effective value after includes.
Is disabling root SSH login actually necessary?
It is not required, but it removes a real attack surface: root is the one username guaranteed to exist, so it is the target of most automated attempts. Key-based login as a normal user with sudo gives you the same capability plus an audit trail showing who did what.
How do I get back in if I lock myself out of SSH?
Use your provider’s serial or VNC console, which bypasses SSH entirely. Failing that, boot into rescue mode, mount the root filesystem, and fix /etc/ssh/sshd_config and any drop-in files. Verify the console works before you start editing SSH config, not after.