devAlice
← Multi-OS

Desarrollo remoto — trabaja en otra máquina vía SSH · Tailscale · VS Code Remote

Controla tu escritorio en casa / servidor doméstico / estación de trabajo en la nube desde un portátil sin complicaciones — configuración unificada de Tailscale · SSH · VS Code Remote · tmux.

«Dejar el potente escritorio en casa y viajar ligero» o «usar una estación de trabajo GPU de forma remota»: el mismo escenario. Herramientas clave: Tailscale (VPN sin configuración) + SSH + VS Code Remote-SSH + tmux. Configúralo una vez y desde cualquier cafetería tendrás la misma experiencia que en tu escritorio.

Pienso que el desarrollo remoto no es un workaround, sino hoy la forma más sensata de trabajar con máquinas potentes. En lugar de cargar con hardware caro, lo que vale la pena invertir es en una conexión limpia y herramientas de sesión persistente.

TL;DR

  1. Tailscale — VPN en malla que atraviesa NAT y firewalls. Conecta máquinas sin VPN corporativa
  2. SSH — todo el tráfico tras la autenticación
  3. VS Code Remote-SSH — edita archivos remotos localmente como si fueran locales
  4. tmux — persistencia de sesión. El trabajo sobrevive a las desconexiones
  5. Mosh (opcional) — alternativa a SSH estable en redes móviles

Requisitos previos

  • SSH + cuentas + acceso a internet en ambos extremos
  • (Opcional) Sin necesidad de dominio ni IP estática: Tailscale lo gestiona

1. Configuración de Tailscale

Tailscale es una VPN en malla basada en WireGuard. Instala en cada máquina e inicia sesión con la misma cuenta → se asignan IPs privadas (100.x.x.x). NAT perforado, conexión directa.

1.1 Instalación

Mac:

brew install --cask tailscale

Windows:

winget install --id tailscale.tailscale

Linux (Ubuntu):

curl -fsSL https://tailscale.com/install.sh | sh

1.2 Iniciar sesión

En cada máquina:

sudo tailscale up      # Mac/Linux
# O usa la bandeja gráfica → Login

Se abre un navegador → regístrate con Google/GitHub/Microsoft (Tailscale gratuito: hasta 100 dispositivos).

1.3 Encontrar la IP de la máquina

tailscale ip -4
# 100.x.x.x

O consulta todas las máquinas en admin.tailscale.com.

1.4 Nombres de máquina (MagicDNS)

Consola de administración → DNS → activa MagicDNS. A partir de ahí, conéctate por SSH usando el nombre de host, p. ej. desktop.tail-scale.ts.net:

ssh me@desktop
# (.tail-scale.ts.net se añade automáticamente)

Una vez activado, puedes olvidarte de las IPs privadas. El resto de esta guía usa el nombre desktop.

2. Preparación de SSH

2.1 Activar SSH en el remoto

Mac (remoto):

  • Ajustes del sistema → General → Compartir → Inicio de sesión remoto activado

Windows (remoto):

  • Configuración → Sistema → Características opcionales → instala OpenSSH Server
  • PowerShell (admin):
    Set-Service -Name sshd -StartupType Automatic
    Start-Service sshd

Linux (remoto):

sudo apt install openssh-server
sudo systemctl enable --now ssh

2.2 Registrar la clave SSH

Añade la clave pública local al ~/.ssh/authorized_keys de la máquina remota:

# Local
ssh-copy-id me@desktop
# O manualmente en el remoto:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo "ssh-ed25519 AAAA..." >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

2.3 Conectar

ssh me@desktop
# O directamente a 100.x.x.x

3. VS Code Remote-SSH

Edita archivos remotos con la fluidez de un entorno local desde VS Code.

3.1 Instala la extensión

Marketplace de VS Code:

  • Remote - SSH (ms-vscode-remote.remote-ssh)

O:

code --install-extension ms-vscode-remote.remote-ssh

3.2 Conectar

Paleta de comandos de VS Code (⌘⇧P / Ctrl+Shift+P) → Remote-SSH: Connect to Host → introduce me@desktop.

La primera conexión instala VS Code Server en el remoto (~50 MB, solo una vez). Las siguientes son instantáneas.

3.3 Uso

La esquina inferior izquierda muestra SSH: desktop. File → Open Folder → abre ~/work/repo en el remoto. Las extensiones se instalan en el remoto (p. ej., la extensión de Python usa el entorno Python de la máquina remota).

3.4 Extensiones recomendadas (remoto)

  • ESLint / Prettier
  • Python / Pylance
  • Docker
  • (Mantén tema/mapa de teclas en local para mayor claridad)

4. tmux — Persistencia de sesión

Si se corta la conexión SSH, el trabajo continúa:

4.1 Instalación (en el remoto)

# Mac / Linux remoto
brew install tmux   # Mac
sudo apt install tmux   # Ubuntu

4.2 Uso

ssh me@desktop
tmux new -s work       # inicia sesión
# ...trabajo...
# Ctrl+B, D  → desconecta (la sesión sigue ejecutándose)
 
# Más tarde
ssh me@desktop
tmux attach -t work    # vuelve a conectar

4.3 Atajos de teclado

Atajo (prefijo = Ctrl+B)Acción
prefix + DDesconectar
prefix + CNueva ventana
prefix + N / PVentana siguiente / anterior
prefix + %División vertical
prefix + "División horizontal
prefix + flechasMover panel
prefix + ZZoom del panel

4.4 Conexión automática

.zshrc (en el remoto):

if [[ -z "$TMUX" && -n "$SSH_CONNECTION" ]]; then
  tmux attach -t main || tmux new -s main
fi

SSH entra → se conecta automáticamente a main (o lo crea).

5. Mosh — En redes móviles

Si la sesión SSH se corta con frecuencia al cambiar de red (5G ↔ Wi-Fi), usa Mosh (Mobile shell). Basado en UDP, con eco local y recuperación automática.

brew install mosh
# Remoto
sudo apt install mosh
mosh me@desktop

Usa SSH para autenticar + puertos UDP 60000-61000. No requiere configuración adicional del firewall si se pasa por Tailscale.

6. Escenario: Estación de trabajo GPU remota

Objetivo: entrenar ML en la GPU del escritorio desde un portátil.

# En el portátil
ssh me@gpu-workstation
tmux new -s train
 
# Dentro de tmux
cd ~/projects/ml
python train.py --epochs 100
 
# Ctrl+B, D para desconectar
 
# Cierra el portátil, ve a una cafetería
# Vuelve a conectar
ssh me@gpu-workstation
tmux attach -t train
# El entrenamiento continúa

Edita con VS Code Remote + ejecuta el entrenamiento en tmux. Ambos funcionan juntos.

7. Seguridad

ACL de Tailscale (opcional)

Por defecto, todas las máquinas de la misma cuenta se ven entre sí. Para mezclar dispositivos corporativos y personales:

  • Consola de administración → ACLs → política JSON
  • Permisos basados en etiquetas (tag:dev, tag:home)

Reforzar SSH

En el remoto /etc/ssh/sshd_config:

PasswordAuthentication no       # solo claves
PermitRootLogin no
AllowUsers me
sudo systemctl restart sshd

Agente SSH de 1Password

Consulta gestor de contraseñas. Con Tailscale + agente de 1Password, SSH solo necesita biométrico: sin frase de contraseña.

Verificación

  1. tailscale status en ambas → «online»
  2. ssh me@desktop → inicio de sesión instantáneo (una frase de contraseña o biométrico)
  3. Paleta de comandos de VS Code → Remote-SSH Connect → edita + guarda → los cambios se reflejan en el remoto
  4. tmux new -s test → desconecta → tmux attach -t test → estado preservado
  5. mosh me@desktop → desconecta la Wi-Fi, cambia de red → la sesión se recupera automáticamente

Resolución de problemas

Tailscale no conecta

  • Ambas máquinas ejecutan tailscale up y tienen sesión iniciada
  • La consola de administración las muestra como «Connected»
  • Firewall: Tailscale usa 41641/UDP. Las redes corporativas pueden bloquearlo (en ese caso usa el relay DERP)

ssh: connect to host 100.x.x.x: Connection refused

  • El servicio SSH no está activo en el remoto (revisa §2.1)
  • Windows: comprueba con Get-Service sshd si el estado es Running

VS Code Remote es lento

  • La primera conexión instala el Server: es lento solo la primera vez
  • Si va por internet (Tailscale Direct falló): ejecuta tailscale ping desktop para ver si la conexión es directa o pasa por DERP

Colores rotos en tmux

.tmux.conf:

set -g default-terminal "screen-256color"
set -ga terminal-overrides ",xterm-256color:Tc"

Mosh no conecta

Los puertos UDP 60000-61000 están bloqueados, algo habitual en redes corporativas. Vuelve a SSH. Mosh requiere UDP.

Reenvío del agente SSH (con precaución)

Para SSH desde el remoto a otro remoto, usa ssh -A. Solo cuando el remoto intermedio sea de confianza: un root malicioso podría ver las claves.

Referencias

Historial de cambios

  • 2026-05-12: Primer borrador. Tailscale · SSH · VS Code Remote · tmux · Mosh + escenario · seguridad + seis casos de resolución de problemas.