Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

SSH Verbose Mode: Reading -v, -vv, -vvv Output to Find the Real Error

Sean

Platform Writer

Jul 06, 2026
6 min read

SSH verbose mode is the right tool for debugging connection issues. ssh -v user@host shows the protocol negotiation step by step. The right way to read the output is from the top, looking for the first error. The team that has this skill can debug a 30-second connection failure in under a minute.

SSH Verbose Mode: Reading -v, -vv, -vvv Output to Find the Real Error

Table of contents

The three levels of verbosity

SSH has three levels of verbosity: -v (basic), -vv (more detail), -vvv (full debug). The right answer for most issues is -vvv. The wrong answer is to start with -v and only escalate if the first attempt does not show the error — -v is often too quiet to show the relevant line.

The command:

ssh -vvv user@host

The output is a long sequence of debug1:, debug2:, and debug3: lines. The right way to read it is to look for debug1: lines first (the highest level), then debug2: and debug3: if the first level does not show the issue. The right answer is to grep for error, failed, unable to, or disconnect:

ssh -vvv user@host 2>&1 | grep -iE 'error|failed|unable|disconnect|denied'

The protocol negotiation steps

SSH connection proceeds in stages. The right way to read the verbose output is to look for the line that says which stage failed. The stages are:

  1. Connecting to ... — DNS resolution and TCP connection. Failure here means DNS or network.
  2. SSH version exchange — protocol version negotiation. Failure here means incompatible versions.
  3. Key exchange — algorithm negotiation. Failure here means no common algorithm.
  4. Host key verification — server identity check. Failure here means the host key changed (possible MITM).
  5. User authentication — login. Failure here means wrong user, wrong key, wrong password.
  6. Session setup — channel and forwarding. Failure here means config issue.

The right way to identify the failure is to look for the first error line. The wrong answer is to read the entire output top to bottom — the right answer is to scan for debug1: ... failed or debug1: ... error first.

Common error patterns and their fixes

The most common error is Permission denied (publickey). The right answer is to check the user’s public key is in the server’s authorized_keys, the file mode is right (chmod 600 ~/.ssh/authorized_keys), and the key is being offered by the client (check ssh-add -l).

The second most common error is Connection refused. The right answer is to check that sshd is running on the server (sudo systemctl status sshd), that the port is open (sudo ss -tlnp | grep 22), and that the firewall is not blocking it (sudo ufw status or sudo firewall-cmd --list-all).

The third most common error is Host key verification failed. The right answer is to remove the old host key from ~/.ssh/known_hosts and reconnect. The wrong answer is to ignore the warning and accept the new key — that is a man-in-the-middle attack vector.

Enabling verbose on the server side

The right way to see the server-side negotiation is to run sshd in debug mode on the server. The right invocation:

sudo systemctl stop sshd
sudo /usr/sbin/sshd -d

This runs sshd in the foreground with debug output. The right answer for production is to use a separate non-standard port for the debug session so you do not lock yourself out. The right way to test from the client while the server is in debug mode:

ssh -p 2222 -vvv user@server

The server-side debug output will show the key exchange, the authentication attempts, and the reason for any rejection. The right answer for a non-disruptive debug is to log in via a separate channel (cloud provider’s console, IPMI) and run the debug sshd in a separate screen session.

The right way to fix the most common issues

The most common fix is to add the client’s public key to the server’s authorized_keys. The right way:

# On the client
cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

The right answer is to verify the file mode after. The wrong answer is to leave the file world-readable, which causes sshd to refuse the key.

The right answer for a key that should be loaded in the agent but is not:

ssh-add ~/.ssh/id_ed25519

The right answer is to verify with ssh-add -l.

The verbose flag on sshd_config

The right way to get more detail on the server side without running sshd in the foreground is to set the LogLevel in /etc/ssh/sshd_config:

LogLevel VERBOSE

The default is LogLevel INFO. VERBOSE adds more detail. DEBUG and DEBUG1 through DEBUG3 are increasingly verbose. The right answer is to set LogLevel VERBOSE for production debugging, then revert to INFO after the issue is resolved.

The right answer is to reload sshd after the change:

sudo systemctl reload sshd

The right answer is to read the logs after a failed connection attempt:

sudo journalctl -u sshd -n 50

FAQ

What is the difference between -v, -vv, and -vvv?

Three levels of detail. -v is basic, -vv adds more, -vvv is full debug. The right answer for most issues is -vvv. The wrong answer is to start with -v and only escalate if needed — -v is often too quiet.

Why does ssh not show any debug output?

The right answer is to add 2>&1 to the command to redirect stderr to stdout. SSH writes debug output to stderr. The right command:

ssh -vvv user@host 2>&1 | less

How do I see the exact key being offered?

ssh -vvv user@host shows lines like debug1: Offering public key: .... The right answer is to grep for Offering in the output to see which keys the client is offering.

How do I see what algorithms the client and server negotiated?

ssh -vvv user@host shows lines like debug1: kex: server->client .... The right answer is to grep for kex to see the key exchange algorithms, cipher to see the cipher, and MAC to see the MAC.

How do I disable verbose mode?

Remove the -v flag. The right answer is to add -o LogLevel=ERROR to the ssh command line or in ~/.ssh/config to suppress all but error messages.

What is the difference between ssh -v and sshd -d?

ssh -v is the client-side debug flag. sshd -d is the server-side debug flag. The right answer is to use both for full visibility into the negotiation.

Why does the host key change on every connection?

The most common cause is a server that regenerates its host keys on every boot. The right fix is to disable host key regeneration in /etc/ssh/sshd_config (comment out the HostKey lines that point to dynamically generated files) or to use a configuration management tool to set the host keys.

What about ‘no matching key exchange method found’?

The right answer is that the client and server have no common key exchange algorithm. The fix is to either upgrade one of them (the right answer) or to add a KexAlgorithms line to ~/.ssh/config that lists the algorithms the server supports. The wrong answer is to add weak algorithms — that is a security downgrade.

How do I see the SSH fingerprint of a host key?

ssh-keyscan server | ssh-keygen -lf -. The right answer is to compare the fingerprint against the value you have stored (e.g., in a runbook or a Slack channel) to verify the host identity before connecting.

What is debug1 vs debug2 vs debug3?

Three levels of verbosity corresponding to -v, -vv, and -vvv. The right answer is to use -vvv for the full picture. The wrong answer is to filter by level — the right answer is to grep for specific keywords (error, failed, denied) regardless of level.

If you are sizing the infrastructure for the kind of project this post covers, the RunxBuild hosting calculator is the right place to model the line items. The compute, the memory, the storage, the bandwidth, the database - each one is a separate number, and the team’s mental model for the platform is the sum of those numbers. The RunxBuild dashboard is where the team sees the actual usage in one place.

Useful related references:

#ssh#guide#dev-infra#tutorial