1. Overview

A side effect of content caching is that content updates on the origin server don’t necessarily propagate immediately to the cache. This means that old content may persist for some time.

For example, whenever the execution of update operations happens, there’s a probability that the client might receive a mixture of stale and current resources making the presentation seem inconsistent.

In this tutorial, we’ll explore different ways to clear the cache on Nginx. Before we move on to how we can clear the cache, we need to know the proxy_cache_path value. In most cases, the path is /var/cache/nginx.

2. Manually Deleting the Files From the Cache Directory

This is one of the simplest methods and works well if we’re looking for a more manual approach.

Below is a response header for a file we have in the cache:

$ curl -I http://my.example.com/index.html
HTTP/1.1 200 OK
Server: nginx/1.20.2
Date: Sun, 20 Nov 2022 17:25:08 GMT
Content-Type: text/html
Content-Length: 2419
Connection: keep-alive
Last-Modified: Mon, 14 Nov 2022 22:16:45 GMT
ETag: "7gx5ntda-fdb"
Cache: HIT
Accept-Ranges: bytes

The cache header has the value ‘HIT’, meaning the file is cached.

Let’s purge the Nginx cache manually:

$ sudo rm -rf /var/cache/nginx/*

Now, let’s check the cache header value after using the curl command above:

$ curl -I http://my.example.com/index.html
HTTP/1.1 200 OK
Server: nginx/1.20.2
Date: Sun, 20 Nov 2022 18:10:25 GMT
Content-Type: text/html
Content-Length: 3782
Connection: keep-alive
Last-Modified: Sun, 20 Nov 2022 17:50:10 GMT
ETag: "7ct9wqxm-fdb"
Cache: MISS
Accept-Ranges: bytes

We can confirm the purging of the cache by looking at the new value in the response header cache showing a ‘MISS’ value.

3. Using proxy_cache_bypass Module

The proxy_cache_bypass module is useful in the invalidation of cache assets. It does this by instructing Nginx to pass the request back to the backend server and refresh the cached resource upon retrieval.

In a real-world scenario, we are looking for this when handling cache invalidation.

To make this type of purge block, we need to first enable purge from local IP only:

if ($remote_addr ~ "^(example.ip)$") {
    set $bypass $http_cache_purge;
}

Then we can enable the BYPASS method:

proxy_cache_bypass $bypass;

Combining the changes above, here’s the full configuration file:

proxy_cache_path /var/cache/nginx keys_zone=my_zone:10m inactive=8h;

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    set $bypass 0;
    if ($remote_addr ~ "^(example.ip)$") {
        set $bypass $http_cache_purge;
    }

    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;
    server_name _;
    proxy_cache_key $scheme$http_host$uri$is_args$args;

    location / {
        proxy_cache my_zone;
        proxy_pass http://my.example;
        proxy_cache_valid 200 1d;
        add_header Cache $upstream_cache_status;
        proxy_cache_min_uses 2;
        proxy_cache_bypass $bypass;
    }
}

To test this method, we need to change the origin file to confirm that Nginx took the fresh version and cached it.

Let’s calculate the MD5 hash signature of the cached file:

% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 10918  100 10918    0     0   710k      0 --:--:-- --:--:-- --:--:--  761k
3526531ccd6c6a1d2340574a305a18f8  -

Next, let’s make any kind of change to the origin file and then check the resulting MD5 hash signature:

% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   162  100   162    0     0   158k      0 --:--:-- --:--:-- --:--:--  158k
1b7c22a214949975556626d7217e9a39  -

After doing this, we have a firm understanding of what to expect on the Nginx side.

Let’s send a new request for the Nginx version with the request header to purge the cache:

% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   162  100   162    0     0   158k      0 --:--:-- --:--:-- --:--:--  158k
1b7c22a214949975556626d7217e9a39  -

Finally, let’s confirm if the cached file was successfully purged:

$ curl localhost/index.html -H 'Cache-Purge: true' -I
HTTP/1.1 200 OK
Server: nginx/1.14.1
Date: Thu, 03 Nov 2022 13:01:37 GMT
Content-Type: text/html
Content-Length: 4059
Connection: keep-alive
Last-Modified: Thu, 03 Nov 2022 14:01:10 GMT
ETag: "5f2befda-fdb"
Cache: BYPASS
Accept-Ranges: bytes

From the above header, we don’t have any ‘HIT’ or ‘MISS’ values. Only a ‘BYPASS’ value is visible.

This is because Nginx bypasses the local cache and heads straight to the backend server for the requested file.

4. Using proxy_cache_purge Module

The proxy_cache_purge module defines conditions under which a request is to be considered a cache purge request.

Whenever the value of at least one string parameter isn’t empty and not “0”, the cache entry with a matching cache key is removed. Successful requests return the 204 (No Content) response.

Purge requests with cache keys that end with an asterisk (“*”) will automatically remove all the cache entries matching the wildcard cache key.

Let’s explore how we can use the proxy_cache_purge module to clear the cache on Nginx.

We first map the $request_method to a custom variable which is the $cache_purge under the HTTP context:

http {
    ...
    map $request_method $cache_purge {
        PURGE 1;
        default 0;
    }
}

Here’s a sample of the full configuration file:

proxy_cache_path /tmp/cache keys_zone=mycache:10m levels=1:2 inactive=60s;

map $request_method $purge_method {
    PURGE 1;
    default 0;
}

server {
    listen 80;
    server_name www.example.com;
    location / {
        proxy_pass http://localhost:8008;
        proxy_cache mycache;
        proxy_cache_purge $purge_method;
    }
}

Then let’s send the purge request:

$ curl -X PURGE -D – "http://www.example.com/*"
<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
.
....truncated....

Here, the command ends with an asterisk that purges all the pages under the http://www.example.com/ domain. We receive HTML content of the homepage as the response.

5. Conclusion

In this article, we have observed the different ways we can clear the cache of an Nginx server. Some of the methods have a manual process of clearing the cache. However, we’ve also explored the proxy_cache_bypass method, which can be helpful in clearing the cache automatically.