Adding and removing nginx response headers

If you’re using nginx as your preferred web server, reverse proxy, load balancer or HTTP cache, then you might be familiar with HTTP response headers.

Nginx allows you to customise those HTTP response headers very easily.

Adding response headers

Adding response headers is quite forward, as you can use the add_header directive documented here. Here’s an example which should help against cross-site scripting:

add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

The directive can be defined on an httpserver or location context. This is quite straightforward, isn’t it?

Removing and modifying response headers

The documentation states the following:

There could be several add_header directives. These directives are inherited from the previous level if and only if there are no add_header directives defined on the current level.

So, let’s say the http context defines a X-Frame-Options header, which is fine for all of your available sites (i.e. servers), except for one. For this case, you’ve to set the header in your server context again:

add_header X-Frame-Options DENY;

However – and this is important – as you now have defined a header in your server context, all the remaining headers defined in the http  context will no longer be inherited. Means, you’ve to define them in your server context again (or alternatively ignore them if they’re not important for your site).

But what about removing pre-defined headers of the http context in your server context?
Let’s say we want to remove that pre-defined X-Frame-Options header in our server context.
With the inheritance lesson learned before, we can now simply set any header in the server context to get rid of the headers in the http  context, or we can use the following workaround:

add_header X-Frame-Options "";

Adding headers to a proxy upstream

If you’re using nginx as reverse proxy and you want to add headers to your proxy upstream, then you’re interested in the proxy_set_header directive documented here. Here’s an example of our default proxy headers:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Please note the $host$remote_addr and $proxy_add_x_forwarded_for variables are defined by deafult by nginx. A list of all variables can be found here.

Better control of HTTP headers

To take better control of your custom and even default nginx headers, you should’ve a look at the headers-more-nginx-module.
Unfortunately, you’ve to compile nginx and this module all by yourself, as this module isn’t distributed with nginx.

Security-related HTTP headers

There are some security-related HTTP response headers. On our servers, we’re setting the following headers by default:

add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

The Strict-Transport-Security header (often abbreviated as HSTS) tells the client that the resource should only be accessed by HTTPS. This helps for MITM (man-in-the-middle) attacks, as the client “forces” an SSL-encrypted connection in case it visited the site before.

The X-Frame-Options and X-Content-Type-Options are used to prevent cross-site scripting, for example in iframes.


  • Alik

    Hi everyone, I have putted all headers that was needed but I want to hide them so if someone would want to check if I do have headers or not they could not . can you advise how I have to do that ?

    • Na

      Ofcause you cannot

  • Binh Thanh Nguyen

    Thanks, nice post

  • Hugh

    Thanks for this great guide

  • 28 day keto challenge

    Hi, thanks for your post, it’s really helpful! Can you explain a little bit more how do you perform the updates of the rest of the packages (the non security ones)? Thank you in advance!

  • Leptitox

    I Personally Like Your Post; You Have Shared Good Insights And Experiences. Keep It Up.

  • Staffing Firms

    Hi, do you have information on how to clear X-Powerer-By?

  • scyto

    Awesome, i had totally missed the inheritance line in the docs – explains some of the unexpected issues i have had over the years – thanks!


    This helps me a lot. Thank you for sharing, I was looking for this code.


    I really love how this guy always puts in so much effort to teach I really appreciate it so much.

  • Horse Names

    Facing issue in WordPress core files from wp-access directory after applying this techinque. I recommend getting a backup before implementing this code.

  • kitchen remodeling

    God thank you, I find that page! This inspiring article! continue to send


    Thanks for this useful blog post I’ve enjoyed reading it. Great information thank you for sharing this with us.