Sincronización de Claves SSH

NoxPanel sincroniza automáticamente las claves SSH del usuario hacia los shell users de hosting, permitiendo acceso SSH sin contraseña tanto a VMs como a hosting compartido desde una única sección del panel.

Visión General

Cuando un usuario añade o elimina una clave SSH en la sección Claves SSH del panel, NoxPanel despliega automáticamente esa clave en todos los shell users de hosting asociados al usuario, escribiendo el fichero authorized_keys en el contenedor hosting-core via SSH.

Note

Las claves SSH sirven tanto para VPS (Proxmox) como para hosting compartido. El panel muestra un banner informativo indicando esta doble funcionalidad.

Arquitectura

Módulo Principal

Ubicación: hosting/ssh_key_sync.py

Funciones principales:

build_authorized_keys_content(user) str

Recopila todas las claves SSH activas del usuario (modelo SSHKey en accounts/models.py) y genera el contenido del fichero authorized_keys.

get_shell_users_for_user(user) QuerySet

Encuentra todos los shell users activos del usuario siguiendo la cadena: User TenantUser Tenant HostingShellUser.

sync_ssh_keys_for_shell_user(shell_user, content) bool

Escribe el fichero authorized_keys en hosting-core via _ssh_exec():

  1. Obtiene UID/GID del usuario Linux con id -u / id -g

  2. Crea el directorio .ssh con mkdir -p

  3. Escribe el contenido con printf

  4. Aplica permisos: chmod 700 .ssh, chmod 600 authorized_keys

  5. Aplica ownership: chown uid:gid

sync_ssh_keys_for_user(user) dict

Función principal: sincroniza todas las claves de un usuario a todos sus shell users. Devuelve {'synced': N, 'errors': [...]}.

Triggers de Sincronización

La sincronización se dispara automáticamente en estos puntos:

Evento

Fichero

Detalle

Añadir clave SSH (web)

accounts/views.py

Después de SSHKey.objects.create()

Eliminar clave SSH (web)

accounts/views.py

Después de SSHKey.objects.filter().delete()

Añadir clave SSH (API)

accounts/api.py

SSHKeyViewSet.perform_create()

Eliminar clave SSH (API)

accounts/api.py

SSHKeyViewSet.perform_destroy()

Crear shell user (API)

hosting/api.py

HostingShellUserViewSet.perform_create()

Path del authorized_keys

Important

El path correcto es el del chroot, no el de ISPConfig:

/var/www/chroot/{username}/home/{username}/.ssh/authorized_keys

SSH lee authorized_keys antes del chroot, usando el home del usuario en /etc/passwd (que apunta a /home/{username} — un directorio que no existe). Por eso se requiere AuthorizedKeysFile explícito en sshd_config.

Configuración SSH en hosting-core

El Match Group shellusers en /etc/ssh/sshd_config debe incluir:

Match Group shellusers
    AuthorizedKeysFile /var/www/chroot/%u/home/%u/.ssh/authorized_keys
    ChrootDirectory /var/www/chroot/%u
    AllowTcpForwarding no
    X11Forwarding no
    PermitTunnel no
    AllowAgentForwarding no

Esta configuración se genera automáticamente en hosting-core/entrypoint.sh durante el arranque del contenedor (función configure_shell_sandbox).

Conexión SSH

Los usuarios se conectan via:

ssh {username}@{dominio} -p 2222

El puerto 2222 del host se mapea al puerto 22 del contenedor hosting-core.

Diagrama de Flujo

┌──────────────────┐
│ Usuario añade    │
│ clave SSH        │
│ (panel/API)      │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ SSHKey.create()  │
│ (accounts)       │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ sync_ssh_keys_   │
│ for_user()       │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐     SSH (paramiko)     ┌──────────────────┐
│ build_authorized │ ──────────────────────> │ hosting-core     │
│ _keys_content()  │                         │ authorized_keys  │
└──────────────────┘                         └──────────────────┘

Troubleshooting

El SSH sigue pidiendo contraseña:

  1. Verificar que la clave está en el path correcto:

    docker exec noxpanel-hosting-core-1 cat /var/www/chroot/{user}/home/{user}/.ssh/authorized_keys
    
  2. Verificar permisos (deben ser 700 el dir, 600 el archivo):

    docker exec noxpanel-hosting-core-1 ls -la /var/www/chroot/{user}/home/{user}/.ssh/
    
  3. Verificar AuthorizedKeysFile en sshd_config:

    docker exec noxpanel-hosting-core-1 grep AuthorizedKeysFile /etc/ssh/sshd_config
    
  4. Verificar que el usuario pertenece al grupo shellusers:

    docker exec noxpanel-hosting-core-1 groups {username}
    

La sincronización falla silenciosamente:

La sincronización usa try/except con pass para no bloquear la operación principal. Revisar logs de Django:

docker logs noxpanel-web-1 2>&1 | grep ssh_key_sync