
Your VPS security starts and ends with SSH. Password logins attract constant brute-force attempts and noisy logs. They can also lead to the occasional “how did this account get in?” surprise.
This SSH key setup guide tutorial uses a safe order: generate keys, create a non-root sudo user, tighten sshd, and keep a recovery path if you misstep.
The commands assume Ubuntu 24.04 LTS, still a common default in 2026 hosting. The same approach works on Debian 12/13 and AlmaLinux/Rocky. Expect small differences in paths and group names.
What you’ll set up (and what you’ll avoid)
- Key-based SSH using modern key types (Ed25519), with RSA only where legacy requires it
- A non-root admin with sudo, then root SSH locked down
- SSHD hardening that reduces exposure without breaking normal admin work
- Rollback safety: keep one working session open and verify logins before you flip final settings
If you’re building production hosting on a VPS, start with a reliable base. A HostMyCode VPS gives you full root access. That lets you apply these controls directly, without shared-hosting limits.
Prerequisites: confirm access and open a safety net
Before you edit anything, make sure you have:
- Current SSH access (root or an admin user)
- Console access via your hosting panel, or a provider rescue mode (your break-glass option)
- A second terminal ready for testing while your original session stays open
On Ubuntu, confirm SSH is running and which port it’s listening on:
sudo systemctl status ssh
sudo ss -tulpn | grep ssh
Also check whether UFW is enabled:
sudo ufw status verbose
If you want a complete baseline pass (SSH + firewall + updates), pair this with HostMyCode’s server hardening tutorial for a new Ubuntu VPS. This post stays focused on SSH keys and sshd.
Create an SSH key on your computer (recommended: Ed25519)
Generate keys on your local machine (Linux/macOS/WSL). Use Ed25519 unless you have a specific legacy requirement.
ssh-keygen -t ed25519 -a 64 -C "yourname@yourdomain"
When prompted:
- Save to the default path (
~/.ssh/id_ed25519) unless you manage multiple identities - Set a passphrase. It protects you if your laptop or key file is stolen
If you need RSA (uncommon in 2026, but sometimes required by older tooling), use at least 4096 bits:
ssh-keygen -t rsa -b 4096 -a 64 -C "yourname@yourdomain"
Confirm your public key exists:
ls -l ~/.ssh/id_ed25519.pub
Create a non-root admin user (do this before disabling root login)
Log in to the server using your current method (often root over SSH). Create a dedicated admin user, then grant sudo access.
adduser admin
usermod -aG sudo admin
On AlmaLinux/Rocky, the sudo group is typically wheel:
usermod -aG wheel admin
Verify sudo works before you touch SSH settings:
su - admin
sudo -v
sudo whoami
If you want a deeper walk-through (including safer sudo policy choices), HostMyCode also has a dedicated guide: sudo setup guide tutorial.
Install your public key on the server (the safe way)
The cleanest option is ssh-copy-id from your local machine. It sets permissions correctly. It also avoids copy/paste mistakes.
ssh-copy-id -i ~/.ssh/id_ed25519.pub admin@YOUR_SERVER_IP
If your server uses a non-standard SSH port (example 2222):
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 2222 admin@YOUR_SERVER_IP
Now test key login from your local machine in a new terminal:
ssh admin@YOUR_SERVER_IP
If you set a passphrase, you’ll be prompted for it. That’s expected.
Fix permissions (if key auth fails)
If key auth fails, permissions are usually the culprit. On the server, check:
sudo ls -ld /home/admin /home/admin/.ssh
sudo ls -l /home/admin/.ssh/authorized_keys
Correct permissions should look like:
/home/adminnot writable by others~/.ssh=700authorized_keys=600
Fix them explicitly:
sudo chmod 700 /home/admin/.ssh
sudo chmod 600 /home/admin/.ssh/authorized_keys
sudo chown -R admin:admin /home/admin/.ssh
Then watch the SSH logs while you attempt another login:
sudo journalctl -u ssh -n 80 --no-pager
Harden sshd_config without locking yourself out
On Ubuntu/Debian the config is typically /etc/ssh/sshd_config. Before you edit it, make a backup you can revert fast:
sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F)
Edit with your preferred editor:
sudo nano /etc/ssh/sshd_config
Apply these settings (adjust for your environment). Keep them grouped so you can audit changes quickly.
# Use keys, not passwords
PasswordAuthentication no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
# Disallow direct root SSH login
PermitRootLogin no
# Reduce exposure
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
# Limit who can SSH in
AllowUsers admin
# Stronger timeouts (cuts down idle sessions)
ClientAliveInterval 300
ClientAliveCountMax 2
# Logging (useful for incident review)
LogLevel VERBOSE
About forwarding: if you rely on SSH port forwarding (for example, to reach a private admin panel), don’t disable it globally. Restrict it per-user instead.
HostMyCode’s SSH port forwarding tutorial shows a safer setup that avoids exposing panels publicly.
Validate the config before restarting SSH:
sudo sshd -t
If that returns nothing, restart SSH:
sudo systemctl restart ssh
Keep your original SSH session open. In a new terminal, confirm you can still log in as admin with your key.
Optional: move SSH to a different port (and do it safely)
Changing the SSH port won’t “secure” the server on its own. It mainly reduces automated scanning noise and log spam.
If you choose to do it, follow a checklist. The goal is to avoid stranding yourself during the change.
Pick a port (example 2222). Edit /etc/ssh/sshd_config and set:
Port 2222
Allow the new port in your firewall before you restart SSH.
UFW (Ubuntu/Debian):
sudo ufw allow 2222/tcp
sudo ufw status numbered
firewalld (AlmaLinux/Rocky):
sudo firewall-cmd --add-port=2222/tcp --permanent
sudo firewall-cmd --reload
Restart SSH and test a new login:
sudo systemctl restart ssh
ssh -p 2222 admin@YOUR_SERVER_IP
After you confirm the new port works, you can remove the old port rule (usually 22) if you want it closed.
If you get locked out or ports behave strangely, use HostMyCode’s firewall troubleshooting tutorial to diagnose the issue from console access.
Use per-user SSH config to simplify daily admin
On your local machine, create or edit ~/.ssh/config:
Host hostmycode-vps
HostName YOUR_SERVER_IP
User admin
Port 2222
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Now connect with:
ssh hostmycode-vps
This file is also the right place to pin stricter client-side behavior (like refusing password auth). It’s also where you can configure ProxyJump later if you add a bastion host.
Add basic brute-force resistance (without turning this into a security project)
Once password auth is disabled, most brute-force traffic becomes background noise. Even so, rate-limiting at the firewall or adding Fail2Ban keeps logs readable. It can also reduce resource spikes on smaller VPS plans.
On Ubuntu, Fail2Ban is quick to set up:
sudo apt update
sudo apt install -y fail2ban
Create a minimal jail override:
sudo nano /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true
maxretry = 5
findtime = 10m
bantime = 1h
Restart and check status:
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
If your environment uses cPanel/WHM, you’ll typically manage firewalling via CSF rather than raw Fail2Ban. See: cPanel CSF firewall setup tutorial.
Quick diagnostics: common SSH key problems and fast fixes
- “Permission denied (publickey)”: wrong user, wrong key, bad permissions, or
AllowUsersdoesn’t include you. - Key not offered: your SSH client didn’t select the key. Force it:
ssh -i ~/.ssh/id_ed25519 admin@IP. - Wrong port: confirm with
ss -tulpn | grep sshon the server and use-pon the client. - SSHD won’t restart: run
sudo sshd -tto see the failing line. - Firewall blocks SSH: from console access, temporarily allow your IP and port, then fix rules properly.
For deeper SSH attack triage (what’s hitting you and how to stop lockouts), pair this with: SSH brute-force troubleshooting tutorial.
Production checklist (print this before you touch sshd again)
- You can log in as
adminusing keys from a new terminal -
sudo sshd -tpasses after config edits - Root SSH login is disabled (
PermitRootLogin no) - Password auth is disabled (
PasswordAuthentication no) - Firewall allows your SSH port from your IP range (or at least from the internet while you’re configuring)
- You have console/rescue access documented
- You’ve recorded SSH connection details in
~/.ssh/config
Where this fits in a hosting workflow (VPS, dedicated, and panels)
On a single WordPress VPS, SSH keys mainly protect access for you and one or two developers. On a reseller or multi-site server, they reduce day-to-day risk. You deal with fewer password resets, fewer leaked credentials, and clearer audit trails.
On busy servers, teams often separate concerns. They keep a locked-down admin surface (keys, limited users). They also keep a public web tier (Nginx/Apache/LiteSpeed).
If you want help during security changes or recovery planning, a managed VPS hosting plan can make sense. You keep control, but you have support when things get tense.
If you’re setting up a new server and want a clean baseline from day one, start with a HostMyCode VPS and put SSH keys in place before you install a control panel or apps. For production workloads where you want help with hardening, updates, and recovery planning, managed VPS hosting is often the more practical option.
FAQ
Should you disable password authentication after adding SSH keys?
Yes—after you confirm key login works from a separate, new terminal. Disable passwords only after a successful test. Keep your original session open until you’re sure.
Is changing the SSH port still useful in 2026?
It can reduce automated scanning noise and failed-login spam. It doesn’t replace keys, firewall rules, or patching. It just makes operations quieter.
What’s the safest way to avoid locking yourself out?
Change one thing at a time. Validate with sshd -t, restart SSH, then test login in a new terminal before closing the old one. Keep console access available.
Can you use one SSH key for multiple servers?
You can, but separate keys per environment (production vs staging) or per client is safer. If a key leaks, you limit the blast radius.
Summary: a tighter SSH surface in under an hour
Keys plus a non-root admin account remove the most common compromise path on VPS servers: guessed, reused, or phished passwords. Add user restrictions, reasonable timeouts, and a recovery option. SSH becomes boring, which is exactly what you want.
If you’re moving from shared hosting to a VPS where you control SSH access, HostMyCode can help you pick a plan and migrate safely. Start with a HostMyCode VPS for full control, or choose managed VPS hosting if you want hands-on help with secure setup.