Skip to content

Hide the nginx version with server_tokens

Severity: lowApplies to: nginx 1.25+Applies to: nginx 1.30 / 1.31Applies to: freenginx
The fix/etc/nginx/nginx.conf
http {
server_tokens off;
}
Terminal window
sudo nginx -t && sudo systemctl reload nginx

server_tokens off changes this:

Server: nginx/1.30.4

into this:

Server: nginx

That is the entire effect. It does not remove the Server header, and it does not hide that you’re running nginx. It removes four digits.

This is obscurity, and it is worth doing for one narrow reason: mass scanners match on version strings. A bot working through the internet looking for hosts vulnerable to a specific CVE will read your banner and move on if it doesn’t match. Removing the version drops you out of that particular bucket.

It buys you nothing at all against anyone who has decided to look at you. Response fingerprinting identifies nginx and narrows the version range without the banner, and error page formatting gives it away too. Do not count this as a control — count it as reducing untargeted noise, which is the same value Fail2Ban offers on SSH, and for the same reason it is rated low.

The version number is not the vulnerability. If you’re on 1.30.4 you’re patched regardless of who knows it; if you’re on an unpatched version, hiding the banner does not unpatch the attacker. Patching is the control. This is housekeeping.

Removing the Server header entirely needs a module

Section titled “Removing the Server header entirely needs a module”

Stock nginx cannot delete the Server header — server_tokens is the only lever, and off is as far as it goes. To remove or replace it you need headers-more-nginx-module:

more_clear_headers 'Server';

That module is packaged as nginx-extras on Debian and Ubuntu, and is the same module worth having for security headers, where it solves a genuinely painful problem. Installing a third-party module purely to hide a banner is not a good trade; installing it for header inheritance and getting this as a bonus is.

server_tokens off also removes the version from nginx’s built-in error page footers, which otherwise print nginx/1.30.4 in the HTML of every 404 and 502. That’s usually where people find it after “removing” it from the header — the directive handles both, but only if it’s in scope.

Put it in the http block so it applies everywhere. A server_tokens on in one server block overrides it for that host.