
SSH (Secure Shell) connects to a remote cloud server via a command-line or GUI client. SSH is a network protocol that is also used by other applications like scp and rsync. Scp copies files between hosts on a network. Rsync can use ssh to transfer files and folders between a local and remote host. Rsync transfers files and folders that have changed since the last transfer. Entire projects can be efficiently backed up via rsync.
This guide explains how to configure SSH on a local host and on a remote Vultr host, including how to use the Vultr Web Console to prevent accidental login lockouts. It explains how to:
This guide uses the OpenSSH ssh command-line client that is available on most Unix-like hosts, including macOS and Linux. Use the Windows Subsystem for Linux on a Windows 10/11 PC to access the OpenSSH ssh client.
For the examples in this guide, the Vultr server FQDN hostname is ap1.example.com. The local macOS host is imac1. The local Debian host is db1.
Note: The SSH commands work the same for a macOS or Debian Linux terminal session except as noted.
You need a Vultr Account. This guide uses macOS and the Debian Linux OS to show how to use SSH. But most other Linux environments that use the OpenSSH ssh client should work. You first create a private/public SSH key on your local host and then install the public key in your Vultr Account. Then you can automatically install that SSH key when you deploy a Vultr server. Or you can install the SSH key later if you have already created the server.
You should be familiar with:
Installing command-line applications on macOS via the Homebrew brew command or the apt command on Linux.
Working with a firewall, such as UFW, to allow and disable ports.
Working with the command line.
Note: Command lines starting with $ use a non-privileged account, and commands starting with # use the root account.
Generate a modern SSH key pair with the following command:
Often the -C key comment is an email address. However, the key comment can be any text. You can set it to your hostname to manage which SSH keys belong to which host. Be sure to use a unique filename to save the key pair for each host and enter a passphrase when prompted. Use the pwgen command to generate a long and secure passphrase:
Note: Use the brew or apt command to install pwgen.
Here is a complete example:
Copy and paste your passphrase when prompted The passphrase is not visible when you enter it. Entering the filename is optional. ~/.ssh/id_ed25519 is the default filename. Create a unique key pair for each host.
Log into your Vultr account. Under your account name, click SSH Keys. Click Add SSH Key. Create a name for your SSH key. Copy and paste your public key, ~/.ssh/ap1_ed25519.pub, into the key field. Click Add SSH Key.
Deploy a new Debian 11 server. Select your SSH key in the SSH Keys section. The SSH key is automatically installed for the root user in ~/.ssh/authorized_keys
Note: You may need to wait a few minutes after the server is running for Cloud-init to complete. Open the View Console window and wait for the Cloud-init finished message.
If you have already created your server, you can select Reinstall SSH Keys under the Settings tab and (re)install your SSH key.
Note: This deletes all your data and reinstalls the server OS.
You can use ssh-copy-id to install your key on an existing server. This command installs the public SSH key in ~/.ssh/authorized_keys on your Vultr host. Before executing this command, be sure that ap1.example.com exists in your DNS data or in /etc/hosts on your local host. Enter your root password when prompted:
Note: The authenticity of host message appears the first time when connecting to the server. Answer yes to continue connecting. The example ssh command to log into the server does not work unless you use the default identity filename, ~/.ssh/id_ed25519. Please refer to the next section, Test the Public Key. If you previously used SSH to log into your server and then you reinstalled your server, you may see this error message:
Just delete the previous ap1 entry in ~/.ssh/known_hosts and run the command again.
Execute the following command to verify that you can log into your server using your SSH key:
The -i option is not required if you use the default identity name, id_ed25519. You have to enter the passphrase every time unless you use the SSH authentication agent, ssh-agent, to hold the private keys. Use the ssh-add command to store the private keys in the ssh-agent:
Note: The -K option stores the passphrase in the macOS keychain to save it over macOS restarts. It does not work with the Linux version of ssh-add. Refer to the next section, Create the Local SSH Configuration File, to see how to automatically add the passphrase to the ssh-agent after starting the first ssh session.
Both macOS and Debian Linux use the ssh-agent to store private keys. The ssh-agent starts automatically and works with the macOS keychain to store the keys. For the Debian Linux server terminal session, the ssh-agent starts for each terminal session after making the following environment changes:
Restart your local Linux terminal session after making the above changes. Use ssh-add to store the private key:
You can now connect to the server without using a passphrase during the Linux terminal session.
You can create an SSH configuration file that stores SSH options for hosts and users. This simplifies the SSH command line used to connect to the server. You can also define a host alias instead of entering the host FQDN. The SSH config file contains global and per-host options. Here is the ~/.ssh/config file for the example server:
Note: For Linux, delete the UseKeychain option.
The Host * line defines the global options. The AddKeysToAgent option adds the private keys to the ssh-agent. The macOS only UseKeychain option adds the passphrase to the macOS keychain. The IdentitiesOnly option limits the authentication entity to the one defined by the IdentityFile. The AddressFamily option specifies using IPv4 when connecting. The Host ap1.example.com ap1 line defines two host aliases for the ssh connection. It includes the FQDN and the short hostnames. The next lines define the DNS FQDN host, port number, user, and the authentication identify file. The Port defaults to the standard port 22 if not specified, but the option can define a non-standard port number. The User option defines a default user if the user is not specified on the ssh command line.
With this ~/.ssh/config file in place, connect to the server with the short alias name:
Enter the passphrase when making the first ssh connection to the server. The identity is automatically added to the ssh-agent:
The macOS keychain contains the passphrase. To verify, open the macOS KeyChain App, click the default login chain, and search for ap1. For Linux, the passphrase remains available during the life of the terminal session.
When connecting to the default user on the server, just do:
Note: This example assumes that the default user account is available on the server.
It's not good practice to allow the root user to log in to the server via SSH. You should use the Vultr Web Console or log in as a regular user and then switch to the root account. This maintains a log of regular users accessing the root account. Before restricting root SSH access and disabling password authentication, you need to create a regular user with sudo privileges.
Log into your root account and create the regular user and give them sudo permissions:
Give the user a secure password when prompted. Fill in the additional user information as desired. Add the user to the sudo group:
Verify that you can log into the new user account:
Installed the SSH public key for the new user:
Enter the user password when prompted.
Verify that you can log into the user account without a password:
Verify that you use sudo to change to the root account:
Enter your user password when prompted. The sudo command remembers your password for 15 minutes.
Note: For the Debian OS, the trust message prints the first time you use sudo.
You can see the root account accessed by the regular user in /var/log/auth.log:
You can also use su to access the root account:
Note: Enter the root password.
Again, you can monitor this access in the /var/log/auth.log:
Normally, you use sudo to execute individual commands that require elevated privileges.
For example:
Looking again at /var/log/auth.log:
As root, make the following changes to /etc/ssh/sshd_config:
PermitRootLogin yes to PermitRootLogin no#PasswordAuthentication yes to PasswordAuthentication no. Make sure to remove the # comment at the beginning of the line if it exists.Restart the sshd daemon:
Try to log into the root and user account from a host that does not have SSH authentication (or disable it):
Even with SSH authentication enabled, the root authentication fails:
But the user account access works:
Changing the SSH port number reduces the number of unauthorized login attempts. You can see these login attempts in the /var/log/auth.log file:
SSH uses a privileged port (less than 1024) by design. It can use any port number that is not assigned to another service. Look at /etc/services to verify unassigned port numbers. For example, to change the SSH port number to 522, do:
If the firewall is active, allow port 522:
Note: This example uses the UFW firewall, which is active on a new Vultr Debian/Ubuntu instance.
Change the port number to 522 in /etc/ssh/sshd_config and restart the sshd daemon:
Your ssh session should remain active. However, use the Vultr Web Console if disconnected and review your changes.
Verify that you cannot connect using port 22:
Update your local host ~/.ssh/config file to use port 522 for the ap1 host and verify that you can connect to the server:
If the firewall is active, disable port 22:
If you are using the Vultr Firewall, you should follow the same procedure.
Fail2ban works with the server installed firewall, for example, UFW, to ban abusive hosts that make multiple login attempts during a short interval.
Install fail2ban:
By default, SSH protection is active:
However, if you have changed the SSH port number, you need to update the fail2ban SSH configuration by creating the /etc/fail2ban/jail.local configuration file:
This example also shows how you can update the find time interval, the ban time, and the maximum number of attempts per findtime before banning the abusive host. It also includes a DEFAULT section where you can set global options like IP addresses to ignore. You can set ignoreip to your SSH source IP to prevent accidental lockouts. Restart fail2ban after making these changes:
Note: If you forget the ignoreip DEFAULT section like I did, log into your Vultr View Console window and execute the unban command noted below.
Any banned IPs are still banned after the restart. The status commands lists the banned IPs:
You can unban an IP address before the ban time has expired with the following command:
Use the status command to verify the unban status. You can also view the status history in the fail2ban log file:
Fail2ban restores the banned status after restarting the fail2ban service. The log file notes the unbanned status after executing the command to unban the IP address. This fail2ban failed/banned login example used SSH port 22. After changing the SSH port number, the number of failed login attempts are typically lower.
SSH agent forwarding enables you to access server B from server A with your server-B private SSH key stored on your local host. An example use would be logging into server A, the ap1 server, and making a pull request from GitHub.com. You do not have to store your GitHub SSH keys on the remote server to access GitHub. The remote server uses SSH agent forwarding to retrieve the GitHub SSH keys from the SSH agent on the local host. SSH forwarding must be explicitly enabled for the remote server. Here is an example using GitHub and the ap1 server that shows how to configure SSH agent forwarding.
If you have not already created and installed SSH keys for GitHub, do:
Save your GitHub keys at ~/.ssh/GitHub and use a secure passphrase.
Add your GitHub SSH private key to the SSH agent on the local host.
You can list the SSH keys stored in the SSH agent with this command:
Install your GitHub public SSH key using the GitHub Setting page.
Add the GitHub SSH configuration in your ~/.ssh/config file:
Verify that your GitHub SSH keys are working from your local host:
Note: You cannot log into GitHub via SSH, but you can test that your SSH authentication is working.
Enable SSH agent forwarding in your SSH ~/.ssh/config file for the ap1 host:
Log into your remote ap1 server and verify that SSH agent forwarding is working:
The remote server receives the GitHub authentication request and forwards it to the SSH agent on the local host. The authentication request is successful. If you try to connect to GitHub from a remote host that does not have SSH agent forwarding enabled, you see this error:
SSH agent forwarding does not work for the root account because SSH access is off for the root account:
By design, the root account cannot forward the SSH request to the local host.
You can use SSH tunneling or port forwarding to create an encrypted SSH connection to access a remote service from a local host. Or you can create a reverse SSH tunnel where the remote host can access a service running on your local host even if your local host is on a local network behind a Network Address Translation (NAT) router.
The following example shows how to create an SSH tunnel to use a local MariaDB client to access a remote MariaDB service. The local client connects on port 3307 to avoid conflicts with the local MariaDB server. The remote MariaDB server listens on port 3306. A remote dbadmin user with a password exists on the remote MariaDB server.
This SSH command creates the tunnel for the MariaDB service between the local host and the ap1 server:
This command creates a non-interactive tunnel from the local host on port 3307 to the remote host at 127.0.0.1:3306. This SSH command runs in the foreground and displays any errors that occur. You can add the -f option to run the tunnel in the background.
In a new local host shell window, install and run the local MariaDB client:
As noted above, the local macOS MariaDB client connects to the remote Debian MariaDB server.
The following example shows how to create a reverse SSH tunnel to access a service on the local host from the remote host. The local host is running a Hugo web server on port 1313. The remote host is using the Lynx text web browser on port 8080.
Note: You can follow the Hugo Quick Start guide to create a Hello, World Hugo test site.
This SSH command creates the reverse tunnel between the local host and the ap1 server:
This command creates the non-interactive reverse tunnel from the remote host on port 8080 to the local host, 127.0.0.1, on port 1313. This SSH command runs in the foreground and displays any errors that occur. You can use the netstat command on the remote host to verify that the sshd daemon is listening on port 8080:
Start the Hugo web server, or other local service, on the local host:
The Hugo web server is listening on 127.0.0.1:1313.
On the ap1 remote host install the lynx web browser and access the local host Hugo web server:
This opens a text window in the remote shell session displaying the Hugo web server content.
If the Hugo web server is not running, the local shell session running the SSH tunnel displays an error message:
Again, disabling SSH access for the root user, disables SSH tunneling for the root user:
Scp securely copies files between hosts using ssh for the data transfer. With the remote host alias defined in ~/.ssh/config, remote file references start with alias:. This is the example ap1 local SSH configuration in ~/.ssh/config:
This config file defines two host aliases--a long and short form.
This scp command copies a file from the local host to the remote host, relative to the user george home directory, to the ~/backup directory:
This scp command copies and renames the file:
Use scp to copy remote files to the local host:
Rsync can use the SSH protocol to transfer files and folders between hosts. It uses the same host alias specification defined in the SSH config file. It uses SSH when the source or destination host specification contains a single colon (:) separator. You can use rsync to backup a user's home file sytem:
The options are:
-a: archive mode-v: increase verbosity--delete: delete extraneous files from dest dirsAnother useful option is --exclude=PATTERN. This option excludes copying files and folders that match a PATTERN.
Rsync copies files and folders that have changed:
For this example, the files and folders on the remote and local hosts are the same. It did not need to copy any files. Refer to the rsync manual page for additional backup examples and usage. One detail to note is the last folder name in the path to copy. The example shows the george folder and its content copied. If the last folder name ends with a trailing slash (/), it only copies the folder content.
Vultr has other featured SSH articles if you'd like to learn more.
Here are other helpful SSH resources:
0 Comments
Be the first to comment and share your perspective with the community.