If you're a Windows user working with SSH, you might have encountered the need to copy your public key to a remote server. On Unix-like systems, the ssh-copy-id
command simplifies this process. However, Windows lacks a built-in equivalent, which can be frustrating for developers accustomed to Unix workflows.
Since Windows doesn't natively support ssh-copy-id
, we need alternative methods. Popular tools like PuTTY, Pageant, and Kitty (a PuTTY alternative) are commonly used, but they don't provide a direct ssh-copy-id
equivalent. Here's how to achieve the same result manually or with scripts.
If you're using PuTTY or Kitty, follow these steps:
- Generate your SSH key pair using PuTTYgen.
- Copy the public key from PuTTYgen.
- SSH into the remote server and append the public key to
~/.ssh/authorized_keys
.
Example command (after SSH login):
echo "ssh-rsa AAAAB3NzaC1yc2EAAA...your_key_here" >> ~/.ssh/authorized_keys
For a more automated approach, you can use PowerShell to replicate ssh-copy-id
functionality:
function ssh-copy-id {
param (
[string]$user,
[string]$hostname,
[string]$pubKeyPath = "$env:USERPROFILE\.ssh\id_rsa.pub"
)
if (-not (Test-Path $pubKeyPath)) {
Write-Error "Public key file not found at $pubKeyPath"
return
}
$pubKey = Get-Content $pubKeyPath
ssh ${user}@${hostname} "mkdir -p ~/.ssh && chmod 700 ~/.ssh && echo '$pubKey' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
}
Usage example:
ssh-copy-id -user myuser -hostname myserver.com
If you have WSL installed, you can simply use the native ssh-copy-id
command:
wsl ssh-copy-id user@hostname
This is often the simplest solution if you're already using WSL for development.
When copying SSH keys:
- Always verify the server's fingerprint before transferring keys
- Use strong passphrases for your private keys
- Set proper permissions on the remote
authorized_keys
file (600) - Consider using ssh certificates for larger deployments
While Windows doesn't have a built-in ssh-copy-id
equivalent, several effective methods exist. The PowerShell script provides a close approximation, while WSL offers the most Unix-like experience. Choose the method that best fits your workflow.
While Linux/Mac users enjoy the convenience of ssh-copy-id
, Windows administrators often struggle with manual SSH key transfers. The core functionality we need is:
- Generate a new key pair (if none exists)
- Copy the public key to remote server's
~/.ssh/authorized_keys
- Set proper permissions (600 for keys, 700 for .ssh folder)
Since Windows 10 1809, you can use OpenSSH client commands:
# Generate keys (if needed)
ssh-keygen -t rsa -b 4096
# Manual copy (replace with your details)
type $env:USERPROFILE\.ssh\id_rsa.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
For Pageant/Kitty users, convert and transfer keys using:
# Convert Putty .ppk to OpenSSH format
puttygen id_rsa.ppk -O private-openssh -o id_rsa
# PowerShell transfer script
$pubKey = Get-Content "$env:USERPROFILE\.ssh\id_rsa.pub"
$session = New-PSSession -HostName remote.server -UserName admin
Invoke-Command -Session $session -ScriptBlock {
if (-not (Test-Path "~/.ssh")) { New-Item -Type Directory -Path "~/.ssh" }
Add-Content -Path "~/.ssh/authoruthorized_keys" -Value $using:pubKey
icacls "~/.ssh/authorized_keys" /inheritance:r /grant:r "$env:USERNAME:F"
}
- WinSCP: GUI-based key management with drag-and-drop
- Git Bash: Provides Linux-like environment including ssh-copy-id
- Cygwin: Full Linux toolchain port including ssh utilities
Create a reusable ssh-copy-id.ps1
script:
param(
[Parameter(Mandatory=$true)]
[string]$RemoteHost,
[string]$User = $(whoami),
[string]$KeyPath = "$env:USERPROFILE\.ssh\id_rsa.pub"
)
if (-not (Test-Path $KeyPath)) {
Write-Error "Public key not found at $KeyPath"
exit 1
}
$pubKey = Get-Content $KeyPath
$sshCommand = @"
if [ ! -d ~/.ssh ]; then mkdir -p ~/.ssh; fi;
echo '$pubKey' >> ~/.ssh/authorized_keys;
chmod 700 ~/.ssh;
chmod 600 ~/.ssh/authorized_keys;
"@
Write-Host "Transferring key to $RemoteHost..."
ssh "${User}@${RemoteHost}" $sshCommand
Always verify:
- SSH server fingerprint before first connection
- Permissions on remote
authorized_keys
file (must be 600) - Private key never leaves your machine during this process