The Server and X-Powered-By headers advertise exactly what you run (nginx/1.25.3,
PHP/8.2, Express). That’s free reconnaissance for attackers matching your version to known CVEs.
You can’t always remove Server entirely, but you can trim it and drop X-Powered-By.
Nginx
Hide the version (keeps Server: nginx):
http {
server_tokens off;
}
To remove the Server header entirely you need the headers-more module:
more_clear_headers Server;
Apache
In the main config (not .htaccess):
ServerTokens Prod
ServerSignature Off
ServerTokens Prod reduces it to Server: Apache. Removing it completely requires mod_security
(SecServerSignature) or building without the token.
PHP (X-Powered-By)
In php.ini:
expose_php = Off
Or strip it at the web server:
Header always unset X-Powered-By
proxy_hide_header X-Powered-By;
fastcgi_hide_header X-Powered-By;
Node / Express
app.disable('x-powered-by');
Caddy
Caddy doesn’t send a version and you can remove its Server header:
header -Server
Verify
curl -sI https://yourdomain.com | grep -iE 'server:|x-powered-by'
Reality check: hiding version strings is defense-in-depth, not a real fix — fingerprinting still works via behaviour. Treat it as a small, free win and spend the real effort on patching and the headers that actually block attacks (CSP, HSTS).