Hide Your NGINX Version

Disable server_tokens to prevent attackers from identifying known vulnerabilities in your specific NGINX version.

Updated: January 2025 * 5 min read

Why Hide the Version?

By default, NGINX exposes its version number in the Server response header and on error pages. While this doesn't directly create vulnerabilities, it helps attackers:

  • Identify known vulnerabilities - CVEs specific to your version
  • Choose targeted exploits - Skip versions that aren't vulnerable
  • Automate attacks - Scanners filter targets by version
  • Fingerprint your infrastructure - Part of reconnaissance phase

Security Through Obscurity

Hiding the version is not a substitute for keeping NGINX updated. It's a defense-in-depth measure that makes attackers work harder. Always patch vulnerabilities promptly.

Where Version is Exposed

1. Server Response Header

HTTP/1.1 200 OK
Server: nginx/1.24.0
Content-Type: text/html
...

2. Default Error Pages

<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.24.0</center>
</body>
</html>

The Fix: server_tokens off

Add this directive to your configuration to hide the version:

# In http, server, or location block
http {
    server_tokens off;

    # ... rest of configuration
}

Result: Header

HTTP/1.1 200 OK
Server: nginx
Content-Type: text/html
...

Result: Error Page

<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

server_tokens Options

Value Server Header Recommendation
on (default) nginx/1.24.0 Avoid
off nginx Recommended
build nginx/1.24.0 (Ubuntu) Avoid - even more info
"" (empty)* No Server header Best (requires module)

* Removing the Server header entirely requires the ngx_headers_more module.

Completely Remove Server Header

To remove the Server header entirely, use the headers-more module:

# Requires ngx_headers_more module
# Install: https://github.com/openresty/headers-more-nginx-module

http {
    more_clear_headers Server;

    # Or set a custom value
    # more_set_headers "Server: MyApp";
}
Installation: On Ubuntu/Debian, install libnginx-mod-http-headers-more-filter. On CentOS/RHEL, it's available in the EPEL repository or GetPageSpeed repo.

Custom Error Pages

Replace default error pages to remove all NGINX branding:

# Custom error pages
error_page 404 /errors/404.html;
error_page 500 502 503 504 /errors/50x.html;

location /errors/ {
    internal;
    root /var/www;
}

Create minimal error pages without any server identification:

<!-- /var/www/errors/404.html -->
<!DOCTYPE html>
<html>
<head><title>Not Found</title></head>
<body>
<h1>Page Not Found</h1>
<p>The requested resource could not be found.</p>
</body>
</html>

Detecting with Gixy

Gixy detects version disclosure issues:

$ gixy /etc/nginx/nginx.conf

==================== Results ====================

[version_disclosure] Do not enable server_tokens on or build.
  Severity: HIGH
  Description: Exposing nginx version allows attackers to learn
               of known vulnerabilities.
  Reason: server_tokens is "on" (default).
  Pseudo config:
      http {
          # server_tokens on; (default)
      }
  File: /etc/nginx/nginx.conf
  Line: 1

==================== Summary ====================
Total issues: 1 (High: 1)

Verify the Fix

# Check response headers
curl -I https://yourdomain.com

# Before:
# Server: nginx/1.24.0

# After:
# Server: nginx

# Check error page (trigger a 404)
curl -I https://yourdomain.com/nonexistent-page-12345

Additional Hardening

While you're at it, consider these related measures:

http {
    # Hide version
    server_tokens off;

    # Don't send NGINX in proxy headers
    proxy_hide_header X-Powered-By;

    # Remove other identifying headers
    fastcgi_hide_header X-Powered-By;

    # Set custom Server header (requires headers-more)
    # more_set_headers "Server: WebServer";
}

Complete Example

http {
    # Security: Hide version info
    server_tokens off;

    # Custom error pages (no NGINX branding)
    error_page 404 /errors/404.html;
    error_page 500 502 503 504 /errors/50x.html;

    server {
        listen 443 ssl http2;
        server_name example.com;

        # Error page location
        location /errors/ {
            internal;
            root /var/www;
        }

        # ... rest of configuration
    }
}

Checklist

  • Set server_tokens off; in the http block
  • Create custom error pages without server identification
  • Consider removing the Server header entirely (headers-more module)
  • Hide X-Powered-By headers from upstream applications
  • Keep NGINX updated - hiding version is not a substitute for patching
  • Run Gixy to verify the configuration

Further Reading