Report this

What is the reason for this report?

SSH Essentials: Working with SSH Servers, Clients, and Keys

Updated on February 10, 2026
SSH Essentials: Working with SSH Servers, Clients, and Keys

Introduction

SSH is a secure protocol used as the primary method for connecting to and managing remote Linux servers. It provides encrypted access for running commands, transferring files, and forwarding network traffic, making it a foundational tool for system administration and development workflows.

This guide covers both the fundamentals and the practical details required to work effectively with SSH. In addition to basic connection methods, it explains how SSH authentication works, how trust is established using keys, and how to configure SSH securely on both the server and client side. It also includes guidance on tunneling traffic, managing sessions, and diagnosing common connection issues.

This article is written as a reference-style resource. You can read it end to end to build a complete understanding of SSH, or jump directly to the sections that address your immediate needs.

Deploy your frontend applications from GitHub using DigitalOcean App Platform. Let DigitalOcean focus on scaling your app.

Key Takeaways:

  • SSH is the default tool for secure remote access to Linux servers. It enables encrypted command execution, file transfers, and network tunneling over untrusted networks.
  • SSH relies on a client-server architecture with explicit responsibilities. The SSH daemon manages incoming connections on the server, while the client controls authentication and session behavior.
  • SSH keys provide stronger security than passwords and should be the standard. Key-based authentication avoids shared secrets and prevents brute-force and credential reuse attacks.
  • SSH trust is established ahead of time, not during login. Servers trust public keys placed in authorized_keys, and clients prove identity by possessing the matching private key.
  • User authentication and host verification solve different security problems. SSH keys authenticate users, while host keys protect clients from connecting to impersonated servers.
  • Private key protection is critical to SSH security. Private keys must remain local, secured with permissions and optional passphrases, and never copied to servers.
  • A secure SSH baseline dramatically reduces exposure. Disabling password logins, blocking direct root access, limiting attempts, and explicitly allowing users should be standard practice.
  • Client-side SSH configuration improves safety and usability. The ~/.ssh/config file simplifies connections, enforces consistent behavior, and reduces human error.
  • SSH tunneling extends SSH beyond remote shells. Local, remote, and dynamic tunnels allow encrypted access to services and networks that would otherwise be unreachable.
  • Most SSH problems are predictable and diagnosable. Permission issues, authentication mismatches, service availability, and host verification errors account for the majority of failures.

How To Use This Guide

  • Use whichever subsequent sections are applicable to what you are trying to achieve. Most sections are not predicated on any other, so you can use the following examples independently.
  • Use the Contents menu on the left side of this page (at wide page widths) or your browser’s find function to locate the sections you need.
  • Copy and paste the command-line examples given, substituting the highlighted values with your own values.

SSH Overview

The most common way of connecting to a remote Linux server is through SSH. SSH stands for Secure Shell and provides a safe and secure way of executing commands, making changes, and configuring services remotely. When you connect through SSH, you log in using an account that exists on the remote server.

How SSH Works

When you connect through SSH, you will be dropped into a shell session, which is a text-based interface where you can interact with your server. For the duration of your SSH session, any commands that you type into your local terminal are sent through an encrypted SSH tunnel and executed on your server.

The SSH connection is implemented using a client-server model. This means that for an SSH connection to be established, the remote machine must be running a piece of software called an SSH daemon. This software listens for connections on a specific network port, authenticates connection requests, and spawns the appropriate environment if the user provides the correct credentials.

The user’s computer must have an SSH client. This is a piece of software that knows how to communicate using the SSH protocol and can be given information about the remote host to connect to, the username to use, and the credentials that should be passed to authenticate. The client can also specify certain details about the connection type they would like to establish.

How SSH Authenticates Users

Clients generally authenticate either using passwords (less secure and not recommended) or SSH keys, which are very secure.

Password logins are encrypted and are easy to understand for new users. However, automated bots and malicious users will often repeatedly try to authenticate to accounts that allow password-based logins, which can lead to security compromises. For this reason, we recommend always setting up SSH key-based authentication for most configurations.

SSH keys are a matching set of cryptographic keys which can be used for authentication. Each set contains a public and a private key. The public key can be shared freely without concern, while the private key must be vigilantly guarded and never exposed to anyone.

To authenticate using SSH keys, a user must have an SSH key pair on their local computer. On the remote server, the public key must be copied to a file within the user’s home directory at ~/.ssh/authorized_keys. This file contains a list of public keys, one-per-line, that are authorized to log into this account.

When a client connects to the host and attempts to use SSH key authentication, the server checks the authorized_keys file for the corresponding public key. The server then sends authentication data to the client, which uses the associated private key to create a digital signature. The server verifies this signature using the public key. If the verification is successful, the server confirms that the client possesses the correct private key and allows the connection.

This authentication process is based on a trust relationship that is established before any login attempt occurs. The server does not learn or store a user’s private key. Instead, it relies on the presence of an approved public key and the client’s ability to prove ownership of the corresponding private key.

How SSH Establishes Trust Between Client and Server

SSH key authentication uses asymmetric cryptography to establish trust without sharing credentials. Trust is created when a server administrator places a public key into the ~/.ssh/authorized_keys file for a user account.

By adding a public key to this file, the server is explicitly configured to trust any client that can demonstrate possession of the matching private key. This is an administrative decision made ahead of time and is not negotiated during login.

During authentication, the server issues a cryptographic challenge that can only be answered correctly by a client that holds the private key. The private key never leaves the client system and is never transmitted to the server or over the network.

Because the server stores only public keys, a server compromise does not expose private credentials. Access can also be revoked at any time by removing a public key from the authorized_keys file.

User Authentication Trust vs Host Verification

SSH uses two separate trust mechanisms that serve different purposes.

  • User authentication verifies that the client is allowed to log in to an account on the server. This process relies on SSH keys and the authorized_keys file.
  • Host verification confirms that the client is connecting to the intended server. This is handled through server host keys, which are stored on the client in the ~/.ssh/known_hosts file.

These mechanisms operate independently. SSH key authentication confirms who is logging in, while host verification protects against connecting to an unexpected or impersonated server.

Now that you know how SSH works, we can begin to discuss some examples to demonstrate different ways of working with SSH.

Generating and Working with SSH Keys

This section will cover how to generate SSH keys on a client machine and distribute the public key to servers where they should be used. This is a good section to start with if you have not previously generated keys due to the increased security that it allows for future connections.

Generating an SSH Key Pair

Generating a new SSH public and private key pair on your local computer is the first step towards authenticating with a remote server without a password. Unless there is a good reason not to, you should always authenticate using SSH keys.

A number of cryptographic algorithms can be used to generate SSH keys, including Ed25519, RSA, and ECDSA. Ed25519 keys are generally preferred due to their strong security, small key size, and good performance. RSA keys are still widely supported, but should be created with a key length of at least 3072 or 4096 bits.

To generate an RSA key pair on your local computer, type:

  1. ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/demo/.ssh/id_rsa):

This prompt allows you to choose the location to store your RSA private key. Press ENTER to leave this as the default, which will store them in the .ssh hidden directory in your user’s home directory. Leaving the default location selected will allow your SSH client to find the keys automatically.

Enter passphrase (empty for no passphrase):
Enter same passphrase again:

The next prompt allows you to enter an arbitrary length passphrase to secure your private key. As an additional security measure, you will have to enter any passphrase you set here every time you use the private key. Feel free to press ENTER to leave this blank if you do not want a passphrase. Keep in mind, though, that this will allow anyone who gains control of your private key to log in to your servers.

If you choose to enter a passphrase, nothing will be displayed as you type. This is a security precaution. The following output reflects RSA key generation:

Output
Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: 8c:e9:7c:fa:bf:c4:e5:9c:c9:b8:60:1f:fe:1c:d3:8a root@here The key's randomart image is: +--[ RSA 2048]----+ | | | | | | | + | | o S . | | o . * + | | o + = O . | | + = = + | | ....Eo+ | +-----------------+

This procedure has generated an RSA SSH key pair located in the .ssh hidden directory within your user’s home directory. These files are:

  • ~/.ssh/id_rsa: The private key. DO NOT SHARE THIS FILE!
  • ~/.ssh/id_rsa.pub: The associated public key. This can be shared freely without consequence.

Generate an SSH Key Pair with a Larger Number of Bits

When generating keys without specifying an algorithm, modern versions of OpenSSH default to Ed25519. RSA keys default to 2048 bits if explicitly selected, though 3072 or 4096 bits are recommended. This is generally considered to be good enough for security, but you can specify a greater number of bits for a more hardened key.

To do this, include the -b argument with the number of bits you would like. Most servers support keys with a length of at least 4096 bits. Most servers support RSA keys up to 4096 bits. Larger key sizes generally provide diminishing security returns and may not be supported by all implementations:

  1. ssh-keygen -b 4096

If you had previously created a different key, you will be asked if you wish to overwrite your previous key:

Overwrite (y/n)?

If you choose “yes”, your previous key will be overwritten and you will no longer be able to log in to servers using that key. Because of this, be sure to overwrite keys with caution.

Removing or Changing the Passphrase on a Private Key

If you have generated a passphrase for your private key and wish to change or remove it, you can do so easily.

Note: To change or remove the passphrase, you must know the original passphrase. If you have lost the passphrase to the key, there is no recourse and you will have to generate a new key pair.

To change or remove the passphrase, simply type:

  1. ssh-keygen -p
Enter file in which the key is (/root/.ssh/id_rsa):

You can type the location of the key you wish to modify or press ENTER to accept the default value:

Enter old passphrase:

Enter the old passphrase that you wish to change. You will then be prompted for a new passphrase:

Enter new passphrase (empty for no passphrase):
Enter same passphrase again:

Here, enter your new passphrase or press ENTER to remove the passphrase.

Displaying the SSH Key Fingerprint

Each SSH key pair shares a single cryptographic “fingerprint” which can be used to uniquely identify the keys. This can be useful in a variety of situations.

To find out the fingerprint of an SSH key, type:

  1. ssh-keygen -l
Enter file in which the key is (/root/.ssh/id_rsa):

You can press ENTER if that is the correct location of the key, else enter the revised location. You will be given a string which contains the bit-length of the key, the fingerprint, and account and host it was created for, and the algorithm used:

Output
4096 8e:c4:82:47:87:c2:26:4b:68:ff:96:1a:39:62:9e:4e demo@test (RSA)

Copying your Public SSH Key to a Server with SSH-Copy-ID

To copy your public key to a server, allowing you to authenticate without a password, a number of approaches can be taken.

If you currently have password-based SSH access configured to your server, and you have the ssh-copy-id utility installed, this is a simple process. The ssh-copy-id tool is included in many Linux distributions’ OpenSSH packages, so it very likely may be installed by default.

If you have this option, you can easily transfer your public key by typing:

  1. ssh-copy-id username@remote_host

This will prompt you for the user account’s password on the remote system:

The authenticity of host '111.111.11.111 (111.111.11.111)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
demo@111.111.11.111's password:

After typing in the password, the contents of your ~/.ssh/id_rsa.pub key will be appended to the end of the user account’s ~/.ssh/authorized_keys file:

Output
Number of key(s) added: 1 Now try logging into the machine, with: "ssh 'demo@111.111.11.111'" and check to make sure that only the key(s) you wanted were added.

You can now log in to that account without a password:

  1. ssh username@remote_host

Copying your Public SSH Key to a Server Without SSH-Copy-ID

If you do not have the ssh-copy-id utility available, but still have password-based SSH access to the remote server, you can copy the contents of your public key in a different way.

You can output the contents of the key and pipe it into the ssh command. On the remote side, you can ensure that the ~/.ssh directory exists, and then append the piped contents into the ~/.ssh/authorized_keys file:

  1. cat ~/.ssh/id_rsa.pub | ssh username@remote_host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

You will be asked to supply the password for the remote account:

The authenticity of host '111.111.11.111 (111.111.11.111)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes
demo@111.111.11.111's password:

After entering the password, your key will be copied, allowing you to log in without a password:

  1. ssh username@remote_IP_host

Copying your Public SSH Key to a Server Manually

If you do not have password-based SSH access available, you will have to add your public key to the remote server manually.

On your local machine, you can find the contents of your public key file by typing:

  1. cat ~/.ssh/id_rsa.pub
Output
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCqql6MzstZYh1TmWWv11q5O3pISj2ZFl9HgH1JLknLLx44+tXfJ7mIrKNxOOwxIxvcBF8PXSYvobFYEZjGIVCEAjrUzLiIxbyCoxVyle7Q+bqgZ8SeeM8wzytsY+dVGcBxF6N4JS+zVk5eMcV385gG3Y6ON3EG112n6d+SMXY0OEBIcO6x+PnUSGHrSgpBgX7Ks1r7xqFa7heJLLt2wWwkARptX7udSq05paBhcpB0pHtA1Rfz3K2B+ZVIpSDfki9UVKzT8JUmwW6NNzSgxUfQHGwnW7kj4jp4AT0VZk3ADw497M2G/12N0PPB5CnhHf7ovgy6nL1ikrygTKRFmNZISvAcywB9GVqNAVE+ZHDSCuURNsAInVzgYo9xgJDW8wUw2o8U77+xiFxgI5QSZX3Iq7YLMgeksaO4rBJEa54k8m5wEiEE1nUhLuJ0X/vh2xPff6SQ1BL/zkOhvJCACK6Vb15mDOeCSq54Cr7kvS46itMosi/uS66+PujOO+xt/2FWYepz6ZlN70bRly57Q06J+ZJoc9FfBCbCyYH7U/ASsmY095ywPsBo1XQ9PqhnN1/YOorJ068foQDNVpm146mUpILVxmq41Cj55YKHEazXGsdBIbXWhcrRf4G2fJLRcGUr9q8/lERo9oxRm5JFX6TCmj6kmiFqv+Ow9gI0x8GvaQ== demo@test

You can copy this value, and manually paste it into the appropriate location on the remote server. You will have to log in to the remote server through other means (like the DigitalOcean web console).

On the remote server, create the ~/.ssh directory if it does not already exist:

  1. mkdir -p ~/.ssh

Afterwards, you can create or append the ~/.ssh/authorized_keys file by typing:

  1. echo public_key_string >> ~/.ssh/authorized_keys

You should now be able to log in to the remote server without a password.

Basic Connection Instructions

The following section will cover some of the basics about how to connect to a server with SSH.

Connecting to a Remote Server

To connect to a remote server and open a shell session there, you can use the ssh command.

The simplest form assumes that your username on your local machine is the same as that on the remote server. If this is true, you can connect using:

  1. ssh remote_host

If your username is different on the remote server, you need to pass the remote user’s name like this:

  1. ssh username@remote_host

Your first time connecting to a new host, you will see a message that looks like this:

The authenticity of host '111.111.11.111 (111.111.11.111)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes

Type yes to accept the authenticity of the remote host.

If you are using password authentication, you will be prompted for the password for the remote account here. If you are using SSH keys, you will be prompted for your private key’s passphrase if one is set, otherwise you will be logged in automatically.

Running a Single Command on a Remote Server

To run a single command on a remote server instead of spawning a shell session, you can add the command after the connection information, like this:

  1. ssh username@remote_host command_to_run

This will connect to the remote host, authenticate with your credentials, and execute the command you specified. The connection will immediately close afterwards.

Logging in to a Server with a Different Port

By default the SSH daemon on a server runs on port 22. Your SSH client will assume that this is the case when trying to connect. If your SSH server is listening on a non-standard port (this is demonstrated in a later section), you will have to specify the new port number when connecting with your client.

You can do this by specifying the port number with the -p option:

  1. ssh -p port_num username@remote_host

To avoid having to do this every time you log in to your remote server, you can create or edit a configuration file in the ~/.ssh directory within the home directory of your local computer.

Edit or create the file now by typing:

  1. nano ~/.ssh/config

In here, you can set host-specific configuration options. To specify your new port, use a format like this:

~/.ssh/config
Host remote_alias
    HostName remote_host
    Port port_num

This will allow you to log in without specifying the specific port number on the command line.

Adding your SSH Keys to an SSH Agent to Avoid Typing the Passphrase

If you have a passphrase on your private SSH key, you will be prompted to enter the passphrase every time you use it to connect to a remote host.

To avoid having to repeatedly do this, you can run an SSH agent. This small utility stores your private key after you have entered the passphrase for the first time. It will be available for the duration of your terminal session, allowing you to connect in the future without re-entering the passphrase.

This is also important if you need to forward your SSH credentials (shown later).

To start the SSH Agent, type the following into your local terminal session:

  1. eval "$(ssh-agent -s)"
Output
Agent pid 10891

This will start the agent program and place it into the background. Now, you need to add your private key to the agent, so that it can manage your key:

  1. ssh-add
Enter passphrase for /home/demo/.ssh/id_rsa:
Identity added: /home/demo/.ssh/id_rsa (/home/demo/.ssh/id_rsa)

You will have to enter your passphrase (if one is set). Afterwards, your identity file is added to the agent, allowing you to use your key to sign in without having to re-enter the passphrase again.

Forwarding your SSH Credentials to Use on a Server

If you wish to be able to connect without a password to one server from within another server, you will need to forward your SSH key information. This will allow you to authenticate to another server through the server you are connected to, using the credentials on your local computer.

To start, you must have your SSH agent started and your SSH key added to the agent (see earlier). After this is done, you need to connect to your first server using the -A option. This forwards your credentials to the server for this session:

  1. ssh -A username@remote_host

Note: Agent forwarding should only be used on trusted servers. A compromised server can potentially use forwarded credentials.

From here, you can SSH in to any other host that your SSH key is authorized to access. You will connect as if your private SSH key were located on this server.

Secure Default SSH Configuration Baseline

Before making advanced customizations to SSH, it is important to understand what constitutes a secure default configuration. A secure baseline reduces exposure to common attacks while preserving the ability to administer the system reliably.

The default SSH configuration provided by most Linux distributions prioritizes compatibility over security. While this allows new users to connect easily, it also enables authentication methods and access patterns that are commonly abused. Establishing a secure baseline ensures that only explicitly permitted users and authentication methods are allowed.

At a high level, a secure SSH baseline for most servers should:

  • Prefer SSH key–based authentication and phase out password logins.
  • Restrict who can log in (for example, by limiting root access and using AllowUsers / AllowGroups).
  • Limit repeated authentication attempts to reduce brute-force attacks.
  • Require a restart or reload of the SSH service after configuration changes are made.

The remainder of this tutorial walks through each of these items in detail in the server-side configuration sections (PasswordAuthentication, PermitRootLogin, AllowUsers/AllowGroups, and restarting the SSH service). Use this list as a quick checklist and refer to those sections when applying the baseline on a new server. Password-based authentication is one of the most common targets for automated attacks. Even strong passwords are susceptible to repeated guessing attempts and may be reused across systems.

Once SSH key authentication has been configured and verified, password authentication no longer provides meaningful benefits. Disabling it ensures that all SSH access requires possession of a valid private key.

To disable password authentication, open the SSH daemon configuration file on the server with root or sudo privileges:

  1. sudo nano /etc/ssh/sshd_config

Locate the PasswordAuthentication directive. If it is commented out, uncomment it and set the value to no:

/etc/ssh/sshd_config
PasswordAuthentication no

This change ensures that users can only authenticate using approved SSH keys.

Ensuring Public Key Authentication Is Enabled

Public key authentication allows clients to prove their identity using cryptographic keys rather than shared secrets. This method is significantly more resistant to interception and guessing attacks.

Although public key authentication is enabled by default on most systems, explicitly defining it helps avoid unexpected behavior if configuration files are modified later.

In the same configuration file, confirm that the following directive is present:

/etc/ssh/sshd_config
PubkeyAuthentication yes

This ensures that SSH key-based authentication remains available after disabling password logins.

Disabling Direct Root Login

Allowing direct SSH access to the root account increases risk and reduces accountability. Instead, administrative access should be performed through unprivileged user accounts with sudo privileges.

To disable direct root login, locate the PermitRootLogin directive and set it to no:

/etc/ssh/sshd_config
PermitRootLogin no

This forces administrators to authenticate as individual users, creating clearer audit trails and reducing the impact of credential compromise.

Limiting Authentication Attempts and Login Time

By default, SSH allows multiple authentication attempts and provides a generous window for completing login. While this improves usability, it also gives attackers more opportunities to guess credentials or test keys.

Limiting the number of authentication attempts reduces the effectiveness of repeated login attempts. Reducing the login grace period limits how long unauthenticated connections can remain open.

Add or adjust the following directives:

/etc/ssh/sshd_config
MaxAuthTries 3
LoginGraceTime 30

These settings restrict the number of failed attempts per connection and shorten the time allowed for authentication.

Explicitly Controlling Which Users Can Connect

On many systems, any local user account can attempt to connect over SSH by default. This behavior is unnecessary in most environments and increases exposure.

Explicitly defining which users or groups are allowed to connect ensures that only intended accounts can use SSH, even if additional system users exist.

You can do this using the AllowUsers or AllowGroups directive. For example:

/etc/ssh/sshd_config
AllowUsers demo admin

Alternatively, access can be controlled using groups with the AllowGroups directive. Both approaches reduce the number of accounts that can attempt SSH authentication.

Applying Changes Safely

After making changes to the SSH configuration file, restart the SSH service to apply them.

On Ubuntu and Debian-based systems:

  1. sudo systemctl restart ssh

On CentOS and Fedora-based systems:

  1. sudo systemctl restart sshd

Before closing your existing session, open a new terminal window and verify that you can still log in using SSH keys. Keeping an active session open while testing helps prevent accidental lockout.

Establishing a Strong Baseline

These settings form a secure starting point for most SSH deployments. Additional hardening can be applied based on specific requirements, but a well-defined baseline ensures that unnecessary access paths are closed early.

By configuring SSH to use key-based authentication, restricting privileged access, and limiting authentication behavior, you reduce the attack surface while maintaining reliable administrative access.

Server-Side Configuration Options

This section contains some common server-side configuration options that can shape the way that your server responds and what types of connections are allowed.

Disabling Password Authentication

If you have SSH keys configured, tested, and working properly, it is probably a good idea to disable password authentication. This will prevent any user from signing in with SSH using a password.

To do this, connect to your remote server and open the /etc/ssh/sshd_config file with root or sudo privileges:

  1. sudo nano /etc/ssh/sshd_config

Inside the file, search for the PasswordAuthentication directive. If it is commented out, uncomment it. Set it to no to disable password logins:

/etc/ssh/sshd_config
PasswordAuthentication no

After you have made the change, save and close the file. To implement the changes, you should restart the SSH service.

On Ubuntu/Debian:

  1. sudo systemctl restart ssh

On CentOS/Fedora:

  1. sudo systemctl restart sshd

Now, all accounts on the system will be unable to log in with SSH using passwords.

Changing the Port that the SSH Daemon Runs On

Some administrators suggest that you change the default port that SSH runs on. This can help decrease the number of authentication attempts your server is subjected to from automated bots.

To change the port that the SSH daemon listens on, you will have to log in to your remote server. Open the sshd_config file on the remote system with root privileges, either by logging in with that user or by using sudo:

  1. sudo nano /etc/ssh/sshd_config

Once you are inside, you can change the port that SSH runs on by finding the Port 22 specification and modifying it to reflect the port you wish to use. For instance, to change the port to 4444, put this in your file:

/etc/ssh/sshd_config
#Port 22
Port 4444

Save and close the file when you are finished. To implement the changes, you must restart the SSH daemon.

On Ubuntu/Debian:

  1. sudo systemctl restart ssh

On CentOS/Fedora:

  1. sudo systemctl restart sshd

Note: Changing the SSH port can reduce automated scanning noise, but it should not be relied on as a primary security measure. Proper authentication controls and firewall rules are far more important.

After the daemon restarts, you will need to authenticate by specifying the port number (demonstrated in an earlier section).

Limiting the Users Who can Connect Through SSH

To explicitly limit the user accounts who are able to log in through SSH, you can take a few different approaches, each of which involve editing the SSH daemon config file.

On your remote server, open this file now with root or sudo privileges:

  1. sudo nano /etc/ssh/sshd_config

The first method of specifying the accounts that are allowed to log in is using the AllowUsers directive. Search for the AllowUsers directive in the file. If one does not exist, create it anywhere. After the directive, list the user accounts that should be allowed to login through SSH:

/etc/ssh/sshd_config
AllowUsers user1 user2

Save and close the file. Restart the daemon to implement your changes.

On Ubuntu/Debian:

  1. sudo systemctl restart ssh

On CentOS/Fedora:

  1. sudo systemctl restart sshd

If you are more comfortable with group management, you can use the AllowGroups directive instead. If this is the case, just add a single group that should be allowed SSH access (we will create this group and add members momentarily):

/etc/ssh/sshd_config
AllowGroups sshmembers

Save and close the file.

Now, you can create a system group (without a home directory) matching the group you specified by typing:

  1. sudo groupadd -r sshmembers

Make sure that you add whatever user accounts you need to this group. This can be done by typing:

  1. sudo usermod -a -G sshmembers user1
  2. sudo usermod -a -G sshmembers user2

Now, restart the SSH daemon to implement your changes.

On Ubuntu/Debian:

  1. sudo systemctl restart ssh

On CentOS/Fedora:

  1. sudo systemctl restart sshd

Disabling Root Login

It is often advisable to completely disable root login through SSH after you have set up an SSH user account that has sudo privileges.

To do this, open the SSH daemon configuration file with root or sudo on your remote server.

  1. sudo nano /etc/ssh/sshd_config

Inside, search for a directive called PermitRootLogin. If it is commented, uncomment it. Change the value to “no”:

/etc/ssh/sshd_config
PermitRootLogin no

Save and close the file. To implement your changes, restart the SSH daemon.

On Ubuntu/Debian:

  1. sudo systemctl restart ssh

On CentOS/Fedora:

  1. sudo systemctl restart sshd

Allowing Root Access for Specific Commands

There are some cases where you might want to disable root access generally, but enable it in order to allow certain applications to run correctly. An example of this might be a backup routine.

Warning: Forced commands executed as root should be used sparingly and audited carefully. Where possible, prefer using a dedicated unprivileged user with sudo permissions restricted to the required command.

This can be accomplished through the root user’s authorized_keys file, which contains SSH keys that are authorized to use the account.

Add the key from your local computer that you wish to use for this process (we recommend creating a new key for each automatic process) to the root user’s authorized_keys file on the server. We will demonstrate with the ssh-copy-id command here, but you can use any of the methods of copying keys we discuss in other sections:

  1. ssh-copy-id root@remote_host

Now, log in to the remote server. We will need to adjust the entry in the authorized_keys file, so open it with root or sudo access:

  1. sudo nano /root/.ssh/authorized_keys

At the beginning of the line with the key you uploaded, add a command= listing that defines the command that this key is valid for. This should include the full path to the executable, plus any arguments:

/root/.ssh/authorized_keys
command="/path/to/command arg1 arg2" ssh-rsa ...

Save and close the file when you are finished.

Now, open the sshd_config file with root or sudo privileges:

  1. sudo nano /etc/ssh/sshd_config

Find the directive PermitRootLogin, and change the value to forced-commands-only. This will only allow SSH key logins to use root when a command has been specified for the key:

/etc/ssh/sshd_config
PermitRootLogin forced-commands-only

Save and close the file. Restart the SSH daemon to implement your changes.

On Ubuntu/Debian:

  1. sudo systemctl restart ssh

On CentOS/Fedora:

  1. sudo systemctl restart sshd

Forwarding X Application Displays to the Client

The SSH daemon can be configured to automatically forward the display of X applications on the server to the client machine. For this to function correctly, the client must have an X server installed and running, and the server may require the xauth package for X11 forwarding to function correctly.

To enable this functionality, log in to your remote server and edit the sshd_config file as root or with sudo privileges:

  1. sudo nano /etc/ssh/sshd_config

Search for the X11Forwarding directive. If it is commented out, uncomment it. Create it if necessary and set the value to “yes”:

/etc/ssh/sshd_config
X11Forwarding yes

Save and close the file. Restart your SSH daemon to implement these changes.

On Ubuntu/Debian:

  1. sudo systemctl restart ssh

On CentOS/Fedora:

  1. sudo systemctl restart sshd

To connect to the server and forward an application’s display, you have to pass the -X option from the client upon connection:

  1. ssh -X username@remote_host

Graphical applications started on the server through this session should be displayed on the local computer. The performance might be a bit slow, but it is very helpful in a pinch.

Client-Side Configuration Options

In the next section, we’ll focus on some adjustments that you can make on the client side of the connection.

Defining Server-Specific Connection Information

On your local computer, you can define individual configurations for some or all of the servers you connect to. These can be stored in the ~/.ssh/config file, which is read by your SSH client each time it is called.

Create or open this file in your text editor on your local computer:

  1. nano ~/.ssh/config

Inside, you can define individual configuration options by introducing each with a Host keyword, followed by an alias. Beneath this and indented, you can define any of the directives found in the ssh_config man page:

  1. man ssh_config

An example configuration would be:

~/.ssh/config
Host testhost
    HostName your_domain
    Port 4444
    User demo

You could then connect to your_domain on port 4444 using the username demo by simply typing:

  1. ssh testhost

You can also use wildcards to match more than one host. Keep in mind that later matches can override earlier ones. Because of this, you should put your most general matches at the top. For instance, you could default all connections to not allow X forwarding, with an override for your_domain by having this in your file:

~/.ssh/config
Host *
    ForwardX11 no

Host testhost
    HostName your_domain
    ForwardX11 yes
    Port 4444
    User demo

Save and close the file when you are finished.

Keeping Connections Alive to Avoid Timeout

If you find yourself being disconnected from SSH sessions before you are ready, it is possible that your connection is timing out.

You can configure your client to send a packet to the server every so often in order to avoid this situation:

On your local computer, you can configure this for every connection by editing your ~/.ssh/config file. Open it now:

  1. nano ~/.ssh/config

If one does not already exist, add one at the top of the file, define a section that will match all hosts. Set the ServerAliveInterval to “120” to send a packet to the server every two minutes. This should be enough to notify the server not to close the connection:

~/.ssh/config
Host *
    ServerAliveInterval 120

Save and close the file when you are finished.

Disabling Host Checking

By default, whenever you connect to a new server, you will be shown the remote SSH daemon’s host key fingerprint.

The authenticity of host '111.111.11.111 (111.111.11.111)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes

This is configured so that you can verify the authenticity of the host you are attempting to connect to and spot instances where a malicious user may be trying to masquerade as the remote host.

In certain circumstances, you may wish to disable this feature.

Note: This can be a big security risk, so make sure you know what you are doing if you set your system up like this.

To make the change, the open the ~/.ssh/config file on your local computer:

  1. nano ~/.ssh/config

If one does not already exist, add one at the top of the file, define a section that will match all hosts. Set the StrictHostKeyChecking directive to no to add new hosts automatically to the known_hosts file. Set the UserKnownHostsFile to /dev/null to not warn on new or changed hosts:

~/.ssh/config
Host *
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null

You can enable the checking on a case-by-case basis by reversing those options for other hosts. The default for StrictHostKeyChecking is ask:

~/.ssh/config
Host *
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null

Host testhost
    HostName your_domain
    StrictHostKeyChecking ask
    UserKnownHostsFile /home/demo/.ssh/known_hosts

Multiplexing SSH Over a Single TCP Connection

There are situations where establishing a new TCP connection can take longer than you would like. If you are making multiple connections to the same machine, you can take advantage of multiplexing.

SSH multiplexing re-uses the same TCP connection for multiple SSH sessions. This removes some of the work necessary to establish a new session, possibly speeding things up. Limiting the number of connections may also be helpful for other reasons.

To set up multiplexing, you can manually set up the connections, or you can configure your client to automatically use multiplexing when available. We will demonstrate the second option here.

To configure multiplexing, edit your SSH client’s configuration file on your local machine:

  1. nano ~/.ssh/config

If you do not already have a wildcard host definition at the top of the file, add one now (as Host *). We will be setting the ControlMaster, ControlPath, and ControlPersist values to establish our multiplexing configuration.

The ControlMaster should be set to auto to automatically allow multiplexing if possible. The ControlPath will establish the path to control socket. The first session will create this socket and subsequent sessions will be able to find it because it is labeled by username, host, and port.

Setting the ControlPersist option to 1 will allow the initial master connection to be backgrounded. The 1 specifies that the TCP connection should automatically terminate one second after the last SSH session is closed:

~/.ssh/config
Host *
    ControlMaster auto
    ControlPath ~/.ssh/multiplex/%r@%h:%p
    ControlPersist 1

Save and close the file when you are finished. Now, we need to actually create the directory we specified in the control path:

  1. mkdir ~/.ssh/multiplex

Now, any sessions that are established with the same machine will attempt to use the existing socket and TCP connection. When the last session exits, the connection will be torn down after one second.

If for some reason you need to bypass the multiplexing configuration temporarily, you can do so by passing the -S flag with none:

  1. ssh -S none username@remote_host

Setting Up SSH Tunnels

Tunneling other traffic through a secure SSH tunnel is an excellent way to work around restrictive firewall settings. It is also a great way to encrypt otherwise unencrypted network traffic.

Configuring Local Tunneling to a Server

SSH connections can be used to tunnel traffic from ports on the local host to ports on a remote host.

A local connection is a way of accessing a network location from your local computer through your remote host. First, an SSH connection is established to your remote host. On the remote server, a connection is made to an external (or internal) network address provided by the user and traffic to this location is tunneled to your local computer on a specified port.

This is often used to tunnel to a less restricted networking environment by bypassing a firewall. Another common use is to access a “localhost-only” web interface from a remote location.

To establish a local tunnel to your remote server, you need to use the -L parameter when connecting and you must supply three pieces of additional information:

  • The local port where you wish to access the tunneled connection.
  • The host that you want your remote host to connect to.
  • The port that you want your remote host to connect on.

These are given, in the order above (separated by colons), as arguments to the -L flag. We will also use the -f flag, which causes SSH to go into the background before executing and the -N flag, which does not open a shell or execute a program on the remote side.

For instance, to connect to your_domain on port 80 on your remote host, making the connection available on your local machine on port 8888, you could type:

  1. ssh -f -N -L 8888:your_domain:80 username@remote_host

Now, if you point your local web browser to 127.0.0.1:8888, you should see whatever content is at your_domain on port 80.

A more general guide to the syntax is:

  1. ssh -L your_port:site_or_IP_to_access:site_port username@host

Since the connection is in the background, you will have to find its PID to kill it. You can do so by searching for the port you forwarded:

  1. ps aux | grep 8888
Output
1001 5965 0.0 0.0 48168 1136 ? Ss 12:28 0:00 ssh -f -N -L 8888:your_domain:80 username@remote_host 1001 6113 0.0 0.0 13648 952 pts/2 S+ 12:37 0:00 grep --colour=auto 8888

You can then kill the process by targeting the PID, which is the number in the second column of the line that matches your SSH command:

  1. kill 5965

Another option is to start the connection without the -f flag. This will keep the connection in the foreground, preventing you from using the terminal window for the duration of the forwarding. The benefit of this is that you can easily kill the tunnel by typing CTRL-C.

Configuring Remote Tunneling to a Server

SSH connections can be used to tunnel traffic from ports on the local host to ports on a remote host.

In a remote tunnel, a connection is made to a remote host. During the creation of the tunnel, a remote port is specified. This port, on the remote host, will then be tunneled to a host and port combination that is connected to from the local computer. This will allow the remote computer to access a host through your local computer.

This can be useful if you need to allow access to an internal network that is locked down to external connections. If the firewall allows connections out of the network, this will allow you to connect out to a remote machine and tunnel traffic from that machine to a location on the internal network.

To establish a remote tunnel to your remote server, you need to use the -R parameter when connecting and you must supply three pieces of additional information:

  • The port where the remote host can access the tunneled connection.
  • The host that you want your local computer to connect to.
  • The port that you want your local computer to connect to.

These are given, in the order above (separated by colons), as arguments to the -R flag. We will also use the -f flag, which causes SSH to go into the background before executing and the -N flag, which does not open a shell or execute a program on the remote side.

For instance, to connect to your_domain on port 80 on our local computer, making the connection available on our remote host on port 8888, you could type:

  1. ssh -f -N -R 8888:your_domain:80 username@remote_host

Now, on the remote host, opening a web browser to 127.0.0.1:8888 would allow you to see whatever content is at your_domain on port 80.

A more general guide to the syntax is:

  1. ssh -R remote_port:site_or_IP_to_access:site_port username@host

Since the connection is in the background, you will have to find its PID to kill it. You can do so by searching for the port you forwarded:

  1. ps aux | grep 8888
Output
1001 5965 0.0 0.0 48168 1136 ? Ss 12:28 0:00 ssh -f -N -R 8888:your_domain:80 username@remote_host 1001 6113 0.0 0.0 13648 952 pts/2 S+ 12:37 0:00 grep --colour=auto 8888

You can then kill the process by targeting the PID, which is the number in the second column, of the line that matches your SSH command:

  1. kill 5965

Another option is to start the connection without the -f flag. This will keep the connection in the foreground, preventing you from using the terminal window for the duration of the forwarding. The benefit of this is that you can easily kill the tunnel by typing CTRL-C.

Configuring Dynamic Tunneling to a Remote Server

SSH connections can be used to tunnel traffic from ports on the local host to ports on a remote host.

A dynamic tunnel is similar to a local tunnel in that it allows the local computer to connect to other resources through a remote host. A dynamic tunnel does this by simply specifying a single local port. Applications that wish to take advantage of this port for tunneling must be able to communicate using the SOCKS protocol so that the packets can be correctly redirected at the other side of the tunnel.

Traffic that is passed to this local port will be sent to the remote host. From there, the SOCKS protocol will be interpreted to establish a connection to the desired end location. This set up allows a SOCKS-capable application to connect to any number of locations through the remote server, without multiple static tunnels.

To establish the connection, we will pass the -D flag along with the local port where we wish to access the tunnel. We will also use the -f flag, which causes SSH to go into the background before executing and the -N flag, which does not open a shell or execute a program on the remote side.

For instance, to establish a tunnel on port 7777, you can type:

  1. ssh -f -N -D 7777 username@remote_host

From here, you can start pointing your SOCKS-aware application (like a web browser), to the port you selected. The application will send its information into a socket associated with the port.

The method of directing traffic to the SOCKS port will differ depending on application. For instance, in Firefox, the general location is Preferences > Advanced > Settings > Manual proxy configurations. In Chrome, you can start the application with the --proxy-server= flag set. You will want to use the localhost interface and the port you forwarded.

Since the connection is in the background, you will have to find its PID to kill it. You can do so by searching for the port you forwarded:

  1. ps aux | grep 8888
Output
1001 5965 0.0 0.0 48168 1136 ? Ss 12:28 0:00 ssh -f -N -D 7777 username@remote_host 1001 6113 0.0 0.0 13648 952 pts/2 S+ 12:37 0:00 grep --colour=auto 8888

You can then kill the process by targeting the PID, which is the number in the second column, of the line that matches your SSH command:

  1. kill 5965

Another option is to start the connection without the -f flag. This will keep the connection in the foreground, preventing you from using the terminal window for the duration of the forwarding. The benefit of this is that you can easily kill the tunnel by typing CTRL-C.

Using SSH Escape Codes to Control Connections

Even after establishing an SSH session, it is possible to exercise control over the connection from within the terminal. We can do this with something called SSH escape codes, which allow us to interact with our local SSH software from within a session.

Forcing a Disconnect from the Client-Side (How to Exit Out of a Stuck or Frozen Session)

One of the most useful features of OpenSSH that goes largely unnoticed is the ability to control certain aspects of the session from within.

These commands are executed using the ~ control character within an SSH session. Control commands will only be interpreted if they are the first thing that is typed after a newline, so always press ENTER one or two times prior to using one.

One of the most useful controls is the ability to initiate a disconnect from the client. SSH connections are typically closed by the server, but this can be a problem if the server is suffering from issues or if the connection has been broken. By using a client-side disconnect, the connection can be cleanly closed from the client.

To close a connection from the client, use the control character (~), with a dot. If your connection is having problems, you will likely be in what appears to be a stuck terminal session. Type the commands despite the lack of feedback to perform a client-side disconnect:

[ENTER]
~.

The connection should immediately close, returning you to your local shell session.

Placing an SSH Session into the Background

One of the most useful features of OpenSSH that goes largely unnoticed is the ability to control certain aspects of the session from within the connection.

These commands can be executed starting with the ~ control character from within an SSH connection. Control commands will only be interpreted if they are the first thing that is typed after a newline, so always press ENTER one or two times prior to using one.

One capability that this provides is to put an SSH session into the background. To do this, we need to supply the control character (~) and then execute the conventional keyboard shortcut to background a task (CTRL-z):

[ENTER]
~[CTRL-z]

This will place the connection into the background, returning you to your local shell session. To return to your SSH session, you can use the conventional job control mechanisms.

You can immediately re-activate your most recent background task by typing:

  1. fg

If you have multiple background tasks, you can see the available jobs by typing:

  1. jobs
Output
[1]+ Stopped ssh username@some_host [2] Stopped ssh username@another_host

You can then bring any of the tasks to the foreground by using the index in the first column with a percentage sign:

  1. fg %2

Changing Port Forwarding Options on an Existing SSH Connection

One of the most useful features of OpenSSH that goes largely unnoticed is the ability to control certain aspects of the session from within the connection.

These commands can be executed starting with the ~ control character from within an SSH connection. Control commands will only be interpreted if they are the first thing that is typed after a newline, so always press ENTER one or two times prior to using one.

One thing that this allows is for a user to alter the port forwarding configuration after the connection has already been established. This allows you to create or tear down port forwarding rules on-the-fly.

These capabilities are part of the SSH command line interface, which can be accessed during a session by using the control character (~) and “C”:

[ENTER]
~C
  1. ssh>

You will be given an SSH command prompt, which has a very limited set of valid commands. To see the available options, you can type -h from this prompt. If nothing is returned, you may have to increase the verbosity of your SSH output by using ~v a few times:

  1. [ENTER]
  2. ~v
  3. ~v
  4. ~v
  5. ~C
  6. -h
Commands:
      -L[bind_address:]port:host:hostport    Request local forward
      -R[bind_address:]port:host:hostport    Request remote forward
      -D[bind_address:]port                  Request dynamic forward
      -KL[bind_address:]port                 Cancel local forward
      -KR[bind_address:]port                 Cancel remote forward
      -KD[bind_address:]port                 Cancel dynamic forward

As you can see, you can easily implement any of the forwarding options using the appropriate options (see the forwarding section for more information). You can also destroy a tunnel with the associated “kill” command specified with a “K” before the forwarding type letter. For instance, to kill a local forward (-L), you could use the -KL command. You will only need to provide the port for this.

So, to set up a local port forward, you may type:

  1. [ENTER]
  2. ~C
  3. -L 8888:127.0.0.1:80

Port 8888 on your local computer will now be able to communicate with the web server on the host you are connecting to. When you are finished, you can tear down that forward by typing:

  1. [ENTER]
  2. ~C
  3. -KL 8888

Troubleshooting Common SSH Errors

Even with a correct SSH setup, connection issues can occur due to configuration changes, permission problems, or network conditions. Understanding how to interpret common SSH error messages makes it easier to identify the source of the problem and apply the appropriate fix.

Most SSH failures fall into a small number of categories. These usually relate to authentication, file permissions, service availability, or host verification. The following sections describe the most common errors, explain why they occur, and outline steps to resolve them.

Permission Denied (publickey)

This is one of the most common SSH errors encountered when using key-based authentication. It indicates that the server did not accept any of the authentication methods offered by the client.

This error typically occurs for one or more of the following reasons:

  • The public key is not present in the server’s authorized_keys file.
  • The client is attempting to authenticate as the wrong user.
  • File or directory permissions prevent SSH from reading the key files.
  • The server is not configured to allow public key authentication.

To begin troubleshooting, confirm that the public key exists on the server:

  1. ls ~/.ssh/authorized_keys

Next, verify the permissions on the relevant files and directories:

  1. ls -ld ~/.ssh
  2. ls -l ~/.ssh/authorized_keys

The correct permissions should be:

  • The .ssh directory must be set to 700.
  • The authorized_keys file must be set to 600.

You can correct permissions using:

  1. chmod 700 ~/.ssh
  2. chmod 600 ~/.ssh/authorized_keys

Also ensure that you are connecting as the correct user:

  1. ssh user@remote_host

If the server still rejects the connection, confirm that public key authentication is enabled in /etc/ssh/sshd_config.

Connection Refused

A “connection refused” error indicates that the SSH client was able to reach the server, but no service accepted the connection on the specified port.

This usually means one of the following:

  • The SSH service is not running.
  • SSH is listening on a different port.
  • A firewall is blocking access to the SSH port.

To check whether the SSH service is running on the server, log in through another access method and run:

  1. sudo systemctl status ssh

Or, on some systems:

  1. sudo systemctl status sshd

To verify which ports SSH is listening on:

  1. sudo ss -tlnp | grep ssh

If SSH is configured to use a non-default port, ensure that your client specifies the correct port:

  1. ssh -p port_number user@remote_host

Also confirm that any firewall rules allow inbound connections on the SSH port.

Host Key Verification Failed

This error occurs when the server’s host key no longer matches the key stored on the client. SSH treats this as a potential security risk and refuses the connection.

Common causes include:

  • The server was rebuilt or reinstalled.
  • The SSH host keys were regenerated.
  • The IP address now points to a different server.

To resolve this issue, remove the old host key entry from the client’s known_hosts file:

  1. ssh-keygen -R remote_host

After removing the entry, reconnect to the server. SSH will prompt you to verify and accept the new host key.

Always verify the new fingerprint through a trusted channel before accepting it.

Too Many Authentication Failures

This error occurs when the SSH client attempts multiple authentication methods or keys and exceeds the server’s allowed number of attempts.

This commonly happens when an SSH agent is loaded with many keys and the client offers them all sequentially.

To explicitly specify which key to use, connect with:

  1. ssh -i ~/.ssh/id_rsa user@remote_host

You can also configure your client to offer only the specified key by adding the following to your ~/.ssh/config file:

~/.ssh/config
Host remote_host
    IdentityFile ~/.ssh/id_rsa
    IdentitiesOnly yes

This prevents SSH from attempting unrelated keys and reduces authentication failures.

Using Verbose Output to Diagnose Issues

When an SSH error is not immediately clear, enabling verbose output provides detailed insight into the connection process.

To enable verbose mode, use the -v option:

  1. ssh -v user@remote_host

For additional detail, you can increase verbosity:

  1. ssh -vvv user@remote_host

Verbose output shows:

  • Which authentication methods are attempted
  • Which keys are offered and accepted or rejected
  • Where the connection process fails

This information is often essential for diagnosing complex or non-obvious SSH issues.

General Troubleshooting Approach

When troubleshooting SSH issues, it is helpful to follow a consistent process:

  1. Confirm network connectivity and port access.
  2. Verify the correct user and authentication method.
  3. Check file ownership and permissions.
  4. Review SSH client output using verbose mode.
  5. Inspect server-side logs if available.

By addressing issues methodically, most SSH problems can be resolved without requiring significant configuration changes.

FAQs

1. What is SSH used for?

SSH is used to securely connect to and manage remote systems over a network. It allows users to log in to remote servers, run commands, transfer files, and forward network traffic through encrypted connections.

SSH is commonly used for server administration, application deployment, remote troubleshooting, and secure file transfers using tools such as scp and sftp.

2. How does SSH differ from Telnet?

SSH and Telnet both provide remote command-line access, but they differ significantly in how data is handled.

Telnet transmits all data, including usernames and passwords, in plain text. This makes it vulnerable to interception and credential theft.

SSH encrypts all traffic between the client and the server. This includes authentication data and command output, protecting the connection from eavesdropping and tampering. For this reason, SSH has largely replaced Telnet in modern systems.

3. Are SSH keys more secure than passwords?

Yes, SSH keys are more secure than passwords when used correctly.

SSH keys rely on asymmetric cryptography rather than shared secrets. The private key never leaves the client system, and authentication is performed by proving possession of that key.

Passwords can be guessed, reused, or intercepted. SSH keys are resistant to brute-force attacks and cannot be derived from the public key stored on the server.

4. Where are SSH keys stored?

On the client system, SSH keys are typically stored in the ~/.ssh directory within the user’s home directory.

Common files include:

  • id_rsa, id_ed25519: private keys
  • id_rsa.pub, id_ed25519.pub: public keys

On the server, public keys are stored in the user’s ~/.ssh/authorized_keys file. Private keys should never be stored on servers.

5. What is the authorized_keys file?

The authorized_keys file is a server-side file that defines which SSH public keys are allowed to authenticate to a user account.

Each line in this file contains a single public key. When a client attempts to authenticate, the server checks this file to determine whether the presented key is authorized.

Removing a key from this file immediately revokes access for that key.

6. How do I restart the SSH service?

After making changes to the SSH configuration, the SSH service must be restarted for the changes to take effect.

On Ubuntu and Debian-based systems:

  1. sudo systemctl restart ssh

On CentOS and Fedora-based systems:

  1. sudo systemctl restart sshd

It is recommended to keep an existing SSH session open while restarting the service to avoid accidental lockout.

7. Can I use SSH on Windows?

Yes, SSH is supported on Windows.

Modern versions of Windows include the OpenSSH client and server by default. You can use SSH from PowerShell or Command Prompt using the same commands available on Linux and macOS.

Third-party clients such as PuTTY are also commonly used, but they are no longer required on recent Windows systems.

8. What port does SSH use?

By default, SSH listens on TCP port 22.

Unless configured otherwise, SSH clients will attempt to connect to port 22 automatically. If the server is configured to use a different port, the client must specify that port explicitly.

9. Is it safe to change the SSH port?

Changing the SSH port is generally safe and can reduce the volume of automated connection attempts.

However, changing the port does not provide strong security by itself. It should be used as a supplementary measure alongside proper authentication controls, such as SSH keys and restricted access.

Firewall rules must also be updated to allow traffic on the new port.

10. How do I disable password login in SSH?

Password login can be disabled by modifying the SSH daemon configuration.

Open the configuration file with root or sudo privileges:

  1. sudo nano /etc/ssh/sshd_config

Set the following directive:

/etc/ssh/sshd_config
PasswordAuthentication no

Restart the SSH service after making the change. Ensure that SSH key authentication is working before disabling password logins to avoid losing access.

Conclusion

SSH is a core tool for securely accessing and managing remote systems. Using it effectively requires more than knowing how to connect. It also involves understanding authentication, trust relationships, configuration choices, and common failure scenarios.

This article covered SSH fundamentals, key-based authentication, secure default configurations, advanced usage patterns, and practical troubleshooting. Together, these topics provide a solid foundation for using SSH safely and confidently in everyday administrative and development tasks.

With these concepts in place, SSH becomes a reliable and flexible mechanism for managing systems and accessing remote resources securely. For more SSH-related tutorials, check out the following articles:

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

Tutorial Series: Getting Started With Cloud Computing

This curriculum introduces open-source cloud computing to a general audience along with the skills necessary to deploy applications and websites securely to the cloud.

About the author(s)

Justin Ellingwood
Justin Ellingwood
Author
See author profile

Former Senior Technical Writer at DigitalOcean, specializing in DevOps topics across multiple Linux distributions, including Ubuntu 18.04, 20.04, 22.04, as well as Debian 10 and 11.

Manikandan Kurup
Manikandan Kurup
Editor
Senior Technical Content Engineer I
See author profile

With over 6 years of experience in tech publishing, Mani has edited and published more than 75 books covering a wide range of data science topics. Known for his strong attention to detail and technical knowledge, Mani specializes in creating clear, concise, and easy-to-understand content tailored for developers.

Still looking for an answer?

Was this helpful?


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Nice tut…really helpful

Very good one!!

The article says:

You can also use wildcards to match more than one host. Keep in mind that later matches can override earlier ones. Because of this, you should put your most general matches at the top.

But from the ssh_config(5) man page:

For each parameter, the first obtained value will be used. … Since the first obtained value for each parameter is used, more host-specific declarations should be given near the beginning of the file, and general defaults at the end.

So it should be the opposite :-)

Nice article…

I always forget how to use the tools provided to put my SSH key on the intended server, so I just end up manually creating the file using vim and then pasting it into the editor.

When this happen, I always forget to set the correct permissions on the ~/.ssh/ directory and the ~/.ssh/authorized_keys file on the server.

~/.ssh/ should be 700 (dwrx------) and ~/.ssh/authorized_keys should be 600 (-wr-------)

Your sshd service may refuse to use the SSH keys if their permissions are not set correctly, which forces you to set them so that your authentication is secure.

Also, and I may be wrong about this, but if you are using OS X, and your SSH private key file has the wrong permissions or is not placed inside an appropriately permissioned directory, OS X may refuse to use your private key. (I remember having this as having happened to me in the past, but I just tried to dupicate it on OS X Yosemite and it never failed on me)

One more point to make regarding permissions is user:group association. If you are making a SSH pub/priv key pair for another user, and you are doing so using root (or anything other than that users id), then you could have problems with SSH being able to use those keys for authentication. Just do a chown user:group ssh_private_key_file to set those correctly (for example: chown beau:beau ~/.ssh/id_rsa ).

Of course if you use ssh-keygen to create the SSH pub/priv key pairs and ssh-copy-id to transfer it to your server, those permissions are already set.

If you are on OS X, which doesn’t include ssh-copy-id, you should look into getting the Homebrew package manager, and use that to get a copy of ssh-copy-id.

Thanks, clear and very useful information.

wonderful article. Thanks.

An omission in this article cost me many hours. Mac users need an extra command in order to use ssh keys after generating them to a file other than the default. Mac OS X users, you need ssh-add -K <private key file name> More information found here : mac instructions

Very well written article. Very informative.

Creative CommonsThis work is licensed under a Creative Commons Attribution-NonCommercial- ShareAlike 4.0 International License.
Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.