Skip to main content

SSH - Access your server remotely

·12 mins
Recommended basics: Articles you should know

To get the full picture of this article, you should know about this topics:

(optional)

Effortless Website Hosting on a Budget with Namecheap

Discover how to effortlessly host your website on a small budget with Namecheap's shared hosting. Explore the process from selecting a plan to configuring SSL, and learn to upload your site for a seamless online presence.
(optional)

File Transfer Protocol (FTP)

Discover how to efficiently upload multiple files of various sizes and types to remote storage using the File Transfer Protocol (FTP). This guide covers both graphical and command-line FTP clients, making it perfect for developers, sysadmins, and self-hosters.

You may also want to use the content map to find interesting articles that play into this one.


If you want to access your server from a remote location (e.g. your computer), SSH will be the tool of your choice. Follow me in this article to understand SSH basics, prevent common pitfalls and ensure you’re using it in a secure way.

Configuring SSH the right way should be one of the very first things you do when setting up a server.

How to setup your (first) VPS in 6 clicks only:

What is SSH (Secure Shell)? #

When you’re into development or administration, sooner or later you need to do something on a remote computer / server. Often, remote means, you cannot physically go to that computer and do whatever you’re supposed to do. Maybe that computer not even has keyboard or monitor. So what now?

You can connect to that server to use your local computer and run any command as if you you would run it on your local computer.

While it’s great that we have such tools in place it comes with a risk of attackers getting access to your server and do things you don’t want them to do.

Can SSH only be used with own Servers / VPS? #

SSH can be used even if you don’t host your own VPS. Maybe you just have your own shared webhosting, some providers (like Namecheap) offer SSH access there as well.

Effortless Website Hosting on a Budget with Namecheap

Discover how to effortlessly host your website on a small budget with Namecheap's shared hosting. Explore the process from selecting a plan to configuring SSL, and learn to upload your site for a seamless online presence.

Also, you can use SSH to clone Git repositories.

Git - Distributed version control

Learn how to use Git for effective version control, track changes, and collaborate seamlessly. This guide covers essential Git commands and concepts - a perfect starting point.

As you see, SSH can be used in more scenarios then just to access your remote server.

Receive high-quality, ad-free updates on software development. Sign up for our free newsletter today!

Can SSH only be used for command execution? #

Beside remote command execution, I tend to use SSH for file transfer. I do this by configuring rclone to use sftp as connection method. This way I can push many files very fast and I can even sync, instead of copy, directories.

How to transfer files to shared hosting fast (e.g. using rclone with sftp):

File Transfer Protocol (FTP)

Discover how to efficiently upload multiple files of various sizes and types to remote storage using the File Transfer Protocol (FTP). This guide covers both graphical and command-line FTP clients, making it perfect for developers, sysadmins, and self-hosters.

Do I use SSH with username and password, similar to the operating system login? #

While you absolutely could do this, for security reasons you shouldn’t. This is because attackers could run attacks against your Server and at some time be able to login (simplified speaking).

So what do use instead?

What is an SSH key and why use it instead? #

The most simple description of a private key probably is a very long password, that never ever would leave your device. But how would the remote server than check that it’s correct?

Asymmetric encryption in SSH #

I’ll not cover mathematics, but at least the rough idea: SSH keys rely on asymmetric encryption, where you have a public and a private key. You need to share the public key with others, but you’ll never share the private key with anybody.

Public key - encrypt data #

As said, you can or even need to share the public key with the services, you want to connect to.

The public key is used to encrypt data. Once encrypted you cannot decrypt that data using the public key. To decrypt such data, you’d need the correct private key.

Private key - decrypt data #

As said, you never share the private key (as you can guess by the name). I’m serious, do not share that key with anybody. Store it in a safe place.

The private key is used to decrypt data, that was encrypted with the matching public key. That means private and public key always come up as a pair. You cannot exchange one part of them, you always would need to replace both.

How SSH authenticates with keys #

Having public and private keys in mind, it’s almost simple:

  1. You open the connection to the server
  2. With that, you send your public keys
  3. Server checks if it knows one of the public keys
  4. If so, it does create a random string (called challenge), encodes it (using that public key) and sends it back to you
  5. Using the private key (that’s just on your device) you decrypt that data and send it back
  6. Server checks if what you sent back is what he encrypted for you
  7. The connection if successful if both values do match
Receive high-quality, ad-free updates on software development. Sign up for our free newsletter today!
sequenceDiagram You->>Server: Hi, here's my keys Server->>Server: Checks if a known key exists Server->>Server: Generates a challenge and encodes it (public key) Server->>You: Sends the challenge You->>You: Decode the challenge (private key) You->>Server: Send decoded challenge Server->>Server: Compares challenge

As you can see, this is a system where nobody needs to trust anybody else. Nobody has the private key except you and nobody can do what you could, using the public key you shared with them.

Even if a service that holds your public key would get hacked, so that someone else now has your public key, that doesn’t pose any risk to you. That’s a whole different story for username/password authentication methods.

How to generate SSH keys? #

You probably wonder, where to get these SSH keys? If you think about that, esp. the private key, there’s just one way: You generate them yourself. Only this way your private key wouldn’t leave your device.

You should simply use your computers shell / terminal to generate the keys. Try this command:

1
ssh-keygen -t ed25519 -C "some helpful comment to identify the key"

If you deal with some older installations / legacy systems, you can pick another encryption method, probably:

1
ssh-keygen -t rsa -b 4096 -C "some helpful comment to identify the key"

The command now will guide you through the process, usually you can leave everything as default and a keypair will be generated.

The keypair consists of two files that have the same name, but a different ending. The private key for example could be called id_ed25519 and the matching public key then will be id_ed25519.pub. By default, keys will be put into the .ssh folder in your users home directory (~/.ssh).

What’s inside an SSH key file? #

SSH keys are files, as you can see. Let’s view the files content.

IMPORTANT: Do not use these keys since I made them public here.

Public key (id_ed25519.pub):

1
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE24M4oSlIHUsisLzR75hbU5nGOEsknMHIPwGeywrbV2 some helpful comment to identify the key

Private key without passphrase (id_ed25519):

1
2
3
4
5
6
7
8
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACBNuDOKEpSB1LIrC80e+YW1OZxjhLJJzByD8BnssK21dgAAALDwkp0I8JKd
CAAAAAtzc2gtZWQyNTUxOQAAACBNuDOKEpSB1LIrC80e+YW1OZxjhLJJzByD8BnssK21dg
AAAEAZmrGEksI+7FingeWuqV8N3t3lzLIGkJTPqP4KfxVXsE24M4oSlIHUsisLzR75hbU5
nGOEsknMHIPwGeywrbV2AAAAKHNvbWUgaGVscGZ1bCBjb21tZW50IHRvIGlkZW50aWZ5IH
RoZSBrZXkBAgMEBQ==
-----END OPENSSH PRIVATE KEY-----

I willingly replaced a character in the private key, so that the keypair is invalid and cannot be used by anybody. Never use publicly available keys. They are not private anymore.

What is a passphrase? #

During generation of a keypair, you’ll get asked to define a passphrase. The idea is to use this value, to encrypt the private key on your device, so even if it get’s stolen, nobody can use that file.

The small drawback is that everytime you wanna use that private key, you need to put in this passphrase. And if you ever forget it, there’s no way to reset it. At the end it’s up to you.

I regenerated the SSH keypair using a passphrase, now the private key looks like this:

1
2
3
4
5
6
7
8
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB0hrIaUf
9+wC2wnyazC3cMAAAAGAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAICVVhN3bXtBsS8de
80qnSPVyaD468SZ9Ay9VcofTOqUrAAAAsOEqcNuavpC+luyXuT2HaVJhDsAuQYlzmZCrtW
I4j/Af58uxs+6I5iMlbpCjsSiix/UMeZpz1Ah+lAeqJpU8GsL9UOIzZl6gXX86nQx5X1ct
JyDmNmMUguzbwzovwgL+uHqSGEmLjibOsEVQfMq7sU4YO9hhX0u1sBpkN8QEgVyBQDAKfX
H3SNsen8fBa5ld+1p8+PtCa3RQjIpvHH/Cfc61miWvkgGfoUab8yjKAlSS
-----END OPENSSH PRIVATE KEY-----

Remember: The passphrase is just used to encrypt the private key. The public key hasn’t changed, it is still readable so you can share it easily.

Demo: Encrypt / Decrypt data using public / private key. #

Let’s give it some test. Let’s act like being an SSH Server: We create a challenge, encrypt it with the public key and try to decrypt it using the private key.

I’ll use age as a command line tool to do that. It is simpler to understand and does come with native ed25519 support.

Encrypt a file using public key #

First, we need a file. Let’s quickly create it with some nice content:

1
echo "https://reliable.codes > original.txt"

Next, let’s encrypt it:

1
age --encrypt --recipients-file ~/.ssh/id_ed25519.pub --output encrypted.txt original.txt

Let’s break this down:

  1. We call age
  2. We ask it to encrypt something (using --encrypt)
  3. We specify the public key to use (using --recipients-file ~/.ssh/id_ed25519.pub)
  4. We tell it where to write the encrypted data to (using --output encrypted.txt)
  5. Finally, we tell it what to encrypt (original.txt in our case)

Now, let’s lookup that file:

> cat encrypted.txt
age-encryption.org/v1
-> ssh-ed25519 UY5WyQ qSeIeLKzFl1wLy1qMJinynDpE5ESPF+FIVUKEztihSk
W6Ut1FPUhHpH7A32lTDkU5MRqf3CERjn2MuqVL2Y61A
--- +B6bUg/WJNSDNaXP67saU6OYkcXLM+W8hTlTVybF2zI
���P�x��.�9	��>~��>��n���)e�[�j �R���u�E/4%

Well, that’s hard to read, I’d say.

Decrypt a file using private key #

As of our process, this data would be sent over to the client, which needs to decrypt it. Let’s try and find out:

1
age --decrypt --identity ~/.ssh/id_ed25519 --output decrypted.txt encrypted.txt

If you now review the decrypted files content, you’ll see:

> cat decrypted.txt
https://reliable.codes

That worked pretty good, I’d say.

Receive high-quality, ad-free updates on software development. Sign up for our free newsletter today!

How to add an public key to a server? #

Before you can use your SSH key, you must tell the server about your public key. Think of it like a “whitelist”. Whoever is on in, has a chance to let be through, but if your key is not on the list, you have no chance.

This “whitelist” is managed by the authorized_keys file which is located within the .ssh folder in your users home directory (~/.ssh).

This means: You don’t add public keys to servers, but to users.

The file is pretty simple: Every line holds a new public key. If I would have a fresh server, and just would add the key generated earlier, it would look like this:

1
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINXTc3bsWmnjv/+mZLt6Xp93hFDfpT08BXoy2jGiD7Up some helpful comment to identify the key

Now you see why that comment that we specified before is useful even if it has no technical impact. If you run that server for some time and probably use multiple tools to do stuff, you end up in multiple entries to that file. When it’s time to clean up, you need a way to identify, what entries you want to be gone and which needs to survive.

The simplest way to add public keys is pushing it using SSH. Either with an already existing SSH key or with username and password, if you have a freshly set up server. Pro tip: With some VPS providers (like Hetzner), you can define the SSH keys directly in the setup. I’ll show this in the upcoming sections.

On my fresh server there’s just the root user, so I push my key using that users credentials:

1
ssh-copy-id -i $HOME/.ssh/id_ed25519 root@2a01:4f9:c013:2907::1

Let’s break this down:

  1. We call ssh-copy-id
  2. We tell it to use our private key (see $HOME/.ssh/id_ed25519)
  3. We tell it to connect as user root (see root@)
  4. We tell it to connect to 2a01:4f9:c013:2907::1 (see @2a01:4f9:c013:2907::1)

I have a IPv6 only VPS here, you can replace the IPv6 with any IPv4, the command doesn’t change.

Whenever you do the first connection to a remote server, SSH will show you a fingerprint and ask if you trust that server.

1
2
3
4
The authenticity of host '2a01:4f9:c013:2907::1 (2a01:4f9:c013:2907::1)' can't be established.
ED25519 key fingerprint is SHA256:s8n40qsX1+qQrRdOnt4Vu/SXKqokilsqXV4TQZSaVcs.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

I have a fresh server, so I accept the fingerprint (type yes and hit return). Now SSH will ask you for a password. Once you send the correct password, you’re logged into the system. Now you’re working as the given user (root in my case) on that server.

The command should exit immediately with a success message.

How to connect to a server via SSH using a private key? #

Connecting to a server using a private key is almost identical to the command not using a private key:

1
ssh -i $HOME/.ssh/id_ed25519 root@2a01:4f9:c013:2907::1

As you can see, with only adding -i argument we can specify the private key to use for this connection. Also, now there’s no password that you need to put in, you’re directly logged in.

How to restrict SSH connections to private key only? #

It’s quiet cool to use SSH keys to connect to servers AND it’s safe. But you must not confuse the “ability” to use SSH keys with “the only option”. Your VPS by default still accepts connections without SSH keys, after adding your public key, you really should consider to enforce SSH keys.

Important: Ensure that you have a valid private key and you can connect to your VPS before enforcing SSH keys.

Often it now get’s recommended to modify /etc/ssh/sshd_config, but I’d rather create a /etc/ssh/sshd_config.d/01-ssh-key.conf with the following content:

PasswordAuthentication no
PermitEmptyPasswords no
PubkeyAuthentication yes
ChallengeResponseAuthentication no

Now save the file and restart the SSH server (this is important to apply the new file):

1
systemctl restart sshd

From this point on, you shouldn’t be able to connect any longer using username/password. If you ever want to revert that decision, you can now simply delete that file again, restart sshd and you’re fine.

Receive high-quality, ad-free updates on software development. Sign up for our free newsletter today!

Simplify VPS setup by directly using SSH keys #

During the few-click-setup of new Servers in Hetzner cloud console, you can easily have your SSH key pre-installed. And you don’t even need to enter it. How cool is that?

First (and just once), go to the Security settings in that project (lefthand menu, last item):

Show SSH keys for project in Hetzner cloud console
Show SSH keys for project in Hetzner console

Now click “Add SSH key” and put in your public key (if suitable, check “default key” checkbox):

Add SSH Key to project in Hetzner cloud console
Add SSH Key to project in Hetezner cloud console

Now during the setup of the new Server, you can simply click the SSH key (default keys are preselected) and it’s directly added on the root user of that server.

Setup new server in Hetzner cloud project, directly with SSH keys
Setup new server in Hetzner cloud project, directly with SSH keys

Remember: You still need to enforce SSH key logins only (see above) to prevent users/attackers from using username/password.

Conclusion #

SSH provides us with a easy and safe way, to access our server remotely. We can use it to run commands (e.g. for maintenance) but also for other use-cases like file transfer or cloning git repositories and more.

It’s always cool to ease up our life, as long as it’s safe. So please enforce SSH keys on your servers to stay safe.