
Password-based SSH is still one of the fastest ways for a new VPS to get owned. This SSH key setup tutorial takes the safer route.
You’ll create keys, prove they work, harden SSH, and then turn off password login.
These steps assume an Ubuntu 24.04/26.04-style server running OpenSSH 9.x.
If you manage client sites, use this as your baseline before you install a control panel, move WordPress, or switch production DNS.
What you’ll build (and what can go wrong if you skip the order)
You’ll end up with:
- An admin user that authenticates via SSH keys (not passwords)
- Root login disabled over SSH (but still available locally/console)
- Sudo configured for admin work without unsafe shortcuts
- A short checklist to confirm you didn’t lock yourself out
The biggest mistake is editing /etc/ssh/sshd_config before you’ve proven key login works from your machine.
Don’t touch hardening settings until you pass the verification checkpoints below.
Prerequisites for this SSH key setup tutorial
- A VPS or dedicated server you can reach via SSH (public IP, port 22 open)
- Console access in your hosting panel (for recovery if you misconfigure SSH)
- A Mac/Linux terminal, or Windows Terminal/PowerShell with OpenSSH client
If you’re provisioning a fresh server for hosting, start with something like a HostMyCode VPS.
It lets you control SSH, firewall rules, and updates from day one.
Step 1 — Create a key pair on your computer (Ed25519)
On your local machine, generate an Ed25519 key. It’s fast, modern, and well-supported.
ssh-keygen -t ed25519 -a 64 -C "yourname@yourdomain"
Accept the default path (usually ~/.ssh/id_ed25519).
Set a passphrase.
Assume this key will end up in backups or sync folders.
Protect it.
Confirm you created two files:
ls -l ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub
Step 2 — Create a dedicated admin user on the server
Log in using your provider’s initial credentials.
This is often root with a temporary password:
ssh root@SERVER_IP
Create an admin user (replace admin with your preference):
adduser admin
Add the user to the sudo group:
usermod -aG sudo admin
Quick sanity check:
id admin
You should see sudo in the group list.
Step 3 — Install your public key (the safe way)
From your local machine, use ssh-copy-id if it’s available:
ssh-copy-id -i ~/.ssh/id_ed25519.pub admin@SERVER_IP
If ssh-copy-id isn’t installed, add the key manually:
- On the server, switch to the admin user:
su - admin
- Create the SSH directory with correct permissions:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
- Paste your public key into
authorized_keys:
nano ~/.ssh/authorized_keys
Paste the entire single-line key from your local id_ed25519.pub, then save.
chmod 600 ~/.ssh/authorized_keys
Step 4 — Verify key login before changing SSH config
Open a new terminal window.
Test logging in as the admin user:
ssh -i ~/.ssh/id_ed25519 admin@SERVER_IP
If you set a passphrase, your SSH agent may prompt you. That’s normal.
Now confirm sudo works:
sudo -v
sudo whoami
sudo whoami should print root.
If it doesn’t, stop here.
Fix the user/sudo setup before you harden anything.
Step 5 — Tighten OpenSSH settings (without locking yourself out)
Keep your original SSH session open as a fallback.
In the verified admin session, edit the SSH daemon config:
sudo nano /etc/ssh/sshd_config
Make these changes.
Stick to settings you can explain and repeat across servers.
# Disable root over SSH (recommended)
PermitRootLogin no
# Prefer keys; keep passwords enabled until you confirm all access paths
PubkeyAuthentication yes
PasswordAuthentication yes
# Reduce noisy/abusive auth methods
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
# Basic session hygiene
X11Forwarding no
AllowTcpForwarding no
# Optional: restrict who can SSH
AllowUsers admin
Why leave PasswordAuthentication yes for now?
You’re still proving key access works from every place you actually administer from (workstation, jump host, etc.).
Disable passwords after a second clean login test.
Step 6 — Test and reload SSH safely
Check the config syntax before you reload anything:
sudo sshd -t
No output means the file parses correctly.
Reload SSH (a reload is gentler than a restart):
sudo systemctl reload ssh
Then test a brand-new login from your local machine:
ssh admin@SERVER_IP
If that succeeds, you’ve cleared the “don’t lock yourself out” checkpoint.
Move on.
Step 7 — Optional but recommended: change SSH port (only if you can manage it)
Changing the port won’t “secure” SSH by itself.
It does reduce automated scanning noise.
If you do it, update your firewall rules and any monitoring checks right away.
Edit /etc/ssh/sshd_config and set a non-standard port, for example:
Port 2222
Then validate and reload:
sudo sshd -t
sudo systemctl reload ssh
Test from your local machine:
ssh -p 2222 admin@SERVER_IP
If you run several servers, keep a simple inventory.
Don’t guess ports during an incident.
Step 8 — Add a firewall rule that won’t break SSH
On Ubuntu, UFW is a straightforward choice for a basic hosting baseline.
If you stayed on port 22:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
If you changed SSH to 2222, allow that instead:
sudo ufw allow 2222/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
For a deeper, hosting-focused firewall baseline, see our UFW firewall setup tutorial.
Step 9 — Disable password SSH (only after you confirm key access from all locations)
Disable passwords only after you’ve confirmed key login from:
- your main workstation
- a backup workstation (or a secure jump host)
- your recovery/console path still works
Once that’s true, shut off password authentication.
Edit:
sudo nano /etc/ssh/sshd_config
Set:
PasswordAuthentication no
Then validate and reload:
sudo sshd -t
sudo systemctl reload ssh
Test a new session again.
You want failures now, not during a late-night maintenance window.
Step 10 — Harden the key itself: permissions and agent use
If SSH “ignores” your key, file permissions are often the culprit.
On your local machine:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
If you juggle multiple servers or keys, use ~/.ssh/config.
It helps you avoid fat-fingering usernames, ports, or identity files:
Host my-vps
HostName SERVER_IP
User admin
IdentityFile ~/.ssh/id_ed25519
Port 2222
Then connect with:
ssh my-vps
Step 11 — Add basic brute-force protection (Fail2Ban)
Even with passwords disabled, bots will keep knocking.
Fail2Ban won’t eliminate attempts. It will rate-limit repeat offenders and quiet the logs.
sudo apt update
sudo apt install -y fail2ban
Create a local jail override:
sudo nano /etc/fail2ban/jail.d/sshd.local
Start with a conservative policy:
[sshd]
enabled = true
bantime = 1h
findtime = 10m
maxretry = 5
Restart and verify:
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
If you also host WordPress on this server, you’ll get better results pairing SSH protection with application-layer rules.
Our Fail2Ban setup tutorial goes deeper on safe jails for hosting.
Step 12 — Quick diagnostics: fix the 5 most common SSH key failures
- Wrong user: you installed the key for
adminbut you’re logging in asroot. Usessh admin@IP. - Bad permissions:
~/.sshmust be700andauthorized_keysmust be600. - Key not offered: force it with
ssh -i ~/.ssh/id_ed25519 admin@IPand add an SSH config entry. - Config not applied: you edited the file but didn’t reload. Run
sudo systemctl reload ssh. - Debug needed: run
ssh -vvv admin@IPand look for “Offering public key” and “Accepted publickey”.
On the server side, tail auth logs while you try a login:
sudo tail -f /var/log/auth.log
How this fits into a real hosting workflow (WordPress, migrations, control panels)
Once key-based SSH works, it becomes your trusted path for everything else.
Use it for pulling backups, running migrations, checking SSL renewals, and debugging performance during traffic spikes.
If you’re migrating sites onto this VPS, pair this with a downtime-focused cutover plan in our server migration tutorial.
If you’re deploying Nginx + PHP-FPM for WordPress, keep our PHP-FPM performance tuning tutorial nearby for the first tuning pass.
Operational checklist (print this before you touch production)
- Two active SSH sessions open before editing
sshd_config - Admin user created and in
sudogroup - Key login verified in a new terminal
sshd -tclean before reload- Firewall rules allow your SSH port before enabling UFW
- Root SSH disabled; password SSH disabled only after full verification
- Fail2Ban installed and
sshdjail enabled - Documented SSH port and admin usernames for your team/client runbook
Summary: a safer default for every VPS and dedicated server
This SSH key setup tutorial gives you a repeatable baseline.
Do keys first, follow checkpoints to prevent lockouts, then tighten SSH settings.
With that in place, commodity password attacks largely stop being your problem.
The rest of your setup work gets quieter.
If you want SSH locked down without tracking every OS and security update, start with managed VPS hosting.
If you prefer full control for custom stacks, a HostMyCode VPS is a clean place to standardize keys, firewalls, backups, and monitoring from day one.
If you’re setting up a new server for client sites, harden SSH first. It prevents the most common early compromises. HostMyCode offers fast provisioning on VPS plans and hands-on help through managed VPS hosting if you’d rather not maintain the checklist yourself.
FAQ
Should I disable root login over SSH?
Yes for almost all hosting servers.
Use an admin user plus sudo. Keep root available via console for recovery, not over the network.
Is changing the SSH port still useful in 2026?
It reduces log noise and basic scanning.
It doesn’t replace keys, firewalling, or rate limiting. Treat it as optional hygiene.
Can I keep password SSH enabled for clients?
For shared access, avoid passwords.
Give each operator their own SSH key and user account. It’s auditable and you can revoke access cleanly.
What’s the fastest way to confirm my key is actually being used?
Run ssh -vvv admin@SERVER_IP and look for Accepted publickey.
On the server, watch /var/log/auth.log during the login attempt.
What should I do next after SSH keys are set up?
Lock in backups and monitoring.
Our VPS backup setup guide and VPS monitoring tutorial are good next steps for production hosting.