Skip to the content.

Key-Based SSH Login — Cross-OS FAQ

A practical guide to setting up passwordless SSH login between any two machines, where any OS (macOS, Linux, Windows) can be the server or the client.

The whole process is four tasks:

  1. Create a key pair (on the client) — identical on every OS.
  2. Put the public key on the server — depends only on the server’s OS.
  3. Configure the client with an ~/.ssh/config alias — identical on every OS.
  4. (Optional) Load the key into an agent so a passphrase is typed once.

Do those and ssh myserver logs you in with no password.


Concepts

Q: What is “the server” vs “the client”?

Either role can be any OS. A Windows laptop can SSH into a Mac; a Mac can SSH into a Linux box; a Linux box can SSH into Windows. The steps below are labelled by role, so mix and match.

Q: How does key-based login actually work?

You generate a key pair: a private key (stays secret on the client, never leaves it) and a public key (safe to share). You place the public key in the server’s authorized_keys. At login, the server challenges the client to prove it holds the matching private key — no password crosses the network.

Q: What has to be true on each machine before I start?


Task 1 — Create a key pair (on the CLIENT)

Q: How do I create a key? (same command on macOS, Linux, and Windows)

Open a terminal (macOS/Linux) or PowerShell (Windows) and run:

ssh-keygen -t ed25519 -C "you@your-machine"

This creates two files. Never share or copy the private one.

Q: Where are my keys stored?

OS Private key Public key (.pub)
macOS ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub
Linux ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub
Windows C:\Users\<you>\.ssh\id_ed25519 C:\Users\<you>\.ssh\id_ed25519.pub

On Windows, %USERPROFILE%\.ssh\ is the same folder.

Q: What does a public key look like?

One single line, e.g.:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... you@your-machine

That entire line is what goes into the server’s authorized_keys.


Task 2 — Put the PUBLIC key on the SERVER

Pick the section that matches the server’s OS. The goal is always the same: add your public-key line to the right authorized_keys file with correct permissions.

Server is Linux or macOS

On a macOS server, first enable Remote Login:

Then add the key. The target file is ~/.ssh/authorized_keys in the server user’s home directory, and permissions must be strict.

Easiest — from a macOS/Linux client, use ssh-copy-id (it creates the folder, appends the key, and fixes permissions for you):

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server

From a Windows client (no ssh-copy-id), pipe the key over in PowerShell:

type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

Manual method (any client): open the .pub file, copy the single line, then on the server:

mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo "ssh-ed25519 AAAA...your-key... you@your-machine" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Permissions matter. ~/.ssh must be 700 and authorized_keys 600, owned by the user. If the home directory is group- or world-writable, sshd silently refuses the key. This is the #1 cause of “Permission denied (publickey)”.

Server is Windows

First, enable the OpenSSH Server (elevated PowerShell, one time):

Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Set-Service -Name sshd -StartupType Automatic
Start-Service sshd

Then add the key — the file location depends on the server account type:

For a standard user, from a macOS/Linux client:

ssh-copy-id user@windows-server

For an administrator account, paste the key into the shared file and fix its ACL (run on the Windows server in elevated PowerShell):

# Paste your public-key line into the file (replace the key text):
Add-Content -Path C:\ProgramData\ssh\administrators_authorized_keys -Value "ssh-ed25519 AAAA...your-key... you@your-machine"

# Lock the file down or sshd will refuse it:
icacls C:\ProgramData\ssh\administrators_authorized_keys /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"

Two Windows-server notes:


Task 3 — Configure the CLIENT for auto-login

Q: How do I set up ~/.ssh/config so I can just type a short name?

Create or edit the SSH client config file and add a Host block per server. The format is identical on every OS; only the file location differs.

Client OS Config file path
macOS ~/.ssh/config
Linux ~/.ssh/config
Windows C:\Users\<you>\.ssh\config

Example config:

Host win11
    HostName 192.168.1.50
    User kishore
    IdentityFile ~/.ssh/id_ed25519
    Port 22

Host macmini
    HostName 192.168.1.60
    User kishore
    IdentityFile ~/.ssh/id_ed25519

# Apply keepalives to every host
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    AddKeysToAgent yes

Now instead of ssh -i ~/.ssh/id_ed25519 kishore@192.168.1.50 you just run:

ssh win11

Q: Anything special about the config on Windows?

Q: What do the fields mean?


Task 4 (Optional) — Use ssh-agent for passphrase-protected keys

If you gave your key a passphrase (recommended), an agent holds the decrypted key so you type the passphrase once per session instead of every login.

macOS — store the passphrase in the Keychain so it’s remembered across reboots:

ssh-add --apple-use-keychain ~/.ssh/id_ed25519

Add to the top of ~/.ssh/config:

Host *
    UseKeychain yes
    AddKeysToAgent yes

Linux — start the agent and add the key:

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

(Most desktop environments start an agent automatically; AddKeysToAgent yes in config loads keys on first use.)

Windows — enable and start the built-in agent service (elevated PowerShell, one time), then add the key:

Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519

Permissions quick reference

Wrong permissions are the most common reason keys are ignored.

Location macOS / Linux Windows
.ssh folder 700 User has full control; not open to others
authorized_keys (standard user) 600 User full control
Admin administrators_authorized_keys n/a icacls ... /inheritance:r /grant Administrators:F /grant SYSTEM:F
Private key on client 600 Only your account should have access
Home directory not group/world-writable

Troubleshooting FAQ

Q: I still get asked for a password.

The server didn’t accept the key, so it fell back to password auth. Check, in order:

  1. Public key is actually in the server’s authorized_keys (and, on a Windows admin account, in administrators_authorized_keys, not the user file).
  2. Server-side permissions (~/.ssh = 700, authorized_keys = 600; Windows ACL set).
  3. The client is offering the right key — IdentityFile points at the private key.

Q: “Permission denied (publickey).”

Same causes as above, plus: wrong User, wrong key, or the server has public-key auth disabled. Run a verbose connection to see exactly which key is tried and why it’s rejected:

ssh -v user@server        # add more v's (-vv, -vvv) for detail

Q: “Unprotected private key file” / “bad permissions” on the client.

Your private key is readable by others. Tighten it:

Q: Windows server — my key works for a standard user but not for my admin account.

You put it in the wrong file. Admin accounts read C:\ProgramData\ssh\administrators_authorized_keys, and that file needs the icacls lockdown shown above.

Q: macOS server refuses all connections.

Remote Login isn’t enabled. Turn it on under System Settings → General → Sharing → Remote Login.

Q: How do I confirm the config alias resolves correctly?

ssh -G win11          # prints the effective settings for that alias

Optional hardening — disable password login once keys work

After you’ve confirmed key login works, you can turn off password auth on the server so only keys are accepted.

Don’t do this until at least one key login succeeds, or you can lock yourself out — keep a second session open while you test.