SysadminGuide

SSH Permission denied (publickey) : le correctif

Sur cette page
  1. Lis d'abord la poignée de main : ssh -vvv
  2. La clé n'est pas chargée dans l'agent
  3. C'est la mauvaise clé qui est proposée
  4. La clé n'est pas dans authorized_keys
  5. Les permissions et le propriétaire sont mauvais
  6. sshd_config bloque l'auth par clé
  7. SELinux étiquette mal ~/.ssh sur RHEL
  8. Le serveur n'autorise que certains utilisateurs
  9. Le serveur est passé en clé uniquement et tu n'en as pas
  10. Cas tordus : ed25519, agent forwarding, homes réseau
  11. Sources et lectures complémentaires

Permission denied (publickey) ressemble à une porte claquée, mais ce n'est jamais mystérieux une fois la poignée de main lue. Le message, c'est juste SSH qui te dit qu'il a proposé une clé, que le serveur n'en a accepté aucune, et que l'auth par clé est la seule option au menu. Le diagnostic ne tient donc jamais du devin. Tu lis la poignée de main avec ssh -vvv, tu repères la porte exacte qui coince, et tu la refermes. Je traite ça dans un ordre fixe, du haut vers le bas : clé non chargée dans l'agent, mauvaise clé proposée, clé absente de authorized_keys, permissions incorrectes, sshd_config qui bloque pubkey, SELinux sur RHEL, limites AllowUsers, et le cas du serveur en clé uniquement.

The short answer

Permission denied (publickey) signifie que SSH a proposé une clé, que le serveur n'en a pris aucune, et que l'auth par clé est la seule méthode autorisée. Lance ssh -vvv et compte les lignes « Offering public key » : zéro, c'est un problème côté client (agent ou chemin de la clé) ; une ou plus, toutes rejetées, c'est côté serveur (authorized_keys ou permissions). Referme la première porte qui coince, puis retente.

ssh -vvvlis d'abord la poignée de main
9 portesvérifie-les du haut vers le bas
1 causela première porte qui coince
Carte réponse pour SSH Permission denied (publickey) : lis la poignée de main, puis referme la première porte qui coince.
Le message n'est pas mystérieux. Lis la poignée de main, repère la seule porte qui dit non, referme-la. PNG

Je tape ssh user@host, confiant, et SSH me renvoie Permission denied (publickey) avant de me raccrocher au nez. Pas d'invite de mot de passe, pas de seconde chance, juste la porte claquée. J'ai couru après ce message sur plus de machines que je ne saurais compter : VM de labo, instances cloud, deux NAS qui m'ont résisté une heure. Et voilà ce que personne ne te dit : ce n'est presque jamais mystérieux. Le message, c'est juste la façon dont SSH te dit « j'ai proposé une clé, le serveur n'en a accepté aucune, et l'auth par clé est la seule option au menu ». C'est tout. Du coup le diagnostic ne tient jamais du devin. Tu lis la poignée de main, tu repères la porte exacte qui coince, tu la refermes. Je traite ça dans un ordre fixe, du haut vers le bas, parce que ces échecs s'empilent de façon assez prévisible et que sauter d'un point à l'autre ne fait que gâcher ta soirée.

Lis d'abord la poignée de main : ssh -vvv

Avant de toucher à quoi que ce soit, fais cracher à SSH ce qu'il fabrique. Le flag verbeux, c'est tout le jeu ici. Un seul -v suffit, mais j'en mets toujours trois, parce que le triple verbeux te montre chaque clé que le client propose et exactement comment le serveur réagit à chacune.

ssh -vvv user@host

Descends jusqu'au moment où ça commence à parler d'authentification. Tu chasses deux lignes. Offering public key: te dit quelles clés ton client a réellement tentées. Authentications that can continue: publickey te dit que le serveur ne prendra *qu'*une clé, rien d'autre. Si tu vois ta clé proposée, puis send_pubkey_test suivi d'une autre proposition, le serveur a regardé cette clé et a dit non. Cette seule observation te dit si ton problème vit sur ta machine (aucune clé n'a été proposée du tout) ou sur le serveur (une clé a été proposée et rejetée). Tout ce qui suit se ramifie à partir de cette lecture.

Petit réflexe avant de creuser : lance ssh -vvv et compte les lignes « Offering public key ». Zéro, c'est un problème côté client, ton agent ou le chemin de ta clé. Une ou plus, toutes rejetées, c'est côté serveur, authorized_keys ou permissions. Ne saute pas cette étape. Ça t'évite de réparer la mauvaise moitié.

L'ordre pour diagnostiquer SSH Permission denied (publickey) : agent chargé, bonne clé proposée, clé dans authorized_keys, permissions et propriétaire, sshd autorise pubkey, contexte SELinux sur RHEL, AllowUsers, serveur en clé uniquement.
Là où l'auth publickey casse, dans l'ordre où je le vérifie vraiment. Le premier nœud qui répond non est en général tout ton correctif. PNG

La clé n'est pas chargée dans l'agent

C'est celui qui me piège le plus, et un peu trop souvent pour mon ego. Symptôme : ssh -vvv ne montre aucune clé proposée, ou en propose une autre que celle que tu voulais. L'agent n'a tout simplement pas ta clé en mémoire. Pour confirmer :

ssh-add -l

Si ça affiche The agent has no identities, tu as ta réponse. L'agent est vide, donc SSH se rabat sur les fichiers de clé par défaut qu'il trouve, et si ce ne sont pas les bons tu te fais refouler. Correctif : charge la clé.

ssh-add ~/.ssh/id_ed25519
# macOS, persist it in the keychain across reboots:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519

Relance ssh-add -l, vois l'empreinte, retente. Sur un shell tout neuf sans aucun agent, ssh-add se plaindra de ne pas pouvoir s'y connecter. Démarre-le d'abord avec eval "$(ssh-agent -s)" puis ajoute la clé. Franchement, la moitié des « ça marchait hier » qu'on me remonte, c'est juste un agent qui n'a pas survécu à un redémarrage.

C'est la mauvaise clé qui est proposée

Tu as cinq clés dans ~/.ssh et SSH les propose toutes joyeusement, dans un ordre qui n'est pas le bon, et le serveur abandonne après quelques tentatives. Symptôme : la poignée de main propose des clés, mais jamais celle qui est réellement autorisée sur le serveur. Pour confirmer : regarde les lignes Offering public key dans ssh -vvv et vérifie si l'empreinte de ta vraie clé apparaît. Compare avec :

ssh-keygen -lf ~/.ssh/id_ed25519.pub

Correctif : arrête de laisser SSH deviner. Pointe-le droit sur la bonne clé, soit en ligne pour un coup unique, soit dans ta config pour de bon. En ligne :

ssh -i ~/.ssh/id_ed25519 user@host

Et la version que je garde vraiment, dans ~/.ssh/config, pour ne plus jamais y penser :

Host myserver
    HostName host.example.com
    User user
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes

Ce IdentitiesOnly yes compte plus qu'il n'en a l'air. Sans lui, SSH balance quand même toutes les clés de l'agent au serveur avant d'essayer celle que tu as nommée, et certains serveurs, surtout ceux avec un MaxAuthTries bas, te jettent pour trop de tentatives ratées avant même que ta bonne clé ait son tour. Tu te retrouves donc refusé alors que tu tiens la bonne clé. Rageant. IdentitiesOnly dit à SSH de ne proposer que ce que tu as listé, rien d'autre.

La clé n'est pas dans authorized_keys

La cause la plus littérale de toutes : on n'a tout simplement jamais dit au serveur de faire confiance à ta clé. Symptôme : bonne clé proposée, le serveur la rejette quand même. Pour confirmer, accède au serveur par un autre moyen (console, une session existante, le shell web du fournisseur cloud) et regarde :

cat ~/.ssh/authorized_keys

Si le contenu de ta clé publique n'est pas là, ligne pour ligne, le serveur n'a aucune raison de te laisser entrer. Correctif : le plus propre, c'est ssh-copy-id, qui ajoute ta clé publique et range le fichier à ta place, mais il lui faut un login fonctionnel (mot de passe, ou une autre clé) pour le faire :

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

Pas de login par mot de passe disponible ? Alors colle-la à la main depuis la console. La clé tient sur une seule ligne, et elle doit y rester, un retour à la ligne égaré au milieu la casse en silence :

mkdir -p ~/.ssh
echo "ssh-ed25519 AAAA...your-key... user@laptop" >> ~/.ssh/authorized_keys

Une subtilité qui piège les gens : la clé doit être dans le authorized_keys du compte sous lequel tu te connectes. La copier dans ton propre home alors que tu voulais te connecter en tant que deploy ou root ne mène à rien. Bonne clé, mauvais fichier, même refus.

Les permissions et le propriétaire sont mauvais

C'est la cause que les gens refusent de croire jusqu'à ce qu'ils la voient. SSH est volontairement paranoïaque : si ton ~/.ssh ou tes fichiers de clé sont lisibles par quelqu'un d'autre que toi, le serveur les ignore purement et simplement, sans le moindre avertissement à ta face. Il part du principe qu'un fichier de clé trop ouvert est un fichier compromis. Symptôme : la clé est dans authorized_keys, refus quand même, et ssh -vvv sur le log du serveur (/var/log/auth.log ou journalctl -u sshd) mentionne « bad ownership or modes ». Pour confirmer :

ls -la ~/.ssh
ls -la ~/.ssh/authorized_keys

Correctif : les chiffres magiques, sur le serveur, pour le compte sous lequel tu te connectes :

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_ed25519
chown -R $USER:$USER ~/.ssh

Et n'oublie pas le répertoire home lui-même. Si ~ est inscriptible par le groupe ou tout le monde, sshd se méfie de toute la chaîne et refuse, même avec ~/.ssh parfaitement verrouillé. Donc chmod 755 ~ au maximum, souvent 700 est plus propre. Le propriétaire, c'est l'autre moitié de l'affaire : chacun de ces fichiers doit appartenir à l'utilisateur de connexion, pas à root, pas à un uid résiduel d'une restauration. chown -R règle ça. De toutes les causes de cette page, des modes incorrects, c'est celle sur laquelle je parierais si la clé est clairement présente et toujours rejetée.

sshd_config bloque l'auth par clé

Parfois ton côté est impeccable et c'est le serveur lui-même qui est configuré pour refuser les clés, ou pour les chercher là où tu ne les as pas mises. Symptôme : tous les clients et toutes les clés se font refuser, pas seulement les tiens. Pour confirmer, sur le serveur :

sudo sshd -T | grep -Ei 'pubkeyauthentication|authorizedkeysfile'

Ça vide la config effective, les valeurs avec lesquelles sshd tourne réellement, pas juste ce qu'il y a dans le fichier. Tu veux voir pubkeyauthentication yes. Si c'est no, les clés sont entièrement coupées. Correctif : édite /etc/ssh/sshd_config (et tout ce qui est dans /etc/ssh/sshd_config.d/, qui le surcharge et qu'on rate facilement) :

PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

Puis recharge, ne te contente jamais d'éditer et de partir : sudo systemctl reload sshd. La ligne AuthorizedKeysFile compte quand quelqu'un a relogé les clés vers un chemin central comme /etc/ssh/authorized_keys/%u. Si c'est réglé ainsi, ton ~/.ssh/authorized_keys est ignoré exprès, et tu dois mettre la clé là où la directive pointe. Teste toujours ton édition avec sudo sshd -t d'abord ; ça attrape une coquille avant qu'un reload n'enferme tout le monde dehors.

SELinux étiquette mal ~/.ssh sur RHEL

Celui-ci est une spécialité RHEL, CentOS, Rocky, Alma, et il est vicieux parce que tout a l'air correct. Symptôme : les permissions sont irréprochables, la clé est dans authorized_keys, sshd autorise pubkey, et tu te fais quand même refuser, seulement sur une machine de la famille Red Hat. Pour confirmer : SELinux journalise la vraie raison là où le client SSH ne la voit jamais :

sudo ausearch -m avc -ts recent
ls -Z ~/.ssh

Si ls -Z montre un contexte qui n'est pas ssh_home_t sur ~/.ssh et ses fichiers, SELinux empêche sshd de les lire, en général après que tu as créé le répertoire à la main ou restauré depuis une sauvegarde qui a perdu ses étiquettes. Correctif : réétiquette-le vers le bon contexte :

restorecon -Rv ~/.ssh

Ça remet le contexte SELinux à ce que la politique attend et le refus disparaît. J'ai vu des admins chevronnés y brûler une heure parce que rien, côté permissions, ne semble cloché. Quand tu es sur RHEL et vraiment coincé, restorecon est la première chose que je dégaine maintenant.

Le serveur n'autorise que certains utilisateurs

Ta clé est parfaite, mais on a dit au serveur que ton compte n'est pas sur la liste des invités. Symptôme : un utilisateur se connecte sans souci, un autre récolte Permission denied (publickey) depuis la même machine avec une clé tout aussi valide. Pour confirmer, sur le serveur :

sudo sshd -T | grep -Ei 'allowusers|allowgroups|denyusers|denygroups'

Correctif : si AllowUsers ou AllowGroups est réglé, seuls les comptes ou groupes qu'il nomme peuvent se connecter, point final, clé ou pas clé. Ajoute ton utilisateur (ou le groupe auquel il appartient) dans /etc/ssh/sshd_config :

AllowUsers alice deploy youruser
# or, group based:
AllowGroups sshusers

Recharge sshd ensuite. Et vérifie aussi DenyUsers, c'est la même idée inversée, et un nom d'utilisateur posé là-dedans bloquera ce compte quoi que tout le reste soit bon. Ces directives, c'est facile à oublier sur une machine durcie que tu as montée il y a des mois, puis tu ne comprends plus pourquoi le nouveau collègue n'arrive pas à entrer.

Le serveur est passé en clé uniquement et tu n'en as pas

Scénario cloud classique. Tu lances une instance, ou un sysadmin durcit une existante, l'auth par mot de passe est coupée, et désormais le seul moyen d'entrer est une clé que tu n'as jamais configurée. Symptôme : Permission denied (publickey) immédiat sans aucune invite de mot de passe, et tu n'as aucune clé côté serveur. Pour confirmer : la poignée de main ssh -vvv montre Authentications that can continue: publickey et rien d'autre, pas de password, pas de keyboard-interactive.

Correctif : il te faut un accès hors-bande pour planter une clé, parce que SSH lui-même t'est fermé. Les voies habituelles :

  • Console cloud : AWS EC2 Instance Connect, le SSH navigateur de GCP, ou la console série d'Azure te donnent tous un shell sans clé. Une fois dedans, dépose ta clé publique dans ~/.ssh/authorized_keys à la main, comme dans la section ci-dessus.
  • Injection de clé par le fournisseur : la plupart des plateformes te laissent attacher une nouvelle clé publique via un mécanisme de rescue ou de user-data et redémarrer dessus.
  • Rescue par snapshot : monte le volume sur une autre instance, écris ta clé dedans, rattache. Lent, mais ça marche toujours.

Ensuite, et seulement après avoir confirmé que ta nouvelle clé te connecte, demande-toi s'il faut rallumer l'auth par mot de passe. En général non. Le clé uniquement est le bon réglage par défaut, tu veux juste être celui qui tient la clé cette fois.

Cas tordus : ed25519, agent forwarding, homes réseau

Quelques cas qui n'entrent pas dans le flux principal mais produisent quand même l'erreur identique.

Vieux types de clé que le serveur refuse maintenant

OpenSSH moderne (8.8 et au-delà) a cessé d'accepter ssh-rsa avec SHA-1 par défaut. Symptôme : une vieille clé RSA qui a marché des années se fait soudain refuser après une mise à jour du serveur. Génère une clé ed25519 fraîche et sers-toi de celle-là, elle est plus petite, plus rapide, et rien de moderne ne s'en plaint :

ssh-keygen -t ed25519 -C "you@laptop"

L'agent forwarding n'est pas réellement activé

Tu sautes vers la machine A, puis tu tentes de faire un SSH de A vers B en utilisant la clé de ton portable. Symptôme : refus au deuxième saut parce que A n'a aucune clé et que l'agent ne t'a pas suivi. Confirme avec ssh-add -l sur la machine A ; un agent vide signifie que le forwarding n'a pas eu lieu. Active-le avec ForwardAgent yes dans ta config pour cet hôte (et assure-toi que le AllowAgentForwarding du serveur est activé). Ne fais suivre l'agent que vers des hôtes de confiance, un utilisateur root sur A peut se servir de ton agent forwardé tant que tu es connecté.

~/.ssh sur un répertoire home réseau

NFS ou n'importe quel home en réseau est un fauteur de troubles discret. Symptôme : les permissions se lisent correctement mais sshd refuse quand même de faire confiance aux fichiers, souvent parce que root est squashé sur le partage NFS et que sshd ne peut pas vérifier le propriétaire comme il le voudrait. Regarde le log du serveur pour une plainte de propriétaire. Le correctif propre est d'habitude de régler AuthorizedKeysFile vers un chemin local que sshd contrôle, comme /etc/ssh/authorized_keys/%u, pour que la clé ne soit pas posée sur un partage avec sa propre politique de permissions. StrictModes peut aussi être ce qui coince ici ; comprends pourquoi avant même d'envisager de l'assouplir.

Sources et lectures complémentaires

Questions fréquentes

Pourquoi j'ai Permission denied (publickey) mais aucune invite de mot de passe ?

Parce que le serveur a coupé l'authentification par mot de passe, donc l'auth par clé est la seule méthode autorisée. SSH a proposé les clés qu'il avait, le serveur n'en a accepté aucune, et il n'y a aucun repli par mot de passe vers lequel basculer. Lance ssh -vvv et cherche « Authentications that can continue: publickey » sans rien d'autre listé. Ça confirme que c'est du clé uniquement, et tu dois soit réparer la clé que le serveur attend, soit entrer par une console cloud pour en planter une nouvelle.

Comment voir quelle clé SSH essaie vraiment ?

Lance ssh -vvv user@host et lis les lignes « Offering public key ». Chacune est une clé que ton client a envoyée, avec son empreinte. Compare cette empreinte à ssh-keygen -lf sur ta clé publique pour être sûr que la bonne est en jeu. Si tu ne vois aucune ligne d'offre du tout, ton agent est vide ou le chemin de ton IdentityFile est faux, donc commence par là plutôt que sur le serveur.

Quelles permissions ~/.ssh demande-t-il vraiment ?

700 sur le répertoire ~/.ssh, 600 sur authorized_keys et sur toute clé privée, et chacun de ces éléments doit appartenir à l'utilisateur de connexion. Le répertoire home lui-même ne peut pas non plus être inscriptible par le groupe ou tout le monde, sinon sshd se méfie de toute la chaîne. SSH ignore les fichiers de clé trop ouverts par mesure de sécurité, donc des modes trop permissifs te font refuser sans aucun avertissement côté client. Le log du serveur, c'est là que la vraie raison apparaît.

Ça marche pour un utilisateur mais pas un autre sur le même serveur. Pourquoi ?

En général AllowUsers ou AllowGroups dans sshd_config. Si l'un des deux est réglé, seuls les comptes ou groupes qui y sont nommés peuvent se connecter, peu importe à quel point la clé de l'autre utilisateur est valide. Lance sudo sshd -T et cherche allowusers et allowgroups pour voir la liste effective. DenyUsers fait la même chose à l'envers, donc vérifie ça aussi. Ajoute le compte, recharge sshd, et le second utilisateur entre.

Tout a l'air correct sur RHEL mais je me fais quand même refuser. Qu'est-ce qui m'échappe ?

SELinux, presque à coup sûr. Sur RHEL, CentOS, Rocky et Alma, si ~/.ssh a le mauvais contexte de sécurité, sshd ne peut pas le lire même si les permissions Unix sont parfaites. Lance ls -Z ~/.ssh et vérifie ssh_home_t, puis regarde sudo ausearch -m avc -ts recent pour le refus réel. Le correctif est restorecon -Rv ~/.ssh, qui réétiquette tout vers le contexte que la politique attend. Ça piège les gens qui ont créé ~/.ssh à la main ou l'ont restauré depuis une sauvegarde.

Ma vieille clé RSA a cessé de marcher après une mise à jour du serveur. Elle est morte ?

Probablement, dans sa forme actuelle. OpenSSH 8.8 a désactivé ssh-rsa avec signatures SHA-1 par défaut, donc une vieille clé RSA qui en dépendait se fait rejeter après que le serveur passe à une version plus récente. Le bon réflexe est de générer une clé ed25519 fraîche avec ssh-keygen -t ed25519 et d'ajouter sa moitié publique à authorized_keys. C'est un type de clé plus robuste auquel rien de moderne n'objecte, et tu arrêtes de te battre avec les avertissements de dépréciation.