LSCache With No Plugins

LiteSpeed has created a built-in cache functionality for its Enterprise edition web server. LSCache is included free in the Free Starter, Site Owner, and Web Host licenses, as well as the 8-CPU legacy licenses, and is available as an add-on for the other legacy licenses. (Available since version 4.0)

LSCache's features are very similar to those in Apache mod_cache, but implemented in a more efficient way. LiteSpeed cache works like Varnish. It is an output cache for dynamic contents, so the usage is not limited to PHP pages. Unlike Varnish, LiteSpeed cache is built into LiteSpeed's web server, thus eliminating one layer of reverse proxy. This translates into higher efficieny for static contents. The uniqueness of LiteSpeed cache is that it uses rewrite rules (either in configuration files or .htaccess) to control its behavior for maximum flexibility.

If there is a LiteSpeed cache plugin available for your web applications (WordPress, WooCommerce, Magento, Xenforo), you should follow the corresponding section to set up your cache. In these cases, following this wiki is not recommended as it was written for more general non-application-specific caching. As a result, it is only applicable when a LiteSpeed cache plugin for your application is not available or you have very customized code base application.

A general way to enable LiteSpeed Cache through rewrite rules is to designate a signature token (such as a cookie) in any page, in most cases it will tell the server that cache can be enabled and that the TTL(Time To Live) of the cache freshness will remain acceptable. Generating cookies usually requires application code modification. Please refer to this thread on our forum for examples. It is worth noting that the cache function SHOULD ONLY be used for pages that are supposed to be cached or cache friendly. Abuse use of this feature would result in performance degradation and/or other unexpected behaviors.

Since 4.1.1, private cache support has been added. Private cache is for caching resources for individuals specifically instead of publicly shared resources. The purposes are:

  • to maintain a persistent cache for applications that do not have a shared cache.
  • to maintain a private persistent cache for specific groups of documents that are not to be shared among other applications.

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 representations 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:

  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 representations it may not be appropriate for public caches to cache them or to return those representations 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
  • Infrequently changed
  • Popular demand (requested frequently)
  • Private cache
  • Can only be used by one user/client, such as personal information on a web site (for authorized users)
  • Resources such as documents only available for one particular user or authorized users.
  • Resources served via the HTTPS protocol
  • Responses with cookies
  • No cache
  • POST request
  • Dynamic content (such as time sensitive info)
  • Frequently changed objects

How to Enable LiteSpeed Cache

Although there is the advanced setting "Enable Cache" in the LSWS Web Admin Console on both the server and virtual host levels, “No” or “Not Set” is always recommended since globally-enabled public cache may cause problems when URLs change or other changes happen on the domain. There are two other ways to enable cache beyond global enabling: through cache plugin by using header, or through rewrite rules. If LiteSpeed cache plugin is available for your application, it is always recommended to get cache and cache purge accurate. If the cache plugin is in development and not available yet, we recommend enabling the cache through rewrite rules. Follow the steps in the following sections to enable LSWS's built-in caching with rewrite rules.

Set Up Server Level Cache Root

For different hosting environments, the steps to set up server level cache root are different. Please choose your hosting environment:

There are also Advanced Cache configurations available.

Set cache policy at Server level

Actually you don't need to change anything here. Just keep the installation default settings. Settings can be enabled through .htaccess file.

Web Admin Console→Virtual Hosts→mytest→Cache → Cache Policy

Enable Public Cache:Not Set
Check Public Cache: Not Set
Max Object Size: Not Set
Cache Expire Time (seconds): Not Set
Cache Stale Age (seconds): Not Set
Cache Request with Query String: Not Set
Cache Request with Cookie: Not Set
Cache Response with Cookie: Not Set
Ignore Request Cache-Control: Not Set
Ignore Response Cache-Control:Not Set
Enable Private Cache: Not Set
Check Private Cache: Not Set
Private Cache Expire Time (seconds): Not Set

Note:

  • Never set “Enable Public Cache” to “yes”. “No” or “Not Set” is always recommended. Even though Cache is disabled globally at the Server Level, it will be enabled through rewrite rules. That's the way it's supposed to be. Cache can be turned on/off with the “CacheEnable” and “CacheDisable” directives in Apache config files: .htaccess (preferred) or httpd.conf, etc.
  • Check Public Cache: “Not Set” or “No”. You can enable it through .htacesss by placing the following to enable cache lookup:
    <IfModule LiteSpeed>
        CacheLookup public on
    </IfModule>
    
  • Cache Request with Cookie can be set to “Yes” as long as the cookie does NOT affect the generated page. Use it carefully.
  • Set “Enable Private Cache” to “No”. Setting this to “Yes” turns on private caching. Private Cache is pertinent to each individual user/browser. This is to speed up performance even for logged-in users or cache for individuals instead of the public. “No” is always recommended then you can enable it through .htaccess

Understand CacheEnable/CacheDisable/CacheLookup directives and rewrite rules

First of all, rewrite rule can disable or enable cache on its own without using CacheEnable/CacheDisable directives. However using combination of both rewrite rules and CacheEable/CacheDisable directives may meet your complicated requirement.

By placing “CacheEnable” or “CacheDisable” directives in Virtual Host document root .htaccess will overwrite server level of cache enabling configuration.

“CacheEnable public /“ means enabling cache for all URLs of this virtual host, similiar to virtual host level of global enabling.

“CacheDisable public /“ means disabling cache for all URLs of this virtual host, similiar to virtual host level of global disabling.

“CacheLookup” will tell the application whether it should look up the cache or not. When “CacheEnable” or “CacheDisable” is used, no “CacheLookup” required since it has been enabled or disabled by default.

CacheEnable directive

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

<IfModule LiteSpeed>
CacheEnable public /
</IfModule>

The above directive will literally enable public cache lookup as well though it is not set in the LSWS Admin configuration nor by “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 root directory (for example, if your site was located in /home/username/public_html and pointed 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).

  • 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 literally enable private cache lookup as well though it is not set in the LSWS Admin configuration nor by “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.

CacheDisable Directive

  • To disable public cache,
    <IfModule LiteSpeed> 
    CacheDisable public /
    </IfModule>
    
  • To disable private cache,
    <IfModule LiteSpeed> 
    CacheDisable private /
    </IfModule>
    

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

Note:

  • Apache mod_cache directives CacheIgnoreCacheControl and CacheMaxExpire can also be used in Apache config files (httpd.conf or .htaccess) to fine-tune cache policy.
  • WHM/cPanel users: since cPanel does not have an option to enable mod_cache, mod_cache directives such as CacheEnable, CacheDisable, etc, need to be manually added to Apache config files: .htaccess or httpd.conf, etc.

Rewrite Rules to setup cache or disable cache

A simple example using rewrite rule to setup public cache (no need to specify as “public”) of everything for 2 minutes through [E=cache-control:max-age=xxx].

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

A simple example Using rewrite rule to disable cache through [E=Cache-Control:no-cache]

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

A simple example using rewrite rule to setup private cache through [E=cache-control:private]. There is no need to specify the max-age for private cache since it is for specific browser and controlled by session.

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

Rewrite rules can be placed in httpd.conf or the in-directory .htaccess file.

The difference between rewrite rule through E=cache-control and CacheEnable directive is rewrite rule can control the cache expired time(TTL) while CacheEnable directive could not.

How to enable cache

To enable cache, you can use either write rules only without “CacheEnable/CacheDisable” directive, 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 to be cached, what's not.

Rewrite rule only example 1

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

Example 1 enables cache and cache everything for 2 minutes.

Rewrite rule only example 2:

<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)?$ - [L,E=Cache-Control:private]
</IfModule>

These rules can be placed in one of the 3 locations below:

  • .htaccess (last line needs to changed as follows:)
    RewriteRule (.*\.php)?$ - [E=Cache-Control:max-age=120]
    RewriteRule (.*\.php)?$ - [E=Cache-Control:private]
    
  • VirutalHost secion in Apache config file
  • LiteSpeed native configuration: Web Admin Console → Configurations → Virtual Hosts → Rewrite

The combination of Rewrite rules and CacheEnable/Disable directives, example 3:

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

Example 3 CacheDisable directive disables all URL from cache, but rewrite rules enable everything to be cached for 2 mins. In this case, “CacheDisable public /” does not have any impact on the settings.

Restart LSWS to Make Changes Effective if Changes Made in Apache/LSWS Config

If there is any change on the Apache/LSWS config file, you will need to restart LSWS. Admin Console → Actions → Graceful Restart or run /path/to/lsws/bin/lswsctrl restart or 'service lsws restart' from command line.

If the changes are made in .htaccess, no need to restart LSWS.

Verify that pages are served from the cache

Open your browsers 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 clikc on it to view it's 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.

Note1: Since its 4.0.19 release, LiteSpeed Web Server outputs a response header “X-LiteSpeed-Cache: hit” if a request is served from cache.

Note2: Since its 4.1.1 release, LiteSpeed Web Server outputs a response header “X-LiteSpeed-Cache: hit,private” if a request is served from private cache.

Note3: 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.

Note4: Will I see “Cache-Control:max-age” header” when I use lscache? No. Please be aware there are two different concepts: Cache-Control:max-age is browser cache header, not cache from the server side. While x-litespeed-cache-control: public,max-age=86400 is lscache control header, which will be seen when cache plugin being used. When using rewrite rules [E=cache-control:max-age=120] to enable cache as instructed in this wiki, you won't see x-litespeed-cache-control at the time of this writing.

Deleting Outdated Cache Files through Linux Command Using A Cron Job

Note: LSWS will now delete expired cache files automatically, making this step optional. A cron job can still be set up to help ensure that the cache works as expected, clearing out pages that may have been misconfigured to have a very long TTL.

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 /home/$USER/lscache for shared hosting users or /tmp/diskspace for dedicated servers.

*/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.

Deleting Outdated Cache Files through cleancache.sh Script

You can run the following command to remove old files:

/usr/local/lsws/admin/misc/cleancache.sh /path/to/cache/directory/

The script basically deletes all cache files created(modified) 24 hours ago. You can also run a cron job to do so. LiteSpeed Web Server periodically cleans up the cache storage directory, so you may not find it necessary to do this yourself.

How to Purge Cache through PHP Script

Please refer to the manual purge doc.

How to Purge Cache by URL

There is a PHP script built into LSWS which will allow you to purge the cache by URL. It is located at /usr/local/lsws/admin/misc/purge_cache_byurl.php

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: 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*/.

Note 2: Server_ip can not be omitted in some cases!

The 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);
}

?>

Examples

Rewrite Examples for applications

If you are running vBulletin site, see examples here.

If you are running IP Board site, see examples here.

If you are running vBSEO site, see examples here.

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

Cache everything for 2 mins (Simple!)

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

Note: Only cache *.php files in “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]

Note: 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 (Joomla framework) to process.

First part of the ruleset indicates that LSWS only caches requests if they

  • Are HEAD or GET type requests AND
  • Don't contain loginuser in the HTTP_COOKIE AND
  • %{ORG_REQ_URI} is not /index.php AND
  • %{ORG_REQ_URI} does not start with /administrator/ AND
  • %{ORG_REQ_URI} ends with .php or .html or .htm or etc.
  • The TTL of the cache is 300 seconds (5 minutes).

This example is for 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>
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]

The ruleset indicates that LSWS only privately caches requests if they

  • Are HEAD and GET type requests AND
  • DO contain loginuser in the HTTP_COOKIE AND
  • %{ORG_REQ_URI} is not /index.php AND
  • %{ORG_REQ_URI} ends with .php or .html or .htm or etc.
  • The TTL of the cache is however long set in the cache policy for private cache.

Disable caching for certain domains when private caching is enabled by default

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 document root of the domain/virtual host in question.
    <IfModule LiteSpeed>
    RewriteEngine On
    RewriteRule .* - [E=Cache-Control:no-cache] 
    </IfModule>
    
    or put the following in the vhost section of your httpd.conf
    <IfModule LiteSpeed>
      CacheDisable private /
    </IfModule>
    

Enable cache for mobile view

Setup difference cache 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>