Skip to content
shellmap

Connect to a server over SSH using a key

Authenticate to a remote host with a private key file (instead of a password), with the right file permissions and an optional config alias.

How to connect to a server over ssh using a key in each shell

Bashunix
ssh -i ~/.ssh/id_ed25519 [email protected]

`-i` selects a private key file (overrides `~/.ssh/config` `IdentityFile` and the default `~/.ssh/id_*` lookup). Key file MUST be `0600` (owner read+write only) or SSH refuses with `WARNING: UNPROTECTED PRIVATE KEY FILE!` — `chmod 600 ~/.ssh/id_ed25519` fixes it. For repeated use, add to `~/.ssh/config`: `Host myhost\n HostName host.example.com\n User user\n IdentityFile ~/.ssh/id_ed25519` — then just `ssh myhost`.

Zshunix
ssh -i ~/.ssh/id_ed25519 [email protected]

Same `ssh` binary as bash. Zsh-specific: tab-completion auto-completes `Host` aliases from `~/.ssh/config` — type `ssh my<TAB>` to expand. Add hosts to config (above) for the cleanest workflow.

Fishunix
ssh -i ~/.ssh/id_ed25519 [email protected]

Same `ssh` binary. Fish also auto-completes Host aliases from `~/.ssh/config` via its built-in completion engine.

PowerShellwindows
ssh -i $HOME\.ssh\id_ed25519 [email protected]

Windows 10 1809+ and Windows Server 2019+ ship OpenSSH client built-in (`C:\Windows\System32\OpenSSH\ssh.exe`) — pwsh just calls it. Key file permissions on Windows aren't Unix-0600 — they're NTFS ACLs. `Get-Acl ~\.ssh\id_ed25519` shows the ACL; the OpenSSH-for-Windows port checks for "owner-only" semantics. If you get the UNPROTECTED PRIVATE KEY warning: `icacls $HOME\.ssh\id_ed25519 /inheritance:r /grant:r "${env:USERNAME}:F"`. Pwsh-on-Linux/macOS uses the platform `ssh` directly.

cmd.exewindows
ssh -i %USERPROFILE%\.ssh\id_ed25519 [email protected]

Same Windows OpenSSH client (1809+). The `%USERPROFILE%` env var expands to `C:\Users\<you>`. ACL fix for "unprotected key" warning: `icacls %USERPROFILE%\.ssh\id_ed25519 /inheritance:r /grant:r "%USERNAME%:F"`. Add `Host` aliases to `%USERPROFILE%\.ssh\config` (no `~` shortcut in cmd) for repeat use.

Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.

Gotchas & notes

  • Private key permission is the #1 first-time gotcha. Linux/macOS need `chmod 600 ~/.ssh/<key>` (or `400` for read-only). Windows OpenSSH needs NTFS ACL with ONLY the owner having access — use `icacls` to strip inheritance and grant owner-only. The error `Permissions 0644 for ... are too open` is the canonical clue.
  • Use `~/.ssh/config` for repeat connections — saves typing `-i path/to/key user@host -p 2222` every time. Per-host blocks support: `HostName`, `User`, `IdentityFile`, `Port`, `ProxyJump` (bastion-host hops), `ForwardAgent` (forward your local agent), `LocalForward`/`RemoteForward` (port tunnels). The config file itself should be `0644` or `0600`.
  • Use `ssh-agent` to avoid re-typing passphrase per session: `eval "$(ssh-agent -s)"; ssh-add ~/.ssh/id_ed25519` (bash/zsh/fish); on Windows pwsh: `Get-Service ssh-agent | Set-Service -StartupType Automatic; Start-Service ssh-agent; ssh-add $HOME\.ssh\id_ed25519`. Then `ssh user@host` works passphrase-free for the agent's lifetime.
  • Ed25519 (`ssh-keygen -t ed25519`) is the modern default since OpenSSH 6.5 (2014) and the only algorithm enabled by default in OpenSSH 9.5+ (2023). RSA still works but minimum 2048 bits (3072 preferred); DSA and ECDSA-NIST are deprecated. If connecting to an OLD server that rejects Ed25519: `ssh -o PubkeyAcceptedKeyTypes=+ssh-rsa user@old-host` (one-shot escape hatch). The right fix is to upgrade the server.

Related commands

Related tasks