Endurecer la seguridad de tu rApanel
El instalador deja rApanel funcionando tanto en HTTP como en HTTPS, porque no puede saber de antemano si vas a poner un certificado. Eso significa que algunas protecciones vienen desactivadas a propósito: activarlas antes de tiempo dejaría a todo el mundo — tú incluido — sin poder iniciar sesión. Esta guía las recorre una por una, en el orden correcto.
No hace falta que audites nada a mano. El panel trae Admin → Health Check, que revisa todo lo de esta página sobre tu instalación real y te muestra qué falta. Cada aviso tiene un botón Guía que te trae exactamente a la sección correspondiente.
1 · HTTPS #
Es el primer paso y el que habilita todos los demás. Sin él, las contraseñas de tus jugadores viajan en texto plano por la red: cualquiera en el camino — el wifi del café, el proveedor de internet, un router intermedio — puede leerlas. Los certificados son gratis con Let's Encrypt.
Antes de empezar, comprueba que el registro A de tu
dominio apunte a la IP pública de este servidor (tanto tudominio.com como
www.tudominio.com) y que los puertos 80 y 443
estén abiertos: Certbot valida por HTTP.
# Nginx
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d tudominio.com -d www.tudominio.com
# Apache2
sudo apt install -y certbot python3-certbot-apache
sudo certbot --apache -d tudominio.com -d www.tudominio.com
Cuando pregunte si redirigir HTTP a HTTPS, elige Redirect (opción 2).
Después apunta el panel al nuevo esquema en su .env:
APP_URL=https://tudominio.com
Si usas la Consola en Vivo del admin, su WebSocket también tiene que
pasar a wss:// — los navegadores bloquean ws:// desde
páginas HTTPS:
RA_WS_PUBLIC_URL=wss://tudominio.com/ws-proxy
php artisan config:clear && php artisan cache:clear
Certbot deja instalado un temporizador que renueva solo. Puedes comprobarlo con
sudo systemctl status certbot.timer y ensayar la renovación con
sudo certbot renew --dry-run.
2 · Modo depuración #
Con APP_DEBUG=true, cualquier error del panel muestra una página de
diagnóstico con el contenido de tu .env: usuario y contraseña de la base
de datos, APP_KEY, claves de las pasarelas de pago. Y no hace falta ser
administrador para verla — basta con provocar el error.
APP_DEBUG=false
APP_ENV=production
php artisan config:clear
Si ya tuviste el panel público con APP_DEBUG=true, da por
comprometidas esas credenciales: cambia la contraseña de la base de datos
y las claves de las pasarelas que tuvieras configuradas.
3 · Cookie de sesión #
Enviarla solo por HTTPS
Evita que la cookie de sesión viaje alguna vez en claro, incluso si alguien entra por error a la versión HTTP del sitio.
SESSION_SECURE_COOKIE=true
Solo con el certificado ya funcionando. Si activas esto mientras el
sitio sigue en HTTP, el navegador descarta la cookie y nadie podrá iniciar
sesión, tú incluido. Si te pasa: vuelve a ponerlo en false y
ejecuta php artisan config:clear.
El prefijo __Host-
Es lo que las auditorías externas reportan como «There is no Cookie Prefix on this cookie». El prefijo hace que el navegador rechace la cookie si alguien intenta escribirla desde un subdominio o por HTTP: cierra la puerta a que un subdominio comprometido — un foro viejo, un blog abandonado — le fije una sesión a tus usuarios.
El navegador solo lo acepta si se cumplen las tres condiciones a la vez (las dos últimas ya vienen así de fábrica):
SESSION_SECURE_COOKIE=true
SESSION_PATH=/
SESSION_DOMAIN=null
SESSION_COOKIE=__Host-mitienda-session
php artisan config:clear
El nombre que va después del prefijo lo eliges tú. Lo único
obligatorio es que empiece por __Host-; el resto es un nombre cualquiera, y
ni siquiera necesita terminar en -session. Estos tres son igual de válidos:
SESSION_COOKIE=__Host-mitienda-session
SESSION_COOKIE=__Host-roh
SESSION_COOKIE=__Host-mi_panel_2026
Usa solo letras, números, - y _ — nada de espacios, acentos ni
=, ;, ,. Si no defines la variable, el nombre sale
del APP_NAME de tu .env (por ejemplo
mi-servidor-session), y por eso hay que escribirlo entero al agregar el
prefijo.
Conviene que siga siendo reconocible: cuando estés depurando algo en las herramientas
del navegador, agradecerás leer __Host-mitienda-session y no
__Host-x7k2. Ofuscarlo no aporta seguridad — el panel se identifica por
muchas otras vías.
Cambiar el nombre de la cookie cierra todas las sesiones abiertas, la tuya incluida. Hazlo en un momento de poco tráfico, vuelve a entrar, y luego no lo toques más: cada cambio vuelve a cerrarlas, porque para el navegador es una cookie distinta y no la misma renombrada.
4 · Permisos del archivo .env #
El .env guarda las credenciales de tus bases de datos y la
APP_KEY con la que se cifran las sesiones. Si queda legible por todo el
sistema, cualquier cuenta del servidor — o un script de otro sitio alojado en la misma
máquina, algo habitual en hosting compartido — puede leerlo.
sudo chown root:www-data .env
sudo chmod 640 .env
No ejecutes solo el chmod. Si el grupo del archivo no es
el del servidor web, le quitas el acceso a PHP y el panel entero responde 500. El
chown de la primera línea es el que garantiza que siga leyéndolo.
En algunas distribuciones el usuario del servidor web no es www-data sino
apache, nginx o www. Compruébalo con:
ps aux | grep -E 'php-fpm|apache' | head -2
El Health Check del panel ya mira el dueño real de tu archivo y te muestra el comando adaptado, así que puedes copiarlo tal cual desde ahí.
5 · Cabeceras de seguridad #
Son instrucciones que tu servidor web le da al navegador sobre cómo tratar el sitio. Las instalaciones nuevas ya las traen puestas; este aviso aparece sobre todo en paneles instalados con versiones anteriores, o cuando un proxy intermedio las descarta.
Nginx
Dentro del bloque server de /etc/nginx/sites-available/rapanel:
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
sudo nginx -t && sudo systemctl reload nginx
Apache
Dentro del <VirtualHost> de /etc/apache2/sites-available/rapanel.conf:
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
sudo a2enmod headers
sudo apache2ctl configtest && sudo systemctl reload apache2
En nginx, declarar un add_header dentro de un location
descarta todas las cabeceras heredadas del bloque
server. Si añades una en un location, tienes que repetir
ahí todas las demás.
6 · Content Security Policy #
El CSP es la defensa de fondo contra los ataques XSS: le dice al navegador exactamente de dónde puede cargar scripts, y bloquea todo lo demás. En rApanel no lo configuras tú — lo emite la propia aplicación en cada petición, con un valor único e irrepetible (un nonce) que marca sus scripts legítimos. Un atacante no puede adivinarlo.
No agregues una cabecera Content-Security-Policy en nginx ni en
Apache. Si llegan dos políticas, el navegador aplica la
intersección de ambas: se rompen cosas sin que aparezca ningún
mensaje de error, y encontrar la causa cuesta horas.
Un servidor web no puede generar un valor distinto por petición, así que cualquier CSP
escrito a mano ahí tiene que permitir todos los scripts inline
('unsafe-inline') — que es precisamente lo que un CSP debería impedir. Si
el Health Check te avisa de esto, busca y elimina la línea de tu configuración:
sudo grep -rn "Content-Security-Policy" /etc/nginx/ /etc/apache2/
Si en cambio el aviso dice que no está llegando al navegador, el culpable suele ser un proxy o un CDN intermedio que la descarta.
7 · HSTS con preload #
El instalador ya envía Strict-Transport-Security con
max-age=31536000; includeSubDomains, que es lo correcto para la mayoría de
los servidores. Si además quieres entrar en la lista de precarga que traen los
navegadores de fábrica, añade preload a esa cabecera y date de alta en
hstspreload.org.
Esto es prácticamente irreversible. Una vez en la lista, los navegadores se niegan a abrir tu dominio y todos sus subdominios por HTTP durante meses, aunque quites la cabecera. Hazlo solo si estás seguro de que todo lo que cuelga de tu dominio irá por HTTPS para siempre.
8 · Lo que las auditorías marcan y no es un problema #
Si pasas tu dominio por securityheaders.com o por el HTTP Observatory de MDN, vas a ver tres avisos que no tienes que arreglar:
XSRF-TOKEN sin HttpOnly
Es intencional y es cómo funciona Laravel: el JavaScript del panel necesita leer esa
cookie para enviar el token anti-CSRF en cada petición. Si le pusieras
HttpOnly, el panel dejaría de funcionar. La cookie de sesión,
que es la que da acceso, sí lo tiene.
X-XSS-Protection obsoleta
Es una cabecera antigua que los navegadores modernos ignoran; se envía solo por compatibilidad con versiones viejas. La protección real la da el Content Security Policy.
Cabeceras Cross-Origin-* en «Upcoming Headers»
Son opcionales y todavía están en adopción. Su ausencia no baja la nota, y activarlas sin cuidado puede romper la carga de imágenes o fuentes externas.
Con los puntos 1 a 6 aplicados, una instalación de rApanel obtiene A+ en securityheaders.com y pasa el análisis de CSP del Observatory de MDN.