Instalación de Servidor VNC en Linux

VNC (Virtual Network Computing) es un protocolo de escritorio remoto multiplataforma que permite acceder y controlar el escritorio gráfico de un servidor Linux desde cualquier sistema operativo con un visor VNC. TigerVNC es la implementación más activa y completa de VNC para Linux, con soporte para cifrado TLS, autenticación mejorada y alta calidad de imagen. Esta guía cubre la instalación de TigerVNC en Ubuntu/Debian y CentOS/Rocky, con tunnel SSH para acceso seguro.

Requisitos Previos

  • Servidor Linux (Ubuntu 22.04/Debian 12 o CentOS 9/Rocky 9)
  • Entorno de escritorio instalado (XFCE recomendado para servidores)
  • Mínimo 1 GB de RAM (2 GB para una experiencia fluida)
  • Conexión SSH al servidor (para túnel seguro)
  • Cliente VNC: TigerVNC Viewer, RealVNC Viewer, Remmina (Linux), o VNC Viewer (macOS/Windows)

Instalación del Entorno de Escritorio

# Ubuntu 22.04 / Debian 12 - XFCE (ligero, recomendado para servidores)
apt-get update
apt-get install -y xfce4 xfce4-goodies dbus-x11 x11-xserver-utils

# Alternativamente, instalar solo los componentes mínimos de XFCE
# apt-get install -y xfce4-session xfce4-panel xfwm4 thunar

# CentOS 9 / Rocky Linux 9
dnf groupinstall -y "Xfce"
# O GNOME si se prefiere:
# dnf groupinstall -y "Server with GUI"

# Verificar que los binarios del escritorio están disponibles
which startxfce4
which xfce4-session

Instalación de TigerVNC

# Ubuntu/Debian
apt-get install -y tigervnc-standalone-server tigervnc-tools

# CentOS/Rocky Linux
dnf install -y tigervnc-server

# Verificar la instalación
vncserver --version

# Ubicación de los binarios
which vncserver   # Script de gestión
which Xvnc       # Servidor X con soporte VNC integrado

Configuración del Servidor VNC

Configura el servidor VNC para el usuario que necesita acceso gráfico:

# Los siguientes comandos se ejecutan como el USUARIO (no root)
# que necesita acceso VNC

# Paso 1: Establecer la contraseña VNC (se usa para autenticar la sesión)
vncpasswd
# Ingresar contraseña (mínimo 6 caracteres, máximo 8 se usan para autenticación)
# Preguntar si se quiere contraseña de solo vista: n (normalmente)

# La contraseña se guarda cifrada en ~/.vnc/passwd
ls -la ~/.vnc/

# Paso 2: Crear el script de inicio de la sesión de escritorio
mkdir -p ~/.vnc
cat > ~/.vnc/xstartup << 'EOF'
#!/bin/bash
# Script de inicio del escritorio para TigerVNC

# Desactivar el salvapantallas y gestor de energía
[ -x /usr/bin/xrdb ] && /usr/bin/xrdb $HOME/.Xresources

# Exportar variables de entorno necesarias
export XDG_CURRENT_DESKTOP=XFCE
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus

# Iniciar gestor de composición (opcional, mejora el aspecto visual)
# xcompmgr &

# Iniciar el entorno XFCE
exec startxfce4
EOF
chmod +x ~/.vnc/xstartup

# Paso 3: Crear el archivo de configuración del servidor VNC
cat > ~/.vnc/config << 'EOF'
# Resolución de la pantalla virtual
geometry=1920x1080

# Profundidad de color (24 bits = color verdadero)
depth=24

# Nivel de compresión (0=sin compresión, 9=máxima, 6 es buen equilibrio)
ZlibLevel=6

# Calidad de JPEG para imágenes (0-9, mayor = mejor calidad pero más ancho de banda)
Quality=7

# Número de pantalla virtual (cambiar si hay conflictos)
# El display :1 es el primero para VNC, escucha en el puerto 5901
# El display :2 escucha en 5902, etc.

# Activar TLS para cifrado (requiere certificado)
# SecurityTypes=VeNCrypt,TLSVnc
# Desactivar autenticación sin cifrar en producción
EOF

Inicia el servidor VNC manualmente para probar:

# Iniciar el servidor VNC en el display :1 (puerto 5901)
vncserver :1

# Ver los servidores VNC en ejecución
vncserver -list

# Para la sesión VNC (cuando sea necesario)
vncserver -kill :1

# Iniciar con configuración personalizada
vncserver :1 \
  -geometry 1920x1080 \
  -depth 24 \
  -localhost no  # Permitir conexiones remotas (sin tunnel SSH)
  # Si se usa tunnel SSH, usar -localhost (por defecto)

Servicio systemd para VNC

Configura VNC como servicio del sistema para inicio automático:

# Crear la unidad de servicio systemd para el usuario VNC
# (ejecutar como ROOT)
cat > /etc/systemd/system/[email protected] << 'EOF'
[Unit]
Description=TigerVNC Server para el display :%i
Documentation=man:vncserver(1) man:Xvnc(1)
After=syslog.target network-online.target

[Service]
Type=forking
# Cambiar 'usuario-vnc' por el nombre del usuario real
User=usuario-vnc
Group=usuario-vnc

# Esperar a que el directorio de runtime del usuario exista
ExecStartPre=/bin/sh -c 'until [ -S /run/user/$(id -u usuario-vnc)/bus ]; do sleep 0.5; done'

# Limpiar el socket de bloqueo si existe de una sesión anterior
ExecStartPre=-/bin/sh -c '/usr/bin/vncserver -kill :%i > /dev/null 2>&1 || :'

# Iniciar el servidor VNC
ExecStart=/usr/bin/vncserver :%i \
    -geometry 1920x1080 \
    -depth 24 \
    -localhost \
    -fg

# Parar el servidor VNC
ExecStop=/usr/bin/vncserver -kill :%i

# Reiniciar si falla inesperadamente
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

# Habilitar el servicio (el número después de @ es el número de display)
systemctl daemon-reload
systemctl enable --now [email protected]

# Verificar el estado
systemctl status [email protected]

# Ver los logs del servicio VNC
journalctl -u [email protected] -f

Tunnel SSH para Acceso Seguro

VNC por defecto no cifra el tráfico. Siempre usar un tunnel SSH o TLS:

# NUNCA exponer VNC directamente en una IP pública
# El puerto 5901 NO debe estar abierto en el firewall externo

# Configurar el firewall para bloquear el acceso directo a VNC
# Ubuntu (UFW)
ufw deny 5901/tcp
ufw deny 5902/tcp
# Solo permitir SSH
ufw allow 22/tcp

# CentOS/Rocky (firewalld)
firewall-cmd --remove-port=5901/tcp --permanent
firewall-cmd --add-service=ssh --permanent
firewall-cmd --reload

Crear el tunnel SSH desde el cliente:

# Linux/macOS - Crear tunnel SSH y conectar VNC
# El tunnel redirige localhost:5901 en el cliente al puerto 5901 del servidor
ssh -L 5901:localhost:5901 -N -f [email protected]

# Conectar el visor VNC a través del tunnel
vncviewer localhost:5901  # Linux con TigerVNC Viewer
# En macOS: open vnc://localhost:5901

# Windows (PowerShell con OpenSSH o PuTTY)
# OpenSSH: ssh -L 5901:localhost:5901 [email protected] -N
# PuTTY: Session > SSH > Tunnels > Source port: 5901, Destination: localhost:5901

# Script completo para Linux/macOS que conecta el tunnel y lanza el visor
cat > ~/vnc-connect.sh << 'SCRIPT'
#!/bin/bash
SERVER="${1:?Especificar servidor: ./vnc-connect.sh [email protected]}"
DISPLAY_NUM="${2:-1}"
LOCAL_PORT=$((5900 + DISPLAY_NUM))

echo "Conectando VNC al servidor $SERVER, display :$DISPLAY_NUM"

# Crear tunnel SSH en segundo plano
ssh -L ${LOCAL_PORT}:localhost:${LOCAL_PORT} \
    -o ExitOnForwardFailure=yes \
    -o ConnectTimeout=10 \
    -N -f "$SERVER"

if [ $? -ne 0 ]; then
    echo "ERROR: No se pudo establecer el tunnel SSH"
    exit 1
fi

echo "Tunnel SSH establecido. Iniciando visor VNC..."
sleep 1

# Conectar visor VNC a través del tunnel
vncviewer localhost:${LOCAL_PORT}

# Al cerrar el visor, terminar el tunnel SSH
pkill -f "ssh -L ${LOCAL_PORT}:localhost:${LOCAL_PORT}"
SCRIPT
chmod +x ~/vnc-connect.sh

Múltiples Usuarios VNC

# Cada usuario puede tener su propio servidor VNC en un display diferente
# Usuario 1: display :1 (puerto 5901)
# Usuario 2: display :2 (puerto 5902)
# Usuario 3: display :3 (puerto 5903)

# Crear servicios systemd para múltiples usuarios
for USUARIO in alice bob charlie; do
    cat > /etc/systemd/system/vncserver-${USUARIO}@.service << EOF
[Unit]
Description=TigerVNC Server para $USUARIO en display :%i
After=syslog.target network-online.target

[Service]
Type=forking
User=$USUARIO
Group=$USUARIO
ExecStartPre=-/bin/sh -c '/usr/bin/vncserver -kill :%i > /dev/null 2>&1 || :'
ExecStart=/usr/bin/vncserver :%i -geometry 1920x1080 -depth 24 -localhost -fg
ExecStop=/usr/bin/vncserver -kill :%i
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
done

# Habilitar servicios en displays distintos
systemctl enable --now [email protected]
systemctl enable --now [email protected]
systemctl enable --now [email protected]

# Script para ver todas las sesiones VNC activas
cat > /usr/local/bin/vnc-status.sh << 'SCRIPT'
#!/bin/bash
echo "=== Sesiones VNC activas ==="
for i in 1 2 3 4 5; do
    if ss -tlnp | grep -q ":590${i} "; then
        PID=$(ss -tlnp | grep ":590${i} " | awk '{print $NF}' | grep -o 'pid=[0-9]*' | cut -d= -f2)
        OWNER=$(ps -o user= -p "$PID" 2>/dev/null)
        echo "Display :$i (puerto 590$i) - Usuario: $OWNER - PID: $PID"
    fi
done
SCRIPT
chmod +x /usr/local/bin/vnc-status.sh

Solución de Problemas

# Ver logs del servidor VNC
cat ~/.vnc/$(hostname):1.log

# O mediante journalctl si se usa el servicio systemd
journalctl -u [email protected] --since "1 hour ago"

# El escritorio no aparece (pantalla negra o gris)
# Verificar que el script ~/.vnc/xstartup está correcto y tiene permisos
chmod +x ~/.vnc/xstartup
# Probar el escritorio manualmente:
DISPLAY=:1 xterm &  # Si esto funciona, el problema es xstartup

# Error "Authentication failed" al conectar
# Verificar la contraseña VNC
vncpasswd  # Restablecer la contraseña VNC

# Error de "connection refused"
# Verificar que el servidor VNC está en ejecución
vncserver -list
ss -tlnp | grep 5901

# El servidor VNC no arranca como servicio
systemctl status [email protected]
# Ver si hay errores de permisos o dependencias

# Sesión VNC muy lenta
# Reducir la resolución o la profundidad de color
vncserver :1 -geometry 1280x720 -depth 16

# Usar un cliente VNC con compresión eficiente
# TigerVNC Viewer soporta compresión Tight+JPEG por defecto

# Problemas con dbus en sesiones VNC (errores de aplicaciones)
dbus-launch --exit-with-session startxfce4 &
# Añadir esta línea al inicio de ~/.vnc/xstartup

Conclusión

TigerVNC es la solución VNC más robusta para Linux, proporcionando acceso remoto a escritorios gráficos con buena calidad de imagen y rendimiento. La clave para un despliegue seguro es siempre usar un tunnel SSH en lugar de exponer el puerto VNC directamente, configurar el servicio systemd para reinicio automático, y usar contraseñas VNC fuertes. Para entornos de producción con múltiples usuarios, considera evaluar Apache Guacamole como alternativa centralizada con autenticación web y sin necesidad de cliente VNC en los dispositivos de los usuarios.