Every guide on this site starts the same way: you SSH into a fresh server as root with a password. That works on day one and becomes your biggest weakness by day two. This guide locks the door properly — while keeping a way back in if you lock yourself out. That last part is the one most tutorials skip.

The plan, and why the order matters

  1. Create a non-root user with sudo, and install your public key for it.
  2. Verify that user works in a second SSH session — before touching anything else.
  3. Only then disable root login and password authentication.
  4. Keep the provider's web console in your back pocket as the recovery path.
Never close the door you're standing in. Keep your original root session open until the new user is proven. If a mistake locks you out, you still have one working session to fix it.

1. Create the user and grant sudo

On the server (your existing root session):

adduser deploy          # pick your own username; set a strong password
usermod -aG sudo deploy

2. Install your public key for the new user

Your private key never leaves your own computer. You copy the public key (the .pub file) to the server:

mkdir -p /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
nano /home/deploy/.ssh/authorized_keys   # paste your PUBLIC key (.pub), one per line
chmod 600 /home/deploy/.ssh/authorized_keys
chown -R deploy:deploy /home/deploy/.ssh

Those permissions are not ceremonial: OpenSSH refuses to honor authorized_keys if the file or its directories are writable by anyone but the owner. If key login ever fails silently, wrong permissions are the first thing to check (sshd logs the refusal — see Troubleshooting).

Don't have a key yet? On your own computer:

ssh-keygen -t ed25519 -C "you@example.com"

Windows: the same command works in PowerShell (OpenSSH is built in). Instead of ssh-copy-id, copy the public key manually — print it with type $env:USERPROFILE\.ssh\id_ed25519.pub, then paste it into the authorized_keys file on the server as shown above.

3. Verify in a NEW session — before changing anything

Open a second terminal on your computer and test the new user end to end:

ssh deploy@your-server-ip
# should log in with your key, no password
sudo whoami     # should print: root

Only when that session works — key login and sudo — do you continue. This is the checkpoint that separates a secured server from a locked one.

4. Disable root login and passwords

sudo nano /etc/ssh/sshd_config

Set or confirm:

PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
Check for included config first. Many distributions ship /etc/ssh/sshd_config.d/*.conf, and files there override the main config — a leftover 60-cloudimg-settings.conf re-enabling password auth has bitten many administrators. Run ls /etc/ssh/sshd_config.d/ and read anything in it before assuming your edit took effect.

Validate the config, then reload — don't restart blindly:

sudo sshd -t                    # syntax check: prints nothing when OK
sudo systemctl reload ssh       # Debian/Ubuntu service name

Service names differ by OS: Debian/Ubuntu use ssh, RHEL-family and newer Fedora use sshd. If unsure, systemctl list-units --type=service | grep -i ssh shows the real name. A reload applies config without dropping existing sessions — which is why your second terminal is still insurance.

Final proof: from a third terminal, confirm password login now fails and key login still works.

5. Your recovery path — set it up before you need it

  • Provider web console. DigitalOcean, RackNerd, and most others offer an emergency console in the control panel. It works even when SSH is misconfigured. Confirm yours exists and know how to reach it.
  • Your private key can be copied or stolen. Treat it like a password: it lives on your devices, protected by your OS permissions. Full-disk encryption and a passphrase on the key itself (ssh-keygen -p -f ~/.ssh/id_ed25519) cover the laptop-left-in-a-café case.
  • The public key alone cannot get anyone in — publishing it is harmless. But adding a key to authorized_keys requires access you already have, so it is not a recovery mechanism if you lose everything.
  • A second, emergency key stored on a different device (or a passphrase-protected key on an offline USB stick) is the standard answer to "laptop died, locked out."

6. A firewall — with one honest caveat

sudo apt install ufw          # UFW is not installed by default on every image
sudo ufw allow OpenSSH        # BEFORE enabling — or you'll lock yourself out
sudo ufw allow 80,443/tcp     # only when you're ready to serve web traffic
sudo ufw enable
sudo ufw status verbose

One caveat that matters later: UFW does not reliably police ports that Docker publishes. Docker manipulates iptables ahead of UFW's rules, which is why every app guide on this site binds web UIs to 127.0.0.1 and reaches them through SSH tunnels. Details in the Docker guide.

Troubleshooting

  • Key login rejected but password works: permissions or ownership on ~/.ssh/authorized_keys, or the key isn't in the right user's file. Server-side, sudo tail /var/log/auth.log (Debian/Ubuntu) names the exact reason.
  • "Permission denied" after editing sshd_config: something in sshd_config.d/ overrides you, or sshd -t would have caught a typo. Use the provider console to fix it.
  • Locked out entirely: provider web console → log in as root → set a temporary password for your user (passwd deploy), log in, fix SSH, then remove the temporary password (passwd -l deploy).