Permission denied (publickey) é o erro de SSH que mais aparece, e a mensagem não te faz favor nenhum. Ela não significa “a sua chave está errada”. Significa: o servidor rejeitou todos os métodos de autenticação que você ofereceu, e chave pública era o único método que ele estava disposto a discutir. O trecho entre parênteses é a lista de métodos que o servidor ainda deixa abertos — (publickey) significa que a autenticação por senha está desligada, então uma chave tem que funcionar, e nenhuma das suas funcionou.
A lista pode ser mais longa, e vale lê-la. Permission denied (publickey,password) significa que o servidor também aceitaria uma senha — então, se você pretendia digitar uma e nunca foi solicitado, o seu cliente desistiu das chaves e deveria ter recorrido à senha; force o prompt com -o PubkeyAuthentication=no para testar. Permission denied (publickey,keyboard-interactive) é a mesma ideia com um método interativo (muitas vezes um prompt do PAM ou 2FA) ainda disponível. Seja o que for que esteja entre parênteses, é o conjunto completo de portas que o servidor deixou abertas; se a que você esperava não está na lista, o servidor nunca ia aceitá-la.
É uma rede ampla: o nome de usuário errado produz esse erro. Também produzem uma chave que o cliente nunca ofereceu, uma chave que o servidor nunca recebeu, um problema de permissões que o sshd se recusa, em silêncio, a relevar, e um rótulo do SELinux do qual você nunca ouviu falar. A correção é sistemática, não um chute — aqui está a rotina, depois os culpados em ordem de quão frequentemente eles são, de fato, a resposta. (Dando push para o GitHub ou o GitLab? Essa é outra lista de verificação — chave SSH do GitHub/GitLab não funciona.)
A rotina de diagnóstico: leia o que o cliente tentou
Rode a conexão que falha com verbosidade máxima (e, se a muralha de saída parecer ruído, como ler o ssh -vvv (em inglês) decodifica as linhas que importam):
ssh -vvv user@host
Três coisas para encontrar na saída:
Authentications that can continue: publickey— a lista de métodos do servidor. Sepasswordestá ausente, nenhuma senha jamais será pedida; uma chave precisa dar certo.Offering public key: /home/you/.ssh/id_ed25519— toda chave que o cliente tentou. Se a chave que você pretendia não está nesta lista, o problema é do lado do cliente (culpado 2). Se está —- o que voltou.
Server accepts keyseguido de uma troca de assinatura significa que a chave combinou e algo falhou depois (raro). O que se costuma ver é a oferta seguida imediatamente da próxima chave ou dePermission denied— o servidor olhou para a chave e deu de ombros, o que aponta para o lado do servidor (culpados 3–8).
Se você tem qualquer outra forma de entrar na máquina (console web do provedor, outro usuário, outro administrador), o log do servidor diz a razão real sem rodeios:
sudo journalctl -u sshd -f # systemd distros
sudo tail -f /var/log/auth.log # Debian/Ubuntu
sudo tail -f /var/log/secure # RHEL/Alma/Rocky
Linhas como Authentication refused: bad ownership or modes for directory /home/deploy encerram a investigação na hora.
Culpado 1: usuário errado
A causa mais comum de todas, principalmente em imagens de nuvem (é a primeira barreira de um primeiro login em um EC2 ou VPS (em inglês)), porque o usuário de login não é o que você imaginaria: ubuntu em imagens Ubuntu, ec2-user no Amazon Linux, admin em AMIs Debian, root na maioria dos VPSes crus, azureuser nos padrões da Azure. A chave certa com o nome de usuário errado produz exatamente esse erro — o servidor verifica ~wronguser/.ssh/authorized_keys, não encontra nada, nega.
Antes de mexer em qualquer outra coisa, confirme o usuário que a documentação da sua imagem indica e fixe-o no ~/.ssh/config para nunca mais redigitá-lo (o guia do ssh_config (em inglês) cobre o padrão):
Host web1
HostName 203.0.113.10
User ubuntu
Culpado 2: a sua chave nunca foi oferecida
Se o ssh -vvv não mostra a sua chave em uma linha Offering public key, o cliente não sabe dela. Aponte para ela explicitamente:
ssh -i ~/.ssh/id_ed25519 user@host
Se isso funcionar, torne-o permanente com IdentityFile no bloco de configuração acima. Duas armadilhas relacionadas: um agente entupido de chaves pode estourar o limite de tentativas do servidor antes de chegar à certa (Too many authentication failures — corrija com IdentitiesOnly yes), e uma chave com uma frase-senha que você cancelou é pulada em silêncio. Verifique o que o agente de fato guarda:
ssh-add -l
No Windows, essa lista pode parecer vazia mesmo quando você acabou de carregar uma chave — o Git Bash, o serviço OpenSSH e o WSL rodam, cada um, um agente separado, e o ssh-add -l só responde pelo ssh que você está de fato usando; ssh-agent no Windows desembaraça os três.
Culpado 3: a chave pública não está no servidor
A metade pública precisa ser uma linha em ~user/.ssh/authorized_keys — para aquele usuário, no home daquele usuário. O jeito confiável de colocá-la lá (usa autenticação por senha ou uma chave existente para a cópia):
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host
Fazendo à mão — digamos, por um console do provedor — acrescente a única linha e nunca sobrescreva o arquivo:
mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys
# paste the one line from id_ed25519.pub, Enter, Ctrl-D
Erros clássicos: a chave foi parar no arquivo do root mas você entra como deploy; a linha foi quebrada por um editor e agora são duas linhas; você colou a chave privada (o arquivo começa com ssh-ed25519 AAAA… — se você vê -----BEGIN, essa é a metade errada).
Culpado 4: permissões e propriedade
O StrictModes do sshd (ligado por padrão) se recusa a honrar o authorized_keys se o caminho até ele puder ser gravado por qualquer um que não seja o dono. É o clássico “copiei a chave e mesmo assim não funciona”. A correção completa, rodada como o usuário de destino:
chmod go-w ~
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R $USER:$USER ~/.ssh
A linha do diretório home importa e costuma ser esquecida: um /home/deploy gravável pelo grupo falha na verificação com a mesma dureza que um arquivo de chave legível por todos. A linha bad ownership or modes do log do servidor te diz exatamente a qual diretório ele faz objeção.
Culpado 5: formato de chave ou frase-senha errados
O OpenSSH não consegue ler os arquivos .ppk do PuTTY — apontar o -i para um falha com invalid format na saída detalhada. Exporte uma chave em formato OpenSSH pelo PuTTYgen (Conversions → Export OpenSSH key), ou gere uma chave moderna nova e cadastre-a (Ed25519, em quase todos os casos (em inglês)). Se você está no Windows e ainda vive no PuTTYgen, um cliente SSH para Windows que importa sessões do PuTTY e usa chaves OpenSSH diretamente dispensa esse passo de conversão por completo. Para verificar que um arquivo de chave privada é legível e que a frase-senha é a que você pensa, peça a ele que imprima a metade pública:
ssh-keygen -y -f ~/.ssh/id_ed25519
Se isso imprime uma chave, o arquivo e a frase-senha estão bem — e você pode comparar a saída com a linha em authorized_keys para confirmar que são, de fato, a mesma chave.
Culpado 6: a configuração do servidor não permite
Menos comum, mas barato de verificar quando você tem acesso ao servidor. Pergunte ao sshd com o que ele está de fato rodando:
sudo sshd -T | grep -Ei 'pubkeyauthentication|authorizedkeysfile'
O PubkeyAuthentication precisa estar yes (padrão, mas scripts de endurecimento às vezes o invertem), e o AuthorizedKeysFile te diz onde o sshd procura — se alguém o apontou para /etc/ssh/authorized_keys/%u, o seu ~/.ssh/authorized_keys cuidadosamente colocado está sendo ignorado. Depois de qualquer mudança no /etc/ssh/sshd_config:
sudo systemctl reload sshd
Culpado 7: contextos do SELinux (família RHEL)
No RHEL, Alma, Rocky, Fedora e afins, um ~/.ssh criado por meios incomuns — restaurado de backup, copiado como root, feito em um volume montado — pode carregar o rótulo errado do SELinux, e o sshd fica sem acesso de leitura a um arquivo com permissões perfeitas. Tudo acima confere, o erro persiste, e ls -Z ~/.ssh mostra algo diferente de ssh_home_t. Um comando conserta os rótulos:
restorecon -R -v ~/.ssh
Se você está sem ideias em uma máquina da família RHEL, rode-o de qualquer jeito — é inofensivo quando os rótulos já estavam certos.
Culpado 8: o login de root está desativado
Padrões modernos definem PermitRootLogin prohibit-password (só chave) ou no (nunca). Se você está tentando root@host e a chave está de fato em /root/.ssh/authorized_keys, verifique:
sudo sshd -T | grep -i permitrootlogin
Com no, nenhuma credencial jamais vai funcionar para o root — entre como o usuário sem privilégios e use sudo, que é o arranjo para o qual o padrão está te empurrando de qualquer forma.
Respostas rápidas
Permission denied (publickey) significa que a minha chave está corrompida?
Quase nunca. Significa que o servidor não aceitou nenhum dos métodos que você ofereceu — normalmente o usuário errado ou a chave errada, não uma chave quebrada. Confirme que a chave é legível e que a frase-senha está certa com ssh-keygen -y -f ~/.ssh/id_ed25519.
Qual é a diferença entre (publickey) e (publickey,password)?
Os parênteses listam os métodos que o servidor ainda permite. (publickey) é só chaves; (publickey,password) significa que uma senha também funcionaria, então você deveria ter sido solicitado — se não foi, o seu cliente desistiu depois de esgotar as chaves.
Funcionava ontem e falha agora — o que mudou?
Um servidor reconstruído, uma chave rotacionada ou um agente que largou a chave depois de um timeout. Rode ssh-add -l primeiro para ver o que está carregado, depois verifique se a máquina foi reimageada (o que também dispara o host key verification failed (em inglês)).
Faça parar de acontecer
Quase todo culpado acima é um fato por host que você não deveria ter que deduzir de novo: qual usuário, qual chave, qual porta. Fixe-os no ~/.ssh/config e essa classe de erro praticamente desaparece — e, para os erros que restarem, o decodificador cobre os outros nove que você vai encontrar.
Os mesmos fatos podem viver em um cliente, em vez de em um dot-file. O Termalin guarda o usuário, a porta e a chave junto com o host salvo, desbloqueia as suas chaves uma vez pelo agente integrado (sem cancelar a frase-senha e pular uma chave em silêncio), verifica a identidade do servidor na primeira conexão e mostra o status ao vivo por host — então “será que está no ar?” e “estou usando a chave certa?” deixam de ser passos de diagnóstico. Ele também importa sessões do PuTTY (em inglês) diretamente, o que aposenta o culpado 5 de vez.
O Termalin é um cliente SSH gratuito e multiplataforma que mantém usuários, portas e chaves por host junto do host e verifica servidores na primeira conexão — baixe o Termalin, ou leia como ele cuida das chaves com segurança.