Todos los ejemplos configuran los mismos valores iniciales. Las plataformas de hosting pueden enviar ya Strict-Transport-Security, así que los ejemplos de Vercel, Netlify y Next.js no la incluyen; revisa la respuesta real y añádela solo si falta.
nginx
Pon las líneas en el bloque server que sirve HTTPS. El parámetro always las añade también a las respuestas de error. Un bloque location con sus propias líneas add_header descarta todas las add_header heredadas del bloque server, así que repite el conjunto allí o guárdalo en un único archivo include.
# In the server block that serves HTTPS (listen 443 ssl)
add_header Strict-Transport-Security "max-age=300" always;
add_header Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'" always;
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 "camera=(), microphone=(), geolocation=()" always;
Apache
Activa mod_headers y añade las líneas al virtual host del puerto 443, o a .htaccess donde esté activado AllowOverride FileInfo. Header always set cubre también las respuestas de error y las redirecciones.
# <VirtualHost *:443> or .htaccess; needs mod_headers (Debian/Ubuntu: a2enmod headers)
Header always set Strict-Transport-Security "max-age=300"
Header always set Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'"
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 "camera=(), microphone=(), geolocation=()"
Cloudflare
En el panel, crea una Response Header Transform Rule para tu nombre de host y añade cada cabecera con la operación Set static, que reemplaza una cabecera del mismo nombre que venga de tu origen. HSTS tiene su propio ajuste en SSL/TLS, Edge Certificates; usa ese ajuste o la regla, no ambos. Los nombres de los menús pueden variar según la versión del panel.
Rule type Response Header Transform Rule
When Hostname equals example.com
Then Set static, one row per header:
X-Content-Type-Options nosniff
Referrer-Policy strict-origin-when-cross-origin
X-Frame-Options SAMEORIGIN
Permissions-Policy camera=(), microphone=(), geolocation=()
Content-Security-Policy-Report-Only default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'
HSTS SSL/TLS > Edge Certificates > HTTP Strict Transport Security (HSTS)
Vercel
Añade una entrada headers a vercel.json en la raíz del proyecto. El patrón source /(.*) coincide con todas las rutas; acótalo si algunas rutas necesitan otra política.
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Content-Security-Policy-Report-Only", "value": "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'" },
{ "key": "X-Frame-Options", "value": "SAMEORIGIN" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
{ "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" }
]
}
]
}
Netlify
Crea un archivo llamado _headers en el directorio de publicación, la carpeta que Netlify despliega. Cada línea de ruta, como /*, va seguida de líneas sangradas Nombre: valor. Las mismas reglas también pueden ir en netlify.toml bajo [[headers]].
/*
Content-Security-Policy-Report-Only: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Next.js
Devuelve las cabeceras desde la función async headers() de next.config.js; el source '/:path*' cubre todas las rutas. headers() no se ejecuta en una exportación estática (output: 'export'), así que en ese caso configura las cabeceras en el hosting que sirve los archivos exportados.
// next.config.js
const securityHeaders = [
{ key: 'Content-Security-Policy-Report-Only', value: "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'" },
{ key: 'X-Frame-Options', value: 'SAMEORIGIN' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
];
module.exports = {
async headers() {
return [{ source: '/:path*', headers: securityHeaders }];
},
};
Después de desplegar, vuelve a ejecutar el comprobador: lee la respuesta final, así que muestra lo que tu CDN o plataforma envía de verdad. Luego abre una página de error y un archivo estático en las herramientas de desarrollo del navegador, porque a menudo las cabeceras solo se configuran para algunas respuestas.