
Locked Out of SSH? How to Regain Access to Your VPS
It always happens at the worst possible moment. You tighten the firewall, restart SSH after a “quick” config edit, or wipe the old laptop that held your key, and the next ssh command just hangs or answers with a flat Permission denied. The server is still running and your website is probably still online, but the door you use to manage it is shut. The good news: being locked out of SSH on a VPS is almost never permanent, because SSH is not the only way in.
In this guide we walk through the recovery the way an experienced admin would. First we read what the SSH client is actually telling us. Then we log in through the out-of-band web console in the client area and fix the five lockouts we see most often in support tickets: a firewall rule blocking port 22, a broken sshd_config, a Fail2ban ban on your own IP, a lost key, and password login turned off with no working key. Every command is written for Debian 13 and Ubuntu 24.04, and we point out each place where the two behave differently.
What you need before you start
- Access to your DreamServer client area (the account you used to order the VPS), ideally protected with 2FA.
- The public IP address of the VPS and the Linux user you normally log in with. In the examples we use
203.0.113.10andalex; replace them with your own. - The password of that user, or of root. The web console is a plain login screen and knows nothing about SSH keys. If you never set a password, Step 2 explains what to do.
- A terminal on your own computer: Terminal on Linux or macOS, or PowerShell on Windows 10/11, which ships with the OpenSSH client.
- About 15 to 30 minutes and some patience. Do not reinstall the VPS: it erases your data and is almost never necessary.
Why the web console works when SSH does not
Let us define the pieces first. SSH (Secure Shell) is the encrypted protocol you use to get a command line on a remote server. On the server, a background program (a daemon) called sshd waits for connections. It listens on a port, a numbered door on the server’s network address; SSH uses TCP port 22 by default.
Before your connection reaches sshd, it passes through other layers. The firewall (ufw or nftables on Linux) is a packet filter in the kernel that decides which ports can be reached at all. Fail2ban is a service that watches login logs and temporarily bans IP addresses that fail too often. Finally sshd reads its configuration and checks your key or password. Any of these layers can lock you out, and all of them sit on the network path.
The web console is out-of-band: the virtualization layer (the hypervisor) gives your VPS a virtual screen and keyboard, and the client area streams that screen into your browser, usually over VNC, a remote screen protocol. It is the equivalent of plugging a monitor into a physical server. Your keystrokes never travel through the VPS network interface, so the firewall, Fail2ban and sshd are simply not involved. As long as the VPS is booted, you get a text login prompt and can repair everything from inside.
A note for container users: on a KVM VPS the console shows the real virtual screen, including the boot loader. On an LXC VPS (an unprivileged container), the console attaches to the container’s terminal from the host. It bypasses the network just as well, but there is no boot loader or kernel of your own, so the GRUB trick described in Step 2 does not apply there.
The recovery procedure at a glance
The whole process has seven steps, but you will not run all of them. Steps 1 and 2 always apply: read the error, then open the console. Steps 3 to 6 are alternative fixes, one per cause, and you only apply the one that matches your error (sometimes two, if you were unlucky and stacked mistakes). Step 7 always closes the loop: you test from outside and make sure nothing was left open.
How long does it take? Once you are logged in at the console and know the cause, most fixes are a matter of minutes. The slowest case is when you have no password for any user and need a rescue boot, because it involves a reboot and some careful typing at the boot loader. The chart below shows typical hands-on times from our own support work; treat them as approximate.
Step 1: Read the SSH error message
The error text is the single most useful clue, and most people skip it. Run your usual command with -v (verbose) so the client explains what it is doing:
ssh -v alex@203.0.113.10
You will see a lot of debug1: lines. The interesting ones are near the end. If you see connect to address 203.0.113.10 port 22: Connection timed out, the packets never got an answer. If you see Authentications that can continue: publickey, the server is reachable and is telling you that only key login is allowed. Use this table to map the message to a cause:
| What you see | Most likely cause | Go to |
|---|---|---|
Connection timed out or the command just hangs | Firewall dropping port 22, Fail2ban ban, wrong IP, VPS stopped | Step 3 or 5 |
Connection refused | sshd not running, SSH moved to another port, a REJECT rule or ban | Step 4, 3 or 5 |
Connection closed or kex_exchange_identification | Often sshd failing to start behind Ubuntu’s ssh.socket | Step 4 |
Permission denied (publickey) | Password login is off and the server accepts none of your keys | Step 6 |
Permission denied (publickey,password) | Wrong password, or the key is rejected | Step 6 |
Too many authentication failures | Your SSH agent offers too many keys | Troubleshooting |
REMOTE HOST IDENTIFICATION HAS CHANGED | VPS reinstalled or host keys regenerated | Troubleshooting |
On Windows you can also test whether the port answers at all, without SSH in the way:
Test-NetConnection 203.0.113.10 -Port 22
The last line, TcpTestSucceeded : True or False, tells you whether anything is listening and reachable on port 22.
One cheap but powerful test: try from a different network, for example your phone’s hotspot. If SSH works from the hotspot but not from the office, the server is fine and your office IP is banned by Fail2ban (Step 5) or filtered by a firewall rule that only allows certain addresses (Step 3). Also glance at the client area: if the VPS shows as stopped, start it before anything else.
Step 2: Open the web console and log in
In the client area, open your VPS and look for the Console (or VNC) button. A new browser tab opens with a black screen and a text prompt such as vps login:. If the screen is completely black, press Enter once: the console may simply have blanked the display.
Log in with your username and password. A few practical notes about typing in a web console:
- The console usually behaves like a US keyboard. If your computer uses a Romanian or German layout, characters such as
|,/,~,yandzmay land differently. Check Caps Lock and Num Lock too, since password characters are not echoed. - Copy and paste often does not work. Some console implementations offer a clipboard or “send text” panel; if yours does, use it for long strings. Otherwise keep the commands short, which is why this guide avoids long one-liners in the console steps.
- You can log in as root here if root has a password.
PermitRootLoginonly applies to SSH, not to the local console.
Once logged in, take a 30-second look around:
ip -br a
systemctl status ssh --no-pager
sudo ss -tlnp
ip -br a should show your public IP on an interface marked UP. The systemctl line tells you whether the SSH service is running. On both Debian and Ubuntu the service is called ssh (with sshd as an alias). In the ss output, look for a line with :22, for example LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=812,fd=3)).
Ubuntu 24.04 differs here: it uses socket activation, meaning systemd itself holds port 22 open (the ssh.socket unit) and starts ssh.service when the first connection arrives. So on Ubuntu, ss may show systemd as the owner of port 22, and ssh.service may say inactive (dead) while nobody is connected. That is normal; check systemctl status ssh.socket as well. Debian 13 does not use socket activation by default, so ssh.service itself listens.
If the console asks for a password you never set
Many VPS images log you in with an SSH key only, so your user may have no password at all. Before anything else, check whether the client area offers a root password reset or a rescue option for your VPS; if it does, that is the easiest path. On a KVM VPS you can also reset the password yourself from the boot loader:
- Reboot the VPS from the client area and immediately open the console.
- When the GRUB menu appears, press
e. If the system boots straight through, reboot again and pressEsc(UEFI) or holdShift(BIOS) right after the reboot to make the menu appear. - Find the line that starts with
linux, move to its end and add a space followed byinit=/bin/bash. PressCtrl+XorF10to boot. - You land in a root shell without any login. Run:
mount -o remount,rw /
passwd alex
sync
exec /sbin/init
The first command makes the disk writable, passwd sets a new password (pick a simple temporary one if the keyboard layout is fighting you, and change it later over SSH), and exec /sbin/init continues the normal boot. This trick does not work on an LXC VPS, which has no boot loader of its own: there, use the reset option in the client area or open a ticket, and we can set the password from the host side.
Step 3: Fix a firewall rule that blocks port 22
This is the classic: someone runs ufw default deny incoming and ufw enable and forgets to allow SSH first. Check ufw:
sudo ufw status numbered
A locked-out output typically looks like this, with web ports open and no SSH rule:
Status: active
To Action From
-- ------ ----
[ 1] 80/tcp ALLOW IN Anywhere
[ 2] 443/tcp ALLOW IN Anywhere
Add the rule. If you moved SSH to another port, allow that number instead of 22:
sudo ufw allow 22/tcp
ufw checks rules in order and the first match wins. If you see a DENY IN or LIMIT IN rule for 22 above an allow rule, delete it by its number (for example sudo ufw delete 3) or put the allow rule at the top with sudo ufw insert 1 allow 22/tcp. A LIMIT rule blocks an IP that opens more than 6 connections in 30 seconds, which can bite deploy scripts. If you are in a hurry, sudo ufw disable turns the firewall off entirely; just remember to fix the rules and run sudo ufw enable again before you leave.
On Debian, ufw is not installed by default, so sudo ufw status may say command not found. In that case look at nftables directly:
sudo nft list ruleset
The warning sign is an input chain with policy drop; and no line accepting port 22. Fix it in the persistent configuration, check the syntax, then reload:
sudo nano /etc/nftables.conf
sudo nft -c -f /etc/nftables.conf
sudo systemctl restart nftables
Inside the chain input block, add tcp dport 22 accept next to your other accept rules. nft -c only checks the file and prints nothing if it is valid. Note that ufw also creates nftables rules behind the scenes; if ufw is installed, fix things through ufw and do not edit its generated rules by hand. As a last resort, sudo nft flush ruleset removes every rule until the next reboot or reload. If Docker runs on the server, follow it with sudo systemctl restart docker, because the flush also deletes the rules Docker needs for its containers.
Step 4: Repair a broken sshd_config
If SSH answers with Connection refused and systemctl status ssh shows failed, the daemon refused to start, almost always because of a typo in its configuration. sshd has a built-in test mode that tells you exactly where:
sudo sshd -t
No output means the configuration is valid. A broken file produces something like:
/etc/ssh/sshd_config: line 42: Bad configuration option: PasswordAuthenticaton
/etc/ssh/sshd_config: terminating, 1 bad configuration options
Note the file name: on Debian and Ubuntu the main file includes every *.conf file from /etc/ssh/sshd_config.d/, so the error may be in a drop-in. Open the file at the reported line, fix it and test again:
sudo nano +42 /etc/ssh/sshd_config
sudo sshd -t
sudo systemctl restart ssh
If sshd -t complains about Missing privilege separation directory: /run/sshd, the service is down and that runtime folder is gone; create it with sudo mkdir -p /run/sshd and test again.
A valid config can still lock you out. Print the effective settings, after all includes are merged:
sudo sshd -T | grep -Ei '^(port|listenaddress|passwordauthentication|pubkeyauthentication|permitrootlogin|allowusers|allowgroups) '
Look for an unexpected port (you changed it and forgot), a listenaddress pointing to an old IP, or an allowusers line that does not include your user. That last one is sneaky: AllowUsers with a misspelled name silently rejects everyone else.
Port changes behave differently on the two distributions. On Debian 13, sudo systemctl restart ssh is enough. On Ubuntu 24.04, the port is read by systemd when it builds ssh.socket, so after changing Port or ListenAddress you need:
sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
If you cannot make sense of a heavily edited file, both distributions keep the packaged default. Save your version for later and put the default back:
sudo cp /etc/ssh/sshd_config /root/sshd_config.broken
sudo cp /usr/share/openssh/sshd_config /etc/ssh/sshd_config
sudo sshd -t
Then restart SSH as shown above and re-apply your hardening carefully, one change at a time.
Step 5: Lift a Fail2ban ban on your IP
Fail2ban counts failed logins per IP and bans offenders for a while (10 minutes by default, often longer on hardened setups). A few wrong passwords, a password manager trying an old entry, or an SSH agent offering five keys can get your own office banned. Depending on the ban action, you see either a timeout or Connection refused. Check the SSH jail:
sudo fail2ban-client status sshd
The output lists Currently banned and a Banned IP list. To find which one is yours, look at the most recent bans in Fail2ban’s log, which lives in the same place on Debian and Ubuntu:
sudo grep -E 'Ban |Unban ' /var/log/fail2ban.log | tail -n 20
Lines look like NOTICE [sshd] Ban 198.51.100.23. Compare with your public IP (search “what is my IP” in a browser on your computer, or check your router). Then unban it from every jail at once:
sudo fail2ban-client unban 198.51.100.23
sudo fail2ban-client unban --all clears all bans if you are unsure. Also check sudo fail2ban-client status: if a recidive jail exists, it bans repeat offenders for much longer, and the unban command above clears it as well.
To stop it from happening again with a fixed office IP, add it to ignoreip. Edit /etc/fail2ban/jail.local (create it if it does not exist; if it already exists, merge the line into its [DEFAULT] section instead of replacing the file):
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 198.51.100.23
Apply it with sudo fail2ban-client reload. Only whitelist addresses that are truly yours and stable; home connections with a changing IP are better handled by fixing the root cause (wrong key or password) than by whitelisting.
Step 6: Restore key or password access
Here the network path works, but authentication fails. Start by reading what sshd logged about your attempt. On Debian 13 the logs live only in the systemd journal; Ubuntu 24.04 also writes /var/log/auth.log:
sudo journalctl -u ssh --since "30 min ago" --no-pager
Permission denied even though the key is right
Typical log lines and what they mean:
Authentication refused: bad ownership or modes for directory /home/alex/.ssh: permissions are too open, sosshdignores your keys on purpose.Invalid user admin: you are using the wrong username for this server.User alex not allowed because not listed in AllowUsers: go back to Step 4.
Fix ownership and permissions, which is the most common case after copying files around as root:
sudo chown -R alex:alex /home/alex/.ssh
sudo chmod 700 /home/alex/.ssh
sudo chmod 600 /home/alex/.ssh/authorized_keys
sudo chmod go-w /home/alex
Also check that authorized_keys actually contains your public key on a single line: cat /home/alex/.ssh/authorized_keys.
Lost key or password login disabled: a temporary password window
If the private key is gone (laptop wiped, lost or stolen) and password login is disabled, typing a 100-character public key into a web console is a recipe for typos. The cleaner method is to open a short, controlled password window, push a new key over SSH, and close the window again.
First make sure your user has a password you know (sudo passwd alex). Then create a temporary drop-in file:
sudo nano /etc/ssh/sshd_config.d/00-recovery.conf
Put a single line in it:
PasswordAuthentication yes
Why this file name? For most options sshd keeps the first value it reads, and Debian and Ubuntu include the drop-in files at the top of the main config in alphabetical order. A file starting with 00- therefore wins over everything else, including Ubuntu’s 50-cloud-init.conf, which on cloud images often sets PasswordAuthentication no. Test and apply:
sudo sshd -t
sudo systemctl restart ssh
sudo sshd -T | grep -i '^passwordauthentication'
The last command should print passwordauthentication yes. Now, on your own computer, create a new key and copy it to the server:
ssh-keygen -t ed25519 -C "alex-laptop-2026"
ssh-copy-id -i ~/.ssh/id_ed25519.pub alex@203.0.113.10
ssh-keygen asks where to save the key (Enter accepts the default) and for a passphrase, which we recommend. ssh-copy-id asks for alex’s password once and appends the public key to the server. Windows PowerShell has no ssh-copy-id, so use this instead:
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh alex@203.0.113.10 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Test that the key works with passwords explicitly disabled on the client side:
ssh -o PasswordAuthentication=no alex@203.0.113.10
If you get a shell, close the window: back in the console (or in this new SSH session), remove the temporary file and restart SSH:
sudo rm /etc/ssh/sshd_config.d/00-recovery.conf
sudo sshd -t
sudo systemctl restart ssh
If the old key was on a lost or stolen device, open ~/.ssh/authorized_keys and delete the line ending with that device’s comment. Do the same on every server where that key was used.
Step 7: Test from outside and lock it down again
Keep the console tab open until you have proven that SSH works. From a new terminal on your computer:
ssh -o PasswordAuthentication=no alex@203.0.113.10 'echo ok'
You should see ok. Then, on the server, confirm that every protection is back in place:
sudo sshd -T | grep -Ei '^(passwordauthentication|permitrootlogin) '
sudo ufw status
sudo fail2ban-client status sshd
Expect passwordauthentication no, permitrootlogin no or without-password (the internal name for prohibit-password), ufw active with your SSH rule present, and the jail running. On Debian with plain nftables, use sudo nft list ruleset instead of ufw.
Now make the next lockout less likely. Before any risky change, schedule an automatic undo with systemd-run, a built-in way to run a command later:
sudo systemd-run --on-active=5m /usr/sbin/ufw disable
It prints something like Running timer as unit: run-r1a2b3c4d.timer. Make your firewall change, test SSH from a second terminal, and if all is well cancel the safety net with sudo systemctl stop run-r1a2b3c4d.timer (use the name it printed). If you locked yourself out, the firewall turns itself off after five minutes. The same idea works for SSH config: copy the file to /root/sshd_config.bak first, and schedule sudo systemd-run --on-active=5m /bin/sh -c 'cp /root/sshd_config.bak /etc/ssh/sshd_config && systemctl restart ssh'.
Other habits that save you: always keep one SSH session open while you restart sshd, run sudo sshd -t before every restart, add the allow rule before ufw enable, keep a second key (on another device or a hardware key) in authorized_keys, and make sure your sudo user has a password so the console is always usable.
Common mistakes and troubleshooting
The console accepts my username but not the password. Almost always the keyboard layout or Caps Lock. Type the password in the username field first to see what actually arrives, then clear it.
PasswordAuthentication yes is set but passwords are still refused. Another file sets no earlier. Run sudo sshd -T | grep -i passwordauth to see the effective value, and look for Match blocks at the end of sshd_config that override it for some users.
I changed the port on Ubuntu 24.04 and SSH still listens on 22. You skipped sudo systemctl daemon-reload and sudo systemctl restart ssh.socket. The opposite also happens: the port changed but the firewall still only allows 22, so remember to allow the new port in ufw before restarting.
Too many authentication failures. Your SSH agent offers every key it has and the server gives up after six tries. Point the client at one key: ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 alex@203.0.113.10.
REMOTE HOST IDENTIFICATION HAS CHANGED. Expected after a reinstall. Verify the new fingerprint in the console with ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub, and only if it matches what your client shows, remove the old entry with ssh-keygen -R 203.0.113.10. If you did not reinstall anything, stop and investigate.
Everything looks fine on the server, but it still times out. The block may be on your side: some office and hotel networks block outgoing port 22. The hotspot test from Step 1 settles it.
Services fail to restart for no clear reason. Check df -h. A root file system at 100% breaks logins, logging and service restarts in strange ways; free space first, then retry.
Security notes
- The web console is root access for anyone who controls your client area account, because of the boot loader trick in Step 2. Protect that account with a unique password and 2FA.
- Never leave the recovery state behind: delete
00-recovery.conf, turn the firewall back on and make sure Fail2ban is running. A “temporary” password login is the kind of thing that stays for years. - A lost or stolen device means its key is compromised. Remove it from
authorized_keyseverywhere and look for logins you do not recognize withsudo journalctl -u ssh | grep Accepted. - Only the
.pubfile ever goes to a server. Never paste a private key into a console, a ticket or a chat. - Keep
ignoreipshort and specific. Whitelisting whole provider ranges makes Fail2ban pointless. - Moving SSH to a non-standard port reduces log noise, but it is not a security control. Keys plus disabled password login are what actually protect you.
So, are you ever really locked out?
Rarely. As long as the VPS boots and you can reach the client area, the web console gives you a way in that no firewall rule, ban or typo can block. Read the error first, open the console, fix the one layer that is actually broken, then test from outside and put every protection back. Next time, a five-minute auto-undo timer and a second key will make the whole exercise unnecessary.
If you want a server where the console, snapshots and sensible defaults are there from day one, start with a VPS hosted in our own data center in Romania. And if you would rather not spend an evening in a VNC window, our server administration team can recover access, harden SSH and set up safe change procedures for you.
FAQ
Will rebooting the VPS fix an SSH lockout?
Usually not. Firewall rules, sshd_config changes and missing keys survive a reboot, and Fail2ban stores its bans in a small database and restores them when it starts again. A reboot only helps if the SSH service had crashed for a temporary reason, such as running out of memory.
Can I fix this without the web console?
Only if you still have another way in: a second user with a working key, a colleague with access, or a management agent you installed earlier. Otherwise the console, or a support ticket, is the way to go.
Does the web console work on an LXC VPS?
Yes. It attaches to the container’s terminal from the host and bypasses the network in the same way. What you cannot do in an unprivileged LXC container is the boot loader password reset, since the container has no boot loader or kernel of its own.
Should I just reinstall the VPS?
Only as a last resort, and only after taking a backup. A reinstall wipes the disk, while every lockout in this guide can be fixed in a few minutes from the console without losing anything.
Is it safe to enable password login temporarily?
For a few minutes, with a strong password and Fail2ban running, the risk is small. The danger is forgetting to turn it off, which is why Step 6 uses a single drop-in file that you delete as soon as your new key works.