Saltar a contenido

🔧 Troubleshooting - Solución de Problemas

Guía de diagnóstico y solución de problemas comunes en el VPS.


Índice


Problemas de SSH

No puedo conectarme por SSH

Síntomas:

ssh: connect to host YOUR_SERVER_IP port 22: Connection refused

Diagnóstico:

# Verificar que el servicio SSH está corriendo
sudo systemctl status ssh

# Ver logs de SSH
sudo journalctl -u ssh -f

# Verificar reglas del firewall UFW
sudo ufw status

# Verificar que el puerto 22 está escuchando
sudo ss -tulpn | grep :22

Soluciones:

  1. SSH no está corriendo:

    sudo systemctl start ssh
    sudo systemctl enable ssh
    

  2. Firewall bloqueando:

    sudo ufw allow OpenSSH
    sudo ufw enable
    

  3. Verificar firewall de Hetzner Cloud:

  4. Ve al panel de Hetzner
  5. Verifica que el puerto 22 está permitido

  6. Usar Hetzner Rescue Console:

  7. Si todo falla, usa la consola de rescate desde el panel de Hetzner
  8. Puedes acceder directamente sin SSH

"Permission denied (publickey)"

Síntomas:

Permission denied (publickey).

Diagnóstico:

# Verificar que tienes clave SSH
ls -la ~/.ssh/

# Conectar con verbose para ver detalles
ssh -v your_username@YOUR_SERVER_IP

Soluciones:

  1. No tienes clave SSH:

    ssh-keygen -t ed25519 -C "[email protected]"
    

  2. Clave no está en el servidor:

    ssh-copy-id your_username@YOUR_SERVER_IP
    

  3. Permisos incorrectos:

    # En el VPS:
    chmod 700 ~/.ssh
    chmod 600 ~/.ssh/authorized_keys
    

  4. Usuario no permitido (AllowUsers):

    # Editar SSH config
    sudo nano /etc/ssh/sshd_config
    # Añadir tu usuario a AllowUsers
    sudo systemctl restart ssh
    

Conexión muy lenta

Síntomas: La conexión SSH tarda mucho en establecerse.

Solución:

# Deshabilitar DNS lookup en SSH
sudo nano /etc/ssh/sshd_config

# Añadir o descomentar:
UseDNS no

# Reiniciar SSH
sudo systemctl restart ssh

Problemas de Docker

"permission denied" al usar Docker

Síntomas:

Got permission denied while trying to connect to the Docker daemon socket

Diagnóstico:

# Verificar que estás en el grupo docker
groups

Solución:

# Añadirte al grupo docker
sudo usermod -aG docker $USER

# Cerrar sesión y volver a entrar
exit
ssh your_username@YOUR_SERVER_IP

# Verificar
groups
# Deberías ver "docker" en la lista

Docker no funciona después de instalarlo

Síntomas: Docker commands no funcionan o dicen que Docker no está instalado.

Diagnóstico:

# Verificar instalación
docker --version

# Verificar servicio
sudo systemctl status docker

Solución:

# Iniciar Docker
sudo systemctl start docker
sudo systemctl enable docker

# Si sigue sin funcionar, reinstalar
sudo apt remove docker.io
sudo apt install docker.io -y

Contenedor no arranca

Síntomas: docker compose up falla o el contenedor se detiene inmediatamente.

Diagnóstico:

# Ver logs del contenedor
docker logs nombre_contenedor

# Ver todos los contenedores (incluidos parados)
docker ps -a

# Inspeccionar contenedor
docker inspect nombre_contenedor

Soluciones comunes:

  1. Puerto ya en uso:

    # Ver qué está usando el puerto
    sudo ss -tulpn | grep :3000
    
    # Cambiar puerto en docker-compose.yml
    

  2. Imagen corrupta:

    # Eliminar imagen y volver a descargar
    docker rmi nombre_imagen
    docker compose pull
    docker compose up -d
    

  3. Error de configuración:

    # Verificar sintaxis de docker-compose.yml
    docker compose config
    

  4. Sin memoria:

    free -h
    docker system prune -a
    

"No space left on device"

Síntomas:

Error: No space left on device

Diagnóstico:

# Ver uso de disco
df -h

# Ver uso de Docker
docker system df

Solución:

# Limpiar imágenes no usadas
docker image prune -a

# Limpiar volúmenes huérfanos
docker volume prune

# Limpieza completa (cuidado)
docker system prune -a --volumes

# Ver logs grandes
sudo du -sh /var/lib/docker/*

Problemas de Nginx

Nginx no arranca

Síntomas:

nginx.service: Failed with result 'exit-code'

Diagnóstico:

# Verificar configuración
sudo nginx -t

# Ver logs de error
sudo tail -f /var/log/nginx/error.log

# Ver qué está usando el puerto 80
sudo ss -tulpn | grep :80

Soluciones comunes:

  1. Error de sintaxis:

    # Ver error específico
    sudo nginx -t
    
    # Editar archivo con error
    sudo nano /etc/nginx/sites-available/nombre-sitio
    

  2. Puerto 80 ya en uso:

    # Ver qué lo está usando
    sudo ss -tulpn | grep :80
    
    # Si es Apache:
    sudo systemctl stop apache2
    sudo systemctl disable apache2
    

  3. Certificado SSL no encontrado:

    # Verificar que existe
    ls -la /etc/letsencrypt/live/tu-dominio/
    
    # Si no existe, emitirlo
    sudo certbot certonly --dns-cloudflare \
      --dns-cloudflare-credentials /root/.secrets/cf.ini \
      -d tu-dominio.com
    

Veo "Welcome to nginx!" en lugar de mi aplicación

Causa: El sitio default está capturando las peticiones.

Solución:

# Deshabilitar sitio default
sudo rm /etc/nginx/sites-enabled/default

# Recargar Nginx
sudo systemctl reload nginx

"502 Bad Gateway"

Síntomas: Nginx responde pero muestra error 502.

Causa: Nginx no puede conectar con la aplicación backend.

Diagnóstico:

# Verificar que el contenedor está corriendo
docker ps

# Verificar logs del contenedor
docker logs nombre_contenedor

# Probar conexión al backend
curl http://localhost:3000

# Ver logs de Nginx
sudo tail -f /var/log/nginx/error.log

Soluciones:

  1. Contenedor no está corriendo:

    cd ~/apps/nombre-app
    docker compose up -d
    

  2. Puerto incorrecto en Nginx:

    # Verificar puerto en docker-compose.yml
    cat ~/apps/nombre-app/docker-compose.yml
    
    # Actualizar proxy_pass en Nginx
    sudo nano /etc/nginx/sites-available/nombre-sitio
    # proxy_pass http://127.0.0.1:PUERTO_CORRECTO;
    
    sudo systemctl reload nginx
    

  3. Aplicación no responde:

    docker logs nombre_contenedor
    docker compose restart
    

"504 Gateway Timeout"

Síntomas: La petición tarda demasiado y Nginx devuelve 504.

Solución:

# Aumentar timeouts en Nginx
sudo nano /etc/nginx/sites-available/nombre-sitio

# Añadir dentro del bloque location:
proxy_connect_timeout 120s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;

sudo nginx -t && sudo systemctl reload nginx

Cambios no se aplican

Síntomas: Editas configuración pero no ves cambios.

Solución:

# Verificar sintaxis primero
sudo nginx -t

# Recargar (NO restart)
sudo systemctl reload nginx

# Si no funciona, reiniciar
sudo systemctl restart nginx

# Limpiar caché del navegador o probar en modo incógnito

Problemas de SSL/Certificados

Certbot falla al emitir certificado

Síntomas:

Timeout during connect (likely firewall problem)

Diagnóstico:

# Verificar credenciales de Cloudflare
sudo cat /root/.secrets/cf.ini

# Verificar que el dominio existe en Cloudflare
ping tu-dominio.com

# Test manual
sudo certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/cf.ini \
  -d tu-dominio.com --dry-run

Soluciones:

  1. Token incorrecto o sin permisos:
  2. Verifica el token en Cloudflare
  3. Crea un nuevo token si es necesario
  4. Actualiza /root/.secrets/cf.ini

  5. Dominio no en Cloudflare:

  6. Añade el dominio a Cloudflare
  7. Espera propagación DNS (puede tardar minutos)

  8. Límite de rate limiting:

  9. Let's Encrypt tiene límites (5 certificados/semana por dominio)
  10. Espera una semana o usa --dry-run para probar

"Certificate verification failed"

Síntomas: El navegador muestra advertencia de certificado inválido.

Diagnóstico:

# Verificar certificado
sudo certbot certificates

# Ver fecha de expiración
sudo openssl x509 -in /etc/letsencrypt/live/tu-dominio/cert.pem -noout -dates

# Ver qué certificado está usando Nginx
curl -vI https://tu-dominio.com 2>&1 | grep -i "certificate"

Soluciones:

  1. Certificado expirado:

    sudo certbot renew --force-renewal
    sudo systemctl reload nginx
    

  2. Nginx usando certificado incorrecto:

    # Verificar paths en Nginx
    sudo grep -r "ssl_certificate" /etc/nginx/sites-enabled/
    
    # Deben apuntar a /etc/letsencrypt/live/...
    

  3. Cloudflare no en modo Full (strict):

  4. Ve a Cloudflare → SSL/TLS
  5. Selecciona "Full (strict)"

Renovación automática falla

Síntomas: El certificado expira porque no se renueva automáticamente.

Diagnóstico:

# Verificar timer de renovación
sudo systemctl status certbot.timer

# Ver logs
sudo journalctl -u certbot -f

# Test renovación
sudo certbot renew --dry-run

Soluciones:

# Habilitar timer si está deshabilitado
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer

# Renovar manualmente
sudo certbot renew
sudo systemctl reload nginx

Problemas de Red/Firewall

No puedo acceder a mi web desde internet

Síntomas: Funciona localmente (curl localhost) pero no desde internet.

Diagnóstico:

# Verificar que Nginx está corriendo
sudo systemctl status nginx

# Verificar puertos abiertos
sudo ss -tulpn | grep -E ':80|:443'

# Verificar UFW
sudo ufw status

# Probar desde el VPS
curl -I http://localhost
curl -H "Host: tu-dominio.com" http://localhost

Checklist de solución:

  1. UFW debe permitir Nginx:

    sudo ufw allow 'Nginx Full'
    sudo ufw status
    

  2. Hetzner Cloud Firewall debe permitir 80 y 443:

  3. Ve al panel de Hetzner
  4. Firewalls → Tu firewall
  5. Verifica reglas inbound para 80 y 443

  6. DNS debe resolver correctamente:

    ping tu-dominio.com
    # Debe resolver a tu IP del VPS (o Cloudflare si proxy activo)
    

  7. Nginx debe tener el virtual host configurado:

    ls -la /etc/nginx/sites-enabled/
    sudo nginx -t
    

Puerto personalizado no accesible

Síntomas: http://YOUR_SERVER_IP:3000 no carga.

Solución:

Debes abrir el puerto en AMBOS firewalls:

# 1. UFW (en el VPS)
sudo ufw allow 3000/tcp
sudo ufw status

# 2. Hetzner Cloud Firewall (desde panel web)
# Añadir regla inbound: TCP, Port 3000, Source: Any IPv4/IPv6

Problemas de Memoria

Sistema lento o sin memoria

Síntomas: El VPS responde lento, contenedores se detienen, errores OOM.

Diagnóstico:

# Ver uso de memoria
free -h

# Ver procesos que consumen memoria
ps aux --sort=-%mem | head -n 10

# Ver uso de Docker
docker stats

# Ver swap
swapon --show

Soluciones:

  1. Activar swap si no está:

    # Ver si existe
    ls -lh /swapfile
    
    # Si no existe, crearlo (ver docs/02-docker.md)
    

  2. Limpiar Docker:

    docker system prune -a
    docker volume prune
    

  3. Reiniciar contenedores pesados:

    docker compose restart
    

  4. Limitar memoria de contenedores:

    # docker-compose.yml
    services:
      web:
        mem_limit: 512m
        memswap_limit: 1g
    

OOM Killer mata procesos

Síntomas:

Out of memory: Killed process

Diagnóstico:

# Ver eventos OOM
dmesg | grep -i "out of memory"
sudo journalctl -k | grep -i "killed process"

Soluciones:

  1. Aumentar swap (ver docs/02-docker.md)
  2. Reducir número de contenedores corriendo simultáneamente
  3. Limitar memoria de contenedores
  4. Actualizar a un VPS con más RAM

Problemas de Cloudflare

Veo contenido antiguo (caché)

Síntomas: Actualizas la aplicación pero sigues viendo contenido viejo.

Diagnóstico:

# Ver headers de respuesta
curl -I https://tu-dominio.com

# Buscar: cf-cache-status: HIT (significa que está cacheado)

Soluciones:

  1. Purgar caché en Cloudflare:
  2. Dashboard → Caching → Purge Cache
  3. Custom Purge → Hostname: tu-dominio.com

  4. Configurar Bypass para contenido dinámico:

  5. Cache Rules → Create Rule
  6. Hostname equals tu-dominio.com → Bypass cache

  7. Forzar no-caché desde Nginx:

    add_header Cache-Control "no-store, no-cache" always;
    

Worker captura todos los subdominios

Síntomas: Todos los subdominios muestran el mismo contenido del dominio principal.

Causa: Ruta de Worker con comodín: *.ejemplo.com/*

Solución:

  1. Ve a Cloudflare → Workers & Pages
  2. Tu proyecto → Settings → Triggers → Routes
  3. Elimina rutas con * al inicio
  4. Usa solo rutas específicas:
    ejemplo.com/*
    www.ejemplo.com/*
    

Error 521 "Web server is down"

Síntomas: Cloudflare no puede conectar con tu origen.

Diagnóstico:

# Verificar que Nginx está corriendo
sudo systemctl status nginx

# Verificar que está escuchando en 443
sudo ss -tulpn | grep :443

# Ver logs
sudo tail -f /var/log/nginx/error.log

Soluciones:

  1. Nginx no está corriendo:

    sudo systemctl start nginx
    

  2. Certificado SSL inválido:

  3. Cloudflare requiere certificado válido en modo "Full (strict)"
  4. Renovar certificado si expiró

  5. Firewall bloqueando Cloudflare:

    # Permitir puertos
    sudo ufw allow 'Nginx Full'
    

Error 525 "SSL handshake failed"

Síntomas: Cloudflare no puede negociar SSL con tu origen.

Causa: Problema con el certificado SSL en el VPS.

Solución:

# Verificar certificado
sudo certbot certificates

# Renovar si es necesario
sudo certbot renew --force-renewal

# Verificar configuración SSL en Nginx
sudo nginx -t

# Verificar que Cloudflare está en "Full (strict)"
# Dashboard → SSL/TLS → Full (strict)

Comandos de Diagnóstico Rápido

Estado general del sistema

# Ver todo el estado de un vistazo
echo "=== SISTEMA ===" && uname -a && \
echo "=== MEMORIA ===" && free -h && \
echo "=== DISCO ===" && df -h && \
echo "=== CONTENEDORES ===" && docker ps && \
echo "=== NGINX ===" && sudo systemctl status nginx --no-pager && \
echo "=== UFW ===" && sudo ufw status && \
echo "=== PUERTOS ===" && sudo ss -tulpn | grep LISTEN

Logs en tiempo real

# Ver todos los logs importantes
sudo tail -f /var/log/nginx/error.log \
  /var/log/letsencrypt/letsencrypt.log \
  /var/log/syslog

Test de conectividad completo

# Desde el VPS
curl -I http://localhost
curl -I https://tu-dominio.com

# Ver resolución DNS
nslookup tu-dominio.com

# Test SSL
echo | openssl s_client -servername tu-dominio.com -connect tu-dominio.com:443 2>/dev/null | grep -i "certificate"

Contactos de Emergencia

Hetzner Cloud

  • Panel: https://console.hetzner.cloud/
  • Soporte: https://www.hetzner.com/support

Cloudflare

  • Dashboard: https://dash.cloudflare.com/
  • Status: https://www.cloudflarestatus.com/

Let's Encrypt

  • Status: https://letsencrypt.status.io/
  • Community: https://community.letsencrypt.org/

⬅️ Volver al índice