# SSH Keys and Secure Server Access

- Link: https://offshorehosting.pk/ssh-keys-and-secure-server-access/
- Published: 2026-10-25T10:24:00+00:00
- Author: admin

# SSH Keys and Secure Server Access

SSH (Secure Shell) is how you administer a Linux server remotely. Every login, every
file transfer and every command runs through it. If SSH is protected only by a password,
an attacker anywhere in the world can try to guess that password thousands of times
a day — and automated bots do exactly that, within minutes of a new server going
online.

SSH keys solve this. Instead of a password, you prove your identity with cryptography:
a private key that never leaves your computer, and a public key stored on the server.
The server challenges your computer, your computer answers using the private key,
and the mathematics makes guessing infeasible. This guide explains how keys work,
how to set them up correctly, and how to manage them safely.

## How SSH Keys Work

A key pair has two parts:

 * **The private key** (`~/.ssh/id_ed25519`) stays on your computer. It is secret.
   Anyone who has it can log in as you. It should be protected with a passphrase
   and never shared, emailed or uploaded anywhere.
 * **The public key** (`~/.ssh/id_ed25519.pub`) goes on the server, in the file `
   ~/.ssh/authorized_keys`. It is not secret — it is designed to be shared. It can
   only be used to verify that someone holds the matching private key; it cannot
   be used to log in by itself.

When you connect, the server checks whether your public key is in `authorized_keys`.
If it is, the server sends a challenge that only the holder of the private key can
answer. Your SSH client answers it automatically. No password crosses the network,
and there is nothing for a brute-force attack to guess.

## Step 1: Generate a Key Pair

On your own computer (not on the server), generate an Ed25519 key. Ed25519 is the
modern standard: it is faster and more secure than RSA, and it is the recommended
default in current OpenSSH versions. RSA with 4096 bits is the fallback if Ed25519
is not supported by an older system.

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

You will be asked where to save the key — accept the default (`~/.ssh/id_ed25519`)
unless you have a reason to use a different name — and then asked for a passphrase.**
Set a passphrase.** It encrypts the private key on your disk, so that even if someone
steals the file, they cannot use it without the passphrase. Use a strong passphrase
and store it in a password manager. (For automated scripts that must log in without
a human present, a passphrase-less key is sometimes necessary — but that key should
be restricted to a single purpose and a single command, and kept on a secured machine.)

The command creates two files:

    ```bash
    ls -l ~/.ssh/
    # -rw-------  id_ed25519      (private key — 600 permissions, only you can read it)
    # -rw-r--r--  id_ed25519.pub  (public key — safe to share)
    ```

If the private key’s permissions are ever more open than `600`, SSH will refuse 
to use it. Fix it with `chmod 600 ~/.ssh/id_ed25519`.

## Step 2: Copy the Public Key to the Server

The simplest method is `ssh-copy-id`, which appends your public key to the server’s`
authorized_keys` file and sets the permissions correctly:

    ```bash
    ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your-server-ip
    ```

You will be asked for your password one last time. After that, the key is installed.

If `ssh-copy-id` is not available, you can do it manually:

    ```bash
    cat ~/.ssh/id_ed25519.pub | ssh user@your-server-ip \
      "mkdir -p ~/.ssh && chmod 700 ~/.ssh && \
       cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
    ```

The permissions matter: `~/.ssh` must be `700` (only you can access it) and `authorized_keys`
must be `600`. If they are looser, the SSH server will ignore the key file and fall
back to asking for a password — a common cause of “key not working” problems.

## Step 3: Test Key Login Before Changing Anything

Test the key now, in a new terminal window, while your existing session is still
open:

    ```bash
    ssh -i ~/.ssh/id_ed25519 user@your-server-ip
    ```

If you set a passphrase, you will be asked for it — that is the key’s passphrase,
not the server password. If you log in without a password prompt, key authentication
is working.

If it does not work, check in order: the key file permissions on your computer, 
the `~/.ssh` and `authorized_keys` permissions on the server, and whether the public
key in `authorized_keys` is complete and on a single line. Running the client with`
ssh -v` shows verbose output that usually identifies the problem.

**Do not proceed to the next step until key login works.** The next step removes
password login, and if the key does not work, you will be locked out.

## Step 4: Disable Password Authentication

Once key login is confirmed, disable password authentication on the server. Edit`/
etc/ssh/sshd_config` (with sudo) and set:

    ```
    PasswordAuthentication no
    ChallengeResponseAuthentication no
    PubkeyAuthentication yes
    PermitRootLogin no
    ```

Then validate the configuration and restart SSH:

    ```bash
    sudo sshd -t
    sudo systemctl restart ssh
    ```

`sshd -t` checks the configuration for syntax errors before you restart — a mistyped
directive could otherwise prevent SSH from starting at all.

**Warning:** from this point on, losing your private key means losing access to 
the server. Keep a secure backup of the private key (for example, in a password 
manager or an encrypted drive), and make sure you know how to reach your hosting
provider’s console access, which is the recovery path if all else fails. If your
provider offers console access, test that you can reach it before you need it.

## Step 5: Harden Further

Key-only authentication removes the biggest risk. These additional steps reduce 
the rest:

 * **Restrict which users can log in.** Add `AllowUsers deploy` (or your username)
   to `sshd_config` so that only named accounts can connect, even with a valid key.
 * **Restrict by source IP where possible.** If you always connect from one office
   or home address, a firewall rule allowing SSH only from that address closes the
   port to the rest of the internet. In UFW: `sudo ufw allow from 203.0.113.10 to
   any port 22 proto tcp` (replace the example address with your own).
 * **Consider a non-standard port.** Changing the SSH port from 22 to something 
   else does not add real security — an attacker can scan for it — but it dramatically
   reduces the volume of automated login attempts in your logs, which makes real
   problems easier to spot. If you change the port, update the firewall rule and
   your SSH configuration at the same time, and test before closing your current
   session.
 * **Use fail2ban.** Even with keys only, fail2ban blocks IP addresses that repeatedly
   fail to authenticate, keeping logs clean and resources free. See [a beginner VPS security checklist](https://offshorehosting.pk/blog/a-beginner-vps-security-checklist).
 * **Use an SSH agent.** `ssh-agent` holds your decrypted key in memory so you enter
   the passphrase once per session instead of once per connection. Start it with`
   eval "$(ssh-agent -s)"` and add your key with `ssh-add ~/.ssh/id_ed25519`. Be
   cautious with agent forwarding (`-A`): it exposes your agent to the remote server,
   and should only be used with servers you fully trust.
 * **For high-security setups, consider hardware keys.** OpenSSH supports FIDO2 
   security keys (`ssh-keygen -t ed25519-sk`), which store the private key on a 
   physical device such as a YubiKey. The key cannot be copied off the device at
   all.

## Managing Keys Over Time

Keys are credentials, and they need lifecycle management:

 * **One key per device, or per person.** Do not share a single private key across
   a team. Each person generates their own key pair, and you add each person’s public
   key to the server. When someone leaves, remove their public key from `authorized_keys`—
   that is the entire revocation process.
 * **Audit `authorized_keys` regularly.** Know whose keys are on each server. An
   unknown key is a security incident until proven otherwise.
 * **Rotate keys periodically.** Generate a new key pair, install the new public
   key, verify it works, then remove the old one. Annual rotation is a sensible 
   baseline; rotate immediately if a device is lost or stolen, or if a key may have
   been exposed.
 * **Never commit private keys to version control.** This is one of the most common
   ways keys leak. A private key in a public repository is compromised the moment
   it is pushed. If it happens, generate a new key pair and remove the old public
   key from every server.
 * **Use `~/.ssh/config` for convenience.** Instead of typing the full command each
   time, define a host entry:

    ```
    Host myserver
      HostName 203.0.113.10
      User deploy
      IdentityFile ~/.ssh/id_ed25519
      IdentitiesOnly yes
    ```

Then `ssh myserver` is all you need.

## If You Get Locked Out

It happens — a lost key, a bad configuration change, a forgotten passphrase. The
recovery path is your hosting provider’s console or rescue mode, which gives you
direct access to the server without SSH. [TO BE CONFIRMED: Offshore Hosting’s console
access method for VPS plans and whether it is available on all plans.] From the 
console you can restore `sshd_config`, add a new public key, or reset access. Knowing
how to reach the console before an emergency is part of the setup, not an afterthought.

## Sources

 * Securing SSH on a Linux server: https://noc.org/learn/securing-ssh
 * Ubuntu UFW firewall documentation: https://wiki.ubuntu.com/UFW
 * OpenSSH — official project site: https://www.openssh.com/
 * Fail2Ban: https://www.fail2ban.org/

## Sources

 * {‘title’: ‘Securing SSH on a Linux server (NOC.org)’, ‘url’: ‘https://noc.org/
   learn/securing-ssh’}
 * {‘title’: ‘Ubuntu UFW firewall documentation’, ‘url’: ‘https://wiki.ubuntu.com/
   UFW’}
 * {‘title’: ‘OpenSSH — official project site’, ‘url’: ‘https://www.openssh.com/’}
 * {‘title’: ‘Fail2Ban — official project site’, ‘url’: ‘https://www.fail2ban.org/’}
