Password authentication for SFTP works, and for a server exposed to the internet it is the weakest link you still control. Passwords get reused, phished, and brute-forced by bots that scan port 22 continuously. Key authentication removes all three problems and, once set up, is also simply faster to use.
The whole process takes about five minutes.
How key authentication works
You generate a key pair: a private key that never leaves your Mac, and a public key that is safe to hand out. You append the public key to ~/.ssh/authorized_keys on the server.
At login the server sends a random challenge; your client signs it with the private key; the server verifies the signature against the public key it already has. Your private key is never transmitted, so there is nothing on the wire for an eavesdropper to capture and nothing on the server for an attacker to steal and reuse elsewhere.
Generate a key
Use ed25519. It is smaller, faster and stronger than RSA at equivalent security, and it has been the sensible default for years:
ssh-keygen -t ed25519 -C "carlo@macbook"
Accept the default location (~/.ssh/id_ed25519) and set a passphrase. The passphrase encrypts the private key on disk, so a stolen laptop backup does not equal a stolen server. macOS can remember it in the Keychain, so you type it once.
You now have two files:
~/.ssh/id_ed25519 ← private. Never share, never copy to a server.
~/.ssh/id_ed25519.pub ← public. This is the one you install.
If your server is old enough to reject ed25519 — rare now, but it happens on long-unpatched systems — generate -t rsa -b 4096 instead. Upstream supports both.
Install the public key on the server
If you have password SSH access, one command does it:
ssh-copy-id deploy@example.com
If ssh-copy-id is not available or you only have a control-panel file manager, do it manually. Copy the contents of the .pub file and append it as a single line to ~/.ssh/authorized_keys on the server, then fix the permissions — SSH refuses to use the file if they are too open:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
Test it before changing anything else:
ssh -i ~/.ssh/id_ed25519 deploy@example.com
If that logs you in without asking for the account password, the server side is done.
Using the key from a Mac client
Here is where macOS adds a wrinkle worth understanding rather than fighting.
Upstream is sandboxed, the same security model the Finder and every App Store app runs under. A sandboxed app cannot read arbitrary paths, and ~/.ssh is very much an arbitrary path — it cannot silently rummage through your private keys, which is precisely the point.
So the first time a site needs a key, Upstream asks you to select the file with a standard open panel. That grant is what authorises access; from then on the key material is stored in your Keychain and the connection works without prompting. The passphrase, if you set one, is stored alongside it.
This is also why importing ~/.ssh/config brings in the path of each IdentityFile rather than the key itself — the path is a note about which key to ask for, and you authorise it once at first connection.
To set it up: open the site, choose SFTP, set authentication to key rather than password, select the key file, enter the passphrase if the key has one, and connect.
Turning off password login
Once keys work for every account you use, disable password authentication entirely. This is the step that actually removes the brute-force exposure — until you do it, the password is still a valid way in.
In /etc/ssh/sshd_config on the server:
PasswordAuthentication no
PubkeyAuthentication yes
Then reload the SSH daemon. Keep your existing session open while you test a new connection in a second window — if something is wrong you want a way back in that does not involve your hosting provider’s console.
Step by step
- Generate an ed25519 key pair with
ssh-keygen -t ed25519 -C "your-note", and set a passphrase when prompted. - Install the public key with
ssh-copy-id user@host, or append the.pubcontents to~/.ssh/authorized_keysmanually. - Fix permissions on the server —
chmod 700 ~/.sshandchmod 600 ~/.ssh/authorized_keys, or SSH will ignore the file. - Test from the Terminal with
ssh -i ~/.ssh/id_ed25519 user@hostbefore involving a GUI client. - Point the client at the key — in Upstream, set the site to key authentication and select the file once; macOS sandboxing means this grant is explicit, and it is then kept in the Keychain.
- Disable password authentication on the server, testing in a second session before closing the first.
Questions people ask
Which key type should I use, ed25519 or RSA?
ed25519 unless the server is too old to accept it. It is faster, the keys are far shorter, and its security margin is at least as good as RSA-4096. Upstream supports both types.
Do I need a passphrase on the key?
Strongly recommended. Without one, anyone who obtains the file — from a backup, a synced folder, a stolen laptop — has your server. With one, the file alone is useless. macOS remembers it in the Keychain so the cost is a single prompt.
Why does the app ask me to pick the key file instead of finding it?
Because it is sandboxed and cannot read ~/.ssh without your explicit consent. That is a security property, not a limitation: the same rule stops any App Store app from quietly reading your private keys.
Can I use the same key for several servers?
Yes, and it is common. If you want to be able to revoke access to one server independently, generate a separate key per server instead.
Does key authentication work with FTP or FTPS?
No. SSH keys are an SSH concept, so they apply to SFTP only. FTPS authenticates the server with a certificate but still authenticates you with a password.
My key works in Terminal but not in the client. Why?
Most often the client is being pointed at the public key (.pub) rather than the private one, or the key is in an old PEM format the client does not parse. Regenerating with ssh-keygen in the default OpenSSH format resolves it.