Skip to main content

NGINX

Headers More NGINX Rocky Linux 10: Header Control

by ,


We have by far the largest RPM repository with NGINX module packages and VMODs for Varnish. If you want to install NGINX, Varnish, and lots of useful performance/security software with smooth yum upgrades for production use, this is the repository for you.
Active subscription is required.

Headers More NGINX Rocky Linux 10 provides advanced HTTP header manipulation beyond what standard NGINX directives offer. This module lets you add, modify, or remove any HTTP header in both requests and responses, enabling security hardening, server fingerprint removal, and custom header injection.

This comprehensive guide shows you how to install and configure the Headers More module for NGINX on Rocky Linux 10, AlmaLinux 10, and other Enterprise Linux 10 distributions. You will learn to remove the Server header, add security headers, and implement advanced header manipulation patterns. By the end, you will have Headers More NGINX Rocky Linux 10 enhancing your server’s security and flexibility.

Why Use the Headers More Module

The standard NGINX add_header directive has significant limitations. It only adds headers to successful responses (2xx and 3xx status codes) and cannot modify or remove existing headers. The Headers More module solves these problems:

  • Remove any header: Delete Server, X-Powered-By, or other revealing headers
  • Works on all responses: Add headers to 4xx and 5xx error responses
  • Modify existing headers: Change header values rather than just adding new ones
  • Request header control: Manipulate incoming request headers before processing
  • Conditional logic: Apply headers based on response status or content type

These capabilities are essential for security hardening and compliance requirements. Many security frameworks require specific headers on all responses, including errors.

Prerequisites

Before installing Headers More NGINX Rocky Linux 10 packages, ensure you have:

  • Rocky Linux 10, AlmaLinux 10, RHEL 10, or Oracle Linux 10
  • Root or sudo access to the server
  • NGINX installed (or we will install it in this guide)

The GetPageSpeed repository provides pre-built Headers More packages ready for immediate use.

Installation

Step 1: Configure GetPageSpeed Repository

The GetPageSpeed repository provides enterprise-grade NGINX modules including Headers More. Install the repository:

sudo dnf -y install https://extras.getpagespeed.com/release-latest.rpm

Step 2: Install NGINX

If NGINX is not already installed:

sudo dnf -y install nginx
sudo systemctl enable --now nginx

Step 3: Install Headers More Module

Install the NGINX Headers More module:

sudo dnf -y install nginx-module-headers-more

After installation, you will see:

----------------------------------------------------------------------

The nginx-module-headers-more package has been installed.
To enable this module, add the following to /etc/nginx/nginx.conf
and reload NGINX:

    load_module modules/ngx_http_headers_more_filter_module.so;

----------------------------------------------------------------------

Step 4: Enable the Module

Add the module loading directive at the top of your NGINX configuration:

# /etc/nginx/nginx.conf
load_module modules/ngx_http_headers_more_filter_module.so;

user nginx;
worker_processes auto;
# ... rest of configuration

Test and reload:

sudo nginx -t && sudo systemctl reload nginx

Core Directives

The Headers More module provides four main directives for header manipulation.

more_set_headers

Adds or replaces response headers:

more_set_headers "X-Custom-Header: value";
more_set_headers "Cache-Control: no-store";

Unlike add_header, this works on all response codes including errors.

more_clear_headers

Removes response headers:

more_clear_headers "Server";
more_clear_headers "X-Powered-By";
more_clear_headers "X-AspNet-Version";

more_set_input_headers

Adds or replaces request headers before processing:

more_set_input_headers "X-Real-IP: $remote_addr";
more_set_input_headers "X-Forwarded-Proto: $scheme";

more_clear_input_headers

Removes request headers:

more_clear_input_headers "X-Forwarded-For";

Common Use Cases

Security Header Hardening

Add comprehensive security headers to all responses:

http {
    # Security headers for all responses
    more_set_headers "X-Content-Type-Options: nosniff";
    more_set_headers "X-Frame-Options: SAMEORIGIN";
    more_set_headers "X-XSS-Protection: 1; mode=block";
    more_set_headers "Referrer-Policy: strict-origin-when-cross-origin";
    more_set_headers "Permissions-Policy: geolocation=(), microphone=()";

    server {
        listen 80;
        # ...
    }
}

These headers protect against:

  • MIME type sniffing attacks
  • Clickjacking via iframes
  • Cross-site scripting (XSS)
  • Referrer information leakage
  • Unwanted browser feature access

Remove Server Fingerprint

Hide server software information:

http {
    # Remove headers that reveal server software
    more_clear_headers "Server";
    more_clear_headers "X-Powered-By";
    more_clear_headers "X-AspNet-Version";
    more_clear_headers "X-AspNetMvc-Version";

    # Optionally set a generic server header
    more_set_headers "Server: WebServer";
}

Before:

Server: nginx/1.28.1
X-Powered-By: PHP/8.1.0

After:

Server: WebServer

Content Security Policy

Add CSP headers for XSS protection:

server {
    more_set_headers "Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'";
}

For complex policies, use line continuation:

more_set_headers "Content-Security-Policy: default-src 'self'; 
    script-src 'self' https://cdn.example.com; 
    style-src 'self' 'unsafe-inline'; 
    img-src 'self' data: https:";

CORS Headers for All Responses

Add CORS headers that work on error responses too:

location /api/ {
    more_set_headers "Access-Control-Allow-Origin: https://example.com";
    more_set_headers "Access-Control-Allow-Methods: GET, POST, OPTIONS";
    more_set_headers "Access-Control-Allow-Headers: Authorization, Content-Type";
    more_set_headers "Access-Control-Max-Age: 86400";

    proxy_pass http://backend;
}

This is superior to add_header because CORS headers appear on 4xx and 5xx responses. When your API returns a 401 or 500 error, browsers still need CORS headers to read the response.

Conditional Headers by Status Code

Add headers only for specific response codes:

location / {
    # Add header only for 404 responses
    more_set_headers -s 404 "X-Error-Type: not-found";

    # Add header for all error responses
    more_set_headers -s '400 401 403 404 500 502 503' "X-Error: true";

    proxy_pass http://backend;
}

Conditional Headers by Content Type

Add headers based on response content type:

# Add cache headers only for static files
more_set_headers -t 'text/css text/javascript application/javascript' 
    "Cache-Control: public, max-age=31536000, immutable";

# Add download header for PDFs
more_set_headers -t 'application/pdf' 
    "Content-Disposition: attachment";

Request Header Manipulation

Modify incoming request headers:

server {
    # Normalize client IP header
    more_set_input_headers "X-Real-IP: $remote_addr";

    # Add tracking header
    more_set_input_headers "X-Request-ID: $request_id";

    # Remove potentially dangerous headers
    more_clear_input_headers "X-Forwarded-Host";

    location / {
        proxy_pass http://backend;
    }
}

Cache Control Strategies

Implement different caching policies:

# Static assets - long cache
location ~* \.(css|js|jpg|png|gif|ico|woff2?)$ {
    more_set_headers "Cache-Control: public, max-age=31536000, immutable";
    root /var/www/html;
}

# HTML pages - no cache
location ~* \.html$ {
    more_set_headers "Cache-Control: no-cache, no-store, must-revalidate";
    more_set_headers "Pragma: no-cache";
    more_set_headers "Expires: 0";
    root /var/www/html;
}

# API responses - short cache
location /api/ {
    more_set_headers "Cache-Control: private, max-age=60";
    proxy_pass http://backend;
}

Comparison with add_header

Understanding when to use Headers More versus standard add_header:

Feature add_header more_set_headers
Works on 2xx/3xx Yes Yes
Works on 4xx/5xx Only with always Yes (default)
Remove headers No Yes
Modify existing No Yes
Request headers No Yes
Filter by status No Yes
Filter by type No Yes

Use add_header for simple cases where you only need headers on successful responses. Use Headers More for security headers, error responses, or any advanced manipulation.

Verification

After configuring Headers More NGINX Rocky Linux 10, verify the setup.

Check Response Headers

curl -sI http://localhost/ | grep -E "(Server|X-)"

Expected output (with security headers, no Server version):

X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN

Test Error Response Headers

Verify headers appear on 404 errors:

curl -sI http://localhost/nonexistent | grep -E "(X-)"

Test with Different Content Types

Check headers vary by content type:

curl -sI http://localhost/style.css | grep Cache-Control
curl -sI http://localhost/index.html | grep Cache-Control

Troubleshooting

Headers Not Applied

Symptom: Headers do not appear in responses

Solutions:

  1. Verify the module file exists: ls /usr/lib64/nginx/modules/ngx_http_headers_more_filter_module.so
  2. Check the module is configured: nginx -T 2>&1 | grep headers_more
  3. Ensure nginx -t passes without errors
  4. Check directive placement (http, server, or location context)
  5. Ensure no conflicting add_header directives

Header Appears Multiple Times

Symptom: Same header appears twice

Solutions:

  1. Remove duplicate add_header directives
  2. Use more_set_headers instead of add_header to replace
  3. Check parent contexts for inherited headers

Input Headers Not Modified

Symptom: Request headers unchanged at backend

Solutions:

  1. Place more_set_input_headers before proxy_pass
  2. Check if backend overwrites headers
  3. Verify directive is in correct location block

SELinux Compatibility

The nginx-module-headers-more package from GetPageSpeed works correctly with SELinux in enforcing mode. No additional policy configuration is required.

Complete Production Configuration

Here is a production-ready Headers More NGINX Rocky Linux 10 configuration:

# /etc/nginx/nginx.conf
load_module modules/ngx_http_headers_more_filter_module.so;

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Remove server fingerprint
    more_clear_headers "Server";
    more_clear_headers "X-Powered-By";

    # Security headers for all responses
    more_set_headers "X-Content-Type-Options: nosniff";
    more_set_headers "X-Frame-Options: SAMEORIGIN";
    more_set_headers "X-XSS-Protection: 1; mode=block";
    more_set_headers "Referrer-Policy: strict-origin-when-cross-origin";

    sendfile on;
    keepalive_timeout 65;

    server {
        listen 80;
        server_name example.com;

        # Static files with long cache
        location ~* \.(css|js|jpg|png|gif|ico|woff2?)$ {
            more_set_headers "Cache-Control: public, max-age=31536000";
            root /usr/share/nginx/html;
        }

        # HTML with no cache
        location / {
            more_set_headers "Cache-Control: no-cache";
            root /usr/share/nginx/html;
            index index.html;
        }
    }
}

Test and apply:

sudo nginx -t && sudo systemctl reload nginx

For more NGINX security and configuration guides:

Conclusion

Headers More NGINX Rocky Linux 10 provides essential header manipulation capabilities for security hardening and compliance. Unlike the standard add_header directive, it works on all response codes, can remove headers, and supports conditional logic based on status or content type.

Key benefits include removing server fingerprints, adding security headers to error responses, and implementing sophisticated caching strategies. The module integrates seamlessly with existing NGINX configurations and requires no application code changes.

For any production NGINX deployment, the Headers More module is essential for implementing proper security headers and meeting compliance requirements. The ability to manipulate headers on error responses alone justifies its use over standard NGINX header directives.

D

Danila Vershinin

Founder & Lead Engineer

NGINX configuration and optimizationLinux system administrationWeb performance engineering

10+ years NGINX experience • Maintainer of GetPageSpeed RPM repository • Contributor to open-source NGINX modules

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.