Updated: 4 November 2026 · Applies to: nginx 1.26.3 (Debian 13), 1.24.0 (Ubuntu 24.04) and 1.28.3 (Ubuntu 26.04), PHP 8.4 FPM and Apache 2.4.68 on Debian 13, tested; AlmaLinux 10.2 default files checked
To hide the nginx version, add server_tokens off; to the http {} block of /etc/nginx/nginx.conf and reload nginx. The header then reads Server: nginx instead of Server: nginx/1.28.3 (Ubuntu). Open-source nginx cannot drop the Server header completely with its own settings: for that, load the headers-more module and add more_clear_headers Server;. To hide the PHP version, set expose_php = Off in PHP-FPM's php.ini, or add fastcgi_hide_header X-Powered-By; in nginx.
1. Check what your server sends now
Ask for the headers only with curl -I, and look at the footer of an error page:
curl -I https://example.com/ curl -s https://example.com/no-such-page | grep center
Lab example on a fresh Ubuntu 26.04 nginx install:
HTTP/1.1 200 OK Server: nginx/1.28.3 (Ubuntu) <hr><center>nginx/1.28.3 (Ubuntu)</center>
The default differs by distribution. In our tests:
- Debian 13:
nginx.confalready hasserver_tokens off;, so the header is justServer: nginx. - Ubuntu 24.04: the line is commented out (
# server_tokens off;), so nginx sendsnginx/1.24.0 (Ubuntu). - Ubuntu 26.04: the file sets
server_tokens build;(version plus build name), and nginx sentnginx/1.28.3 (Ubuntu). - AlmaLinux 10.2 (nginx 1.26.3) and the official nginx Docker image (1.30.5): there is no
server_tokensline, so the defaultonapplies and the version is shown.
2. Hide the nginx version with server_tokens off
- Open
/etc/nginx/nginx.confand find thehttp {block. Add the line, or change an existingserver_tokensline:http { server_tokens off; ... } - Test the configuration:
nginx -t - Reload:
systemctl reload nginx - Check again with
curl -I.
Lab result on Ubuntu 26.04 after the change:
Server: nginx <hr><center>nginx</center>
The version is gone from the header and from nginx's built-in error pages, but the word "nginx" stays in both. server_tokens also works in a single server {} or location {} block, but the http block covers every site at once.
3. Remove the Server header completely (headers-more)
According to nginx, setting server_tokens to a custom string, or to an empty string to drop the header, is only available in the commercial subscription. On open-source nginx, use the headers-more module. Debian and Ubuntu package it:
- Install it:
apt install libnginx-mod-http-headers-more-filter(the package adds aload_moduleline under/etc/nginx/modules-enabled/). - In the
http {}block, next toserver_tokens off;, add:more_clear_headers Server;
- Run
nginx -tandsystemctl reload nginx.
Lab result on Debian 13: the Server line is gone, also on error responses:
$ curl -I http://127.0.0.1/ HTTP/1.1 200 OK Date: Mon, 12 Oct 2026 10:02:32 GMT Content-Type: text/html Content-Length: 10703
To send your own value instead, use more_set_headers "Server: webserver";, which gave Server: webserver. Two things that do not work:
- Without the module loaded,
nginx -tfails withunknown directive "more_clear_headers". add_header Server "webserver";does not replace the header. It adds a second one, so the response carried bothServer: nginxandServer: webserver.
4. Remove "nginx" from error pages
Even with the header removed, nginx's built-in error pages still end with <center>nginx</center>. Serve your own page instead. In the server {} block:
error_page 404 /404.html;
location = /404.html {
root /var/www/errors;
internal;
}
With /var/www/errors/404.html in place, a missing page returned only our own HTML. List more status codes on one line for other errors, as nginx's own default config does with error_page 500 502 503 504 /50x.html;.
5. Hide the PHP version (X-Powered-By)
With expose_php = On, every PHP page sends a header such as X-Powered-By: PHP/8.4.26. There are two ways to stop it:
- In PHP: set
expose_php = Offin the php.ini that PHP-FPM reads (/etc/php/8.4/fpm/php.inion Debian 13, with your PHP version in the path on Ubuntu;/etc/php.inion AlmaLinux and Rocky Linux), then restart PHP-FPM, for examplesystemctl restart php8.4-fpm. According to PHP, this setting can only be changed in php.ini, not withini_set(). - In nginx: add
fastcgi_hide_header X-Powered-By;next tofastcgi_pass. In our test the header disappeared whileexpose_phpwas stillOn. For an app behindproxy_pass, the equivalent isproxy_hide_header X-Powered-By;.
Check with curl -I https://example.com/index.php. The production php.ini shipped for PHP-FPM on Debian 13, Ubuntu 24.04 and Ubuntu 26.04 already has expose_php = Off, so if you still see the header there, check which file PHP-FPM really loads: php-fpm8.4 -i | grep -E "Loaded Configuration|expose_php" (lab output: expose_php => Off => Off). The CLI php.ini says On, but it does not affect web requests. On AlmaLinux 10.2, /etc/php.ini (PHP 8.3) has expose_php = On, so the header is sent until you change it.
6. Apache: ServerTokens and ServerSignature
If Apache serves the site (alone or behind nginx), set these two lines in /etc/apache2/conf-enabled/security.conf on Debian and Ubuntu, or in /etc/httpd/conf/httpd.conf on AlmaLinux and Rocky Linux (the AlmaLinux 10.2 file has neither line, so add both):
ServerTokens Prod ServerSignature Off
After apachectl configtest and a graceful reload, the lab header changed from Server: Apache/2.4.68 (Debian) to Server: Apache, and the <address> line with the version disappeared from error pages. Header unset Server and Header always unset Server did not remove the header in our test. More detail is in How to Hide the Apache Version Number?
Is it worth doing?
Hiding versions makes automated scans a little less precise, but it does not fix anything. Keeping nginx, PHP and Apache updated is what protects the server. If you run your own server, for example a Ucartz KVM VPS, you can make these changes yourself as root.
Official documentation: nginx server_tokens, headers-more module and PHP expose_php.