FTP is older than the web and sends passwords in plain text. It is still offered by many hosts, and it should be avoided. The replacements are built on SSH, a protocol that encrypts everything between you and the server.
The practical problem with plain FTP is not theory. On a café network, a shared office or a compromised router, anyone who can see the traffic can read the username and password as they go past, and then log in as you. Both are sent as ordinary text. Automated tools that harvest FTP logins from unencrypted connections have existed for decades, and a stolen FTP login is a regular starting point for a hacked WordPress site.
The rest of this article covers what the SSH family contains, how keys work and how to set them up, a worked session from your first connection to a finished file transfer, and the error messages you will meet along the way.
The family
SSH gives you a command line on the server. SFTP uses the same secure channel to transfer files, and nearly every file transfer program supports it. SCP copies individual files from the terminal. FTPS is FTP wrapped in TLS, which works but is fiddlier to firewall. rsync, run over SSH, copies only what has changed, and is the best tool for big migrations and backups.
A common misunderstanding is that SFTP means "FTP, but secure". It does not. SFTP is a different protocol that merely shares a name fragment; it travels inside an SSH connection on port 22 and has nothing to do with the old FTP commands. That is why switching from FTP to SFTP in a program means changing the protocol setting and the port, not just ticking a box.
| Tool | What it does | Port | Best for |
|---|---|---|---|
| SSH | Interactive command line | 22 | Running commands, reading logs, editing configuration |
| SFTP | File transfer inside SSH | 22 | Everyday uploads with a graphical client |
| SCP | Copy single files or folders | 22 | Quick one-off transfers from the terminal |
| rsync over SSH | Copy only the differences | 22 | Migrations, backups, repeat syncs of large trees |
| FTPS | FTP with TLS | 21 plus data ports | Hosts that offer nothing else |
| Plain FTP | Unencrypted transfer | 21 | Nothing new; avoid |
Keys instead of passwords
A key pair consists of a private key that stays on your computer and a public key that you place on the server. When you connect, you prove you hold the private key without sending it. Create a pair with ssh-keygen -t ed25519, protect the private key with a passphrase, and add the public key to the server's ~/.ssh/authorized_keys. Many hosts let you paste it into the panel.
The reason this is better than a password is that there is nothing to guess and nothing to steal in transit. A password can be tried a million times by a bot; a key cannot be guessed at all in any practical sense. Even if the server is bugged and someone records the whole session, the private key is never in it.
Setting up a key, step by step
- On your own computer, run
ssh-keygen -t ed25519 -C "laptop 2026". Accept the default location, which is~/.ssh/id_ed25519, and choose a passphrase when asked. - Two files appear.
id_ed25519is the private key; never move it off the machine.id_ed25519.pubis the public key, a single line you can share freely. - Copy the public key to the server. If you can already log in with a password,
ssh-copy-id [email protected]does it in one step. Otherwise print it withcat ~/.ssh/id_ed25519.puband paste it into the panel's SSH keys page. - Connect with
ssh [email protected]. If the key is used, you are asked for the key's passphrase (or nothing, if an agent already holds it) and not the server password.
The passphrase matters. It encrypts the private key file on disk, so a stolen laptop or a copied backup does not hand over access. An SSH agent, built into macOS and most Linux desktops and available on Windows, remembers the unlocked key for the session so that you type the passphrase once.
A first session, from login to upload
Here is what a typical first connection to a shared hosting account looks like, with example values throughout.
$ ssh -p 22 [email protected]
The authenticity of host 'example.com (203.0.113.10)' can't be established.
ED25519 key fingerprint is SHA256:abc123exampleFingerprint.
Are you sure you want to continue connecting (yes/no)? yes
[email protected]:~$ pwd
/home/user
[email protected]:~$ ls
public_html logs mail
That first question is worth a moment. The fingerprint identifies the server. If your host publishes it in their documentation or panel, compare the two. Saying yes stores it in ~/.ssh/known_hosts, and from then on your computer will complain if it ever changes. That check is the thing that catches an impostor.
To move files, the commands are short:
# one file up
scp backup.sql [email protected]:~/
# a whole folder down, resuming safely, showing progress
rsync -avz --progress [email protected]:~/public_html/ ./site-copy/
# upload only changes, deleting files that no longer exist locally
rsync -avz --delete ./site/ [email protected]:~/public_html/
The trailing slash in rsync matters. public_html/ means "the contents of the folder", while public_html without it means "the folder itself". Getting that wrong creates a nested folder, or in the case of --delete removes things you meant to keep. Run with --dry-run first when in doubt, and it prints what would happen without doing it.
rsync --delete makes the destination match the source exactly. Point it at the wrong directory and it will tidy away everything that does not match. Always test with --dry-run before the first real run.Habits that protect you
Never share a private key, never email it, and never store it where a backup service uploads it unencrypted. Use a different key per device so you can revoke one without disturbing the others. If you run a server, turn off password logins for SSH once keys work. On shared hosting, you may not be able to, but you can still use keys for your own account.
On your own server, the setting lives in /etc/ssh/sshd_config:
PasswordAuthentication no
PermitRootLogin prohibit-password
PubkeyAuthentication yes
Test a second login in a new terminal before closing the one you are using, and reload the service afterwards. If you made a mistake, the open session is how you fix it. A few more habits are worth adopting: keep a record of which key belongs to which device; remove keys from authorized_keys when a laptop is sold or a contractor leaves; and keep SSH software updated, because the protocol is sound but individual programs have had flaws.
For the panel side of this, such as where to paste keys and how to limit logins, see the earlier note on what a control panel does.
Shared, VPS and dedicated
What you can do with SSH depends on where the account lives. Some shared plans offer only SFTP, with no shell, because a shell gives a user far more power. Others provide a restricted shell where common commands work but system areas are off limits. A VPS or dedicated server gives you a full login, often as root or a user with sudo, and that carries responsibility. A server exposed to the internet on port 22 receives automatic login attempts within minutes of going online. Keys, a disabled root password login and a tool such as fail2ban or a firewall allow-list keep this background noise harmless.
Common problems
"Permission denied (publickey)" usually means the server does not have the right public key, or the permissions on ~/.ssh are too loose. "Connection refused" means nothing is listening on that port, or a firewall blocks you. "Host key verification failed" appears when the server's identity changed, which is normal after a reinstall and alarming if you did not expect it.
Taking them one at a time:
- Permission denied (publickey). Run
ssh -v [email protected]and read the lines about which keys were offered. Check that the public key is inauthorized_keysexactly, on one line. On the server,~/.sshshould be mode 700 andauthorized_keysmode 600, and the home directory must not be writable by others. Many servers refuse keys silently when these are too open. - Connection refused or timed out. Test the port with
nc -vz example.com 22. Refused means the service is off or on another port (shared hosts sometimes use a nonstandard one, so check your host's documentation). Timed out suggests a firewall. See the ports article in this series. - Host key verification failed. If you reinstalled the server or moved the address, remove the old entry with
ssh-keygen -R example.comand accept the new fingerprint after confirming it with your host. If nothing changed on your side, stop and ask why before continuing. - Too many authentication failures. An agent holding many keys offers each in turn until the server gives up. Use
ssh -i ~/.ssh/id_ed25519 -o IdentitiesOnly=yes [email protected]to offer only one.
The config file that saves typing
Once you have more than one server, typing user names, ports and key paths gets tedious and error-prone. OpenSSH reads a per-user file, ~/.ssh/config, where each host gets a short alias.
Host shop
HostName example.com
User shopuser
Port 22
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Host staging
HostName 203.0.113.50
User deploy
IdentityFile ~/.ssh/id_ed25519_staging
After that, ssh shop is the whole command, and scp backup.sql shop:~/ and rsync -avz ./site/ shop:~/public_html/ work the same way, because every tool in the family reads the same file. Graphical clients often import it too. The file also documents your setup: a year from now, you will not remember which port the staging server used, but the file will.
A related trick is the SSH tunnel, which lets you reach something that is not open to the internet. If a database listens only on the server's loopback address, ssh -L 3307:127.0.0.1:3306 shop makes it appear on your own computer at port 3307 for as long as the session lasts. Point your database tool at 127.0.0.1:3307 and it talks to the remote database through the encrypted channel, with the database port never exposed to the public network.