---
title: "SSH"
lang: "en"
author: "Mohammad Abu Mattar"
canonical: https://mkabumattar.com/ssh
---

0

[Home](/)›[Cheatsheets](/cheatsheets)

Cheatsheets

# SSH

SSH cheatsheet covering OpenSSH client usage, authentication methods, port forwarding, key management, X11 forwarding, and configuration options. Includes real-world examples and security best practices.

9 Categories17 Sections51 ExamplesPublished: 16 Jan 2025Updated: 28 Feb 2026

[Markdown for AI(opens in a new tab)](/ssh/index.md "Open the plain-Markdown version of this page, for pasting into an AI tool")

Series

[Linux & System Administration](/series/linux--system-administration)11/12

[PreviousSed](/cheatsheets/sed)[NextLinux Networking](/cheatsheets/linux-networking)

All posts in this series (12)

Cheatsheets12

1.  [AWK](/cheatsheets/awk)
2.  [Bash](/cheatsheets/bash)
3.  [Chmod](/cheatsheets/chmod)
4.  [Cron](/cheatsheets/cron)
5.  [Curl](/cheatsheets/curl)
6.  [Find](/cheatsheets/find)
7.  [Grep](/cheatsheets/grep)
8.  [Netcat](/cheatsheets/nc)
9.  [Netstat](/cheatsheets/netstat)
10.  [Sed](/cheatsheets/sed)
11.  [SSHYou are here](/cheatsheets/ssh)
12.  [Linux Networking](/cheatsheets/linux-networking)

[Getting Started](#category-getting-started)

-   [Basic SSH Connection](#section-basic-connection)

[Authentication Methods](#category-authentication)

-   [Public Key Authentication](#section-public-key-auth)
-   [Password Authentication](#section-password-auth)
-   [SSH Agent & Key Forwarding](#section-agent-forwarding)

[Port Forwarding & Tunneling](#category-port-forwarding)

-   [Local Port Forwarding](#section-local-forwarding)
-   [Remote Port Forwarding](#section-remote-forwarding)
-   [Dynamic Port Forwarding (SOCKS Proxy)](#section-dynamic-forwarding)

[Key Management](#category-key-management)

-   [Creating and Managing Keys](#section-key-generation)
-   [Managing Authorized Keys](#section-authorized-keys)

[Configuration & Advanced Setup](#category-config-options)

-   [SSH Config File](#section-ssh-config-file)
-   [Connection Multiplexing](#section-multiplexing)

[Security Best Practices](#category-security)

-   [Protecting Your Keys](#section-key-security)
-   [Host Key Verification](#section-host-verification)

[Advanced Usage](#category-advanced)

-   [Jump Hosts & Bastion Patterns](#section-jump-hosts)
-   [X11 Forwarding](#section-x11-forwarding)

[Practical Real-World Examples](#category-practical-examples)

-   [Common Use Cases](#section-real-world-scenarios)

[Troubleshooting](#category-troubleshooting)

-   [Debugging SSH Connection Issues](#section-common-issues)

No commands found

Try adjusting your search term

## Getting Started

### Basic SSH Connection

Establishing remote connections to servers

#### Accessibility

Beginner

#### Best Practices

-   Always verify host key fingerprint on first connection
-   Use non-standard ports to reduce exposure to automated attacks
-   Set up public key authentication rather than password

#### Common Errors

-   **Connection refused:** Check if SSH service is running on target host
-   **Permission denied:** Verify username and authentication method

#### Keywords

connectionremoteloginhostbasic

[Learn more](https://man7.org/linux/man-pages/man1/ssh.1.html)

#### Connect to Remote Host with Default Settings

Connects to a remote host using SSH, with interactive password authentication. The host key is verified and stored in ~/.ssh/known\_hosts

Code

Terminal window

```
ssh hostname
```

Execution

Terminal window

```
The authenticity of host 'hostname (192.168.1.100)' can't be established.ECDSA key fingerprint is SHA256:abc123xyz...Are you sure you want to continue connecting (yes/no)? yesWarning: Permanently added 'hostname' (ECDSA) to the list of known hosts.Last login: Wed Feb 28 10:30:42 2026 from 192.168.1.50user@hostname:~$
```

-   First connection will prompt for host key verification
-   Uses default SSH port 22
-   Requires password authentication if no keys configured

#### Connect with Specific Username

Connect using a specific username different from local user. Format is \[user@\]hostname

Code

Terminal window

```
ssh user@hostname
```

Execution

Terminal window

```
user@hostname's password:Last login: Wed Feb 28 10:35:15 2026 from 192.168.1.50user@hostname:~$
```

-   If username not specified, uses current local username
-   Can also specify as user@domain.com or user@ip.address

#### Connect to Non-Standard Port

SSH server might run on ports other than 22. Use -p flag to specify alternative port

Code

Terminal window

```
ssh -p 2222 user@hostname
```

Execution

Terminal window

```
user@hostname's password:Last login: Wed Feb 28 09:15:22 2026 from 192.168.1.50user@hostname:~$
```

-   Port must be specified before hostname
-   Common alternative port is 2222
-   Can also configure in ~/.ssh/config

## Authentication Methods

### Public Key Authentication

Using SSH keys for passwordless authentication

#### Accessibility

Intermediate

#### Best Practices

-   Use ED25519 keys instead of RSA for better security and smaller size
-   Always protect private keys with passphrase
-   Regularly rotate keys (annually recommended)
-   Disable password authentication on servers once keys configured

#### Common Errors

-   **Permission denied (publickey):** Public key not in authorized\_keys
-   **Bad permissions on ~/.ssh:** Directory must be 700, files 600

#### Keywords

keyspublicprivateed25519rsaauthentication

[Learn more](https://man7.org/linux/man-pages/man1/ssh-keygen.1.html)

#### Generate ED25519 SSH Key Pair

Create a new ED25519 key pair. This modern algorithm is preferred over RSA for better security

Code

Terminal window

```
ssh-keygen -t ed25519 -C "user@example.com"
```

Execution

Terminal window

```
Generating public/private ed25519 key pair.Enter file in which to save the key (/home/user/.ssh/id_ed25519):Enter passphrase (empty for no passphrase):Enter same passphrase again:Your identification has been saved in /home/user/.ssh/id_ed25519Your public key has been saved in /home/user/.ssh/id_ed25519.pubThe key fingerprint is: SHA256:xyz123abc... user@example.com
```

-   Ed25519 is the recommended key type (fast, secure, compact)
-   Use -C to add a comment identifying the key
-   Protect private key with strong passphrase

#### Add Public Key to Remote Host

Copy public key to remote host's authorized\_keys. Enables passwordless login

Code

Terminal window

```
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@hostname
```

Execution

Terminal window

```
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/id_ed25519.pub"/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s).../usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed - if you want to re-run this setup...Number of key(s) added: 1
```

-   Requires initial password authentication
-   Appends to ~/.ssh/authorized\_keys on remote

#### Connect Using Specific Key

Explicitly specify private key for authentication. Useful when multiple keys exist

Code

Terminal window

```
ssh -i ~/.ssh/id_ed25519 user@hostname
```

Execution

Terminal window

```
Last login: Wed Feb 28 11:45:30 2026 from 192.168.1.50user@hostname:~$
```

-   SSH tries default keys if -i not specified
-   Default keys: ~/.ssh/id\_rsa, ~/.ssh/id\_ecdsa, ~/.ssh/id\_ed25519

### Password Authentication

Interactive password-based login

#### Accessibility

Beginner

#### Best Practices

-   Use SSH keys for all automation and scripts
-   Disable password authentication on production servers
-   If password needed, use key-based auth with ssh-agent

#### Common Errors

-   **Permission denied (password):** Wrong password or account disabled

#### Keywords

passwordauthenticationinteractiveprompt

[Learn more](https://man7.org/linux/man-pages/man1/ssh.1.html)

#### Force Password Authentication

Disable public key auth and force password authentication. Useful for testing or shared accounts

Code

Terminal window

```
ssh -o PubkeyAuthentication=no user@hostname
```

Execution

Terminal window

```
user@hostname's password:Last login: Wed Feb 28 10:20:15 2026user@hostname:~$
```

-   Password transmitted securely through SSH tunnel
-   Server must have PasswordAuthentication enabled

#### Non-Interactive Password (Using sshpass)

Pass password non-interactively using sshpass utility. Not recommended for security

Code

Terminal window

```
sshpass -p 'password' ssh user@hostname
```

Execution

Terminal window

```
Last login: Wed Feb 28 11:25:10 2026user@hostname:~$
```

-   sshpass must be installed separately
-   Security risk: password visible in process list and history
-   Use SSH keys instead for automation

### SSH Agent & Key Forwarding

Use ssh-agent to manage keys across multiple hops

#### Accessibility

Advanced

#### Best Practices

-   Start ssh-agent once per session
-   Use agent forwarding only with fully trusted hosts
-   Set SSH\_ASKPASS for secure passphrase prompts in X11
-   Use AddKeysToAgent in ssh\_config for automatic key management

#### Common Errors

-   **SSH\_AUTH\_SOCK not set: ssh-agent not running or not initialized in shell:**
-   **Agent refused operation:** Key not added to agent

#### Keywords

agentforwardingssh-agentidentitykeys

[Learn more](https://man7.org/linux/man-pages/man1/ssh-agent.1.html)

#### Start SSH Agent in Current Shell

Initialize SSH agent in current shell session. Required before adding keys

Code

Terminal window

```
eval "$(ssh-agent -s)"
```

Execution

Terminal window

```
Agent pid 12345
```

-   Agent runs as background process
-   PID stored in SSH\_AUTH\_SOCK environment variable

#### Add Private Key to Agent

Add private key to SSH agent. Enter the passphrase once and the agent handles authentication for later connections

Code

Terminal window

```
ssh-add ~/.ssh/id_ed25519
```

Execution

Terminal window

```
Enter passphrase for /home/user/.ssh/id_ed25519:Identity added: /home/user/.ssh/id_ed25519 (user@example.com)
```

-   Prompted for passphrase only once
-   Key unlocked in agent memory until timeout or logout

#### Enable Agent Forwarding to Remote Host

Forward SSH agent connection to remote host. Allows using local keys from remote for further hops (jump hosts)

Code

Terminal window

```
ssh -A user@hostname
```

Execution

Terminal window

```
Last login: Wed Feb 28 12:00:00 2026user@hostname:~$ ssh-add -l256 SHA256:xyz... user@example.com (ED25519)
```

-   Requires ForwardAgent yes in ssh\_config (or use -A flag)
-   Security: Only enable for trusted hosts
-   Useful for jump host scenarios

## Port Forwarding & Tunneling

### Local Port Forwarding

Forward local port to remote service

#### Accessibility

Intermediate

#### Best Practices

-   Use with privileged ports: sudo ssh -L 80:localhost:8080 ...
-   Keep SSH connection alive in separate terminal
-   Use -N flag to not execute remote command when only forwarding

#### Common Errors

-   **Address already in use:** Local port occupied
-   **Connection refused:** Remote host/port not accessible

#### Keywords

forwardinglocal\-Ltunnelport

[Learn more](https://man7.org/linux/man-pages/man1/ssh.1.html)

#### Forward Local Port to Remote Service

Forward localhost:3306 through SSH tunnel to remote database server. Local connections to 3306 proxy through SSH

Code

Terminal window

```
ssh -L 3306:localhost:3306 user@database-host
```

Execution

Terminal window

```
Last login: Wed Feb 28 08:30:00 2026user@database-host:~$
```

-   Format: -L \[bind\_address:\]local\_port:remote\_host:remote\_port
-   Connection stays open for tunnel to function
-   Useful for accessing internal services through SSH

#### Forward with Non-Standard Local Port

Forward local port 13306 to remote database server db.internal:3306. Avoids port conflicts with local services

Code

Terminal window

```
ssh -L 13306:db.internal:3306 user@bastion-host
```

Execution

Terminal window

```
user@bastion-host:~$
```

-   Connect to localhost:13306 to access remote database
-   Allows multiple forwards on different local ports

#### Forward Multiple Ports

Forward multiple local ports to different remote services through single SSH connection

Code

Terminal window

```
ssh -L 3306:db:3306 -L 5432:db:5432 user@bastion-host
```

Execution

Terminal window

```
user@bastion-host:~$
```

-   Use multiple -L flags for each port forward
-   Only one SSH tunnel to the bastion is needed

### Remote Port Forwarding

Forward remote port to local service

#### Accessibility

Advanced

#### Best Practices

-   Use with caution: exposes local services to remote network
-   Pair with -N flag when only tunneling
-   Verify GatewayPorts setting on remote server

#### Common Errors

-   **Remote forward not working:** GatewayPorts may be disabled

#### Keywords

forwardingremote\-Rreversetunnel

[Learn more](https://man7.org/linux/man-pages/man1/ssh.1.html)

#### Expose Local Service to Remote Network

Forward remote port 8080 to local service on 8080. Remote server can access local service. Enables public access to private service

Code

Terminal window

```
ssh -R 8080:localhost:8080 user@public-server
```

Execution

Terminal window

```
user@public-server:~$
```

-   Format: -R \[bind\_address:\]remote\_port:local\_host:local\_port
-   Requires GatewayPorts yes on remote server for external access
-   Useful for exposing localhost dev server to internet

#### Bind to All Interfaces on Remote

Expose local service to all interfaces on remote host (not just localhost). Requires GatewayPorts enabled

Code

Terminal window

```
ssh -R '*':3000:localhost:3000 user@public-server
```

Execution

Terminal window

```
user@public-server:~$
```

-   Use '\*' or empty bind\_address for all interfaces
-   Security: Only do for development, not production

### Dynamic Port Forwarding (SOCKS Proxy)

Create SOCKS proxy through SSH tunnel

#### Accessibility

Advanced

#### Best Practices

-   Keep SSH connection running while using proxy
-   Use -N flag to not spawn shell
-   Verify proxy is working: 'netstat -tlnp | grep 1080'

#### Common Errors

-   **Connection refused:** Port may be used by another service

#### Keywords

forwardingdynamic\-Dsocksproxytunnel

[Learn more](https://man7.org/linux/man-pages/man1/ssh.1.html)

#### Create SOCKS5 Proxy

Create SOCKS5 proxy on localhost:1080. All traffic through proxy routes through SSH tunnel to remote network

Code

Terminal window

```
ssh -D 1080 user@ssh-server
```

Execution

Terminal window

```
Last login: Wed Feb 28 09:15:00 2026user@ssh-server:~$
```

-   Format: -D \[bind\_address:\]local\_port
-   Browser/application must support SOCKS5
-   Useful for accessing services on remote private network

#### Configure Browser to Use SOCKS Proxy

Route traffic through SOCKS proxy to access internal services as if on remote network

Code

Terminal window

```
# Firefox: Preferences > General > Network Settings > SOCKS Host# localhost, port 1080, SOCKS v5
# Or use command-line toolcurl --socks5 localhost:1080 https://internal.company.com
```

Execution

Terminal window

```
<!DOCTYPE html><html><head><title>Internal Company Site</title></head><body>Welcome to internal site</body></html>
```

-   Many tools support SOCKS: curl, youtube-dl, etc.

## Key Management

### Creating and Managing Keys

Generate, manage, and secure SSH keys

#### Accessibility

Intermediate

#### Best Practices

-   Store keys in ~/.ssh/ directory with 600 permissions
-   Use strong passphrase (20+ characters)
-   Rotate keys annually or after suspicious activity
-   Use separate keys for different purposes/hosts if needed

#### Common Errors

-   **Permissions too open on private key:** chmod 600 ~/.ssh/id\_\*
-   **Bad permissions on ~/.ssh:** chmod 700 ~/.ssh

#### Keywords

keygenkeygenerationed25519rsapassphrase

[Learn more](https://man7.org/linux/man-pages/man1/ssh-keygen.1.html)

#### Generate RSA Key for Legacy Systems

Create RSA key for systems that don't support Ed25519. Use 4096-bit for adequate security

Code

Terminal window

```
ssh-keygen -t rsa -b 4096 -C "legacy-key"
```

Execution

Terminal window

```
Generating public/private rsa key pair.Enter file in which to save the key (/home/user/.ssh/id_rsa):Enter passphrase (empty for no passphrase):Your identification has been saved in /home/user/.ssh/id_rsaYour public key has been saved in /home/user/.ssh/id_rsa.pub
```

-   RSA requires larger key size (4096) compared to Ed25519 (256)
-   Slower but widely supported

#### List Keys Added to Agent

Display all keys currently loaded in SSH agent with their fingerprints

Code

Terminal window

```
ssh-add -l
```

Execution

Terminal window

```
256 SHA256:xyz... user@example.com (ED25519)4096 SHA256:abc... legacy-key (RSA)
```

-   Shows key type, fingerprint, and comment
-   Returns exit code 1 if agent not running

#### Export Public Key from Private Key

Recover/regenerate public key from existing private key

Code

Terminal window

```
ssh-keygen -y -f ~/.ssh/id_ed25519 > ~/.ssh/id_ed25519.pub
```

Execution

Terminal window

```
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJxyz... user@example.com
```

-   Useful if public key lost
-   Only works if you have the private key

### Managing Authorized Keys

Control which keys can access your account

#### Accessibility

Intermediate

#### Best Practices

-   Regularly audit authorized\_keys for unused keys
-   Use command restrictions for service accounts
-   Keep permissions: ~/.ssh/ (700) and authorized\_keys (600)
-   Include descriptive comments in pub keys

#### Common Errors

-   **Permission denied for key in authorized\_keys:** Check file permissions

#### Keywords

authorized\_keyspermissionsaccesscontrol

[Learn more](https://man7.org/linux/man-pages/man8/sshd.8.html)

#### View Authorized Keys

Display all public keys that can authenticate as current user. One key per line

Code

Terminal window

```
cat ~/.ssh/authorized_keys
```

Execution

Terminal window

```
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO.../key1 user@host1ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO.../key2 user@host2ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAA... legacy-key
```

-   File location: ~/.ssh/authorized\_keys
-   Permissions must be 600
-   Directory ~/.ssh must be 700

#### Remove Specific Key

Remove specific key by filtering it out. Revokes access for that key

Code

Terminal window

```
grep -v "key1" ~/.ssh/authorized_keys > /tmp/authorized_keys.tmpmv /tmp/authorized_keys.tmp ~/.ssh/authorized_keys
```

Execution

Terminal window

```
(file updated)
```

-   Use tools like ssh-keyscan for managing multiple hosts

#### Set Command Restrictions on Key

Restrict key to only execute specific command. Useful for automation/backups with limited permissions

Code

Terminal window

```
echo 'command="/usr/local/bin/backup.sh" ssh-ed25519 AAAAC3...' >> ~/.ssh/authorized_keys
```

Execution

Terminal window

```
(user logging in with this key will only run backup.sh)
```

-   Key can only run the specified command
-   Useful for automated backups, deployments

## Configuration & Advanced Setup

### SSH Config File

Configure hosts, defaults, and connection settings in ~/.ssh/config

#### Accessibility

Intermediate

#### Best Practices

-   Use descriptive Host names
-   Set IdentityFile explicitly to avoid trying all keys
-   Use StrictHostKeyChecking accept-new for automation
-   Set AddKeysToAgent yes for automatic key management

#### Common Errors

-   **Config not applied:** Check formatting and Host pattern matching

#### Keywords

configconfigurationhostoptionsaliases

[Learn more](https://man7.org/linux/man-pages/man5/ssh_config.5.html)

#### Basic Host Configuration

Define host aliases and connection parameters in ~/.ssh/config. Simplifies repeated connections

Code

Terminal window

```
cat ~/.ssh/config
```

Execution

Terminal window

```
Host myserver  HostName server.example.com  User admin  Port 2222  IdentityFile ~/.ssh/id_ed25519
Host *.internal  User intern_user  ProxyJump bastion
```

-   Format: Host pattern followed by configuration options
-   \* and ? wildcards supported in Host patterns
-   Configuration applied in order, first match wins

#### Connect Using Host Alias

Use hostname alias instead of full connection details. All config parameters applied automatically

Code

Terminal window

```
ssh myserver
```

Execution

Terminal window

```
Last login: Wed Feb 28 14:30:00 2026admin@myserver:~$
```

-   Reads from ~/.ssh/config automatically
-   Command line options override config file

#### Jump Host / Bastion Configuration

Use ProxyJump to tunnel through bastion host to reach internal servers. Cleaner than -J flag

Code

Terminal window

```
Host bastion  HostName bastion.company.com  User bastionuser
Host internal-*.company.com  ProxyJump bastion  User internaluser
ssh internal-db.company.com
```

Execution

Terminal window

```
(SSH connects through bastion automatically)Last login: Wed Feb 28 15:00:00 2026internaluser@internal-db:~$
```

-   ProxyJump added in OpenSSH 7.3
-   Can chain multiple jumps: ProxyJump host1,host2

### Connection Multiplexing

Reuse SSH connections for faster subsequent logins

#### Accessibility

Advanced

#### Best Practices

-   Enable for frequently accessed hosts
-   Set appropriate ControlPersist timeout
-   Use %h (host), %r (user), %p (port) in ControlPath

#### Common Errors

-   **ControlPath directory doesn't exist:** Create ~/.ssh/ first

#### Keywords

multiplexingmastercontrolconnectionsharing

[Learn more](https://man7.org/linux/man-pages/man5/ssh_config.5.html)

#### Enable Connection Multiplexing

Enable multiplexing globally. Auto reuses master connections for 1 hour

Code

Terminal window

```
# Add to ~/.ssh/configHost *  ControlMaster auto  ControlPath ~/.ssh/control-%h-%r-%p  ControlPersist 3600
```

Execution

Terminal window

```
(settings saved)
```

-   ControlMaster auto: automatically create master on first connection
-   ControlPath: location of control socket
-   ControlPersist 3600: keep master alive for 1 hour after last client

#### Multiple Connections Using Master

Second and subsequent connections reuse the master SSH tunnel, bypassing authentication

Code

Terminal window

```
# First connection (creates master)ssh user@host
# In another terminal: reuses existing connectionssh user@host
```

Execution

Terminal window

```
(second connection opens instantly)
```

-   Faster because TCP setup and authentication are already done
-   Check control sockets: ls -la ~/.ssh/control-\*

#### Explicitly Check Master Connection

Check if multiplexed connection is active to a host

Code

Terminal window

```
ssh -O check user@host
```

Execution

Terminal window

```
Master running (pid=12345)
```

-   exit code 0 if master running
-   Useful for scripts

## Security Best Practices

### Protecting Your Keys

Keep SSH keys secure from unauthorized access

#### Accessibility

Beginner

#### Best Practices

-   Never share private keys
-   Always use passphrase to protect keys
-   Set strict file permissions (700/600)
-   Rotate keys annually or after suspected compromise
-   Use separate keys for different purposes

#### Common Errors

-   **SSH refuses key:** Wrong permissions on ~/.ssh directory

#### Keywords

securitypermissionspassphraseprotectionbest-practices

[Learn more](https://man7.org/linux/man-pages/man1/ssh-keygen.1.html)

#### Fix SSH Directory Permissions

SSH requires specific permissions for security. SSH will refuse keys with wrong permissions

Code

Terminal window

```
chmod 700 ~/.sshchmod 600 ~/.ssh/id_*chmod 600 ~/.ssh/authorized_keyschmod 644 ~/.ssh/*.pub
```

Execution

Terminal window

```
(permissions updated)
```

-   ~/.ssh directory: 700 (rwx------)
-   Private key files: 600 (rw-------)
-   Public key files: 644 (rw-r--r--)
-   authorized\_keys: 600 (rw-------)

#### Test Key Permissions

Verify all permissions are correct. Private keys only readable by owner

Code

Terminal window

```
ls -la ~/.ssh/
```

Execution

Terminal window

```
total 32drwx------ 2 user user 4096 Feb 28 10:30 .-rw------- 1 user user  464 Feb 28 10:30 id_ed25519-rw-r--r-- 1 user user   89 Feb 28 10:30 id_ed25519.pub-rw------- 1 user user 1679 Feb 28 10:30 authorized_keys
```

-   First column shows permissions
-   Directory should start with 'd'
-   Private keys should be 'rw-------'

#### Rotate Compromised Key

After compromise, remove old key from all authorized\_keys and generate new one

Code

Terminal window

```
# Step 1: Remove old key from authorized_keys on all serversgrep -l "old_key_fingerprint" ~/.ssh/authorized_keys | while read f; do  sed -i '/old_key_fingerprint/d' "$f"done
# Step 2: Delete local private keyrm ~/.ssh/id_rsa
# Step 3: Generate new keyssh-keygen -t ed25519 -C "new-key"
```

Execution

Terminal window

```
(key rotated)
```

-   Must rotate across all servers
-   May need temporary password access to add new key

### Host Key Verification

Verify remote host authenticity to prevent MITM attacks

#### Accessibility

Intermediate

#### Best Practices

-   Always verify host key on first connection
-   Update ~/.ssh/known\_hosts when host keys change
-   Use DNSSEC SSHFP records for DNS-based verification
-   Monitor for unexpected host key changes

#### Common Errors

-   **Remote host identification has changed:** Host key may have changed or you're connecting to different host

#### Keywords

host-keyfingerprintverificationknown\_hostsmitm

[Learn more](https://man7.org/linux/man-pages/man1/ssh-keygen.1.html)

#### First Connection Host Key Verification

On first connection, SSH shows host key fingerprint for verification. Accept only if verified from trusted source

Code

Terminal window

```
ssh user@newhost
```

Execution

Terminal window

```
The authenticity of host 'newhost (192.168.1.100)' can't be established.ED25519 key fingerprint is SHA256:abcxy123...This key is not known by any other namesAre you sure you want to continue connecting (yes/no/[fingerprint])?
```

-   Fingerprint should match official host key
-   Answer 'yes' to add to ~/.ssh/known\_hosts
-   Subsequent connections won't show this prompt

#### Verify Host Key Fingerprint Manually

Verify fingerprint matches what SSH showed during connection attempt

Code

Terminal window

```
# On the remote hostssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub
```

Execution

Terminal window

```
256 SHA256:abcxy123... root@newhost (ED25519)
```

-   Run on remote server admin console
-   Compare with fingerprint displayed during SSH connection

#### Check Existing Host Key

Display all known host keys and their fingerprints from ~/.ssh/known\_hosts

Code

Terminal window

```
ssh-keygen -l -f ~/.ssh/known_hosts
```

Execution

Terminal window

```
256 SHA256:old_key... hostname1 (ED25519)256 SHA256:new_key... hostname2 (ED25519)
```

-   Helps identify if host key has changed
-   Unexpected changes may indicate compromise or reconfiguration

## Advanced Usage

### Jump Hosts & Bastion Patterns

Connect through intermediate hosts to reach internal servers

#### Accessibility

Advanced

#### Best Practices

-   Keep bastion host security hardened
-   Monitor bastion access logs
-   Use MFA on bastion if possible
-   Implement host key verification

#### Common Errors

-   **Cannot reach final host:** Check routing/ACLs from bastion

#### Keywords

jumpbastionintermediatemulti-hopproxy

[Learn more](https://man7.org/linux/man-pages/man5/ssh_config.5.html)

#### Single Hop Through Jump Host

Use jump host to reach internal server. SSH tunnels through bastion automatically

Code

Terminal window

```
ssh -J user@bastion:2222 user@internal-server
```

Execution

Terminal window

```
Last login: Wed Feb 28 16:30:00 2026user@internal-server:~$
```

-   Format: -J \[user@\]host\[:port\]
-   Can specify non-standard port on jump host
-   Automatically applies ProxyCommand

#### Multiple Hops Through Jump Hosts

Chain multiple jump hosts. Connection routes through bastion1 -> bastion2 -> final-host

Code

Terminal window

```
ssh -J user@bastion1,user@bastion2 user@final-host
```

Execution

Terminal window

```
(connected through chain of hosts)user@final-host:~$
```

-   Separate hosts with commas
-   Each hop authenticates independently

#### Persistent Jump Host Configuration

Configure jump host in ~/.ssh/config for permanent setup. All internal-\* hosts use bastion

Code

~/.ssh/config

```
Host bastion  HostName bastion.company.com  User admin
Host internal-*  ProxyJump bastion  User devuser
# Usage: ssh internal-server1
```

Execution

Terminal window

```
(automatic jump through bastion)
```

-   ProxyJump simpler than older ProxyCommand
-   Inherits authentication from config

### X11 Forwarding

Run graphical applications on remote servers and display locally

#### Accessibility

Advanced

#### Best Practices

-   Use only on trusted connections
-   Disable remote X11 forwarding if not needed (in sshd\_config)
-   Verify ForwardX11 disabled for untrusted hosts

#### Common Errors

-   **X11 forwarding not working:** Server may have X11Forwarding disabled

#### Keywords

x11graphicaldisplayguiforwarding

[Learn more](https://man7.org/linux/man-pages/man1/ssh.1.html)

#### Enable X11 Forwarding

Forward X11 display from remote to local machine. Start GUI apps on remote, see them locally

Code

Terminal window

```
ssh -X user@remote-host
```

Execution

Terminal window

```
user@remote-host:~$ gedit &(gedit window opens on local display)
```

-   Requires X11 server on local machine (native on Linux/macOS)
-   \-X: standard X11 forwarding
-   \-Y: trusted X11 forwarding (skips security checks)

#### Trusted X11 Forwarding

Trusted X11 forwarding allows apps to access X11 security extensions. Faster but less secure

Code

Terminal window

```
ssh -Y user@remote-host
```

Execution

Terminal window

```
user@remote-host:~$ firefox &(firefox window opens on local display)
```

-   Use for trusted hosts only
-   \-Y skips X11 SECURITY extension
-   Performance improvement over standard -X

#### Test X11 Forwarding

DISPLAY variable set by SSH indicates X11 tunnel is active

Code

Terminal window

```
ssh -X user@remote-hostecho $DISPLAY
```

Execution

Terminal window

```
localhost:10.0
```

-   DISPLAY set to localhost:N where N > 0
-   Value 0 would indicate no X11 forwarding

## Practical Real-World Examples

### Common Use Cases

Real-world examples and practical patterns

#### Accessibility

Intermediate

#### Best Practices

-   Use SSH keys for all automation
-   Validate output and errors in scripts
-   Use -o BatchMode=yes in scripts to fail fast
-   Log all remote operations for audit trail

#### Common Errors

-   **Permission denied in script:** Check key has correct permissions
-   **Script hangs:** Remote command may be waiting for input

#### Keywords

examplespracticalreal-worldscenariosuse-cases

[Learn more](https://man7.org/linux/man-pages/man1/ssh.1.html)

#### Copy Files Using SCP

SCP (secure copy) transfers files through SSH tunnel. Secure alternative to FTP

Code

Terminal window

```
# Copy file from local to remotescp /local/path/file user@host:/remote/path/
# Copy file from remote to localscp user@host:/remote/path/file /local/path/
# Copy directory recursivelyscp -r user@host:/remote/path/ /local/path/
```

Execution

Terminal window

```
file                      100%   1234KB    5.2MB/s   00:00
```

-   Uses SSH for encryption
-   \-r flag for recursive directory copy
-   \-P for non-standard port (uppercase!)

#### Sync Directory with rsync Over SSH

rsync over SSH synchronizes directories. Only changed files are transferred

Code

Terminal window

```
# Sync local to remotersync -avz -e ssh /local/path/ user@host:/remote/path/
# Sync remote to localrsync -avz -e ssh user@host:/remote/path/ /local/path/
# With non-standard SSH portrsync -avz -e 'ssh -p 2222' /local/path/ user@host:/remote/path/
```

Execution

Terminal window

```
sending incremental file listfile1file2sent 1234 bytes  received 567 bytestotal size is 5678  speedup is 3.21
```

-   Much faster than scp for large directories
-   \-a: archive mode (preserves permissions)
-   \-v: verbose, -z: compress
-   Better for backups and deployments

#### Run Remote Command and Get Output

Execute remote commands and get output without interactive shell. Useful for scripts

Code

Terminal window

```
# Execute single commandssh user@host "ps aux | grep nodejs"
# Execute multiple commandsssh user@host "cd /app && npm start"
# Run command and capture outputresult=$(ssh user@host "docker ps -a")echo "$result"
```

Execution

Terminal window

```
user        12345  0.5 15.3 234567 89012 ?  Sl  14:30   0:05 node /app/server.js
```

-   Command in quotes runs on remote, output sent to stdout
-   Exit code preserved: useful in bash conditionals
-   Suited to cronjobs and automation

#### Automated Backup to Remote Host

Stream compressed backup to remote server. No local temporary files are written

Code

```
#!/bin/bash# backup.sh - automated backup script
LOCAL_PATH="/home/user/important-data"BACKUP_HOST="backup.example.com"BACKUP_USER="backup"BACKUP_PATH="/backups/$(hostname)"
# Create backuptar czf - "$LOCAL_PATH" | ssh $BACKUP_USER@$BACKUP_HOST \  "cat > $BACKUP_PATH/backup-$(date +%Y%m%d).tar.gz"
echo "Backup completed"
```

Execution

Terminal window

```
Backup completed
```

-   tar pipes directly through SSH
-   No local disk space needed for backup
-   Useful for cron jobs with SSH key auth

#### Port Forward for Database Connection

Access private database server through SSH tunnel. Database thinks it's local

Code

Terminal window

```
# Terminal 1: Create tunnelssh -L 3306:internal-db:3306 -N user@bastion
# Terminal 2: Connect to local portmysql -h localhost -u dbuser -p
```

Execution

Terminal window

```
Enter password:Welcome to MariaDB Monitor. Commands...
```

-   \-N: don't execute remote command
-   Keep tunnel running in separate terminal
-   Connection is end-to-end encrypted

#### SSH Agent for Automated Deployments

Use SSH agent in scripts for passwordless authentication. Clean up after

Code

```
#!/bin/bash# deploy.sh - automated deployment
# Start SSH agent for this scripteval "$(ssh-agent -s)"ssh-add ~/.ssh/deploy-key
# Deploy to multiple serversfor server in web1 web2 web3; do  ssh -o StrictHostKeyChecking=accept-new deploy@$server \    "cd /app && git pull && npm start"done
# Kill agent when donessh-agent -k
```

Execution

Terminal window

```
deployment to web1... donedeployment to web2... donedeployment to web3... done
```

-   ssh-agent managed within script
-   StrictHostKeyChecking=accept-new for new hosts
-   Always kill agent to avoid leaked credentials

## Troubleshooting

### Debugging SSH Connection Issues

Diagnose and fix common SSH problems

#### Accessibility

Beginner

#### Best Practices

-   Always start with -v flag when debugging
-   Check permissions first, they are a frequent cause of refused keys
-   Test with alternate auth methods (e.g., password) to isolate key issues

#### Common Errors

-   **Permission denied (publickey):** Check authorized\_keys on remote
-   **Connection refused:** SSH daemon may not be running
-   **Timeout:** Network/firewall issue, not SSH

#### Keywords

troubleshootingdebugverboseerrorfix

[Learn more](https://man7.org/linux/man-pages/man1/ssh.1.html)

#### Enable Verbose Output for Debugging

Verbose flags show detailed connection process. Level indicates where connection fails

Code

Terminal window

```
# Single verbose (-v): shows authentication methodssh -v user@host
# Double verbose (-vv): shows handshake detailsssh -vv user@host
# Triple verbose (-vvv): shows all details including cryptossh -vvv user@host
```

Execution

Terminal window

```
OpenSSH_8.0p1 Ubuntu 1:8.0p1-6ubuntu1, OpenSSL 1.1.1debug1: Reading configuration data /home/user/.ssh/configdebug1: No more authentication methods to try.Permission denied (publickey,password).
```

-   \-v: high-level flow
-   \-vv: detailed authentication
-   \-vvv: packet-level (very verbose)

#### Check SSH Key Permissions

SSH refuses to use keys with improper permissions. Directory 700, private keys 600

Code

Terminal window

```
# Check directory permissionsls -ld ~/.ssh
# Check key file permissionsls -l ~/.ssh/id_*
```

Execution

Terminal window

```
drwx------ 2 user user 4096 Feb 28 10:00 /home/user/.ssh-rw------- 1 user user  1234 Feb 28 10:00 /home/user/.ssh/id_ed25519-rw-r--r-- 1 user user   456 Feb 28 10:00 /home/user/.ssh/id_ed25519.pub
```

-   Private keys must be readable only by owner
-   Use 'chmod 700 ~/.ssh' and 'chmod 600 ~/.ssh/id\_\*'

#### Test Remote SSH Server Configuration

Test which authentication methods server allows. Helpful for debugging auth failures

Code

Terminal window

```
# List available authentication methodsssh -o PreferredAuthentications=none user@host
# Test specific auth methodssh -o PreferredAuthentications=publickey user@hostssh -o PreferredAuthentications=password user@host
```

Execution

Terminal window

```
Permission denied (publickey).debug1: Authentications that can continue: publickey,password
```

-   Shows which methods server supports
-   Can isolate auth method issues

Was this useful?

## Share

[Facebook](https://facebook.com/sharer/sharer.php?u=https%3A%2F%2Fmkabumattar.com%2Fcheatsheets%2Fssh "Share on Facebook")[Twitter](https://twitter.com/intent/tweet/?text=SSH&url=https%3A%2F%2Fmkabumattar.com%2Fcheatsheets%2Fssh "Share on Twitter")[LinkedIn](https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fmkabumattar.com%2Fcheatsheets%2Fssh&title=SSH&summary=SSH%20cheatsheet%20covering%20OpenSSH%20client%20usage%2C%20authentication%20methods%2C%20port%20forwarding%2C%20key%20management%2C%20X11%20forwarding%2C%20and%20configuration%20options.%20Includes%20real-world%20examples%20and%20security%20best%20practices.&source=https://mkabumattar.com "Share on LinkedIn")[WhatsApp](https://wa.me/?text=SSH%20https%3A%2F%2Fmkabumattar.com%2Fcheatsheets%2Fssh "Share on WhatsApp")[Telegram](https://t.me/share/url?url=https%3A%2F%2Fmkabumattar.com%2Fcheatsheets%2Fssh&text=SSH "Share on Telegram")[Reddit](https://www.reddit.com/submit?url=https%3A%2F%2Fmkabumattar.com%2Fcheatsheets%2Fssh&title=SSH "Share on Reddit")[Hacker News](http://news.ycombinator.com/submitlink?u=https%3A%2F%2Fmkabumattar.com%2Fcheatsheets%2Fssh&t=SSH "Share on Hacker News")[Pinterest](https://pinterest.com/pin/create/button/?url=https%3A%2F%2Fmkabumattar.com%2Fcheatsheets%2Fssh&media=&description=SSH%20cheatsheet%20covering%20OpenSSH%20client%20usage%2C%20authentication%20methods%2C%20port%20forwarding%2C%20key%20management%2C%20X11%20forwarding%2C%20and%20configuration%20options.%20Includes%20real-world%20examples%20and%20security%20best%20practices. "Share on Pinterest")[Email](<mailto:?subject=SSH&body=Check out this article: https%3A%2F%2Fmkabumattar.com%2Fcheatsheets%2Fssh>)

## Comments

## You might also enjoy

More posts on similar topics

## [AWK](/cheatsheets/awk)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   Terminal
-   Text Processing
-   Linux
-   Command Line
-   Development Tools
-   Scripting

AWK complete reference guide Quick start Print entire file awk '{ print }' file.txt# Print specific column awk '{ print $1 }' file.txt# Print lines matching pattern awk '/patter

#AWK#Text Processing#Pattern Matching+3 tags

[read more](/cheatsheets/awk)

## [Bash](/cheatsheets/bash)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   Scripting
-   Shell
-   Linux
-   Unix
-   Command Line
-   Automation

Bash is a Unix shell and command language written by Brian Fox for the GNU Project as a free software replacement for the Bourne shell. The sections below cover Bash commands, syntax, and examples.

#Scripting#Shell#Linux+3 tags

[read more](/cheatsheets/bash)

## [Chmod](/cheatsheets/chmod)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   Terminal
-   Programming
-   Linux
-   File Management
-   Tools

Complete chmod reference covering file permissions, recursive changes with -v and -c, reference mode, logical operators, batch operations, practical examples, and security best practices for Linux fil

#Chmod#Permissions#File Permissions+5 tags

[read more](/cheatsheets/chmod)

## [Cron](/cheatsheets/cron)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   Terminal
-   System Administration
-   Linux
-   Scheduling
-   Automation
-   Tools

Quick reference Field layout Min Hour Day Month Weekday Command\* /path/to/command ┬ ┬ ┬ ┬ ┬ │ │ │ │ └───── Weekday (0=Sunday,

#Cron#Crontab#Scheduling+3 tags

[read more](/cheatsheets/cron)

## [Curl](/cheatsheets/curl)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   Terminal
-   Web Development
-   APIs
-   HTTP
-   Command Line
-   Tools

Getting started with Curl cURL (client URL) is a command-line tool for transferring data using URLs. It speaks HTTP, HTTPS, FTP, SFTP, and many other protocols, which makes it the usual choice for

#Curl#HTTP#REST+3 tags

[read more](/cheatsheets/curl)

## [Find](/cheatsheets/find)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   Terminal
-   Programming
-   Linux
-   File Operations
-   Tools

Best practices for find command usageAlways quote patterns to prevent shell expansion of special characters Use -type f first in find expressions for optimal performance \*\*Prune hea

#Find#File Search#Discovery+3 tags

[read more](/cheatsheets/find)

6 related posts
