🔧 Troubleshooting - Solución de Problemas
Guía de diagnóstico y solución de problemas comunes en el VPS.
Índice
- Problemas de SSH
- Problemas de Docker
- Problemas de Nginx
- Problemas de SSL/Certificados
- Problemas de Red/Firewall
- Problemas de Memoria
- Problemas de Cloudflare
Problemas de SSH
No puedo conectarme por SSH
Síntomas:
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:
-
SSH no está corriendo:
-
Firewall bloqueando:
-
Verificar firewall de Hetzner Cloud:
- Ve al panel de Hetzner
-
Verifica que el puerto 22 está permitido
-
Usar Hetzner Rescue Console:
- Si todo falla, usa la consola de rescate desde el panel de Hetzner
- Puedes acceder directamente sin SSH
"Permission denied (publickey)"
Síntomas:
Diagnóstico:
# Verificar que tienes clave SSH
ls -la ~/.ssh/
# Conectar con verbose para ver detalles
ssh -v your_username@YOUR_SERVER_IP
Soluciones:
-
No tienes clave SSH:
ssh-keygen -t ed25519 -C "[email protected]" -
Clave no está en el servidor:
-
Permisos incorrectos:
-
Usuario no permitido (AllowUsers):
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:
Diagnóstico:
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:
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:
-
Puerto ya en uso:
-
Imagen corrupta:
-
Error de configuración:
-
Sin memoria:
"No space left on device"
Síntomas:
Diagnóstico:
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:
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:
-
Error de sintaxis:
-
Puerto 80 ya en uso:
-
Certificado SSL no encontrado:
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:
-
Contenedor no está corriendo:
-
Puerto incorrecto en Nginx:
-
Aplicación no responde:
"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:
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:
- Token incorrecto o sin permisos:
- Verifica el token en Cloudflare
- Crea un nuevo token si es necesario
-
Actualiza
/root/.secrets/cf.ini -
Dominio no en Cloudflare:
- Añade el dominio a Cloudflare
-
Espera propagación DNS (puede tardar minutos)
-
Límite de rate limiting:
- Let's Encrypt tiene límites (5 certificados/semana por dominio)
- Espera una semana o usa
--dry-runpara 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:
-
Certificado expirado:
-
Nginx usando certificado incorrecto:
-
Cloudflare no en modo Full (strict):
- Ve a Cloudflare → SSL/TLS
- 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:
-
UFW debe permitir Nginx:
-
Hetzner Cloud Firewall debe permitir 80 y 443:
- Ve al panel de Hetzner
- Firewalls → Tu firewall
-
Verifica reglas inbound para 80 y 443
-
DNS debe resolver correctamente:
-
Nginx debe tener el virtual host configurado:
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:
-
Activar swap si no está:
-
Limpiar Docker:
-
Reiniciar contenedores pesados:
-
Limitar memoria de contenedores:
OOM Killer mata procesos
Síntomas:
Diagnóstico:
Soluciones:
- Aumentar swap (ver docs/02-docker.md)
- Reducir número de contenedores corriendo simultáneamente
- Limitar memoria de contenedores
- 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:
- Purgar caché en Cloudflare:
- Dashboard → Caching → Purge Cache
-
Custom Purge → Hostname:
tu-dominio.com -
Configurar Bypass para contenido dinámico:
- Cache Rules → Create Rule
-
Hostname equals
tu-dominio.com→ Bypass cache -
Forzar no-caché desde Nginx:
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:
- Ve a Cloudflare → Workers & Pages
- Tu proyecto → Settings → Triggers → Routes
- Elimina rutas con
*al inicio - Usa solo rutas específicas:
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:
-
Nginx no está corriendo:
-
Certificado SSL inválido:
- Cloudflare requiere certificado válido en modo "Full (strict)"
-
Renovar certificado si expiró
-
Firewall bloqueando Cloudflare:
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/