Permission denied (publickey) en GitHub: cómo arreglarlo

Si GitHub te rechaza con Permission denied (publickey), aquí tienes las cuatro comprobaciones en orden para arreglarlo en minutos.

Permission denied (publickey) en GitHub: cómo arreglarlo

Haces git push, esperas ver cómo suben tus commits, y en su lugar la terminal te escupe esto:

git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Lo primero que piensas es que tu contraseña está mal. No es eso. Por SSH no hay contraseña de cuenta que valga: GitHub esperaba que le presentaras una clave criptográfica y ninguna de las que le ofreció tu máquina fue reconocida. La buena noticia es que casi siempre es una de cuatro cosas, y se comprueban en orden en un par de minutos. Vamos a ellas. Si además quieres el mapa completo de cómo colaborar en repositorios con otras personas, lo tienes en la guía de trabajo en equipo con Git y GitHub.

¿Qué significa “Permission denied (publickey)”?

Significa que GitHub pidió autenticación por clave pública y la conexión no le ofreció ninguna clave válida. Nada más. No es que tu usuario no exista, ni que el repositorio esté mal escrito, ni que hayas perdido permisos sobre él.

Conviene entender la mecánica, porque cada comprobación de abajo ataca un eslabón de esta cadena. SSH usa un par de claves: una clave privada que vive en tu ordenador y que no sale de ahí jamás, y una clave pública que puedes repartir libremente. Cuando te conectas, GitHub te lanza un reto que solo se puede resolver con tu clave privada, y comprueba la respuesta contra la clave pública que tú le diste de alta. Si tu máquina no ofrece ninguna clave privada, o la que ofrece no coincide con ninguna clave pública registrada en tu cuenta, GitHub cierra la puerta con ese Permission denied (publickey).

Así que el error no significa que te rechacen a ti, sino que GitHub no ha reconocido tu clave. Y para que te reconozca tienen que cumplirse cuatro condiciones a la vez.

Diagrama de flujo con las cuatro comprobaciones para diagnosticar el error Permission denied (publickey) de GitHub, en orden: agente ssh, clave pública en GitHub, saludo de ssh -T, y URL del remoto.
Las cuatro comprobaciones en orden: cada rombo es un punto de decisión, cada ‘no’ te manda a la acción concreta que lo arregla.

Comprobación 1: ¿tiene el agente ssh tu clave cargada?

Empieza por preguntarle al agente ssh qué claves tiene disponibles. El agente ssh es un pequeño proceso que guarda tus claves privadas descifradas en memoria para no pedirte la passphrase en cada conexión. Si la clave no está ahí, SSH no tiene nada que ofrecerle a GitHub.

ssh-add -l

Puede responderte dos cosas. Si el agente tiene tu clave, verás una línea con la huella:

256 SHA256:aBcD3fGhIjKlMnOpQrStUvWxYz1234567890abcdEFGh tu_correo@ejemplo.com (ED25519)

Si el agente está vacío, verás justo esto:

The agent has no identities.

Ese es el caso más común cuando el push falla nada más abrir una terminal nueva. La clave existe en el disco, pero el agente no la ha cargado. Se arregla añadiéndola:

ssh-add ~/.ssh/id_ed25519

id_ed25519 es el nombre por defecto de las claves Ed25519, el tipo que GitHub recomienda para claves nuevas. Si al ejecutar ssh-add ~/.ssh/id_ed25519 te dice No such file or directory, tu clave no está ahí o tiene otro nombre, y el problema pasa a estar en la clave, que todavía no existe. En ese caso el sitio al que ir es la guía para configurar SSH con GitHub desde cero, donde está el paso a paso para generarla.

Vuelve a lanzar ssh-add -l. Si ahora aparece la huella, el primer eslabón está resuelto. Que el agente tenga la clave no garantiza que GitHub la acepte, claro: falta comprobar que esa clave pública está registrada en tu cuenta.

Comprobación 2: ¿está tu clave pública dada de alta en GitHub?

GitHub solo reconoce las claves públicas que tú hayas subido a tu cuenta. Aunque el agente tenga la clave privada perfectamente cargada, si la pública correspondiente no está en GitHub, el reto criptográfico no cuadra y vuelves al mismo error.

Saca el contenido de tu clave pública:

cat ~/.ssh/id_ed25519.pub

Verás una sola línea con esta forma:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... tu_correo@ejemplo.com

Fíjate en el .pub del final del nombre. Ese es el fichero que va a GitHub. En la web, entra en Settings → SSH and GPG keys → New SSH key, pega ahí toda esa línea, ponle un título que te diga de qué máquina es (por ejemplo “Portátil trabajo”) y guarda.

Un aviso que parece obvio pero que la gente se salta con las prisas: solo se pega el fichero .pub. El otro fichero, el que no lleva extensión (~/.ssh/id_ed25519 a secas), es tu clave privada y no se comparte con nadie ni se sube a ningún sitio. Si la pegas en GitHub, además de no funcionar, estás publicando el secreto que te identifica.

Con la clave cargada en el agente y registrada en GitHub, ya tienes los dos extremos conectados. Toca comprobar que de verdad se dan la mano.

Comprobación 3: ¿qué dice ssh -T git@github.com?

Este comando prueba la autenticación SSH contra GitHub sin tocar ningún repositorio. Es la forma más limpia de saber si tu clave funciona, aislada de cualquier lío con el remoto.

ssh -T git@github.com

La primera vez que te conectas te preguntará si confías en el host:

The authenticity of host 'github.com (140.82.121.4)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

Escribe yes. Si todo está en orden, GitHub te saluda así:

Hi usuario! You've successfully authenticated, but GitHub does not provide shell access.

Aquí es donde mucha gente se asusta sin motivo. Ese does not provide shell access confirma que la autenticación fue perfecta; solo te avisa de que GitHub no da consola remota. Ver ese mensaje es exactamente el resultado que buscabas [1]. Si lo ves, tu clave está bien y el problema, si sigue habiéndolo, está en el remoto del repositorio.

Si en cambio te devuelve otra vez Permission denied (publickey), algo de las comprobaciones 1 o 2 no quedó bien. Para ver qué clave está ofreciendo tu máquina y por qué la rechaza, repite con el modo detallado:

ssh -T -v git@github.com

Las líneas Offering public key: te dicen qué claves prueba, y Authentications that can continue: publickey seguido de un rechazo te confirma que la que ofrece no está registrada en tu cuenta. Es la herramienta de diagnóstico fino cuando lo básico no basta.

Diagrama de secuencia del reto criptográfico entre tu máquina, el agente ssh y GitHub durante la autenticación por clave pública.
Lo que pasa por dentro cuando ejecutas ssh -T: GitHub lanza un reto que solo tu clave privada puede firmar.

Comprobación 4: ¿el remoto usa SSH o HTTPS?

Aquí está el fallo que más despista, porque tu clave puede estar perfecta y aun así el push falla. La razón: el repositorio no está configurado para hablar por SSH. Mira qué URL tiene tu remoto:

git remote -v

Si ves algo así, tu remoto es HTTPS y SSH ni siquiera entra en juego:

origin  https://github.com/usuario/repo.git (fetch)
origin  https://github.com/usuario/repo.git (push)

Cambiarlo a SSH es una sola orden:

git remote set-url origin git@github.com:usuario/repo.git

Vuelve a lanzar git remote -v y comprueba que ahora la URL empieza por git@github.com:. La diferencia entre las dos formas es de fondo: cada una autentica de una manera distinta:

AspectoURL SSHURL HTTPS
Formagit@github.com:usuario/repo.githttps://github.com/usuario/repo.git
Cómo autenticaPar de claves: tu clave privada firma el reto y GitHub lo valida con tu .pubToken de acceso personal guardado en el gestor de credenciales
Qué te pide al usarNada, si el agente tiene la clave cargadaUsuario y token la primera vez (GitHub ya no acepta contraseña de cuenta)
Síntoma si te equivocas de URLPermission denied (publickey) cuando falta o no coincide la claveTe pide usuario y contraseña, o falla el token

Ese mismo error también aparece al clonar. Si intentas git clone git@github.com:usuario/repo.git sin la clave lista, GitHub te corta con el mismo Permission denied (publickey) antes de descargar nada; el diagnóstico es idéntico al de aquí, y lo tienes desarrollado en la guía para clonar un repositorio de Git.

Errores que repetimos todos

Los cuatro pasos de arriba resuelven la mayoría de los casos. Estos son los tropiezos concretos que hacen que se resistan.

Pegar la clave privada en GitHub

Es el más peligroso. Con las prisas abres ~/.ssh/id_ed25519 en vez de id_ed25519.pub, copias su contenido y lo pegas en Settings. No solo no funciona (GitHub espera una clave pública, no una privada): acabas de exponer el secreto que te identifica. Si te ha pasado, borra esa clave, genera un par nuevo y sube solo el .pub. La regla es simple: a GitHub solo va el fichero que termina en .pub.

Esperar que SSH arregle un remoto en HTTPS

Puedes cargar la clave en el agente, registrarla en GitHub y ver el saludo de éxito en ssh -T, y aun así el push seguirá fallando si el remoto es https://. SSH y HTTPS son dos caminos separados. Toda la configuración SSH del mundo no toca un remoto que apunta a HTTPS. Por eso la comprobación 4 no es opcional.

La clave se llama distinto de lo que crees

Las claves RSA antiguas se llamaban id_rsa; las Ed25519 actuales, id_ed25519. Si generaste la clave hace tiempo, o le pusiste un nombre a medida, ssh-add ~/.ssh/id_ed25519 apunta a un fichero que no existe. Lista lo que de verdad tienes con ls ~/.ssh/ y añade el nombre correcto.

Generar la clave y no terminar el trabajo

Crear la clave con ssh-keygen es solo el primer paso. Una clave recién generada no está ni en el agente ni en GitHub hasta que la añades a los dos sitios. Es el motivo número uno del error en gente que “ya configuró SSH”: lo configuró a medias.

Confundir el mensaje de éxito con un fallo

Ya lo vimos, pero se repite tanto que merece estar en la lista. You've successfully authenticated, but GitHub does not provide shell access. es el mensaje que quieres ver. La palabra que engaña es “but”, pero lo que va después solo describe cómo funciona GitHub.

Repaso rápido

Cuando vuelva a salirte el error, recorre esto de arriba abajo y sabrás en qué eslabón está el problema:

  • ssh-add -l muestra la huella de tu clave y no The agent has no identities.
  • Has ejecutado ssh-add ~/.ssh/id_ed25519 si el agente estaba vacío
  • El contenido de ~/.ssh/id_ed25519.pub está pegado en Settings → SSH and GPG keys
  • Nunca has pegado en GitHub el fichero sin .pub (la clave privada)
  • ssh -T git@github.com responde con el saludo Hi usuario! You've successfully authenticated...
  • git remote -v muestra una URL que empieza por git@github.com: y no por https://

Con estas seis casillas marcadas, el git push sube. Si aún no lo hace, ssh -T -v git@github.com te dice exactamente qué clave está ofreciendo tu máquina y por qué la rechazan.

Este error suele aparecer justo cuando empiezas a trabajar en serio con repositorios remotos y en equipo. Si es tu caso y quieres dejar de pelearte con Git a base de copiar comandos de Stack Overflow, en el curso Git de cero a profesional montamos el flujo completo, desde el primer commit hasta trabajar con ramas y pull requests sin miedo.

Fuentes

  1. Testing your SSH connection (GitHub Docs). Texto literal del saludo de éxito de ssh -T git@github.com y del mensaje sobre el acceso a shell.

Preguntas Frecuentes

¿“Permission denied” significa que mi contraseña de GitHub es incorrecta?

No. En una conexión SSH no interviene la contraseña de tu cuenta en ningún momento: ese error significa que GitHub no reconoció ninguna clave criptográfica válida, así que el problema está en tu clave o en la URL del remoto, nunca en tus credenciales de la web.

¿Tengo que volver a generar la clave desde cero?

Casi nunca. Regenerar la clave es lo último que deberías hacer, no lo primero. La mayoría de las veces la clave está bien y lo único que falla es que el agente no la tiene cargada, que no está registrada en GitHub, o que el remoto apunta a HTTPS. Pasa las cuatro comprobaciones antes de tocar ssh-keygen.

¿Por qué funcionaba ayer y hoy me da el error?

Lo más habitual es que el agente ssh se reinició con el equipo y perdió la clave que tenía en memoria. Un ssh-add -l te lo confirma en un segundo. Si responde:

The agent has no identities.

vuelve a añadirla con ssh-add ~/.ssh/id_ed25519. Si quieres que la clave se cargue sola en cada arranque, eso se configura en el fichero ~/.ssh/config; en macOS con eso suele bastar, pero en Linux necesitas además que algo arranque y persista el agente al iniciar sesión. El paso a paso lo cubre la guía de configuración de SSH.

¿SSH o HTTPS, cuál me conviene?

Para trabajar a diario desde tu propia máquina, SSH es más cómodo: una vez configurado, no vuelve a pedirte credenciales. HTTPS encaja mejor en entornos donde no puedes dejar una clave privada guardada, como algunos servidores de integración continua. Si estás empezando y quieres el flujo recomendado paso a paso, lo tienes en la guía para configurar SSH con GitHub.

Un concepto nuevo cada semana