ssh-copy-id sous Windows : la commande PowerShell qui fonctionne

Windows n'a pas de ssh-copy-id. Dans PowerShell, lancez Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && echo >> ~/.ssh/authorized_keys && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys", en tapant votre mot de passe quand on vous le demande. Cela fonctionne pour un serveur Linux ou Mac. Un serveur Windows exige une autre commande.

Mis à jour le . La ligne de commande a été exécutée dans PowerShell 7.4 sous Linux contre un serveur Ubuntu 24.04, et les cas limites de fichier (fins de ligne, UTF-16, saut de ligne final manquant) ont été testés contre ce serveur.

Copier une clé vers un serveur Linux ou Mac

Lancez ceci dans PowerShell sur votre machine Windows :

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

Vous tapez une fois le mot de passe du compte. Pour un autre port, ajoutez -p 2222 après ssh. La même commande fonctionne dans l'Invite de commandes si vous remplacez la première partie par type %USERPROFILE%\.ssh\id_ed25519.pub.

Testez ensuite. Cette commande refuse de se rabattre sur un mot de passe : elle ne réussit donc que si la clé fonctionne :

ssh -o PasswordAuthentication=no user@server

Pas encore de clé ? Créez-la d'abord, comme expliqué dans générer une clé SSH sous Windows.

Pourquoi cette version

La plupart des copies de cette commande en ligne omettent la partie echo >>. Elle ajoute d'abord une ligne vide, car un authorized_keys existant peut ne pas se terminer par un saut de ligne. Sans elle, votre clé est collée à la fin de la dernière ligne, et cette clé comme la vôtre cessent de fonctionner. Dans notre essai, la connexion était refusée dans ce cas et fonctionnait avec la ligne vide, que le serveur ignore.

Trois autres points que nous avons vérifiés :

  • Fins de ligne Windows. Une clé suivie de CRLF fonctionnait toujours, avec ou sans commentaire, sur OpenSSH 9.6.
  • UTF-16. Un fichier en UTF-16 ne fonctionne pas : la connexion a été refusée. Dans Windows PowerShell 5.1, > et >> écrivent en UTF-16 : ne créez donc jamais authorized_keys avec eux. Add-Content et le tube ci-dessus n'ont pas ce problème pour une clé simple.
  • Répétition. Lancer la commande deux fois ajoute la clé deux fois. C'est sans danger, mais ssh-copy-id l'aurait ignorée.

Si vous avez Git Bash ou WSL

Ce sont des environnements Unix avec leurs propres outils. Vérifiez si la vraie commande est présente :

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

Rappelez-vous que WSL a son propre dossier personnel : son ~/.ssh n'est donc pas le .ssh de Windows.

Copier une clé vers un serveur Windows

La ligne de commande échoue ici, car le shell par défaut est cmd.exe et l'emplacement du fichier est différent. Le plus simple est de travailler sur le serveur lui-même et de coller la clé, comme indiqué dans le guide du serveur OpenSSH.

Pour le faire à distance, Microsoft documente ceci pour un utilisateur standard :

$authorizedKey = Get-Content -Path $env:USERPROFILE\.ssh\id_ed25519.pub
$remotePowershell = "powershell New-Item -Force -ItemType Directory -Path $env:USERPROFILE\.ssh; Add-Content -Force -Path $env:USERPROFILE\.ssh\authorized_keys -Value '$authorizedKey'"
ssh user@server $remotePowershell

Notez que $env:USERPROFILE entre guillemets doubles est remplacé sur votre machine, avant l'envoi. Il ne tombe au bon endroit que si le chemin du profil est le même sur les deux : vérifiez donc le résultat.

Pour un membre du groupe Administrateurs, la clé va dans un autre fichier avec des permissions strictes :

$authorizedKey = Get-Content -Path $env:USERPROFILE\.ssh\id_ed25519.pub
$remotePowershell = "powershell Add-Content -Force -Path $env:ProgramData\ssh\administrators_authorized_keys -Value '$authorizedKey';icacls.exe ""$env:ProgramData\ssh\administrators_authorized_keys"" /inheritance:r /grant ""Administrators:F"" /grant ""SYSTEM:F"""
ssh user@server $remotePowershell

Si la connexion demande toujours un mot de passe

Sous Linux, regardez le journal du serveur pendant votre essai : les permissions du dossier personnel, de ~/.ssh et d'authorized_keys sont la cause habituelle. Voir Permission denied (publickey). Sur un serveur Windows, vérifiez d'abord si le compte est un administrateur et si vous avez utilisé le fichier correspondant.

Questions

Existe-t-il un ssh-copy-id pour Windows ?

Pas dans le client OpenSSH fourni avec Windows. Git Bash ou WSL peuvent avoir la vraie commande, à vérifier avec command -v ssh-copy-id. Dans PowerShell, envoyez plutôt la clé publique à ssh par un pipe.

Pourquoi le serveur demande-t-il encore le mot de passe après la copie de la clé ?

En général à cause des permissions sur le serveur : le dossier personnel, ~/.ssh et authorized_keys ne doivent pas être modifiables par d'autres. Une clé enregistrée en UTF-16 ou collée à la ligne précédente échoue aussi. Surveillez le journal du serveur pendant l'essai.

Où va la clé publique sur un serveur Windows ?

Pour un utilisateur standard, dans .ssh\authorized_keys du profil de l'utilisateur. Pour un membre d'Administrators, dans C:\ProgramData\ssh\administrators_authorized_keys, lisible seulement par Administrators et SYSTEM.

Sources

Autres guides : SSH sur chaque système

Tous les guides