yum upgrades for production use, this is the repository for you.
Active subscription is required.
The Problem: Unwanted Cookies Bloat Your Backend Requests
Every time a client visits your website, their browser accumulates cookies — Google Analytics (_ga, _gid), Facebook Pixel (_fbp, _fbc), HubSpot (__hstc, hubspotutk), and many more. When NGINX proxies those requests to your upstream servers, every single cookie travels along, even though your application never needs them. The NGINX request cookies filter module exists to solve exactly this problem.
This causes real issues for production systems:
- Broken caching: NGINX proxy cache and Varnish skip caching entirely when a
Cookieheader is present. Your cache hit rate drops to near zero because tracking cookies ride along on every request. - Privacy violations: GDPR and similar regulations require minimizing personal data exposure. Forwarding tracking cookies to your backend means your application processes data it does not need — increasing your compliance risk.
- Wasted bandwidth: A typical request can carry 500+ bytes of tracking cookies. At thousands of requests per second, that adds up to significant bandwidth wasted between NGINX and your backend.
- Security leaks: In microservices architectures, session cookies get forwarded to backends that should never see them. A compromised API service could expose session tokens it was never meant to receive.
The Solution: NGINX Request Cookies Filter Module
The NGINX request cookies filter module solves these problems with clean, declarative directives. It lets you strip, rewrite, add, or clear individual cookies in the Cookie request header before the request reaches your upstream server. No regex hacks, no Lua scripts, no fragile workarounds.
Here is what a typical configuration looks like:
location / {
# Strip tracking cookies your backend doesn't need
clear_request_cookie _ga;
clear_request_cookie _gid;
clear_request_cookie _fbp;
# Forward only the cookies your app actually uses
proxy_set_header Cookie $filtered_request_cookies;
proxy_pass http://backend;
}
With this configuration, your backend receives only the cookies it needs. Tracking cookies never reach your application, your cache starts working again, and your compliance surface shrinks.
How the Request Cookies Filter Works
The module operates on the Cookie request header during variable evaluation. When you reference the $filtered_request_cookies variable, the module:
- Parses all
Cookieheaders into individual name-value pairs - Applies your filter rules in order (set, add, rewrite, clear)
- Rebuilds a clean
Cookiestring from the surviving cookies
You then pass this filtered string to your upstream via proxy_set_header. The original request headers remain untouched — the filtering affects only what gets forwarded.
Installation
RHEL, CentOS, AlmaLinux, Rocky Linux
Install the NGINX request cookies filter module from the GetPageSpeed RPM repository:
sudo dnf install https://extras.getpagespeed.com/release-latest.rpm
sudo dnf install nginx-module-request-cookies-filter
Then load the module by adding this line at the top of /etc/nginx/nginx.conf:
load_module modules/ngx_http_request_cookies_filter_module.so;
Debian and Ubuntu
First, set up the GetPageSpeed APT repository, then install:
sudo apt-get update
sudo apt-get install nginx-module-request-cookies-filter
On Debian/Ubuntu, the package handles module loading automatically. No
load_moduledirective is needed.
You can find additional details on the module page.
Directives
The module provides four directives for manipulating request cookies. All directives are valid in http, server, and location contexts. Cookie names are matched case-insensitively.
set_request_cookie
Syntax: set_request_cookie cookie_name value;
Default: —
Context: http, server, location
Sets a cookie to the given value. If the cookie already exists, its value is replaced. If not, it is added. This combines add and rewrite into one operation.
location /app {
# Always ensure the "source" cookie is set to "nginx"
set_request_cookie source "nginx";
proxy_set_header Cookie $filtered_request_cookies;
proxy_pass http://backend;
}
add_request_cookie
Syntax: add_request_cookie cookie_name value;
Default: —
Context: http, server, location
Adds a cookie only if it does not already exist. If the client already sent a cookie with the same name, this directive is ignored. Use it for setting default values.
location /app {
# Set a default theme if the client hasn't chosen one
add_request_cookie theme "light";
proxy_set_header Cookie $filtered_request_cookies;
proxy_pass http://backend;
}
rewrite_request_cookie
Syntax: rewrite_request_cookie cookie_name value;
Default: —
Context: http, server, location
Changes an existing cookie’s value. If the cookie does not exist, this directive does nothing. Use it when you need to transform a value without creating new cookies.
location /app {
# Normalize the session type cookie
rewrite_request_cookie session_type "standard";
proxy_set_header Cookie $filtered_request_cookies;
proxy_pass http://backend;
}
clear_request_cookie
Syntax: clear_request_cookie cookie_name [if=condition];
Default: —
Context: http, server, location
Removes a cookie from the request. If the cookie does not exist, this directive does nothing. This is the most commonly used directive for stripping tracking and analytics cookies.
The clear_request_cookie directive supports an optional if= parameter for conditional execution. The cookie is cleared only when the condition variable evaluates to a non-empty, non-zero value.
location /api {
# Strip common tracking cookies
clear_request_cookie _ga;
clear_request_cookie _gid;
clear_request_cookie _fbp;
clear_request_cookie _fbc;
proxy_set_header Cookie $filtered_request_cookies;
proxy_pass http://api_backend;
}
Conditional clearing example:
You can use the if= parameter with any NGINX variable to conditionally clear cookies. For example, clear tracking cookies only when a query parameter is present:
location /app {
# Clear the tracking cookie only when ?strip=1 is in the URL
clear_request_cookie _ga if=$arg_strip;
proxy_set_header Cookie $filtered_request_cookies;
proxy_pass http://backend;
}
Variables
$filtered_request_cookies
Contains the rebuilt Cookie header string after all filter rules are applied. Cookies are joined with ; (semicolon and space), following the standard format.
If no filter rules exist in the current context, this variable returns the same value as $http_cookie. This makes it safe to use across locations where some filter cookies and others do not.
Important: You must forward this variable to your upstream with proxy_set_header. Defining filter rules alone does not modify the forwarded cookies:
proxy_set_header Cookie $filtered_request_cookies;
Practical Examples
Strip All Analytics Cookies
This is the most common use case. Remove tracking cookies your backend does not need:
server {
listen 80;
server_name example.com;
location / {
# Google Analytics
clear_request_cookie _ga;
clear_request_cookie _gid;
clear_request_cookie _gat;
# Facebook Pixel
clear_request_cookie _fbp;
clear_request_cookie _fbc;
# HubSpot
clear_request_cookie __hstc;
clear_request_cookie hubspotutk;
clear_request_cookie __hssc;
clear_request_cookie __hssrc;
proxy_set_header Cookie $filtered_request_cookies;
proxy_pass http://backend;
}
}
Improve Proxy Cache Hit Rate
Cookies prevent NGINX from caching by default. Strip unnecessary cookies from static asset requests to let the proxy cache work:
proxy_cache_path /var/cache/nginx levels=1:2
keys_zone=app_cache:10m max_size=1g;
server {
listen 80;
server_name example.com;
location /static/ {
# Remove all cookies for static content
clear_request_cookie _ga;
clear_request_cookie _gid;
clear_request_cookie _fbp;
clear_request_cookie session;
proxy_set_header Cookie $filtered_request_cookies;
proxy_cache app_cache;
proxy_pass http://backend;
}
location / {
# Keep all cookies for dynamic content
proxy_pass http://backend;
}
}
Inject Server-Side Cookies
Add cookies that your backend expects but the client does not provide, like a routing hint or feature flag:
location / {
# Add a routing cookie for the backend
add_request_cookie route_hint "$server_addr";
# Mark requests processed by this instance
set_request_cookie processed_by "nginx-frontend";
proxy_set_header Cookie $filtered_request_cookies;
proxy_pass http://backend;
}
Isolate Cookies per Microservice
In a microservices architecture, prevent cookies from leaking between services. The NGINX request cookies filter lets you control exactly which cookies each backend receives:
upstream auth_service {
server 10.0.1.10:8080;
}
upstream api_service {
server 10.0.1.20:8080;
}
server {
listen 80;
location /auth/ {
# Auth only needs session cookies
clear_request_cookie _ga;
clear_request_cookie _gid;
clear_request_cookie _fbp;
proxy_set_header Cookie $filtered_request_cookies;
proxy_pass http://auth_service;
}
location /api/ {
# API only needs the token cookie
clear_request_cookie _ga;
clear_request_cookie _gid;
clear_request_cookie _fbp;
clear_request_cookie session;
proxy_set_header Cookie $filtered_request_cookies;
proxy_pass http://api_service;
}
}
Why Not Use Native NGINX Features?
You might wonder whether NGINX can strip cookies without a module. There are native approaches, but each has significant drawbacks.
The map + Regex Approach
A common workaround uses a map block with regex to strip cookies:
map $http_cookie $cleaned_cookies {
default $http_cookie;
"~*(?:^|;\s*)_ga=[^;]+(?:;\s*|$)" "";
}
This breaks quickly with multiple cookies. Regex patterns for cookie strings are brittle — they must handle cookies at the beginning, middle, and end of the header string. They must also deal with varying whitespace and avoid matching substrings.
The proxy_set_header Cookie "" Approach
You can strip all cookies with one directive:
proxy_set_header Cookie "";
However, this is all-or-nothing. You cannot keep the cookies your application needs while stripping only the unwanted ones.
Lua and njs Scripting
Both Lua (OpenResty) and njs can manipulate cookies programmatically. However, they add runtime dependencies and are harder to audit. They are overkill when declarative cookie filtering is all you need. The NGINX request cookies filter module is lighter and purpose-built for this task.
Configuration Inheritance
Directives in a parent context (http or server) are inherited by child contexts. If a child defines its own rules for a cookie, those override the parent for that cookie name. Rules for other cookies are still inherited.
server {
# These apply to all locations
clear_request_cookie _ga;
clear_request_cookie _gid;
location /analytics {
# Override: keep _ga for analytics
# _gid is still cleared (inherited)
set_request_cookie _ga $cookie__ga;
proxy_set_header Cookie $filtered_request_cookies;
proxy_pass http://analytics_backend;
}
location /app {
# Both _ga and _gid are cleared (inherited)
proxy_set_header Cookie $filtered_request_cookies;
proxy_pass http://app_backend;
}
}
Performance Considerations
The NGINX request cookies filter module adds minimal overhead. It processes cookies only when $filtered_request_cookies is evaluated. If you do not reference this variable, no parsing occurs.
The module performs a single pass through the cookie string and rule list. For a typical configuration with 5–10 filter rules, processing time is negligible compared to network latency.
Using NGINX variables in cookie values (e.g., set_request_cookie routing "$upstream_addr") adds a small evaluation cost per request, but this is still extremely fast.
Troubleshooting
Cookies Are Not Being Filtered
The most common mistake is forgetting proxy_set_header. Filter rules alone do not modify the request:
# Wrong — missing proxy_set_header
location /app {
clear_request_cookie _ga;
proxy_pass http://backend;
}
# Correct — forward filtered cookies
location /app {
clear_request_cookie _ga;
proxy_set_header Cookie $filtered_request_cookies;
proxy_pass http://backend;
}
Unknown Directive Error
If NGINX reports unknown directive "set_request_cookie", the module is not loaded. Add the load_module directive at the top of nginx.conf, before the events block:
load_module modules/ngx_http_request_cookies_filter_module.so;
Verifying the Filter
Add filtered cookies as a response header for debugging:
location /debug {
clear_request_cookie _ga;
set_request_cookie test "hello";
add_header X-Filtered-Cookies $filtered_request_cookies always;
return 200 "debug\n";
}
Test with curl:
curl -I -b "_ga=GA1.2.123; session=abc" http://localhost/debug
You should see _ga removed and test=hello added:
X-Filtered-Cookies: session=abc; test=hello
Remove the debug header before deploying to production.
Conclusion
The NGINX request cookies filter module provides a clean, declarative way to control which cookies reach your upstream servers. Whether you need to strip tracking cookies for privacy, improve cache hit rates, or isolate cookies between microservices, this module handles it without scripting or fragile regex patterns.
Install the module from the GetPageSpeed repository for RHEL-based or Debian/Ubuntu systems. The source code is available on GitHub.
