SSH is the standard way to work on a remote computer from the terminal, used both to administer servers and to push code to a repository. Many people, though, use it in the most laborious way: an IP address to remember, a password typed every time, files copied with graphical tools. With keys, a well-written configuration file and two commands for transfers, daily work becomes quicker and safer too. Here I deal with the client side, the computer you connect from.
Keys: how they work
A key pair consists of a private key, which stays on your computer and must never be shared, and a public key, which you copy to the servers you want to access. When you connect, the server poses a challenge that only the holder of the private key can solve. No password travels over the network, and an attack based on trying different passwords becomes useless.
To generate a modern pair:
ssh-keygen -t ed25519 -C "anna-laptop"
The ed25519 type produces short, fast and robust keys. The comment only serves to recognise the key once you have several. The program asks for a passphrase: set one, because it protects the private key if the computer is stolen or the disk copied. The files are saved as ~/.ssh/id_ed25519, the private key, and ~/.ssh/id_ed25519.pub, the public one.
Copying the key to the server
The simplest way:
ssh-copy-id user@server.example.com
The command asks for the password one last time and adds the public key to the ~/.ssh/authorized_keys file on the server. From the next connection onwards, login uses the key. Many server providers' control panels also let you paste the public key when the machine is created.
ssh-agent: the passphrase only once
Typing the passphrase at every connection is tedious. The ssh-agent keeps the key unlocked in memory for the length of the session:
ssh-add ~/.ssh/id_ed25519
ssh-add -l
On the most common Linux desktops and on macOS the agent is already running and tied to the system keyring. On macOS, with the UseKeychain yes option in the configuration file, the passphrase is stored in the Keychain.
The ~/.ssh/config file
This is the tool that saves the most time. Each block defines an alias with its own settings:
Host production
HostName 203.0.113.10
User deploy
Port 2222
IdentityFile ~/.ssh/id_ed25519
Host backup
HostName backup.example.com
User anna
ProxyJump production
Host *
ServerAliveInterval 60
AddKeysToAgent yes
With this configuration, ssh production replaces ssh -p 2222 -i ~/.ssh/id_ed25519 deploy@203.0.113.10. The second block shows ProxyJump: to reach a server not exposed to the internet, you pass through another one, transparently. The Host * block applies to every connection: ServerAliveInterval sends a periodic signal and stops an idle connection from being dropped by a router.
Aliases also work with scp, rsync and Git, which use SSH under the hood. The file must be readable only by you: chmod 600 ~/.ssh/config.
The first connection and the server fingerprint
On the first connection SSH shows the fingerprint of the server's key and asks for confirmation. Once accepted, it is saved in ~/.ssh/known_hosts. If one day a warning appears saying the server's identification has changed, don't ignore it: it may be a legitimate reinstallation, but it may also be an interception. Before removing the old entry with ssh-keygen -R hostname, check the fingerprint with whoever manages the server.
Copying files with scp
For one-off transfers scp uses the same syntax as cp, with the server written as alias:path:
scp report.pdf production:/home/deploy/
scp production:/var/log/nginx/error.log .
scp -r folder/ production:/srv/
Syncing with rsync
When there are many files, or the transfer has to be repeated, rsync is clearly superior: it compares source and destination and copies only what has changed.
rsync -avz --progress site/ production:/var/www/site/
The options: -a preserves permissions, dates and links; -v shows details; -z compresses during transfer. Two habits avoid the most common mistakes:
- the trailing slash on the source matters:
site/copies the folder's contents,sitecopies the folder itself into the destination; --deleteremoves from the destination any files no longer present in the source, and it is as powerful as it is dangerous. Before using it, a trial run with-n(--dry-run) shows what would happen without touching anything.
In my work, rsync -avn --delete followed by a careful read of the list is a fixed step before every sync to a production server.
Good habits
- One key per device, so if you lose a laptop you revoke only that one.
- Always set a passphrase on private keys.
- Correct permissions:
chmod 700 ~/.sshandchmod 600on private files, otherwise SSH may refuse to use them. - Remove keys that are no longer needed from
authorized_keys.
In short
- ed25519 keys with a passphrase replace passwords and resist automated guessing.
ssh-copy-idinstalls the key on the server;ssh-agentsaves you retyping the passphrase.~/.ssh/configturns addresses, ports and users into short aliases, ProxyJump included.scpfor one-off copies,rsyncfor repeated or large transfers.- Before
rsync --delete, always do a--dry-runfirst.