Una clave SSH que no se autentica en GitHub o GitLab es uno de los problemas de desarrollador más buscados en Google, y la mitad de las veces la clave está bien — lo que falla es el diagnóstico. Así que antes de regenerar nada, ejecuta una prueba y aprende a leer su respuesta. Luego repasa los culpables por orden de cuántas veces son realmente la causa.
«You’ve successfully authenticated, but GitHub does not provide shell access»
Si esa es la línea que te devolvió, para — tu clave ya funciona. GitHub y GitLab no te dan una shell; solo hablan git sobre SSH, así que te autentican y cuelgan de inmediato, y «does not provide shell access» es su forma de decirlo, no un error. La redacción de GitLab es un poco distinta (Welcome to GitLab, @you!) pero significa lo mismo. Si tu clave funciona y aun así git push sigue pidiéndote una contraseña, la clave nunca fue el problema — salta al culpable del remoto HTTPS de más abajo, que es la causa real habitual.
Paso 0: la prueba que te dice si siquiera está roto
Pregúntale directamente al host de git si reconoce tu clave:
ssh -T git@github.com # GitHub
ssh -T git@gitlab.com # GitLab
Ahora lee la respuesta con atención, porque el mensaje de éxito parece un error:
Hi <username>! You've successfully authenticated, but GitHub does not
provide shell access.
Eso es un éxito. «Does not provide shell access» no es un fallo — GitHub y GitLab no te dan una shell, solo hablan git sobre SSH, así que te autentican y luego cuelgan. La gente ve «does not provide» y se pone a depurar una configuración que funciona. Si ves tu nombre de usuario en esa línea, tu clave funciona; tu problema está en otra parte (salta al culpable del remoto HTTPS de más abajo — ese es el problema real habitual).
El fallo de verdad tiene este aspecto en cambio:
git@github.com: Permission denied (publickey).
Ese es el que venimos a arreglar. Fíjate en el final: Permission denied (publickey) significa que el servidor no aceptó ninguna clave que ofreciste. Baja por la lista.
Culpable 1: la clave no está añadida a tu cuenta
La causa real más común. Una clave en tu portátil no hace nada hasta que su mitad pública está registrada en el host de git. Copia la clave pública:
cat ~/.ssh/id_ed25519.pub # note the .pub — this is the safe half to share
Pega eso en GitHub → Settings → SSH and GPG keys → New SSH key, o en GitLab → Preferences → SSH Keys.
Una regla, sin excepciones: pega el archivo .pub, nunca el archivo sin .pub. La clave pública es una línea que empieza por ssh-ed25519 AAAA… (o ssh-rsa AAAA…). Si lo que vas a pegar empieza por -----BEGIN OPENSSH PRIVATE KEY-----, para — esa es tu clave privada, el secreto que es tu identidad. Pegarla en un formulario web entrega tu credencial a cualquiera que pueda leer esa página. Comparte la mitad pública; protege la mitad privada.
(¿Aún sin clave? Genera una — Ed25519 en casi todos los casos (en inglés): ssh-keygen -t ed25519 -C "you@device".)
Culpable 2: se ofrece la clave equivocada
Tu clave está registrada, pero SSH está ofreciendo otra — habitual cuando llevas varias claves y el agente las prueba en un orden que el servidor rechaza. Mira exactamente qué clave se envía:
ssh -vT git@github.com
Busca las líneas Offering public key:. Si la clave que registraste no está entre ellas, o se está aceptando una equivocada, fija la clave correcta por host en ~/.ssh/config:
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
IdentitiesOnly yes es la línea clave — le dice a SSH que ofrezca solo el IdentityFile que nombraste y deje de rociar al servidor con cada clave de tu agente (lo que también cura Too many authentication failures). Haz lo mismo con Host gitlab.com para GitLab. Más sobre cómo estructurar el archivo en la guía de ssh_config (en inglés).
Culpable 3: el agente no está corriendo, o la clave no está cargada
Si tu clave tiene frase de contraseña y el agente no la guarda, SSH puede saltársela en silencio. Comprueba qué tiene el agente:
ssh-add -l
The agent has no identities (o Could not open a connection to your authentication agent) significa que necesitas arrancarlo y cargar la clave:
eval "$(ssh-agent -s)" # start the agent in this shell
ssh-add ~/.ssh/id_ed25519 # load the key (prompts for the passphrase once)
ssh-add -l debería listar ahora la huella de tu clave. (Para saber qué es el agente en realidad y cómo guarda las claves, mira qué es el agente SSH (en inglés).)
Culpable 4: estás en un remoto HTTPS, no en uno SSH
Este es el culpable detrás de «mi clave funciona (ssh -T tuvo éxito) pero git push sigue pidiéndome una contraseña». Tu repositorio está configurado para usar HTTPS, que ignora por completo las claves SSH y quiere un token. Comprueba:
git remote -v
Si ves https://github.com/you/repo.git, ese es el problema — HTTPS nunca toca tu clave SSH. Cambia el remoto a SSH:
git remote set-url origin git@github.com:you/repo.git # GitHub
git remote set-url origin git@gitlab.com:you/repo.git # GitLab
Ejecuta git remote -v de nuevo para confirmar que ahora empieza por git@. Este único arreglo resuelve una enorme parte de los reportes de «la clave SSH no funciona» en los que la clave estaba bien desde el principio.
Culpable 5: permisos en ~/.ssh
SSH se niega a usar claves y config que otros podrían manipular. Si la salida detallada menciona modos incorrectos, o se ignoran claves sin razón clara:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519 # private key
chmod 644 ~/.ssh/id_ed25519.pub # public key
chmod 600 ~/.ssh/config
En Windows esto aflora tras copiar claves desde una unidad sincronizada o entre máquinas; corrígelo en las propiedades de Seguridad del archivo, o mantén las claves fuera de las carpetas sincronizadas en la nube.
Culpable 6: te pide la frase de contraseña cada vez
Si cada operación de git exige la frase de contraseña de tu clave, el agente no la está cacheando. Cárgala una vez con ssh-add (en inglés) (culpable 3), y haz que persista entre sesiones añadiendo a ~/.ssh/config:
Host github.com gitlab.com
AddKeysToAgent yes
En macOS, ssh-add --apple-use-keychain ~/.ssh/id_ed25519 guarda la frase de contraseña en el Keychain para que sobreviva a los reinicios.
Culpable 7: dos cuentas, un solo host
Las cuentas de GitHub del trabajo y personal no pueden compartir una clave — una clave pública dada pertenece a exactamente una cuenta. Dale a cada una su propia clave y un alias Host que la seleccione:
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/work_ed25519
IdentitiesOnly yes
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/personal_ed25519
IdentitiesOnly yes
Luego clona o fija el remoto con el alias como host: git@github-work:org/repo.git. SSH coincide con github-work, elige la clave del trabajo, y reescribe la conexión a github.com por debajo.
Culpable 8: SSO de organización no autorizado (GitHub)
Te autenticas bien en tus propios repos pero obtienes Permission denied en los repos de una organización detrás de SAML SSO. La clave existe pero no está autorizada para esa organización. Ve a Settings → SSH and GPG keys, encuentra la clave, pulsa Configure SSO y autorízala para la organización. GitLab tiene un caso paralelo en el que una clave caducada se rechaza en silencio — revisa la fecha de caducidad de la clave en SSH Keys si una clave que funcionaba de repente deja de hacerlo.
Cuando sigue siendo Permission denied (publickey)
Si has repasado la lista y sigues topándote con el final, lo has acotado a un problema genuino de aceptación de clave — el bucle sistemático para ese error exacto (leer ssh -vvv, la lista de métodos del servidor, claves ofrecidas frente a aceptadas) está en permission denied (publickey), una solución sistemática rápida (en inglés), y el mapa más amplio de errores de SSH está en errores de SSH descifrados. Pero para los hosts de git en concreto, el orden de arriba atrapa casi todo: registra la clave pública, ofrece la correcta, cárgala en el agente, y asegúrate de que de verdad estás en un remoto SSH.
Donde un cliente elimina la configuración por completo
Casi toda esta fricción es contabilidad — qué clave pertenece a qué host, si está cargada, si el remoto siquiera es SSH. Termalin guarda la clave con el host al que pertenece, desbloquea tus claves una vez a través de un agente integrado para no reteclear frases de contraseña (y una petición cancelada nunca se salta una clave en silencio), y — como habla el protocolo estándar de ssh-agent — git y tu CLI pueden firmar a través de ese mismo agente. Las huellas son visibles por clave, así que registrar la mitad pública correcta en GitHub o GitLab es copiar y pegar en lugar de una caza por cinco carpetas ~/.ssh. Los malabares de cuentas y alias de arriba se convierten en un ajuste por host en lugar de un rompecabezas de archivo de configuración.
Termalin es un cliente SSH gratuito y multiplataforma que gestiona tus claves con un agente de un solo desbloqueo a través del cual git puede firmar — descárgalo, o lee cómo gestiona las claves con seguridad.