One of the common issues preventing Cloudflare from caching a website (always returning status REVALIDATED 5px EXPIRED instead of HIT) is the presence of the header Cache-Control: no-cache from the origin server. This article will guide you through detailed diagnosis and a complete fix for this issue on systems using Nginx as a Reverse Proxy in front of OpenLiteSpeed.

1. Symptoms of the issue

When checking the Response Headers of your website or static files (such as CSS, JS, and images) using the curl command or Developer Tools (F12) in your browser, you see the following headers appearing at the same time:

Cache-Control: public, max-age=2592000
Cache-Control: no-cache
Cf-Cache-Status: EXPIRED (or REVALIDATED)

The simultaneous presence of two conflicting Cache-Control headers confuses Cloudflare. The no-cache header forces Cloudflare to send a revalidation request to the origin server on every visit, increasing response time (TTFB) and overloading your origin server.

2. Diagnosis process and root-cause identification

To resolve this issue completely, we need to go through steps to isolate the cause:

  • Step 1: Check plugins and .htaccess: Many people often assume the issue is caused by WordPress cache plugins (such as LiteSpeed Cache) or the .htaccess. file. However, if you use OpenLiteSpeed, it usually ignores header configurations (such as mod_headers) in the file .htaccess.
  • Step 2: Check the Origin Server IP directly: Run curl directly against the origin server IP (bypassing Cloudflare) to see which headers are generated at the server:
    curl -I -k -H "Host: yourdomain.com" https://[SERVER_IP]/wp-includes/css/dist/block-library/style.min.css

    If the Server: nginx header appears together with x-turbo-charged-by: LiteSpeed, your system is definitely running an Nginx Reverse Proxy model in front of OpenLiteSpeed.

3. Complete solution

Step 1: Remove the hardcoded configuration line in Nginx

When configuring a Reverse Proxy on control panels such as aaPanel, the system often automatically adds a cache-prevention line in Nginx to avoid dynamic-data issues for Node.js/Python applications. You need to remove it.

Open the Nginx configuration file for the domain (usually located at /www/server/panel/vhost/nginx/yourdomain.com.conf), find the configuration block location /:

location / {
    proxy_pass http://127.0.0.1:8188;
    ...
    # DELETE OR COMMENT OUT THE LINE BELOW:
    # add_header Cache-Control no-cache;
}

Then save and Restart Nginx (Restart Nginx).

Step 2: Disable the OpenLiteSpeed Cache Module (when using Cloudflare Page Cache)

If you are using plugins such as Super Page Cache for Cloudflare to manage caching on Cloudflare and local disk, disable the OpenLiteSpeed cache module to avoid conflicts.

Open the main OpenLiteSpeed configuration file (httpd_config.conf) through the aaPanel interface, find the block module cache and change:

module cache {
    ls_enabled          0 # Change from 1 to 0 to disable the module
    ...
}

Save and Restart OpenLiteSpeed.

4. Results after the fix

After completing these two steps, run the check command again. You will see only one header remaining Cache-Control valid from WordPress/LiteSpeed, and Cloudflare will return the status HIT immediately on subsequent visits.