{*}SecureCodeHQ
SSH para developers: claves, servidores y agentes IA
·por Juan Isidoro·9 min de lectura

SSH para developers: claves, servidores y agentes IA

Configura SSH paso a paso: conexion a servidores, deploy keys en GitHub, y como proteger tus claves cuando usas Claude Code o Cursor.

sshsecuritydevopsai-agentsbest-practices

SSH te autentica sin contrasenas usando criptografia asimetrica. En lugar de enviar un secreto por la red, demuestras que tienes la clave privada sin revelarla jamas.

Este tutorial cubre tres escenarios que vas a encontrarte si o si:

  1. Conectar desde tu PC a un servidor
  2. Que tu servidor clone repos privados de GitHub
  3. Usar SSH con agentes de IA (Claude Code, Cursor, Copilot Workspace...)

Una vez entiendas estos tres, entiendes SSH.


Como funciona: pares de claves

Siempre trabajas con un par:

ClaveDonde viveQue hace
PrivadaNunca sale de donde se generoFirma mensajes para demostrar identidad
PublicaSe copia a donde quieres accederVerifica que la firma es valida

Piensalo asi: la privada es tu DNI. La publica es una fotocopia que dejas en recepcion de los sitios donde quieres que te dejen pasar.


Caso 1: Conectar tu PC a un servidor

El escenario mas comun. Quieres hacer ssh usuario@servidor sin escribir contrasena cada vez.

Paso 1: Genera el par en tu PC

ssh-keygen -t ed25519 -C "tu-email@ejemplo.com"

Esto crea dos ficheros en ~/.ssh/:

~/.ssh/
├── id_ed25519       # Clave privada — no la compartas jamas
└── id_ed25519.pub   # Clave publica — esta si la copias

Paso 2: Copia la publica al servidor

# Opcion automatica (recomendada)
ssh-copy-id usuario@ip-del-servidor

# Opcion manual
cat ~/.ssh/id_ed25519.pub | ssh usuario@ip-del-servidor "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Paso 3: Conecta

ssh usuario@ip-del-servidor

Sin contrasena. SSH firma con tu clave privada, el servidor verifica con la publica que tiene guardada.

Que hay en el servidor

~/.ssh/
└── authorized_keys   # Una linea por cada PC/persona autorizada

El contenido es simple:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... tu-email@ejemplo.com
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... otro-dev@empresa.com

Quieres dar acceso a alguien? Anade su .pub como nueva linea. Revocar? Borra la linea.

Diagrama del flujo

TU PC                              SERVIDOR
─────                              ────────
~/.ssh/id_ed25519      ──firma──►
~/.ssh/id_ed25519.pub             ~/.ssh/authorized_keys
                       ◄─verifica─

Caso 2: Tu servidor necesita acceso a GitHub

El servidor tiene que clonar repos privados o hacer git pull en deployments automaticos.

Paso 1: Genera el par en el servidor

ssh-keygen -t ed25519 -C "deploy@mi-servidor"

Paso 2: Anade la publica a GitHub

cat ~/.ssh/id_ed25519.pub

Copia el contenido y ve a:

  • Un repo concreto: Settings > Deploy Keys > Add deploy key
  • Todos tus repos: Profile > Settings > SSH Keys

Paso 3: Prueba la conexion

ssh -T git@github.com

Si funciona:

Hi usuario! You've successfully authenticated...

Paso 4: Clona o haz pull

git clone git@github.com:usuario/repo-privado.git

Sin credenciales.

Diagrama

SERVIDOR                           GITHUB
────────                           ──────
~/.ssh/id_ed25519      ──firma──►
~/.ssh/id_ed25519.pub             Deploy Key
                       ◄─verifica─

Caso 3: SSH con agentes de IA

Aqui es donde muchos developers la lian sin darse cuenta.

Herramientas como Claude Code, Cursor, Aider o Copilot Workspace ejecutan comandos en tu nombre. Cuando dices "despliega esto en produccion" o "clona el repo y arregla el bug", el agente necesita acceso SSH.

El problema

Tu clave SSH privada es lo mas sensible que tienes. Si un agente tiene acceso a ~/.ssh/id_ed25519, tiene acceso a todo lo que esa clave abre: servidores de produccion, repos privados, infraestructura critica.

No es que el agente sea malicioso. Es que:

  1. Errores de contexto: le pides que "limpie ficheros temporales" y borra ~/.ssh/ porque interpreto mal
  2. Prompt injection: codigo malicioso en un repo que clona le inyecta instrucciones
  3. Logs y telemetria: algunos agentes loguean comandos ejecutados, incluyendo claves si las pasas inline
  4. Scope excesivo: le das acceso a produccion para una tarea que solo necesitaba staging

Reglas para usar SSH con agentes

1. Nunca expongas tu clave principal

Crea claves especificas para el agente con permisos minimos:

# Clave solo para el agente, solo para staging
ssh-keygen -t ed25519 -f ~/.ssh/id_agent_staging -C "agent-staging-only"

2. Usa deploy keys de solo lectura

En GitHub, no marques "Allow write access" a menos que el agente realmente necesite hacer push.

3. Limita el scope en ~/.ssh/config

# El agente solo puede usar esta clave para staging
Host staging-for-agent
    HostName staging.miempresa.com
    User deployer
    IdentityFile ~/.ssh/id_agent_staging
    # Produccion ni aparece en su config

4. Usa passphrase + ssh-agent con timeout

# Clave protegida con passphrase
ssh-keygen -t ed25519 -f ~/.ssh/id_agent -C "agent"
# (te pedira passphrase)

# Anadela al agente SSH con expiracion de 1 hora
ssh-add -t 3600 ~/.ssh/id_agent

El agente de IA puede usar la clave mientras este en memoria, pero no puede extraerla ni usarla despues del timeout.

5. Audita que comandos ejecuta

Antes de dar acceso SSH a un agente, entiende que va a hacer. Si la tarea es "formatea este codigo", no necesita SSH. Si es "despliega en produccion", piensatelo dos veces.

6. Separa entornos radicalmente

~/.ssh/
├── id_personal           # Tu uso, nunca para agentes
├── id_trabajo            # Uso manual en trabajo
├── id_agent_staging      # Solo agentes, solo staging
└── id_agent_ci           # Solo CI/CD automatizado

7. Considera un vault para claves sensibles

En lugar de dejar claves en disco, usa un gestor de secretos que requiera autenticacion explicita para cada uso. El agente no puede usar lo que no tiene.

Lo que NO debes hacer

  • Dar al agente tu ~/.ssh/id_ed25519 principal
  • Ejecutar comandos SSH que el agente sugiere sin revisarlos
  • Asumir que "es solo desarrollo" cuando la clave tambien abre produccion
  • Poner claves privadas en variables de entorno que el agente puede leer
  • Confiar en que el agente "sabe" que claves son sensibles

Ejemplo de setup seguro para Claude Code

# 1. Crea clave especifica
ssh-keygen -t ed25519 -f ~/.ssh/id_claude_code -C "claude-code-dev"

# 2. Config restrictivo
cat >> ~/.ssh/config << 'EOF'
Host dev-server
    HostName 192.168.1.50
    User developer
    IdentityFile ~/.ssh/id_claude_code
EOF

# 3. Solo esta clave en authorized_keys del servidor de dev
# (no en produccion)

# 4. En GitHub: deploy key de solo lectura en repos no criticos

Ahora Claude Code puede trabajar en tu servidor de desarrollo, pero no tiene acceso a produccion ni puede hacer push a repos criticos.


Anatomia del directorio ~/.ssh/

FicheroQue esNombre fijo?
id_ed25519Tu clave privadaNo, es el default
id_ed25519.pubTu clave publicaNo, es el default
authorized_keysClaves publicas que pueden conectarSi
known_hostsHuellas de servidores conocidosSi
configConfiguracion de hosts y aliasesSi

El fichero known_hosts

La primera vez que conectas a un servidor, SSH pregunta:

The authenticity of host '192.168.1.100' can't be established.
ED25519 key fingerprint is SHA256:xXxXxXx...
Are you sure you want to continue connecting (yes/no)?

Si dices yes, guarda la huella. La proxima vez no pregunta.

Si el servidor cambia (lo reinstalaste, cambio de IP), SSH avisa:

WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

Solucion:

ssh-keygen -R 192.168.1.100

Multiples claves con ~/.ssh/config

Si manejas varios servidores y servicios:

# Produccion
Host prod
    HostName 162.55.62.72
    User deployer
    IdentityFile ~/.ssh/id_produccion

# Desarrollo
Host dev
    HostName 192.168.1.50
    User dev
    IdentityFile ~/.ssh/id_desarrollo

# GitHub personal
Host github.com
    IdentityFile ~/.ssh/id_github_personal

# GitHub trabajo (cuenta diferente)
Host github-trabajo
    HostName github.com
    IdentityFile ~/.ssh/id_github_trabajo

Ahora:

ssh prod                    # en lugar de ssh deployer@162.55.62.72
git clone git@github-trabajo:empresa/repo.git

Diagrama completo

TU PC                          SERVIDOR                         GITHUB
─────                          ────────                         ──────

~/.ssh/                        ~/.ssh/
├── id_ed25519 ───────────────► authorized_keys
├── id_ed25519.pub             ├── id_ed25519 ─────────────────► Deploy Key
├── id_agent_staging ─────────► authorized_keys (solo staging)
├── known_hosts                ├── id_ed25519.pub
└── config                     └── known_hosts


Flujo 1: PC > Servidor
         Firma con privada local, verifica con publica en authorized_keys

Flujo 2: Servidor > GitHub
         Firma con privada del servidor, verifica con publica en Deploy Keys

Flujo 3: Agente IA > Servidor dev
         Usa clave especifica con scope limitado

Comandos de referencia

# Generar par de claves
ssh-keygen -t ed25519 -C "comentario"

# Generar con nombre especifico
ssh-keygen -t ed25519 -f ~/.ssh/mi_clave -C "comentario"

# Copiar publica a servidor
ssh-copy-id usuario@servidor

# Ver tu clave publica
cat ~/.ssh/id_ed25519.pub

# Probar conexion a GitHub
ssh -T git@github.com

# Limpiar huella de servidor antiguo
ssh-keygen -R ip-del-servidor

# Conectar con clave especifica
ssh -i ~/.ssh/mi_clave usuario@servidor

# Ver fingerprint de una clave
ssh-keygen -lf ~/.ssh/id_ed25519.pub

# Anadir clave al agente SSH con timeout (1 hora)
ssh-add -t 3600 ~/.ssh/mi_clave

# Listar claves en el agente SSH
ssh-add -l

# Eliminar todas las claves del agente SSH
ssh-add -D

Errores comunes

"Permission denied (publickey)"

  • Tu clave publica no esta en authorized_keys del servidor
  • Estas usando la clave privada incorrecta
  • Solucion: verifica con ssh -v usuario@servidor para ver que clave intenta usar

"WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED"

  • El servidor cambio (reinstalado, IP reasignada a otra maquina)
  • Solucion: ssh-keygen -R ip-del-servidor

"Permissions are too open"

  • La clave privada tiene permisos 644 o similares
  • Solucion: chmod 600 ~/.ssh/id_ed25519

"Could not resolve hostname"

  • El alias en ~/.ssh/config esta mal escrito
  • No tienes entrada para ese host

"Agent admitted failure to sign"

  • El agente SSH no tiene la clave cargada
  • Solucion: ssh-add ~/.ssh/tu_clave

Checklist de seguridad SSH

  • Cada contexto (personal, trabajo, CI, agentes IA) tiene su propia clave
  • Las claves privadas tienen permisos 600
  • El directorio ~/.ssh tiene permisos 700
  • Las claves sensibles tienen passphrase
  • Los agentes de IA solo acceden a claves de scope limitado
  • Deploy keys en GitHub son de solo lectura salvo que necesites push
  • Tienes backup de claves de infraestructura en un vault
  • Rotas claves cuando alguien deja el equipo o una maquina se compromete
  • No hay claves privadas en repos, logs ni variables de entorno expuestas

Conclusion

SSH no es complicado una vez entiendes que todo gira alrededor de un concepto: la clave privada firma, la publica verifica.

Lo que si se complica es gestionar multiples claves en multiples contextos, sobre todo ahora que los agentes de IA entran en el flujo de trabajo. La regla de oro: minimo privilegio. Cada clave debe abrir solo las puertas que necesita abrir, y los agentes automatizados deben tener las llaves mas restrictivas de todas.


Lectura adicional