Publicar una web en un VPS parece sencillo: subes los ficheros, apuntas el dominio, configuras Apache o Nginx y activas HTTPS. Pero cuando algo falla, normalmente no falla “la web” en abstracto. Falla DNS, falla el VirtualHost, falla el certificado, falla una redirección, falla el DocumentRoot, fallan permisos, falla un proxy o simplemente estás viendo otra web porque el servidor está cogiendo el vhost equivocado.
Esta guía está pensada para revisar una web real desplegada en un VPS, con Apache o Nginx, dominio propio, HTTPS, logs, robots.txt, sitemap.xml y comprobaciones básicas de publicación. No es una guía de diseño web. Es una guía de operación.
Cuando una web no carga, conviene separar el problema por capas:
1. DNS 2. Conectividad 3. Servidor web 4. VirtualHost / Server Block 5. DocumentRoot 6. Permisos 7. HTTPS 8. Redirecciones 9. Aplicación o HTML 10. SEO técnico básico
Si no separas capas, puedes perder mucho tiempo tocando Apache cuando el problema es DNS, o revisando DNS cuando el problema es que el VirtualHost apunta a otra carpeta.
Lo primero es validar que el dominio resuelve a la IP correcta.
dig dominio.com +short dig www.dominio.com +short
También puedes usar:
host dominio.com nslookup dominio.com
Lo importante es confirmar:
- dominio raíz apunta al VPS - www apunta al VPS - no hay registros antiguos - no hay CNAME mal encadenados - la IP devuelta es la esperada
Si el dominio no resuelve, Apache o Nginx no tienen nada que arreglar todavía.
Una prueba muy útil es forzar la cabecera Host contra localhost. Así validas el VirtualHost sin depender de DNS externo.
curl -I -H "Host: dominio.com" http://127.0.0.1 curl -s -H "Host: dominio.com" http://127.0.0.1 | head -40
Si esto devuelve la web correcta, el servidor web está respondiendo bien para ese dominio. Si desde fuera falla, probablemente el problema está en DNS, firewall, HTTPS o red.
En Apache, empieza revisando estado:
sudo systemctl status apache2 sudo apache2ctl -S sudo apache2ctl configtest
El comando más importante aquí es:
sudo apache2ctl -S
Te muestra qué VirtualHosts están activos, en qué puerto, qué ServerName tienen y desde qué fichero se cargan.
Hay que revisar:
- puerto 80 - puerto 443 - ServerName correcto - ServerAlias correcto - DocumentRoot correcto - vhost SSL correcto - si el dominio cae en el default vhost
Si la web usa Nginx:
sudo systemctl status nginx sudo nginx -t sudo nginx -T | grep -E "server_name|root|listen"
En Nginx interesa revisar:
- listen 80 - listen 443 ssl - server_name - root - index - certificados - redirecciones - proxy_pass si aplica
Uno de los fallos más habituales es que el VirtualHost apunte a una carpeta que no es la que crees.
grep -R "DocumentRoot" /etc/apache2/sites-available/ /etc/apache2/sites-enabled/ grep -R "root " /etc/nginx/sites-available/ /etc/nginx/sites-enabled/
Después valida la carpeta:
ls -la /var/www/dominio.com/public ls -la /var/www/dominio.com/public/index.html
Si Apache/Nginx apunta a una carpeta vacía o antigua, verás otra web, un 403, un 404 o contenido que no corresponde.
Para una web estática típica:
sudo chown -R www-data:www-data /var/www/dominio.com
sudo find /var/www/dominio.com -type d -exec chmod 755 {} \;
sudo find /var/www/dominio.com -type f -exec chmod 644 {} \;
Comprueba:
namei -l /var/www/dominio.com/public/index.html ls -ld /var/www ls -ld /var/www/dominio.com ls -ld /var/www/dominio.com/public
Un error de permisos puede provocar 403 aunque todo lo demás esté bien.
curl -I http://dominio.com curl -I http://www.dominio.com curl -L -I http://dominio.com
Revisa:
HTTP/1.1 200 OK HTTP/1.1 301 Moved Permanently Location: Content-Type: Content-Length: Server:
Si esperas una redirección HTTP → HTTPS, lo normal es ver 301 en HTTP y 200 en HTTPS.
curl -I https://dominio.com curl -I https://www.dominio.com openssl s_client -connect dominio.com:443 -servername dominio.com /dev/null | openssl x509 -noout -dates
Revisa:
- certificado válido - fecha de expiración - CN/SAN correcto - cadena completa - respuesta 200 o 301 esperada
Con Certbot en Apache:
sudo certbot certificates sudo systemctl status certbot.timer sudo certbot renew --dry-run
Conviene decidir una versión principal:
https://dominio.com
o:
https://www.dominio.com
Y redirigir la otra.
Ejemplo Apache para www → sin www:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.dominio\.com$ [NC]
RewriteRule ^ https://dominio.com%{REQUEST_URI} [L,R=301]
Validación:
curl -I https://www.dominio.com curl -I https://dominio.com
Lo esperado:
www → 301 sin www → 200
sudo tail -f /var/log/apache2/error.log sudo tail -f /var/log/apache2/access.log sudo ls -lah /var/log/apache2
Si tienes logs separados por vhost:
sudo tail -f /var/log/apache2/dominio-error.log sudo tail -f /var/log/apache2/dominio-access.log
Busca:
AH00112 permission denied client denied by server configuration File does not exist certificate rewrite proxy error
sudo tail -f /var/log/nginx/error.log sudo tail -f /var/log/nginx/access.log
Errores típicos:
permission denied no such file or directory upstream timed out connect() failed directory index forbidden SSL_do_handshake
Comprueba que 80 y 443 están accesibles.
sudo ss -lntp | grep -E ':80|:443' sudo ufw status verbose sudo iptables -S sudo nft list ruleset
Desde fuera:
nc -vz dominio.com 80 nc -vz dominio.com 443
En VPS también hay que revisar firewall del proveedor si existe.
Debe existir si quieres controlar rastreo básico.
curl -I https://dominio.com/robots.txt curl https://dominio.com/robots.txt
Ejemplo:
User-agent: * Allow: / Sitemap: https://dominio.com/sitemap.xml
Ojo con dejar accidentalmente:
Disallow: /
Eso bloquea rastreo.
curl -I https://dominio.com/sitemap.xml curl https://dominio.com/sitemap.xml | head
Debe devolver:
HTTP/1.1 200 OK Content-Type: application/xml
Ejemplo básico:
https://dominio.com/
Comprobar:
curl -I https://dominio.com
Cabeceras útiles:
Strict-Transport-Security X-Content-Type-Options X-Frame-Options Referrer-Policy Permissions-Policy Content-Security-Policy
No metas CSP agresiva sin probar. Puede romper recursos, scripts o estilos.
Comprueba enlaces principales:
curl -I https://dominio.com/ curl -I https://dominio.com/entradas.html curl -I https://dominio.com/guias.html curl -I https://dominio.com/libros.html curl -I https://dominio.com/sobre-mi.html
Y busca 404:
grep " 404 " /var/log/apache2/access.log | tail grep " 404 " /var/log/nginx/access.log | tail
A veces la web responde 200 pero no es la web correcta.
curl -s https://dominio.com | head -40 curl -s https://dominio.com | grep -i ""
Esto ayuda a detectar si estás sirviendo otra web por vhost incorrecto.
Si corriges algo y sigues viendo lo viejo:
Ctrl + F5 modo incógnito otro navegador curl desde consola
El navegador puede engañarte. curl no suele mentir.
DNS raíz apunta al VPS www apunta al VPS Apache/Nginx activo VirtualHost correcto DocumentRoot correcto index.html existe permisos correctos HTTP responde HTTPS responde certificado válido redirección canónica correcta robots.txt accesible sitemap.xml accesible logs sin errores relevantes puertos 80/443 abiertos rutas principales devuelven 200 contenido servido es el correcto
Cuando publico una web nueva en VPS, suelo seguir este orden:
1. Crear carpeta de publicación. 2. Subir HTML/CSS/JS. 3. Ajustar permisos. 4. Crear VirtualHost. 5. Validar con Host contra 127.0.0.1. 6. Apuntar DNS. 7. Probar HTTP. 8. Activar HTTPS. 9. Forzar canónica. 10. Crear robots.txt. 11. Crear sitemap.xml. 12. Revisar logs. 13. Probar rutas. 14. Enviar sitemap a Search Console.
Ejemplo de validación local antes de DNS:
curl -I -H "Host: dominio.com" http://127.0.0.1 curl -s -H "Host: dominio.com" http://127.0.0.1 | head -40
Si esto funciona, puedes separar claramente servidor web de DNS.
DNS apuntando a otra IP VirtualHost con ServerName incorrecto DocumentRoot equivocado permisos 700 en carpetas web certificado emitido para otro dominio www sin configurar redirecciones en bucle robots bloqueando todo sitemap con URLs antiguas caché del navegador Apache sirviendo el vhost por defecto Nginx con server block duplicado
Revisar una web en un VPS no es solo mirar si carga en el navegador. Hay que comprobar DNS, servidor web, VirtualHost, permisos, HTTPS, logs, robots, sitemap y contenido real servido.
La clave está en separar capas. Si haces eso, la mayoría de problemas dejan de ser confusos y pasan a ser diagnosticables.
Y en operación real, una web bien publicada no es solo la que se ve. Es la que puedes mantener, auditar, renovar, indexar y recuperar sin depender de memoria ni improvisación.