LSCache Configuration Without Plugins

You are here:
< Back

Public Cache vs. Private Cache

A public, or “shared” cache is used by more than one client. As such, it gives a greater performance gain and a much greater scalability gain, as a user may receive cached copies of web pages without ever having obtained a copy directly from the origin server. Reverse Proxies (gateway caches) and the vast majority of proxies are public caches.

A private cache is only used by one client. Generally this applies only to a cache maintained by that client itself, though if you had a proxy that was only being used by one client (say you had a small LAN for your own use only and put a web proxy near the gateway) it would be possible to configure it to act as a private cache. Private caches do not offer quite as much scalability as public caches, but they do have certain important advantages over public caches.

Advantages of Private Cache

  1. They offer immense benefits to the user of that one client.
  2. Almost every client on the visible web (that is, browsers, RSS readers, and other interactive user agents) and a very large number of those on the machine-only parts of the web (that is, spiders and clients of web services) use a private cache of some sort. As such, you can rely upon the presence of at least one cache being involved in almost everything you do on the web.
  3. With some web pages it may not be appropriate for public caches to cache them or to return those web pages without re-validating them but perfectly acceptable for private caches to do so (e.g. anything which can only be seen by authorized users or which changes its representation depending upon who is looking at it). It can even be appropriate for encrypted documents to be so cached (though this requires one to be very sure as to the security of the cache itself, and so is generally not done).

When to use Public Cache, Private Cache, or no Cache

Each particular URL of a website can be set up to be publicly cached, privately cached, or not cached at all, but can not be both public and private cache at the same time. That is to say, you can only setup one cache type for a particular URL. Depending on the situation, you might want to set different URLs to be cached differently. The following outlines a few scenarios helpful in determining which type of caching should be used for a URL or a set of URLs.

Public cache

  1. Infrequently changed
  2. Popular demand (requested frequently)

Private cache

  1. Can only be used by one user/client, such as personal information on a web site (for authorized users)
  2. Resources such as documents only available for one particular user or authorized users.
  3. Resources served via the HTTPS protocol
  4. Responses with cookies

No cache

  1. POST request
  2. Dynamic content (such as time sensitive info)
  3. Frequently changed objects

How to Enable LiteSpeed Cache

Please refer this article to learn how to enable LiteSpeed Cache.

Using CacheEnable, CacheDisable, and CacheLookup Directives

A rewrite rule can disable or enable cache on its own without using CacheEnable or CacheDisable directives. However, using a combination of both rewrite rules and these directives allows you to meet complicated requirements.

Placing CacheEnable or CacheDisable directives in a virtual host document root .htaccess will overwrite the server level of cache configuration.

  • CacheEnable public /: Enable cache for all URLs of this virtual host, similiar to a virtual host level of global enabling.
  • CacheDisable public /: Disable cache for all URLs of this virtual host, similiar to a virtual host level of global disabling.
  • CacheLookup: Tells the application whether it should look up the cache or not. When CacheEnable or CacheDisable is used, this is not required since it has already been enabled or disabled by default.

The CacheEnable directive

Enable Public Cache

To enable public cache, you can add the following to .htaccess:

<IfModule LiteSpeed> 
CacheEnable public /
</IfModule>

The above directive will enable public cache and cache lookup as well, though it is not set in the LSWS Admin configuration nor by the CacheLookup public on directive. If a LiteSpeed cache plugin for an application is used, CacheEnable public / will not be needed. However, CacheLookup public on would still be needed. LiteSpeed Cache will work through header control. That is, however, beyond of the scope of this wiki.

When using / in your directive, you are enabling public cache on everything located under the website’s root directory. For example, if your site is located in /home/username/public_html and points to http://www.example.com, everything located within that directory and any subdirectories within it would be cached. If you used CacheEnable public /blog, everything under /home/username/public_html/blog, pointing to http://www.example.com/blog would be cached.

Enable Private Cache

To enable private cache, you can add the following lines to the .htaccess file under the document root of the website:

<IfModule LiteSpeed>
CacheEnable private /
</IfModule>

The above directive will enable private cache and cache lookup as well, though it is not set in the LSWS Admin configuration nor by the CacheLookup private on directive. If a LiteSpeed cache plugin for an application is used, CacheEnable private / will not be needed. However, CacheLookup private on would still be needed. LiteSpeed Cache will work through header control. This is, however, beyond of the scope of this wiki.

The CacheDisable Directive

Public cache:

<IfModule LiteSpeed>
CacheDisable public /
</IfModule>

Private cache:

<IfModule LiteSpeed>
CacheDisable private /
</IfModule>

To enable/disable cache for a certain URL, just replace / with the desired the URL.

Using Rewrite Rules

You may also use rewrite rules to set up cache or disable cache. Rewrite rules can be placed in a directory’s .htaccess file. The difference between using rewrite rules through E=cache-control and the CacheEnable directive is that a rewrite rule can control the cache expiration (TTL), while CacheEnable cannot.

Here’s a simple example using a rewrite rule to set up public caching of the entire site for 2 minutes:

RewriteEngine On
RewriteCond condition1
RewriteRule .* - [E=cache-control:max-age=120]

Note that there is no need to specify “public” because that is the default. Also, caching time is in seconds (i.e. use 120 seconds to cache for 2 minutes).

Here’s a simple example using a rewrite rule to disable cache:

RewriteEngine On
RewriteCond condition4
RewriteRule .* - [E=Cache-Control:no-cache]

Here’s a simple example using a rewrite rule to set up private cache:

RewriteEngine On
RewriteCond condition3
RewriteRule .* - [E=cache-control:private]

Note that there is no need to specify the max-age for private cache since it is for a specific browser and is controlled by the session.

How to Enable Cache

To enable cache, you can use either rewrite rules alone, or with CacheEnable/CacheDisable to define more complicated requirements. The rewrite rules or the combination of rewrite rules with CacheEnable/CacheDisable directives are used to control what is to be cached, and what’s not.

Example 1: Rewrite Rules Only

Enable cache and cache everything for 2 minutes:

<IfModule LiteSpeed>
RewriteEngine On
RewriteRule (.*\.php)?$ - [E=cache-control:max-age=120]
</IfModule>

Example 2: Rewrite Rules Only

<IfModule LiteSpeed>
RewriteEngine On
## cache should be available for HEAD or GET requests
RewriteCond %{REQUEST_METHOD} ^HEAD|GET$
## select which pages to cache
RewriteCond %{HTTP_COOKIE} page_contain_cachetoken=yes
# with other condition
RewriteCond %{QUERY_STRING} !s=[a-fA-F0-9]{32}
# excluding certain URLs
RewriteCond %{REQUEST_URI} !/(login|register|usercp|private|profile|cron|image)\.php$
# cache for 2 mins for php pages only
RewriteRule /(.*\.php)?$ - [E=Cache-Control:max-age=120]
</IfModule>
<IfModule LiteSpeed>
# for those not met above condition, enable private cache.
RewriteCond %{REQUEST_METHOD} ^HEAD|GET$
## select which pages to serve from private cache
RewriteCond %{HTTP_COOKIE} !page_contain_cachetoken=yes
# with other condition
RewriteCond %{QUERY_STRING} !s=[a-fA-F0-9]{32}
# excluding certain URLs
RewriteCond %{REQUEST_URI} !/(login|register|usercp|private|profile|cron|image)\.php$
# private cache for however long set in cache policy for php pages only
RewriteRule (.*\.php)?$ - [E=Cache-Control:max-age=120]
RewriteRule (.*\.php)?$ - [E=Cache-Control:private]
</IfModule>

These rules can be placed in one of the following 2 locations:

  • .htaccess (last line needs to changed as follows:)
  • LiteSpeed native configuration: Web Admin Console > Configurations > Virtual Hosts > Rewrite

Example 3: Rewrite Rules and Cache Directives

CacheDisable public /
RewriteEngine On
RewriteRule .* - [L,E=cache-control:max-age=120]

The CacheDisable directive disables all URLs from caching, but the rewrite rules //enable// everything to be cached for 2 minutes. In this case, CacheDisable public / does not have any impact on the settings.

Restart LSWS to make changes effective.

Any time thre is a change on .htaccess or the WebAdmin console, you will need to restart LSWS. Admin Console > Actions > Graceful Restart or run /path/to/lsws/bin/lswsctrl restart or service lsws restart from the command line.

Verify Caching is Working

Open your browser’s inspector, by right-clicking and selecting Inspector or pressing the F12 key, and refresh the page. Under the Network tab, look for the HTML page you just loaded and click on it to view its response header.

In the response header you should see X-LiteSpeed-Cache: hit to indicate that the page was served from cache successfully. If you see X-LiteSpeed-Cache: miss, reload the page and check again.

Notes

OpenLiteSpeed outputs a response header X-LiteSpeed-Cache: hit if a request is served from public cache.

OpenLiteSpeed outputs a response header X-LiteSpeed-Cache: hit,private if a request is served from private cache.

The LSCache hit rate is calculated based on all files served. Many of the files served by LSWS, like CSS or HTML, are intentionally not cached by LSCache. Because these files are included in the LSCache hit rate calculation, the hit rate may sometimes look much lower than one might expect.

You will not see a Cache-Control:max-age header when you use LSCache. Please be aware there are two different concepts: Cache-Control:max-age is a browser cache header. It is not for server-side cache. x-litespeed-cache-control: public,max-age=86400 is an LSCache control header, which will be seen when the cache plugin being used. When using a rewrite rule like [E=cache-control:max-age=120]to enable cache as instructed in this wiki, you won’t see the x-litespeed-cache-control header.

Cache Purge

OpenLiteSpeed will delete expired cache files automatically, making this step optional. Assuming you have a need to manually delete the outdated files, you can choose one of the following ways:

Linux Command via Cron

A cron job should be set to clear out old cache files that are past the set Time To Live (TTL).

To do this, you should run the crontab either as the root user or as the cache owner for self-management.

crontab -e

The virtual host cache root directory is normally located in /usr/local/lsws/cachedata

*/10 * * * * root find /virtualhost/cache/root/directory/ -type f -mmin +8 -delete 2>/dev/null

Note: This cron job deletes cached files that are more than 8 minutes old every 10 minutes. Since the cache TTL is set at 120 seconds (2 minutes), it is safe to delete these files as they are way past their TTL.

By URL via PHP Script

You can create a PHP script to do purge the cache by URL.

Usage: php $argv[0] -(r|p) domain url [server_ip] [port]
-r method option: Refresh cache (use stale cache while updating cache)
-p method option: Purge cache (delete cache entry)
domain: required parameter for domain name
url: required parameter for url
server_ip: optional parameter, default is 127.0.0.1
server_port: optional parameter, default is 80

Example 1:

/usr/local/lsws/admin/fcgi-bin/admin_php5 /usr/local/lsws/admin/misc/purge_cache_byurl.php -r mywebsite.com /index.php

Example 2:

/usr/local/lsws/admin/misc>php purge_cache_byurl.php -p www.domain.com /
HTTP/1.0 200 Purged
Date: Wed, 03 Jun 2015 05:48:31 GMT
Server: LiteSpeed
Connection: close

Note 1: The required URL has to be a //specific// URL and can not include wildcards, otherwise it may return 400 – Bad request error. Alternately, if you want to delete all cached files, you can do it through OS command, e.g.: rm -rf /lsws-cache-folder*

Note2: Server_ip can not be omitted in some cases!

The PHP script code:

<?php

/****
* purge_cache_byurl
*
* Example: /usr/local/lsws/admin/fcgi-bin/admin_php5 /usr/local/lsws/admin/misc/purge_cache_byurl.php -r mywebsite.com /index.php
*/

if ($argc < 4 || $argc > 6) {
echo "Invalid arguments!\n";
echo "Usage: php $argv[0] -(r|p) domain url [server_ip] [port]
-r method option: Refresh cache (use stale cache while updating cache)
-p method option: Purge cache (delete cache entry)
domain: required parameter for domain name
url: required parameter for url
server_ip: optional parameter, default is 127.0.0.1
server_port: optional parameter, default is 80
";
exit;
}
if ( $argv[1] == '-p' )
$method = "PURGE";
else if ($argv[1] == '-r' )
$method = "REFRESH";
else
{
echo "ERROR: unknown or missing method option";
exit;
}
$domain = $argv[2];
$url = $argv[3];
$server_ip = ($argc >= 5) ? $argv[4] : '127.0.0.1';
$port = ($argc == 6) ? $argv[5] : 80;

$fp = fsockopen($server_ip, $port, $errno, $errstr, 2);
if (!$fp) {
echo "$errstr ($errno)\n";
} else {
$out = "$method $url HTTP/1.0\r\n"
. "Host: $domain\r\n"
. "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}

?>

Please refer to the LiteSpeed wiki for more instructions.

Rewrite Rule Examples

By Application

If you are running WordPress, Joomla! 3, Drupal 8, Mediawiki, or any other site for which we have cache plugins available, you should NOT follow this wiki. Instead, your plugins should be installed and configured by following the related articles.

General Examples

If none of above applications are being used, please refer the following general rewrite examples.

Cache Everything for 2 Minutes (Simple!)

<IfModule LiteSpeed>
RewriteEngine On
RewriteRule cacheablefolder/(.*\.php)?$ - [E=cache-control:max-age=120]
</IfModule>

Note: Only cache *.php files in the cacheablefolder directory. As pointed out previously, it is a good practice to cache only the files that are supposed to be cached.

Only Cache Pages That Have a Certain Signature

Note: %{ORG_REQ_URI} is a LiteSpeed-specific variable. In this case, it keeps the value of %{REQUEST_URI} prior to the rewrite to index.php in the first part.

# this part is for public cache.
<IfModule LiteSpeed>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^HEAD|GET$
RewriteCond %{HTTP_COOKIE} !cookiename ## cookiename needs to be replaced by real cookie name
RewriteCond %{ORG_REQ_URI} !^/administrator
RewriteRule .* - [E=Cache-Control:max-age=300]
</IfModule>

#application orgiginal rewite rules
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php [L]

This example demonstrates how LSCache rewrite rules fit in an application’s rewrite rules. The first part is from the application (such as Joomla). Essentially everything goes through index.php (the Joomla framework) to process.

The first part of the ruleset indicates that LSWS only caches requests if the following is true:

  • they are HEAD or GET type requests
  • they don’t contain loginuser in the HTTP_COOKIE
  • %{ORG_REQ_URI} is not /index.php
  • %{ORG_REQ_URI} does not start with /administrator/
  • %{ORG_REQ_URI} ends with .php or .html or .htm, etc.

The TTL of the cache is 300 seconds (5 minutes).

Private Cache

<IfModule LiteSpeed>
# this part is for private cache, note that HTTP_COOKIE is for loginuser
RewriteCond %{REQUEST_METHOD} ^HEAD|GET$
RewriteCond %{HTTP_COOKIE} loginuser
RewriteCond %{ORG_REQ_URI} !^/index\.php$
# there is no need to exclude admin area. it can be private cached.
# RewriteCond %{ORG_REQ_URI} !^/administrator/
RewriteRule .* - [E=Cache-Control:private]
</IfModule>

or

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{REQUEST_URI} (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$  [NC]
RewriteRule (.*) index.php [L]

This ruleset indicates that LSWS only privately caches requests if they

  • are HEAD and GET type requests
  • DO contain loginuser in the HTTP_COOKIE
  • %{ORG_REQ_URI} is not /index.php
  • %{ORG_REQ_URI} ends with .php or .html or .htm, etc.

The TTL of the cache is however long the cache policy indicates.

Disable Caching When Private Caching is Enabled

While it is not recommended to have private caching enabled in the cache policy, doing so enables private caching for all domains/vhosts. However, certain domains/vhosts may not work well when private cache is on by default. In this case, we need to disable private caching for those domains/vhosts.

To do so:

  1. Purge the private cache copy if it is still valid(fresh).
  2. Put the following entry in .htaccess` under the document root of the domain/virtual host in question.
<IfModule LiteSpeed>
RewriteEngine On
RewriteRule .* - [E=Cache-Control:no-cache]
</IfModule>

Enable Cache for Mobile View

Set up a different cache copy for mobile view through cache vary. Also exclude some folders from cache, then cache everything else:

<IfModule LiteSpeed>
RewriteEngine On
CacheDisable public /
RewriteCond %{HTTP_USER_AGENT} "iPhone|iPod|BlackBerry|Palm|Mobile|Opera Mini|Fennec|Windows Phone"
RewriteRule .* - [E=Cache-Control:vary=ismobile]
RewriteCond %{REQUEST_METHOD} ^HEAD|PURGE|GET$
RewriteCond %{ORG_REQ_URI} !/news
RewriteCond %{ORG_REQ_URI} !/admincp
RewriteRule .* - [E=Cache-Control:max-age=120]
</IfModule>