<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nuster Cache Server</title>
    <description>The latest articles on DEV Community by Nuster Cache Server (@nuster).</description>
    <link>https://dev.to/nuster</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F56008%2Fedbaf386-c2ab-4fca-b14e-f8ba7cacec00.jpeg</url>
      <title>DEV Community: Nuster Cache Server</title>
      <link>https://dev.to/nuster</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nuster"/>
    <language>en</language>
    <item>
      <title>Nuster v5.0.0.21 released. A web cache server based on HAProxy  </title>
      <dc:creator>Nuster Cache Server</dc:creator>
      <pubDate>Sat, 11 Apr 2020 13:46:09 +0000</pubDate>
      <link>https://dev.to/nuster/nuster-v5-0-0-21-released-a-web-cache-server-based-on-haproxy-5gbd</link>
      <guid>https://dev.to/nuster/nuster-v5-0-0-21-released-a-web-cache-server-based-on-haproxy-5gbd</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/jiangwenyuan/nuster"&gt;nuster&lt;/a&gt;, A caching proxy server based on HAProxy released v5.0.0.21.&lt;/p&gt;

&lt;h1&gt;
  
  
  nuster
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/jiangwenyuan/nuster/wiki"&gt;Wiki&lt;/a&gt; | &lt;a href="//README.md"&gt;English&lt;/a&gt; | &lt;a href="//README-CN.md"&gt;中文&lt;/a&gt; | &lt;a href="//README-JP.md"&gt;日本語&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A high-performance HTTP proxy cache server and RESTful NoSQL cache server based on HAProxy.&lt;/p&gt;

&lt;h1&gt;
  
  
  Table of Contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Getting Started&lt;/li&gt;
&lt;li&gt;Usage&lt;/li&gt;
&lt;li&gt;Directives&lt;/li&gt;
&lt;li&gt;Cache&lt;/li&gt;
&lt;li&gt;NoSQL&lt;/li&gt;
&lt;li&gt;
Manager

&lt;ul&gt;
&lt;li&gt;Stats&lt;/li&gt;
&lt;li&gt;Enable disable rules&lt;/li&gt;
&lt;li&gt;Update ttl&lt;/li&gt;
&lt;li&gt;Purging&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Store&lt;/li&gt;
&lt;li&gt;Sample fetches&lt;/li&gt;
&lt;li&gt;FAQ&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;nuster is a high-performance HTTP proxy cache server and RESTful NoSQL cache server based on HAProxy.&lt;br&gt;
It is 100% compatible with HAProxy and takes full advantage of the ACL functionality of HAProxy to provide fine-grained caching policy based on the content of request, response or server status.&lt;/p&gt;
&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;
&lt;h3&gt;
  
  
  As HTTP/TCP loader balancer
&lt;/h3&gt;

&lt;p&gt;nuster can be used as an HTTP/TCP load balancer just like HAProxy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All features of HAProxy are inherited, 100% compatible with HAProxy&lt;/li&gt;
&lt;li&gt;Load balancing&lt;/li&gt;
&lt;li&gt;HTTPS supports on both frontend and backend&lt;/li&gt;
&lt;li&gt;HTTP compression&lt;/li&gt;
&lt;li&gt;HTTP rewriting and redirection&lt;/li&gt;
&lt;li&gt;HTTP fixing&lt;/li&gt;
&lt;li&gt;HTTP2&lt;/li&gt;
&lt;li&gt;Monitoring&lt;/li&gt;
&lt;li&gt;Stickiness&lt;/li&gt;
&lt;li&gt;ACLs and conditions&lt;/li&gt;
&lt;li&gt;Content switching&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  As HTTP cache server
&lt;/h3&gt;

&lt;p&gt;nuster can also be used as an HTTP proxy cache server like Varnish or Nginx to cache dynamic and static HTTP response.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All features from HAProxy(HTTPS, HTTP/2, ACL, etc)&lt;/li&gt;
&lt;li&gt;Extremely fast&lt;/li&gt;
&lt;li&gt;Powerful dynamic cache ability

&lt;ul&gt;
&lt;li&gt;Based on HTTP method, URI, path, query, header, cookies, etc&lt;/li&gt;
&lt;li&gt;Based on HTTP request or response contents, etc&lt;/li&gt;
&lt;li&gt;Based on environment variables, server state, etc&lt;/li&gt;
&lt;li&gt;Based on SSL version, SNI, etc&lt;/li&gt;
&lt;li&gt;Based on connection rate, number, byte, etc&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cache management&lt;/li&gt;
&lt;li&gt;Cache purging&lt;/li&gt;
&lt;li&gt;Cache stats&lt;/li&gt;
&lt;li&gt;Cache TTL&lt;/li&gt;
&lt;li&gt;Disk persistence&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  As RESTful NoSQL cache server
&lt;/h3&gt;

&lt;p&gt;nuster can also be used as a RESTful NoSQL cache server, using HTTP &lt;code&gt;POST/GET/DELETE&lt;/code&gt; to set/get/delete Key/Value object.&lt;/p&gt;

&lt;p&gt;It can be used as an internal NoSQL cache sits between your application and database like Memcached or Redis as well as a user-facing NoSQL cache that sits between end-user and your application.&lt;br&gt;
It supports headers, cookies, so you can store per-user data to the same endpoint.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All features from HAProxy(HTTPS, HTTP/2, ACL, etc)&lt;/li&gt;
&lt;li&gt;Conditional cache&lt;/li&gt;
&lt;li&gt;Internal KV cache&lt;/li&gt;
&lt;li&gt;User facing RESTful cache&lt;/li&gt;
&lt;li&gt;Support any kind of data&lt;/li&gt;
&lt;li&gt;Support all programming languages as long as HTTP is supported&lt;/li&gt;
&lt;li&gt;Disk persistence&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Performance
&lt;/h1&gt;

&lt;p&gt;nuster is very fast, some test shows nuster is almost three times faster than nginx when both using single core, and nearly two times faster than nginx and three times faster than varnish when using all cores.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://github.com/jiangwenyuan/nuster/wiki/Web-cache-server-performance-benchmark:-nuster-vs-nginx-vs-varnish-vs-squid"&gt;detailed benchmark&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Getting Started
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Download
&lt;/h2&gt;

&lt;p&gt;Download stable version from &lt;a href="//Download.md"&gt;Download&lt;/a&gt; page for production use, otherwise git clone the source code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Build
&lt;/h2&gt;


&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make TARGET=linux-glibc USE_LUA=1 LUA_INC=/usr/include/lua5.3 USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1
make install PREFIX=/usr/local/nuster
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;use &lt;code&gt;USE_PTHREAD_PSHARED=1&lt;/code&gt; to use pthread lib&lt;/p&gt;

&lt;p&gt;omit &lt;code&gt;USE_LUA=1 LUA_INC=/usr/include/lua5.3 USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1&lt;/code&gt; if unnecessary&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;See &lt;a href="https://dev.toINSTALL"&gt;HAProxy INSTALL&lt;/a&gt; for details.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create a config file
&lt;/h2&gt;

&lt;p&gt;A minimal config file: &lt;code&gt;nuster.cfg&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global
    nuster cache on data-size 100m
    nuster nosql on data-size 200m
    master-worker # since v3
defaults
    mode http
frontend fe
    bind *:8080
    #bind *:4433 ssl crt example.com.pem alpn h2,http/1.1
    use_backend be2 if { path_beg /_kv/ }
    default_backend be1
backend be1
    nuster cache on
    nuster rule img ttl 1d if { path_beg /img/ }
    nuster rule api ttl 30s if { path /api/some/api }
    server s1 127.0.0.1:8081
    server s2 127.0.0.1:8082
backend be2
    nuster nosql on
    nuster rule r1 ttl 3600
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;nuster listens on port 8080 and accepts HTTP requests.&lt;br&gt;
Requests start with &lt;code&gt;/_kv/&lt;/code&gt; go to backend &lt;code&gt;be2&lt;/code&gt;, you can make &lt;code&gt;POST/GET/DELETE&lt;/code&gt; requests to &lt;code&gt;/_kv/any_key&lt;/code&gt; to &lt;code&gt;set/get/delete&lt;/code&gt; K/V object.&lt;br&gt;
Other requests go to backend &lt;code&gt;be1&lt;/code&gt;, and will be passed to servers &lt;code&gt;s1&lt;/code&gt; or &lt;code&gt;s2&lt;/code&gt;. Among those requests, &lt;code&gt;/img/*&lt;/code&gt; will be cached for 1 day and &lt;code&gt;/api/some/api&lt;/code&gt; will be cached for 30 seconds.&lt;/p&gt;
&lt;h2&gt;
  
  
  Start
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;/usr/local/nuster/sbin/nuster -f nuster.cfg&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Docker
&lt;/h2&gt;


&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker pull nuster/nuster
docker run -d -v /path/to/nuster.cfg:/etc/nuster/nuster.cfg:ro -p 8080:8080 nuster/nuster
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Usage
&lt;/h1&gt;

&lt;p&gt;nuster is based on HAProxy, all directives from HAProxy are supported in nuster.&lt;/p&gt;
&lt;h2&gt;
  
  
  Basic
&lt;/h2&gt;

&lt;p&gt;There are four basic &lt;code&gt;section&lt;/code&gt;s: &lt;code&gt;global&lt;/code&gt;, &lt;code&gt;defaults&lt;/code&gt;, &lt;code&gt;frontend&lt;/code&gt; and &lt;code&gt;backend&lt;/code&gt; as you can find out in the above config file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;global

&lt;ul&gt;
&lt;li&gt;defines process-wide and often OS-specific parameters&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nuster cache on&lt;/code&gt; or &lt;code&gt;nuster nosql on&lt;/code&gt; must be declared in this section in order to use cache or nosql functionality&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;defaults

&lt;ul&gt;
&lt;li&gt;defines default parameters for all other &lt;code&gt;frontend&lt;/code&gt;, &lt;code&gt;backend&lt;/code&gt; sections&lt;/li&gt;
&lt;li&gt;and can be overwritten in specific &lt;code&gt;frontend&lt;/code&gt; or &lt;code&gt;backend&lt;/code&gt; section&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;frontend

&lt;ul&gt;
&lt;li&gt;describes a set of listening sockets accepting client connections&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;backend

&lt;ul&gt;
&lt;li&gt;describes a set of servers to which the proxy will connect to forward incoming connections&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nuster cache on&lt;/code&gt; or &lt;code&gt;nuster nosql on&lt;/code&gt; must be declared in this section&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nuster rule&lt;/code&gt; must be declared here&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can define multiple &lt;code&gt;frontend&lt;/code&gt; or &lt;code&gt;backend&lt;/code&gt; sections. If &lt;code&gt;nuster cache|nosql off&lt;/code&gt; is declared or no &lt;code&gt;nuster cache|nosql on|off&lt;/code&gt; declared, nuster acts just like HAProxy, as a TCP and HTTP load balancer.&lt;/p&gt;

&lt;p&gt;Although &lt;code&gt;listen&lt;/code&gt; is a complete proxy with its frontend and backend parts combined in one section, you cannot use nuster in &lt;code&gt;listen&lt;/code&gt;, use &lt;code&gt;frontend&lt;/code&gt; and &lt;code&gt;backend&lt;/code&gt; pairs.&lt;/p&gt;

&lt;p&gt;You can find HAProxy documentation in &lt;code&gt;/doc&lt;/code&gt;, and &lt;a href="https://cbonte.github.io/haproxy-dconv/"&gt;Online HAProxy Documentation&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  As TCP loader balancer
&lt;/h2&gt;


&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;frontend mysql-lb
   bind *:3306
   mode tcp
   default_backend mysql-cluster
backend mysql-cluster
   balance roundrobin
   mode tcp
   server s1 10.0.0.101:3306
   server s2 10.0.0.102:3306
   server s3 10.0.0.103:3306
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  As HTTP/HTTPS loader balancer
&lt;/h2&gt;


&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;frontend web-lb
   bind *:80
   #bind *:443 ssl crt XXX.pem
   mode http
   default_backend apps
backend apps
   balance roundrobin
   mode http
   server s1 10.0.0.101:8080
   server s2 10.0.0.102:8080
   server s3 10.0.0.103:8080
   #server s4 10.0.0.101:8443 ssl verify none
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  As HTTP cache server
&lt;/h2&gt;


&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global
    nuster cache on data-size 200m
frontend fe
    bind *:8080
    default_backend be
backend be
    nuster cache on
    nuster rule all
    server s1 127.0.0.1:8081
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  As RESTful NoSQL cache server
&lt;/h2&gt;


&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global
    nuster nosql on data-size 200m
frontend fe
    bind *:8080
    default_backend be
backend be
    nuster nosql on
    nuster rule r1 ttl 3600
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Directives
&lt;/h1&gt;
&lt;h2&gt;
  
  
  global: nuster manager
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;syntax:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nuster manager on|off [uri URI] [purge-method method]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;default:&lt;/strong&gt; &lt;em&gt;off&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;context:&lt;/strong&gt; &lt;em&gt;global&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Enable manager/stats/purge API, define the endpoint and purge method.&lt;/p&gt;

&lt;p&gt;By default, it is disabled. When it is enabled, remember to restrict the access(see FAQ).&lt;/p&gt;

&lt;p&gt;See Manager for details.&lt;/p&gt;
&lt;h3&gt;
  
  
  uri
&lt;/h3&gt;

&lt;p&gt;Define endpoint URI, &lt;code&gt;/nuster&lt;/code&gt; by default.&lt;/p&gt;
&lt;h3&gt;
  
  
  purge-method
&lt;/h3&gt;

&lt;p&gt;Define a customized HTTP method to purge, it is &lt;code&gt;PURGE&lt;/code&gt; by default.&lt;/p&gt;
&lt;h2&gt;
  
  
  global: nuster cache|nosql
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;syntax:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nuster cache on|off [data-size size] [dict-size size] [dir DIR] [dict-cleaner n] [data-cleaner n] [disk-cleaner n] [disk-loader n] [disk-saver n]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nuster nosql on|off [data-size size] [dict-size size] [dir DIR] [dict-cleaner n] [data-cleaner n] [disk-cleaner n] [disk-loader n] [disk-saver n]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;default:&lt;/strong&gt; &lt;em&gt;none&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;context:&lt;/strong&gt; &lt;em&gt;global&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Determines whether to use cache/nosql or not.&lt;/p&gt;

&lt;p&gt;A memory zone with a size of &lt;code&gt;data-size + dict-size&lt;/code&gt; will be created.&lt;/p&gt;

&lt;p&gt;Except for temporary data created and destroyed within a request, all cache related data including HTTP response data, keys and overheads are stored in this memory zone and shared between all processes.&lt;br&gt;
If no more memory can be allocated from this memory zone, new requests that should be cached according to defined rules will not be cached unless some memory is freed.&lt;br&gt;
Temporary data are stored in a memory pool which allocates memory dynamically from system in case there is no available memory in the pool.&lt;br&gt;
A global internal counter monitors the memory usage of all HTTP response data across all processes, new requests will not be cached if the counter exceeds &lt;code&gt;data-size&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  data-size
&lt;/h3&gt;

&lt;p&gt;Determines the size of the memory zone along with &lt;code&gt;dict-size&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It accepts units like &lt;code&gt;m&lt;/code&gt;, &lt;code&gt;M&lt;/code&gt;, &lt;code&gt;g&lt;/code&gt; and &lt;code&gt;G&lt;/code&gt;. By default, the size is 1024 * 1024 bytes, which is also the minimal size.&lt;/p&gt;
&lt;h3&gt;
  
  
  dict-size
&lt;/h3&gt;

&lt;p&gt;Determines the size of memory used by the hash table.&lt;/p&gt;

&lt;p&gt;It accepts units like &lt;code&gt;m&lt;/code&gt;, &lt;code&gt;M&lt;/code&gt;, &lt;code&gt;g&lt;/code&gt; and &lt;code&gt;G&lt;/code&gt;. By default, the size is 1024 * 1024 bytes, which is also the minimal size.&lt;/p&gt;

&lt;p&gt;Note that it only decides the memory used by hash table buckets, not keys. In fact, keys are stored in the memory zone which is limited by &lt;code&gt;data-size&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dict-size(number of buckets)&lt;/strong&gt; is different from &lt;strong&gt;number of keys&lt;/strong&gt;. New keys can still be added to the hash table even if the number of keys exceeds dict-size(number of buckets) as long as there is enough memory.&lt;/p&gt;

&lt;p&gt;Nevertheless, it may lead to a potential performance drop if &lt;code&gt;number of keys&lt;/code&gt; is greater than &lt;code&gt;dict-size(number of buckets)&lt;/code&gt;. An approximate number of keys multiplied by 8 (normally) as &lt;code&gt;dict-size&lt;/code&gt; should be fine.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;dict-size will be removed in a future release, automatically resizing the hash table in the first version will be added back.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  dir
&lt;/h3&gt;

&lt;p&gt;Specify the root directory of the disk persistence. This has to be set in order to use disk persistence.&lt;/p&gt;
&lt;h3&gt;
  
  
  dict-cleaner
&lt;/h3&gt;

&lt;p&gt;Prior to v2.x, manager tasks like removing invalid cache data, resetting dict entries are executed in iterations in each HTTP request. Corresponding indicators or pointers are increased or advanced in each iteration.&lt;/p&gt;

&lt;p&gt;In v3.x these tasks are moved to the master process and also done in iterations, and these parameters can be set to control the number of times of certain task during one iteration.&lt;/p&gt;

&lt;p&gt;During one iteration &lt;code&gt;dict-cleaner&lt;/code&gt; entries are checked, invalid entries will be deleted (by default, 100).&lt;/p&gt;
&lt;h3&gt;
  
  
  data-cleaner
&lt;/h3&gt;

&lt;p&gt;During one iteration &lt;code&gt;data-cleaner&lt;/code&gt; data are checked, invalid data will be deleted (by default, 100).&lt;/p&gt;
&lt;h3&gt;
  
  
  disk-cleaner
&lt;/h3&gt;

&lt;p&gt;If disk persistence is enabled, data are stored in files. These files are checked by master process and will be deleted if invalid, for example, expired.&lt;/p&gt;

&lt;p&gt;During one iteration &lt;code&gt;disk-cleaner&lt;/code&gt; files are checked, invalid files will be deleted (by default, 100).&lt;/p&gt;
&lt;h3&gt;
  
  
  disk-loader
&lt;/h3&gt;

&lt;p&gt;After the start of nuster, master process will load information about data previously stored on disk into memory.&lt;/p&gt;

&lt;p&gt;During one iteration &lt;code&gt;disk-loader&lt;/code&gt; files are loaded(by default, 100).&lt;/p&gt;
&lt;h3&gt;
  
  
  disk-saver
&lt;/h3&gt;

&lt;p&gt;Master process will save &lt;code&gt;disk sync&lt;/code&gt; cache data periodically.&lt;/p&gt;

&lt;p&gt;During one iteration &lt;code&gt;disk-saver&lt;/code&gt; data are checked and saved to disk if necessary (by default, 100).&lt;/p&gt;

&lt;p&gt;See Store for details.&lt;/p&gt;
&lt;h2&gt;
  
  
  proxy: nuster cache|nosql
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;syntax:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nuster cache [on|off]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nuster nosql [on|off]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;default:&lt;/strong&gt; &lt;em&gt;on&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;context:&lt;/strong&gt; &lt;em&gt;backend&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Determines whether or not to use cache/nosql on this proxy, additional &lt;code&gt;nuster rule&lt;/code&gt; should be defined.&lt;br&gt;
If there are filters on this proxy, put this directive after all other filters.&lt;/p&gt;
&lt;h2&gt;
  
  
  proxy: nuster rule
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;syntax:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nuster rule name [key KEY] [ttl TTL] [extend EXTEND] [code CODE] [memory on|off] [disk on|off|sync] [etag on|off] [last-modified on|off] [if|unless condition]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;default:&lt;/strong&gt; &lt;em&gt;none&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;context:&lt;/strong&gt; &lt;em&gt;backend&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Define rule to specify cache/nosql creating conditions, properties. At least one rule should be defined.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nuster cache on

# cache request `/asdf` for 30 seconds
nuster rule asdf ttl 30 if { path /asdf }

# cache if the request path begins with /img/
nuster rule img if { path_beg /img/ }

# cache if the response header `cache` is `yes`
acl resHdrCache res.hdr(cache) yes
nuster rule r1 if resHdrCache
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It is possible and recommended to declare multiple rules in the same section. The order is important because the matching process stops on the first match.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;acl pathA path /a.html
nuster cache on
nuster rule all ttl 3600
nuster rule path01 ttl 60 if pathA
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;rule &lt;code&gt;path01&lt;/code&gt; will never match because the first rule will cache everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  name
&lt;/h3&gt;

&lt;p&gt;Define a name for this rule.&lt;/p&gt;

&lt;p&gt;It will be used in cache manager API, it does not have to be unique, but it might be a good idea to make it unique. Rules with the same name are treated as one.&lt;/p&gt;

&lt;h3&gt;
  
  
  key KEY
&lt;/h3&gt;

&lt;p&gt;Define the key for cache/nosql, it takes a string combined by following keywords with &lt;code&gt;.&lt;/code&gt; separator:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;method:       http method, GET/POST...&lt;/li&gt;
&lt;li&gt;scheme:       http or https&lt;/li&gt;
&lt;li&gt;host:         the host in the request&lt;/li&gt;
&lt;li&gt;uri:          first slash to end of the url&lt;/li&gt;
&lt;li&gt;path:         the URL path of the request&lt;/li&gt;
&lt;li&gt;delimiter:    '?' if query exists otherwise empty&lt;/li&gt;
&lt;li&gt;query:        the whole query string of the request&lt;/li&gt;
&lt;li&gt;header_NAME: the value of header &lt;code&gt;NAME&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;cookie_NAME: the value of cookie &lt;code&gt;NAME&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;param_NAME:  the value of query &lt;code&gt;NAME&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;body:         the body of the request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The default key of CACHE is &lt;code&gt;method.scheme.host.uri&lt;/code&gt;, and default key of NoSQL is &lt;code&gt;GET.scheme.host.uri&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET http://www.example.com/q?name=X&amp;amp;type=Y

http header:
GET /q?name=X&amp;amp;type=Y HTTP/1.1
Host: www.example.com
ASDF: Z
Cookie: logged_in=yes; user=nuster;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Should result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;method:       GET&lt;/li&gt;
&lt;li&gt;scheme:       http&lt;/li&gt;
&lt;li&gt;host:         &lt;a href="http://www.example.com"&gt;www.example.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;uri:          /q?name=X&amp;amp;type=Y&lt;/li&gt;
&lt;li&gt;path:         /q&lt;/li&gt;
&lt;li&gt;delimiter:    ?&lt;/li&gt;
&lt;li&gt;query:        name=X&amp;amp;type=Y&lt;/li&gt;
&lt;li&gt;header_ASDF: Z&lt;/li&gt;
&lt;li&gt;cookie_user: nuster&lt;/li&gt;
&lt;li&gt;param_type:  Y&lt;/li&gt;
&lt;li&gt;body:         (empty)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So default key produces &lt;code&gt;GET\0http\0www.example.com\0/q?name=X&amp;amp;type=Y\0&lt;/code&gt;, and &lt;code&gt;key method.scheme.host.path.header_ASDF.cookie_user.param_type&lt;/code&gt; produces &lt;code&gt;GET\0http\0www.example.com\0/q\0Z\0nuster\0Y\0&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;\0&lt;/code&gt; is NULL character&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If a request has the same key as a cached HTTP response data, then cached data will be sent to the client.&lt;/p&gt;

&lt;h3&gt;
  
  
  ttl TTL
&lt;/h3&gt;

&lt;p&gt;Set a TTL on key, after the TTL has expired, the key will be deleted.&lt;/p&gt;

&lt;p&gt;It accepts units like &lt;code&gt;d&lt;/code&gt;, &lt;code&gt;h&lt;/code&gt;, &lt;code&gt;m&lt;/code&gt; and &lt;code&gt;s&lt;/code&gt;. Default ttl is &lt;code&gt;0&lt;/code&gt; which does not expire the key.&lt;/p&gt;

&lt;p&gt;ttl can be automatically extended by using &lt;code&gt;extend&lt;/code&gt; keyword.&lt;/p&gt;

&lt;h3&gt;
  
  
  extend EXTEND
&lt;/h3&gt;

&lt;p&gt;Automatically extend the ttl.&lt;/p&gt;

&lt;h4&gt;
  
  
  Format
&lt;/h4&gt;

&lt;p&gt;extend on|off|n1,n2,n3,n4&lt;/p&gt;

&lt;p&gt;Default: off.&lt;/p&gt;

&lt;p&gt;n1,n2,n3,n4: positive integer less than 100, and n1 + n2 + n3 is less than 100. Together they define four time slots as following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;time:       0                                                       ttl         ttl * (1 + n4%)
access:     |            A1             |   A2    |   A3    |   A4    |         |
            |---------------------------|---------|---------|---------|---------|
percentage: |&amp;lt;- (100 - n1 - n2 - n3)% -&amp;gt;|&amp;lt;- n1% -&amp;gt;|&amp;lt;- n2% -&amp;gt;|&amp;lt;- n3% -&amp;gt;|&amp;lt;- n4% -&amp;gt;|
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;ttl will be extended if:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A4 &amp;gt; A3 &amp;gt; A2&lt;/li&gt;
&lt;li&gt;A new request takes place between &lt;code&gt;ttl&lt;/code&gt; and &lt;code&gt;ttl * (1 + n4%)&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;on&lt;/code&gt; equals to 33,33,33,33&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  code CODE1,CODE2...
&lt;/h3&gt;

&lt;p&gt;Cache only if the response status code is CODE.&lt;/p&gt;

&lt;p&gt;By default, only 200 response is cached. You can use &lt;code&gt;all&lt;/code&gt; to cache all responses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nuster rule only200
nuster rule 200and404 code 200,404
nuster rule all code all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  memory on|off
&lt;/h3&gt;

&lt;p&gt;Save data to memory or not, default on.&lt;/p&gt;

&lt;p&gt;See Store for details.&lt;/p&gt;

&lt;h3&gt;
  
  
  disk on|off|sync
&lt;/h3&gt;

&lt;p&gt;Save data to disk or not, and how, default off.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;memory on&lt;/code&gt; needs to be set in order to use &lt;code&gt;disk sync&lt;/code&gt; mode.&lt;/p&gt;

&lt;p&gt;See Store for details.&lt;/p&gt;

&lt;h3&gt;
  
  
  etag on|off
&lt;/h3&gt;

&lt;p&gt;Enable etag conditional requests handling. Add &lt;code&gt;ETag&lt;/code&gt; header if absent.&lt;/p&gt;

&lt;p&gt;Default off.&lt;/p&gt;

&lt;h3&gt;
  
  
  last-modified on|off
&lt;/h3&gt;

&lt;p&gt;Enable last-modified conditional requests handling. Add &lt;code&gt;Last-Modified&lt;/code&gt; header if absent.&lt;/p&gt;

&lt;p&gt;Default off.&lt;/p&gt;

&lt;h3&gt;
  
  
  if|unless condition
&lt;/h3&gt;

&lt;p&gt;Define when to cache using HAProxy ACL.&lt;/p&gt;

&lt;p&gt;The evaluation involves two stages: request stage and response stage.&lt;/p&gt;

&lt;p&gt;Cache will be performed if:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The evaluation in the request stage is true,&lt;/li&gt;
&lt;li&gt;The evaluation in the request stage is false but true in the response stage.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Please be very careful if you use negation in the condition or samples not available in certain stage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Cache if the request path begins with &lt;code&gt;/img/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;nuster rule img if { path_beg /img/ }&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will work because the evaluation in the request stage will either be true or false and will never be true in the response stage as &lt;code&gt;path&lt;/code&gt; is not available in the response stage.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Cache if &lt;code&gt;Content-Type&lt;/code&gt; in response is &lt;code&gt;image/jpeg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;nuster rule jpeg if { res.hdr(Content-Type) image/jpeg }&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will work because the evaluation in the request stage is always false as &lt;code&gt;res.hdr&lt;/code&gt; is not available in the request stage, and will be either true or false in the response stage.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cache if the request path begins with &lt;code&gt;/img/&lt;/code&gt; and &lt;code&gt;Content-Type&lt;/code&gt; in response is &lt;code&gt;image/jpeg&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It won't work if you define the rule as:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nuster rule img if { path_beg /img/ } { res.hdr(Content-Type) image/jpeg }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;because &lt;code&gt;path&lt;/code&gt; is not available in the response stage and &lt;code&gt;res.hdr&lt;/code&gt; is not available in the request stage, so the evaluation will never be true.&lt;/p&gt;

&lt;p&gt;In order the make this work, &lt;code&gt;path&lt;/code&gt; needs to be allocated for further use in reponse stage:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http-request set-var(txn.pathImg) path
acl pathImg var(txn.pathImg) -m beg /img/
acl resHdrCT res.hdr(Content-Type) image/jpeg
nuster rule r3 if pathImg resHdrCT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Another example, cache if the request path does not begin with &lt;code&gt;/api/&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It won't work neither:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;acl NoCache path_beg /api/
nuster rule r3 if !NoCache
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because the evaluation of &lt;code&gt;NoCache&lt;/code&gt; against &lt;code&gt;/api/&lt;/code&gt; in the request stage is true, and the negation is false, which is the desired state, but in response stage, the evaluation of &lt;code&gt;NoCache&lt;/code&gt; is always false as &lt;code&gt;path&lt;/code&gt; is not available in response stage, and it will be cached as the negation &lt;code&gt;!NoCache&lt;/code&gt; is true.&lt;/p&gt;

&lt;p&gt;This will work:&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http-request set-var(txn.path) path
acl NoCache var(txn.path) -m beg /api/
nuster rule r1 if !NoCache
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I will add several new sample fetch methods to simplify this kind of tasks in future versions.&lt;/p&gt;

&lt;p&gt;See &lt;strong&gt;7. Using ACLs and fetching samples&lt;/strong&gt; section in &lt;a href="//doc/configuration.txt"&gt;HAProxy configuration&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Cache
&lt;/h1&gt;

&lt;p&gt;nuster can be used as an HTTP proxy cache server like Varnish or Nginx to cache dynamic and static HTTP response.&lt;/p&gt;

&lt;p&gt;You can use HAProxy functionalities to terminate SSL, normalize HTTP, support HTTP2, rewrite the URL or modify headers and so on, and additional functionalities provided by nuster to control cache.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global
    nuster cache on data-size 200m
frontend fe
    bind *:8080
    default_backend be
backend be
    nuster cache on
    nuster rule r1 if { path /a1 }
    nuster rule r2 key method.scheme.host.path.delimiter.query.cookie_userId if { path /a2 }
    nuster rule r3 ttl 10 if { path /a3 }
    nuster rule r4 disk only if { path /a4 }

    server s1 127.0.0.1:8081
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When a request is accepted, nuster will check the rules one by one. Key will be created and used to lookup in the cache, and if it's a HIT, the cached data will be returned to client. Otherwise the ACL will be tested, and if it passes the test, response will be cached.&lt;/p&gt;

&lt;h1&gt;
  
  
  NoSQL
&lt;/h1&gt;

&lt;p&gt;nuster can be used as a RESTful NoSQL cache server, using HTTP &lt;code&gt;POST/GET/DELETE&lt;/code&gt; to set/get/delete Key/Value object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Operations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Set
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -v -X POST -d value1 http://127.0.0.1:8080/key1
curl -v -X POST --data-binary @icon.jpg http://127.0.0.1:8080/imgs/icon.jpg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Get
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;curl -v http://127.0.0.1:8080/key1&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Delete
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;curl -v -X DELETE http://127.0.0.1:8080/key1&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Response
&lt;/h2&gt;

&lt;p&gt;Check status code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;200 OK

&lt;ul&gt;
&lt;li&gt;POST/GET: succeeds&lt;/li&gt;
&lt;li&gt;DELETE: always&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;400 Bad request

&lt;ul&gt;
&lt;li&gt;empty value&lt;/li&gt;
&lt;li&gt;incorrect acl, rules, etc&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;404 Not Found

&lt;ul&gt;
&lt;li&gt;POST: failed on all rule tests&lt;/li&gt;
&lt;li&gt;GET: not found&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;405 Method Not Allowed

&lt;ul&gt;
&lt;li&gt;other methods&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;500 Internal Server Error

&lt;ul&gt;
&lt;li&gt;any error occurs&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;507 Insufficient Storage

&lt;ul&gt;
&lt;li&gt;exceeds max data-size&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Per-user data
&lt;/h2&gt;

&lt;p&gt;By using header or cookie in key, you can save per-user data to the same endpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nuster rule r1 key method.scheme.host.uri.header_userId if { path /mypoint }
nuster rule r2 key method.scheme.host.uri.cookie_sessionId if { path /mydata }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Set
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -v -X POST -d "333" -H "userId: 1000" http://127.0.0.1:8080/mypoint
curl -v -X POST -d "555" -H "userId: 1001" http://127.0.0.1:8080/mypoint

curl -v -X POST -d "userA data" --cookie "sessionId=ijsf023xe" http://127.0.0.1:8080/mydata
curl -v -X POST -d "userB data" --cookie "sessionId=rosre329x" http://127.0.0.1:8080/mydata
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Get
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -v http://127.0.0.1:8080/mypoint
&amp;lt; 404 Not Found

curl -v -H "userId: 1000" http://127.0.0.1:8080/mypoint
&amp;lt; 200 OK
333

curl -v --cookie "sessionId=ijsf023xe" http://127.0.0.1:8080/mydata
&amp;lt; 200 OK
userA data
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Clients
&lt;/h2&gt;

&lt;p&gt;You can use any tools or libs which support HTTP: &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;postman&lt;/code&gt;, python &lt;code&gt;requests&lt;/code&gt;, go &lt;code&gt;net/http&lt;/code&gt;, etc.&lt;/p&gt;

&lt;h1&gt;
  
  
  Manager
&lt;/h1&gt;

&lt;p&gt;Nuster can be managed via a manager API which endpoints is defined by &lt;code&gt;uri&lt;/code&gt; and can be accessed by making HTTP requests along with some headers&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enable and define the endpoint uri and purge method&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nuster manager on uri /internal/nuster purge-method PURGEX
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage matrix
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;METHOD&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/internal/nuster&lt;/td&gt;
&lt;td&gt;get stats&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;/internal/nuster&lt;/td&gt;
&lt;td&gt;enable and disable rule, update ttl&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;/internal/nuster&lt;/td&gt;
&lt;td&gt;advanced purge cache&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PURGEX&lt;/td&gt;
&lt;td&gt;/any/real/path&lt;/td&gt;
&lt;td&gt;basic purge&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Stats
&lt;/h2&gt;

&lt;p&gt;Nuster stats can be accessed by making HTTP GET request to the endpoint defined by &lt;code&gt;uri&lt;/code&gt;;&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;curl http://127.0.0.1/internal/nuster&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Output
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**NUSTER**
nuster.cache:                   on
nuster.nosql:                   on
nuster.manager:                 on

**MANAGER**
manager.uri:                    /nuster
manager.purge_method:           PURGE

**MEMORY**
memory.common.total:            1048576
memory.common.used:             1600
memory.cache.total:             2098200576
memory.cache.used:              1048960
memory.nosql.total:             11534336
memory.nosql.used:              1048960

**DISK**
disk.cache.dir:                 /tmp/nuster/cache
disk.cache.loaded:              no
disk.nosql.dir:                 /tmp/nuster/nosql
disk.nosql.loaded:              no

**STATISTICS**
statistics.cache.total:         0
statistics.cache.hit:           0
statistics.cache.fetch:         0
statistics.cache.abort:         0
statistics.nosql.total:         0
statistics.nosql.get:           0
statistics.nosql.post:          0
statistics.nosql.delete:        0

**PROXY cache app1**
app1.rule.rule1:                state=on  memory=on  disk=off   ttl=10
app1.rule.rule2:                state=on  memory=on  disk=on    ttl=10
app1.rule.rule3:                state=on  memory=on  disk=sync  ttl=10
app1.rule.rule4:                state=on  memory=off disk=on    ttl=10
app1.rule.rule5:                state=on  memory=off disk=off   ttl=10

**PROXY nosql app2**
app2.rule.ruleA:                state=on  memory=on  disk=off   ttl=10
app2.rule.ruleB:                state=on  memory=on  disk=on    ttl=10
app2.rule.ruleC:                state=on  memory=on  disk=sync  ttl=10
app2.rule.ruleD:                state=on  memory=off disk=on    ttl=10
app2.rule.ruleE:                state=on  memory=off disk=off   ttl=10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Enable and disable rule
&lt;/h2&gt;

&lt;p&gt;Rule can be disabled at run time through manager uri. Disabled rule will not be processed, nor will the cache created by that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;headers&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;header&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;state&lt;/td&gt;
&lt;td&gt;enable&lt;/td&gt;
&lt;td&gt;enable  rule&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;disable&lt;/td&gt;
&lt;td&gt;disable rule&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;rule NAME&lt;/td&gt;
&lt;td&gt;the rule to be enabled/disabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;proxy NAME&lt;/td&gt;
&lt;td&gt;all rules of proxy NAME&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;all rules&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Keep in mind that if name is not unique, &lt;strong&gt;all&lt;/strong&gt; rules with that name will be disabled/enabled.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Examples&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Disable rule r1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;curl -X POST -H "name: r1" -H "state: disable" http://127.0.0.1/nuster&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Disable all rules defined in proxy app1b&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;curl -X POST -H "name: app1b" -H "state: disable" http://127.0.0.1/nuster&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable all rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;curl -X POST -H "name: *" -H "state: enable" http://127.0.0.1/nuster&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Update ttl
&lt;/h2&gt;

&lt;p&gt;Change the TTL. It only affects the TTL of the responses to be cached, &lt;strong&gt;does not&lt;/strong&gt; update the TTL of existing caches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;headers&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;header&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ttl&lt;/td&gt;
&lt;td&gt;new TTL&lt;/td&gt;
&lt;td&gt;see &lt;code&gt;ttl&lt;/code&gt; in &lt;code&gt;nuster rule&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;rule NAME&lt;/td&gt;
&lt;td&gt;the rule to be changed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;proxy NAME&lt;/td&gt;
&lt;td&gt;all rules of proxy NAME&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;all rules&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Examples&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST -H "name: r1" -H "ttl: 0" http://127.0.0.1/nuster
curl -X POST -H "name: r2" -H "ttl: 2h" http://127.0.0.1/nuster
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Update state and TTL
&lt;/h3&gt;

&lt;p&gt;state and ttl can be updated at the same time&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST -H "name: r1" -H "ttl: 0" -H "state: enabled" http://127.0.0.1/nuster
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Purging
&lt;/h2&gt;

&lt;p&gt;There are two purging mode: basic and advanced.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;basic: Send HTTP method defined by &lt;code&gt;purge-method MYPURGE&lt;/code&gt; to the path you want to delete&lt;/li&gt;
&lt;li&gt;advanced: Send DELETE method to the manager uri defined by &lt;code&gt;uri&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Basic purging
&lt;/h3&gt;

&lt;p&gt;This method deletes the specific url that is being requested, like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -XPURGE http://127.0.0.1/imgs/test.jpg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Key is created in the same way when the cache created except that the &lt;code&gt;method&lt;/code&gt; is &lt;code&gt;GET&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note by default cache key contains &lt;code&gt;Host&lt;/code&gt; if you cache a request like &lt;code&gt;http://example.com/test&lt;/code&gt; and purge from localhost you need to specify &lt;code&gt;Host&lt;/code&gt; header:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -XPURGE -H "Host: example.com" http://127.0.0.1/test&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It works for both cache and nosql, it is an alias of &lt;code&gt;DELETE&lt;/code&gt; in nosql mode.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advanced purging: purge by name
&lt;/h3&gt;

&lt;p&gt;Cache can be purged by making HTTP &lt;code&gt;DELETE&lt;/code&gt; requests to the manager uri along with a &lt;code&gt;name&lt;/code&gt; HEADER.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;headers&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;header&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;nuster rule NAME&lt;/td&gt;
&lt;td&gt;caches created by rule ${NAME} will be purged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;proxy NAME&lt;/td&gt;
&lt;td&gt;caches of proxy ${NAME}&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Examples&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# purge all caches of proxy applb
curl -X DELETE -H "name: app1b" http://127.0.0.1/nuster
# purge all caches of rule r1
curl -X DELETE -H "name: r1" http://127.0.0.1/nuster
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Advanced purging: purge by host
&lt;/h3&gt;

&lt;p&gt;You can also purge cache by host, all caches with that host will be deleted:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;headers&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;header&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;host&lt;/td&gt;
&lt;td&gt;HOST&lt;/td&gt;
&lt;td&gt;the ${HOST}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nuster-host&lt;/td&gt;
&lt;td&gt;HOST&lt;/td&gt;
&lt;td&gt;nuster-host has higher precedence over host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mode&lt;/td&gt;
&lt;td&gt;cache, nosql&lt;/td&gt;
&lt;td&gt;purge cache or nosql data&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Examples&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X DELETE -H "nuster-host: 127.0.0.1:8080" http://127.0.0.1/nuster
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Advanced purging: purge by path
&lt;/h3&gt;

&lt;p&gt;By default, the query part is also used as a cache key, so there will be multiple caches if the query differs.&lt;/p&gt;

&lt;p&gt;For example, for rule &lt;code&gt;nuster rule imgs if { path_beg /imgs/ }&lt;/code&gt;, and request&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl http://127.0.0.1/imgs/test.jpg?w=120&amp;amp;h=120
curl http://127.0.0.1/imgs/test.jpg?w=180&amp;amp;h=180
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There will be two cache objects since the default key contains the query part.&lt;/p&gt;

&lt;p&gt;In order to delete that, you can&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;delete one by one in case you know all queries&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -XPURGE http://127.0.0.1/imgs/test.jpg?w=120&amp;amp;h=120
curl -XPURGE http://127.0.0.1/imgs/test.jpg?w=180&amp;amp;h=180
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It does not work if you don't know all queries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;use a customized key and delete once in case that the query part is irrelevant&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Define a key like &lt;code&gt;nuster rule imgs key method.scheme.host.path if { path_beg /imgs }&lt;/code&gt;, in this way only one cache will be created, and you can purge without query:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -XPURGE http://127.0.0.1/imgs/test.jpg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It does not work if the query part is required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;delete by rule NAME&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -X DELETE -H "name: imgs" http://127.0.0.1/nuster&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It does not work if the nuster rule is defined something like &lt;code&gt;nuster rule static if { path_beg /imgs/ /css/ }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This method provides a way to purge just by path:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;headers&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;header&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;path&lt;/td&gt;
&lt;td&gt;PATH&lt;/td&gt;
&lt;td&gt;caches with ${PATH} will be purged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;host&lt;/td&gt;
&lt;td&gt;HOST&lt;/td&gt;
&lt;td&gt;and host is ${HOST}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nuster-host&lt;/td&gt;
&lt;td&gt;HOST&lt;/td&gt;
&lt;td&gt;nuster-host has higher precedence over host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mode&lt;/td&gt;
&lt;td&gt;cache, nosql&lt;/td&gt;
&lt;td&gt;purge cache or nosql data&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Examples&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#delete all caches which path is /imgs/test.jpg
curl -X DELETE -H "path: /imgs/test.jpg" http://127.0.0.1/nuster
#delete all caches which path is /imgs/test.jpg and with host of 127.0.0.1:8080
curl -X DELETE -H "path: /imgs/test.jpg" -H "nuster-host: 127.0.0.1:8080" http://127.0.0.1/nuster
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Advanced purging: purge by regex
&lt;/h3&gt;

&lt;p&gt;You can also purge cache by regex, the caches which path match the regex will be deleted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;headers&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;header&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;regex&lt;/td&gt;
&lt;td&gt;REGEX&lt;/td&gt;
&lt;td&gt;caches which path match with ${REGEX} will be purged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;host&lt;/td&gt;
&lt;td&gt;HOST&lt;/td&gt;
&lt;td&gt;and host is ${HOST}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nuster-host&lt;/td&gt;
&lt;td&gt;HOST&lt;/td&gt;
&lt;td&gt;nuster-host has higher precedence over host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mode&lt;/td&gt;
&lt;td&gt;cache, nosql&lt;/td&gt;
&lt;td&gt;purge cache or nosql data&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Examples&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#delete all caches which path starts with /imgs and ends with .jpg
curl -X DELETE -H "regex: ^/imgs/.*\.jpg$" http://127.0.0.1/nuster
#delete all caches which path starts with /imgs and ends with .jpg and with host of 127.0.0.1:8080
curl -X DELETE -H "regex: ^/imgs/.*\.jpg$" -H "127.0.0.1:8080" http://127.0.0.1/nuster
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;PURGE CAUTION&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ENABLE ACCESS RESTRICTION&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If there are mixed headers, use the precedence of &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;path &amp;amp; host&lt;/code&gt;, &lt;code&gt;path&lt;/code&gt;, &lt;code&gt;regex &amp;amp; host&lt;/code&gt;, &lt;code&gt;regex&lt;/code&gt;, &lt;code&gt;host&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;curl -X DELETE -H "name: rule1" -H "path: /imgs/a.jpg"&lt;/code&gt;: purge by name&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If there are redundant headers, use the first occurrence&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;curl -X DELETE -H "name: rule1" -H "name: rule2"&lt;/code&gt;: purge by &lt;code&gt;rule1&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;regex&lt;/code&gt; is &lt;strong&gt;NOT glob&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, all jpg files under /imgs should be &lt;code&gt;^/imgs/.*\.jpg$&lt;/code&gt; instead of &lt;code&gt;/imgs/*.jpg&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Purging cache files by rule name or proxy name only works in current session. If nuster restarts, then cache files cannot be purged by rule name or proxy name as information like rule name and proxy name is not persisted in the cache fiels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Purging cache files by host or path or regex only works after the disk loader process is finished. You can check the status through stats url.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Store
&lt;/h1&gt;

&lt;p&gt;Nuster(both cache and nosql) supports different backend stores. Currently memory and disk are supported. More stores will be added.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory
&lt;/h2&gt;

&lt;p&gt;Data is stored into a memory area which size is defined by &lt;code&gt;data-size&lt;/code&gt;. Data does not persist in memory and will lost after restarts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disk
&lt;/h2&gt;

&lt;p&gt;Data is stored to disk and under the path defined by &lt;code&gt;dir&lt;/code&gt;. Data persists after restarts.&lt;/p&gt;

&lt;p&gt;There are 3 modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;off:   default, disable disk persistence.&lt;/li&gt;
&lt;li&gt;on:    save data to disk.&lt;/li&gt;
&lt;li&gt;sync:  &lt;code&gt;memory on&lt;/code&gt; has to be set in order to use this mode. Save data to memory first and data will be synced to disk later by the master process. One iteration &lt;code&gt;disk-saver&lt;/code&gt; data are checked and saved to disk.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Sample fetches
&lt;/h1&gt;

&lt;p&gt;Nuster introduced following sample fetches&lt;/p&gt;

&lt;h2&gt;
  
  
  nuster.cache.hit: boolean
&lt;/h2&gt;

&lt;p&gt;Returns a boolean indicating whether it's a HIT or not and can be used like&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http-response set-header x-cache hit if { nuster.cache.hit }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;
  
  
  FAQ
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Cannot start: not in master-worker mode
&lt;/h2&gt;

&lt;p&gt;Set &lt;code&gt;master-worker&lt;/code&gt; in &lt;code&gt;global&lt;/code&gt; section, or start &lt;code&gt;nuster&lt;/code&gt; with &lt;code&gt;-W&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to debug?
&lt;/h2&gt;

&lt;p&gt;Set &lt;code&gt;debug&lt;/code&gt; in &lt;code&gt;global&lt;/code&gt; section, or start &lt;code&gt;nuster&lt;/code&gt; with &lt;code&gt;-d&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nuster related debug messages start with &lt;code&gt;[nuster&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to cache POST request?
&lt;/h2&gt;

&lt;p&gt;Enable &lt;code&gt;option http-buffer-request&lt;/code&gt; and set &lt;code&gt;body&lt;/code&gt; in cache rule &lt;code&gt;key&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By default, the cache key does not include the body of the request, remember to put &lt;code&gt;body&lt;/code&gt; in key field.&lt;/p&gt;

&lt;p&gt;Note that the size of the request body must be smaller than &lt;code&gt;tune.bufsize - tune.maxrewrite - request_header_size&lt;/code&gt;, which by default is &lt;code&gt;16384 - 1024 - request_header_size&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Refer to &lt;strong&gt;option http-buffer-request&lt;/strong&gt; and &lt;strong&gt;tune.bufsize&lt;/strong&gt; section in &lt;a href="//doc/configuration.txt"&gt;HAProxy configuration&lt;/a&gt; for details.&lt;/p&gt;

&lt;p&gt;Also, it might be a good idea to put it separately in a dedicated backend as the example does.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to restrict access?
&lt;/h2&gt;

&lt;p&gt;You can use the powerful HAProxy ACL, something like this&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;acl network_allowed src 127.0.0.1
acl purge_method method PURGE
http-request deny if purge_method !network_allowed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  How to enable HTTP2
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bind :443 ssl crt pub.pem alpn h2,http/1.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Example
&lt;/h1&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global
    nuster manager on uri /_/nuster purge-method MYPURGE
    nuster cache on data-size 100m
    nuster nosql on data-size 100m
    master-worker # since v3
    # daemon
    # debug
defaults
    retries 3
    option redispatch
    timeout client  30s
    timeout connect 30s
    timeout server  30s
frontend web1
    bind *:8080
    mode http
    acl pathPost path /search
    use_backend app1a if pathPost
    default_backend app1b
backend app1a
    balance roundrobin
    # mode must be http
    mode http

    # http-buffer-request must be enabled to cache post request
    option http-buffer-request

    acl pathPost path /search

    # enable cache for this proxy
    nuster cache

    # cache /search for 120 seconds. Only works when POST/PUT
    nuster rule rpost key method.scheme.host.uri.body ttl 120 if pathPost

    server s1 10.0.0.10:8080
backend app1b
    balance     roundrobin
    mode http

    nuster cache on

    # cache /a.jpg, not expire
    acl pathA path /a.jpg
    nuster rule r1 ttl 0 if pathA

    # cache /mypage, key contains cookie[userId], so it will be cached per user
    acl pathB path /mypage
    nuster rule r2 key method.scheme.host.path.delimiter.query.cookie_userId ttl 60 if pathB

    # cache /a.html if response's header[cache] is yes
    http-request set-var(txn.pathC) path
    acl pathC var(txn.pathC) -m str /a.html
    acl resHdrCache1 res.hdr(cache) yes
    nuster rule r3 if pathC resHdrCache1

    # cache /heavy for 100 seconds if be_conn greater than 10
    acl heavypage path /heavy
    acl tooFast be_conn ge 100
    nuster rule heavy ttl 100 if heavypage tooFast

    # cache all if response's header[asdf] is fdsa
    acl resHdrCache2 res.hdr(asdf)  fdsa
    nuster rule resCache ttl 0 if resHdrCache1

    server s1 10.0.0.10:8080

frontend web2
    bind *:8081
    mode http
    default_backend app2
backend app2
    balance     roundrobin
    mode http

    # disable cache on this proxy
    nuster cache off
    nuster rule all

    server s2 10.0.0.11:8080

frontend nosql_fe
    bind *:9090
    default_backend nosql_be
backend nosql_be
    nuster nosql on
    nuster rule r1 ttl 3600
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Contributing
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Join the development&lt;/li&gt;
&lt;li&gt;Give feedback&lt;/li&gt;
&lt;li&gt;Report issues&lt;/li&gt;
&lt;li&gt;Send pull requests&lt;/li&gt;
&lt;li&gt;Spread nuster&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  License
&lt;/h1&gt;

&lt;p&gt;Copyright (C) 2017-present, &lt;a href="https://github.com/jiangwenyuan"&gt;Jiang Wenyuan&lt;/a&gt;, &amp;lt; koubunen AT gmail DOT com &amp;gt;&lt;/p&gt;

&lt;p&gt;All rights reserved.&lt;/p&gt;

&lt;p&gt;Licensed under GPL, the same as HAProxy&lt;/p&gt;

&lt;p&gt;HAProxy and other sources license notices: see relevant individual files.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>devops</category>
      <category>opensource</category>
      <category>linux</category>
    </item>
    <item>
      <title>Nuster, a cache server based on HAProxy, now supports disk persistence, purging cache files, etc</title>
      <dc:creator>Nuster Cache Server</dc:creator>
      <pubDate>Fri, 04 Oct 2019 01:35:07 +0000</pubDate>
      <link>https://dev.to/nuster/nuster-a-cache-server-based-on-haproxy-now-supports-disk-persistence-purging-cache-files-etc-110i</link>
      <guid>https://dev.to/nuster/nuster-a-cache-server-based-on-haproxy-now-supports-disk-persistence-purging-cache-files-etc-110i</guid>
      <description>&lt;p&gt;nuster v3.1.0.19 released, now supports disk persistence, purging cache files, persistence cache stats&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jiangwenyuan/nuster"&gt;https://github.com/jiangwenyuan/nuster&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are four MODEs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;off: default, disable disk persistence, data are stored in memory only&lt;/li&gt;
&lt;li&gt;only: save data to disk only, do not store in memory&lt;/li&gt;
&lt;li&gt;sync: save data to memory and disk(kernel), then return to the client&lt;/li&gt;
&lt;li&gt;async: save data to memory and return to the client, cached data will be saved to disk later by the master process
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global
    master-worker
    nuster cache on data-size 10m dir /tmp/cache
    nuster nosql on data-size 10m dir /tmp/nosql
backend be
    nuster cache on
    nuster rule off   disk off   ttl 1m if { path_beg /disk-off }
    nuster rule only  disk only  ttl 1d if { path_beg /disk-only }
    nuster rule sync  disk sync  ttl 1h if { path_beg /disk-sync }
    nuster rule async disk async ttl 2h if { path_beg /disk-async }
    nuster rule others ttl 100
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;/disk-offwill be cached only in memory&lt;/li&gt;
&lt;li&gt;/disk-onlywill be cached only in disk&lt;/li&gt;
&lt;li&gt;/disk-syncwill be cached in memory and in disk, then return to the client&lt;/li&gt;
&lt;li&gt;/disk-asyncwill be cached in memory and return to the client, cached data will be saved to disk later&lt;/li&gt;
&lt;li&gt;other requests will be cached only in memory&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>showdev</category>
      <category>devops</category>
      <category>linux</category>
    </item>
    <item>
      <title>Nuster, a cache server based on HAProxy, now supports disk persistence </title>
      <dc:creator>Nuster Cache Server</dc:creator>
      <pubDate>Tue, 30 Jul 2019 04:13:45 +0000</pubDate>
      <link>https://dev.to/nuster/nuster-a-cache-server-based-on-haproxy-now-supports-disk-persistence-3f9m</link>
      <guid>https://dev.to/nuster/nuster-a-cache-server-based-on-haproxy-now-supports-disk-persistence-3f9m</guid>
      <description>&lt;p&gt;nuster v3.0.0.19 released, now supports disk persistence&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jiangwenyuan/nuster"&gt;https://github.com/jiangwenyuan/nuster&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are four MODEs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;off: default, disable disk persistence, data are stored in memory only&lt;/li&gt;
&lt;li&gt;only: save data to disk only, do not store in memory&lt;/li&gt;
&lt;li&gt;sync: save data to memory and disk(kernel), then return to the client&lt;/li&gt;
&lt;li&gt;async: save data to memory and return to the client, cached data will be saved to disk later by the master process
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nuster rule off   disk off   ttl 1m if { path_beg /disk-off } 
nuster rule only  disk only  ttl 1d if { path_beg /disk-only }
nuster rule sync  disk sync  ttl 1h if { path_beg /disk-sync }     
nuster rule async disk async ttl 2h if { path_beg /disk-async } 
nuster rule others ttl 100  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;/disk-offwill be cached only in memory&lt;/li&gt;
&lt;li&gt;/disk-onlywill be cached only in disk&lt;/li&gt;
&lt;li&gt;/disk-syncwill be cached in memory and in disk, then return to the client&lt;/li&gt;
&lt;li&gt;/disk-asyncwill be cached in memory and return to the client, cached data will be saved to disk later&lt;/li&gt;
&lt;li&gt;other requests will be cached only in memory&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>showdev</category>
      <category>devops</category>
      <category>linux</category>
    </item>
    <item>
      <title>nuster - A high performance HTTP proxy cache server and RESTful NoSQL cache server based on HAProxy </title>
      <dc:creator>Nuster Cache Server</dc:creator>
      <pubDate>Mon, 09 Jul 2018 01:17:59 +0000</pubDate>
      <link>https://dev.to/nuster/nuster---a-high-performance-http-proxy-cache-server-and-restful-nosql-cache-server-based-on-haproxy--4aa2</link>
      <guid>https://dev.to/nuster/nuster---a-high-performance-http-proxy-cache-server-and-restful-nosql-cache-server-based-on-haproxy--4aa2</guid>
      <description>&lt;p&gt;Hi all, I have created a high performance HTTP proxy cache server and RESTful NoSQL cache server based on HAProxy: &lt;a href="https://github.com/jiangwenyuan/nuster"&gt;nuster&lt;/a&gt;, please give it a try and star:)&lt;/p&gt;

&lt;h1&gt;
  
  
  nuster
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/jiangwenyuan/nuster/wiki"&gt;Wiki&lt;/a&gt; | &lt;a href="//README.md"&gt;English&lt;/a&gt; | &lt;a href="//README-CN.md"&gt;中文&lt;/a&gt; | &lt;a href="//README-JP.md"&gt;日本語&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A high-performance HTTP proxy cache server and RESTful NoSQL cache server based on HAProxy.&lt;/p&gt;

&lt;h1&gt;
  
  
  Table of Contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Getting Started&lt;/li&gt;
&lt;li&gt;Usage&lt;/li&gt;
&lt;li&gt;Directives&lt;/li&gt;
&lt;li&gt;Cache&lt;/li&gt;
&lt;li&gt;NoSQL&lt;/li&gt;
&lt;li&gt;
Manager

&lt;ul&gt;
&lt;li&gt;Stats&lt;/li&gt;
&lt;li&gt;Enable disable rules&lt;/li&gt;
&lt;li&gt;Update ttl&lt;/li&gt;
&lt;li&gt;Purging&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Store&lt;/li&gt;
&lt;li&gt;Sample fetches&lt;/li&gt;
&lt;li&gt;FAQ&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;nuster is a high-performance HTTP proxy cache server and RESTful NoSQL cache server based on HAProxy.&lt;br&gt;
It is 100% compatible with HAProxy and takes full advantage of the ACL functionality of HAProxy to provide fine-grained caching policy based on the content of request, response or server status.&lt;/p&gt;
&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;
&lt;h3&gt;
  
  
  As HTTP/TCP loader balancer
&lt;/h3&gt;

&lt;p&gt;nuster can be used as an HTTP/TCP load balancer just like HAProxy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All features of HAProxy are inherited, 100% compatible with HAProxy&lt;/li&gt;
&lt;li&gt;Load balancing&lt;/li&gt;
&lt;li&gt;HTTPS supports on both frontend and backend&lt;/li&gt;
&lt;li&gt;HTTP compression&lt;/li&gt;
&lt;li&gt;HTTP rewriting and redirection&lt;/li&gt;
&lt;li&gt;HTTP fixing&lt;/li&gt;
&lt;li&gt;HTTP2&lt;/li&gt;
&lt;li&gt;Monitoring&lt;/li&gt;
&lt;li&gt;Stickiness&lt;/li&gt;
&lt;li&gt;ACLs and conditions&lt;/li&gt;
&lt;li&gt;Content switching&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  As HTTP cache server
&lt;/h3&gt;

&lt;p&gt;nuster can also be used as an HTTP proxy cache server like Varnish or Nginx to cache dynamic and static HTTP response.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All features from HAProxy(HTTPS, HTTP/2, ACL, etc)&lt;/li&gt;
&lt;li&gt;Extremely fast&lt;/li&gt;
&lt;li&gt;Powerful dynamic cache ability

&lt;ul&gt;
&lt;li&gt;Based on HTTP method, URI, path, query, header, cookies, etc&lt;/li&gt;
&lt;li&gt;Based on HTTP request or response contents, etc&lt;/li&gt;
&lt;li&gt;Based on environment variables, server state, etc&lt;/li&gt;
&lt;li&gt;Based on SSL version, SNI, etc&lt;/li&gt;
&lt;li&gt;Based on connection rate, number, byte, etc&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cache management&lt;/li&gt;
&lt;li&gt;Cache purging&lt;/li&gt;
&lt;li&gt;Cache stats&lt;/li&gt;
&lt;li&gt;Cache TTL&lt;/li&gt;
&lt;li&gt;Disk persistence&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  As RESTful NoSQL cache server
&lt;/h3&gt;

&lt;p&gt;nuster can also be used as a RESTful NoSQL cache server, using HTTP &lt;code&gt;POST/GET/DELETE&lt;/code&gt; to set/get/delete Key/Value object.&lt;/p&gt;

&lt;p&gt;It can be used as an internal NoSQL cache sits between your application and database like Memcached or Redis as well as a user-facing NoSQL cache that sits between end-user and your application.&lt;br&gt;
It supports headers, cookies, so you can store per-user data to the same endpoint.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All features from HAProxy(HTTPS, HTTP/2, ACL, etc)&lt;/li&gt;
&lt;li&gt;Conditional cache&lt;/li&gt;
&lt;li&gt;Internal KV cache&lt;/li&gt;
&lt;li&gt;User facing RESTful cache&lt;/li&gt;
&lt;li&gt;Support any kind of data&lt;/li&gt;
&lt;li&gt;Support all programming languages as long as HTTP is supported&lt;/li&gt;
&lt;li&gt;Disk persistence&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Performance
&lt;/h1&gt;

&lt;p&gt;nuster is very fast, some test shows nuster is almost three times faster than nginx when both using single core, and nearly two times faster than nginx and three times faster than varnish when using all cores.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://github.com/jiangwenyuan/nuster/wiki/Web-cache-server-performance-benchmark:-nuster-vs-nginx-vs-varnish-vs-squid"&gt;detailed benchmark&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Getting Started
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Download
&lt;/h2&gt;

&lt;p&gt;Download stable version from &lt;a href="//Download.md"&gt;Download&lt;/a&gt; page for production use, otherwise git clone the source code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Build
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make TARGET=linux-glibc USE_LUA=1 LUA_INC=/usr/include/lua5.3 USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1
make install PREFIX=/usr/local/nuster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;use &lt;code&gt;USE_PTHREAD_PSHARED=1&lt;/code&gt; to use pthread lib&lt;/p&gt;

&lt;p&gt;omit &lt;code&gt;USE_LUA=1 LUA_INC=/usr/include/lua5.3 USE_OPENSSL=1 USE_PCRE=1 USE_ZLIB=1&lt;/code&gt; if unnecessary&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;See &lt;a href="https://dev.toINSTALL"&gt;HAProxy INSTALL&lt;/a&gt; for details.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create a config file
&lt;/h2&gt;

&lt;p&gt;A minimal config file: &lt;code&gt;nuster.cfg&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global
    nuster cache on data-size 100m
    nuster nosql on data-size 200m
    master-worker # since v3
defaults
    mode http
frontend fe
    bind *:8080
    #bind *:4433 ssl crt example.com.pem alpn h2,http/1.1
    use_backend be2 if { path_beg /_kv/ }
    default_backend be1
backend be1
    nuster cache on
    nuster rule img ttl 1d if { path_beg /img/ }
    nuster rule api ttl 30s if { path /api/some/api }
    server s1 127.0.0.1:8081
    server s2 127.0.0.1:8082
backend be2
    nuster nosql on
    nuster rule r1 ttl 3600
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;nuster listens on port 8080 and accepts HTTP requests.&lt;br&gt;
Requests start with &lt;code&gt;/_kv/&lt;/code&gt; go to backend &lt;code&gt;be2&lt;/code&gt;, you can make &lt;code&gt;POST/GET/DELETE&lt;/code&gt; requests to &lt;code&gt;/_kv/any_key&lt;/code&gt; to &lt;code&gt;set/get/delete&lt;/code&gt; K/V object.&lt;br&gt;
Other requests go to backend &lt;code&gt;be1&lt;/code&gt;, and will be passed to servers &lt;code&gt;s1&lt;/code&gt; or &lt;code&gt;s2&lt;/code&gt;. Among those requests, &lt;code&gt;/img/*&lt;/code&gt; will be cached for 1 day and &lt;code&gt;/api/some/api&lt;/code&gt; will be cached for 30 seconds.&lt;/p&gt;
&lt;h2&gt;
  
  
  Start
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;/usr/local/nuster/sbin/nuster -f nuster.cfg&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Docker
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker pull nuster/nuster
docker run -d -v /path/to/nuster.cfg:/etc/nuster/nuster.cfg:ro -p 8080:8080 nuster/nuster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Usage
&lt;/h1&gt;

&lt;p&gt;nuster is based on HAProxy, all directives from HAProxy are supported in nuster.&lt;/p&gt;
&lt;h2&gt;
  
  
  Basic
&lt;/h2&gt;

&lt;p&gt;There are four basic &lt;code&gt;section&lt;/code&gt;s: &lt;code&gt;global&lt;/code&gt;, &lt;code&gt;defaults&lt;/code&gt;, &lt;code&gt;frontend&lt;/code&gt; and &lt;code&gt;backend&lt;/code&gt; as you can find out in the above config file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;global

&lt;ul&gt;
&lt;li&gt;defines process-wide and often OS-specific parameters&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nuster cache on&lt;/code&gt; or &lt;code&gt;nuster nosql on&lt;/code&gt; must be declared in this section in order to use cache or nosql functionality&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;defaults

&lt;ul&gt;
&lt;li&gt;defines default parameters for all other &lt;code&gt;frontend&lt;/code&gt;, &lt;code&gt;backend&lt;/code&gt; sections&lt;/li&gt;
&lt;li&gt;and can be overwritten in specific &lt;code&gt;frontend&lt;/code&gt; or &lt;code&gt;backend&lt;/code&gt; section&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;frontend

&lt;ul&gt;
&lt;li&gt;describes a set of listening sockets accepting client connections&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;backend

&lt;ul&gt;
&lt;li&gt;describes a set of servers to which the proxy will connect to forward incoming connections&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nuster cache on&lt;/code&gt; or &lt;code&gt;nuster nosql on&lt;/code&gt; must be declared in this section&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nuster rule&lt;/code&gt; must be declared here&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can define multiple &lt;code&gt;frontend&lt;/code&gt; or &lt;code&gt;backend&lt;/code&gt; sections. If &lt;code&gt;nuster cache|nosql off&lt;/code&gt; is declared or no &lt;code&gt;nuster cache|nosql on|off&lt;/code&gt; declared, nuster acts just like HAProxy, as a TCP and HTTP load balancer.&lt;/p&gt;

&lt;p&gt;Although &lt;code&gt;listen&lt;/code&gt; is a complete proxy with its frontend and backend parts combined in one section, you cannot use nuster in &lt;code&gt;listen&lt;/code&gt;, use &lt;code&gt;frontend&lt;/code&gt; and &lt;code&gt;backend&lt;/code&gt; pairs.&lt;/p&gt;

&lt;p&gt;You can find HAProxy documentation in &lt;code&gt;/doc&lt;/code&gt;, and &lt;a href="https://cbonte.github.io/haproxy-dconv/"&gt;Online HAProxy Documentation&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  As TCP loader balancer
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;frontend mysql-lb
    bind *:3306
    mode tcp
    default_backend mysql-cluster
backend mysql-cluster
    balance roundrobin
    mode tcp
    server s1 10.0.0.101:3306
    server s2 10.0.0.102:3306
    server s3 10.0.0.103:3306
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  As HTTP/HTTPS loader balancer
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;frontend web-lb
    bind *:80
    #bind *:443 ssl crt XXX.pem
    mode http
    default_backend apps
backend apps
    balance roundrobin
    mode http
    server s1 10.0.0.101:8080
    server s2 10.0.0.102:8080
    server s3 10.0.0.103:8080
    #server s4 10.0.0.101:8443 ssl verify none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  As HTTP cache server
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global
    nuster cache on data-size 200m
frontend fe
    bind *:8080
    mode http
    default_backend be
backend be
    mode http
    nuster cache on
    nuster rule all
    server s1 127.0.0.1:8081
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  As RESTful NoSQL cache server
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global
    nuster nosql on data-size 200m
frontend fe
    bind *:8080
    mode http
    default_backend be
backend be
    nuster nosql on
    mode http
    nuster rule r1 ttl 3600
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Directives
&lt;/h1&gt;
&lt;h2&gt;
  
  
  global: nuster manager
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;syntax:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nuster manager on|off [uri URI] [purge-method method]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;default:&lt;/strong&gt; &lt;em&gt;off&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;context:&lt;/strong&gt; &lt;em&gt;global&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Enable manager/stats/purge API, define the endpoint and purge method.&lt;/p&gt;

&lt;p&gt;By default, it is disabled. When it is enabled, remember to restrict the access(see FAQ).&lt;/p&gt;

&lt;p&gt;See Manager for details.&lt;/p&gt;
&lt;h3&gt;
  
  
  uri
&lt;/h3&gt;

&lt;p&gt;Define endpoint URI, &lt;code&gt;/nuster&lt;/code&gt; by default.&lt;/p&gt;
&lt;h3&gt;
  
  
  purge-method
&lt;/h3&gt;

&lt;p&gt;Define a customized HTTP method to purge, it is &lt;code&gt;PURGE&lt;/code&gt; by default.&lt;/p&gt;
&lt;h2&gt;
  
  
  global: nuster cache|nosql
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;syntax:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nuster cache on|off [data-size size] [dict-size size] [dir DIR] [dict-cleaner n] [data-cleaner n] [disk-cleaner n] [disk-loader n] [disk-saver n] [clean-temp on|off]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nuster nosql on|off [data-size size] [dict-size size] [dir DIR] [dict-cleaner n] [data-cleaner n] [disk-cleaner n] [disk-loader n] [disk-saver n] [clean-temp on|off]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;default:&lt;/strong&gt; &lt;em&gt;none&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;context:&lt;/strong&gt; &lt;em&gt;global&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Determines whether to use cache/nosql or not.&lt;/p&gt;

&lt;p&gt;A memory zone with a size of &lt;code&gt;data-size + dict-size&lt;/code&gt; will be created.&lt;/p&gt;

&lt;p&gt;Except for temporary data created and destroyed within a request, all cache related data including HTTP response data, keys and overheads are stored in this memory zone and shared between all processes.&lt;br&gt;
If no more memory can be allocated from this memory zone, new requests that should be cached according to defined rules will not be cached unless some memory is freed.&lt;br&gt;
Temporary data are stored in a memory pool which allocates memory dynamically from system in case there is no available memory in the pool.&lt;br&gt;
A global internal counter monitors the memory usage of all HTTP response data across all processes, new requests will not be cached if the counter exceeds &lt;code&gt;data-size&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  data-size
&lt;/h3&gt;

&lt;p&gt;Determines the size of the memory zone along with &lt;code&gt;dict-size&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It accepts units like &lt;code&gt;m&lt;/code&gt;, &lt;code&gt;M&lt;/code&gt;, &lt;code&gt;g&lt;/code&gt; and &lt;code&gt;G&lt;/code&gt;. By default, the size is 1024 * 1024 bytes, which is also the minimal size.&lt;/p&gt;
&lt;h3&gt;
  
  
  dict-size
&lt;/h3&gt;

&lt;p&gt;Determines the size of memory used by the hash table.&lt;/p&gt;

&lt;p&gt;It accepts units like &lt;code&gt;m&lt;/code&gt;, &lt;code&gt;M&lt;/code&gt;, &lt;code&gt;g&lt;/code&gt; and &lt;code&gt;G&lt;/code&gt;. By default, the size is 1024 * 1024 bytes, which is also the minimal size.&lt;/p&gt;

&lt;p&gt;Note that it only decides the memory used by hash table buckets, not keys. In fact, keys are stored in the memory zone which is limited by &lt;code&gt;data-size&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dict-size(number of buckets)&lt;/strong&gt; is different from &lt;strong&gt;number of keys&lt;/strong&gt;. New keys can still be added to the hash table even if the number of keys exceeds dict-size(number of buckets) as long as there is enough memory.&lt;/p&gt;

&lt;p&gt;Nevertheless, it may lead to a potential performance drop if &lt;code&gt;number of keys&lt;/code&gt; is greater than &lt;code&gt;dict-size(number of buckets)&lt;/code&gt;. An approximate number of keys multiplied by 8 (normally) as &lt;code&gt;dict-size&lt;/code&gt; should be fine. Basically, the bigger the better.&lt;/p&gt;

&lt;p&gt;Enable stats API and check following stats:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dict.nosql.length:              131072
dict.nosql.used:                0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;dict.nosql.used&lt;/code&gt; is greater than &lt;code&gt;dict.nosql.length&lt;/code&gt;, then increase &lt;code&gt;dict-size&lt;/code&gt; would be a good idea.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;dict-size will be removed in a future release, automatically resizing the hash table in the first version will be added back.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  dir
&lt;/h3&gt;

&lt;p&gt;Specify the root directory of the disk persistence. This has to be set in order to use disk persistence.&lt;/p&gt;

&lt;h3&gt;
  
  
  dict-cleaner
&lt;/h3&gt;

&lt;p&gt;Prior to v2.x, manager tasks like removing invalid cache data, resetting dict entries are executed in iterations in each HTTP request. Corresponding indicators or pointers are increased or advanced in each iteration.&lt;/p&gt;

&lt;p&gt;In v3.x these tasks are moved to the master process and also done in iterations, and these parameters can be set to control the number of times of certain task during one iteration.&lt;/p&gt;

&lt;p&gt;During one iteration no more than &lt;code&gt;dict-cleaner&lt;/code&gt; entries are checked, invalid entries will be deleted (by default, 1000).&lt;/p&gt;

&lt;h3&gt;
  
  
  data-cleaner
&lt;/h3&gt;

&lt;p&gt;During one iteration no more than &lt;code&gt;data-cleaner&lt;/code&gt; data are checked, invalid data will be deleted (by default, 1000).&lt;/p&gt;

&lt;p&gt;When the invalid data ratio is greater than 20%, an internal mechanism will speed up the clean process, so it is recommended not to change this from the default value.&lt;/p&gt;

&lt;h3&gt;
  
  
  disk-cleaner
&lt;/h3&gt;

&lt;p&gt;If disk persistence is enabled, data are stored in files. These files are checked by master process and will be deleted if invalid, for example, expired.&lt;/p&gt;

&lt;p&gt;During one iteration no more than &lt;code&gt;disk-cleaner&lt;/code&gt; files are checked, invalid files will be deleted (by default, 100).&lt;/p&gt;

&lt;h3&gt;
  
  
  disk-loader
&lt;/h3&gt;

&lt;p&gt;After the start of nuster, master process will load information about data previously stored on disk into memory.&lt;/p&gt;

&lt;p&gt;During one iteration no more than &lt;code&gt;disk-loader&lt;/code&gt; files are loaded(by default, 100).&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;USE_THREAD&lt;/code&gt; is used, a separate thread will be created to load disk files and this parameter is ignored.&lt;/p&gt;

&lt;h3&gt;
  
  
  disk-saver
&lt;/h3&gt;

&lt;p&gt;Master process will save &lt;code&gt;disk sync&lt;/code&gt; cache data periodically.&lt;/p&gt;

&lt;p&gt;During one iteration no more than &lt;code&gt;disk-saver&lt;/code&gt; data are checked and saved to disk if necessary (by default, 100).&lt;/p&gt;

&lt;p&gt;See Store for details.&lt;/p&gt;

&lt;h3&gt;
  
  
  clean-temp on|off
&lt;/h3&gt;

&lt;p&gt;Under the directory defined by &lt;code&gt;dir&lt;/code&gt;, a temporary directory &lt;code&gt;.tmp&lt;/code&gt; will be created to store temporary files.&lt;/p&gt;

&lt;p&gt;Use this option to determine whether or not to remove those temporary files on startup.&lt;/p&gt;

&lt;p&gt;By default, it is &lt;code&gt;off&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  proxy: nuster cache|nosql
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;syntax:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nuster cache [on|off]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nuster nosql [on|off]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;default:&lt;/strong&gt; &lt;em&gt;on&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;context:&lt;/strong&gt; &lt;em&gt;backend&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Determines whether or not to use cache/nosql on this proxy, additional &lt;code&gt;nuster rule&lt;/code&gt; should be defined.&lt;br&gt;
If there are filters on this proxy, put this directive after all other filters.&lt;/p&gt;
&lt;h2&gt;
  
  
  proxy: nuster rule
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;syntax:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nuster rule name [key KEY] [ttl auto|TTL] [extend EXTEND] [wait on|off|TIME] [use-stale on|off|TIME] [inactive off|TIME] [code CODE] [memory on|off] [disk on|off|sync] [etag on|off] [last-modified on|off] [if|unless condition]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;default:&lt;/strong&gt; &lt;em&gt;none&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;context:&lt;/strong&gt; &lt;em&gt;backend&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Define rule to specify cache/nosql creating conditions, properties. At least one rule should be defined.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nuster cache on

# cache request `/asdf` for 30 seconds
nuster rule asdf ttl 30 if { path /asdf }

# cache if the request path begins with /img/
nuster rule img if { path_beg /img/ }

# cache if the response header `cache` is `yes`
acl resHdrCache res.hdr(cache) yes
nuster rule r1 if resHdrCache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is possible and recommended to declare multiple rules in the same section. The order is important because the matching process stops on the first match.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;acl pathA path /a.html
nuster cache on
nuster rule all ttl 3600
nuster rule path01 ttl 60 if pathA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;rule &lt;code&gt;path01&lt;/code&gt; will never match because the first rule will cache everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  name
&lt;/h3&gt;

&lt;p&gt;Define a name for this rule. Must be globally unique since v5.&lt;/p&gt;

&lt;h3&gt;
  
  
  key KEY
&lt;/h3&gt;

&lt;p&gt;Define the key for cache/nosql, it takes a string combined by following keywords with &lt;code&gt;.&lt;/code&gt; separator:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;method:       http method, GET/POST...&lt;/li&gt;
&lt;li&gt;scheme:       http or https&lt;/li&gt;
&lt;li&gt;host:         the host in the request&lt;/li&gt;
&lt;li&gt;uri:          first slash to end of the url&lt;/li&gt;
&lt;li&gt;path:         the URL path of the request&lt;/li&gt;
&lt;li&gt;delimiter:    '?' if query exists otherwise empty&lt;/li&gt;
&lt;li&gt;query:        the whole query string of the request&lt;/li&gt;
&lt;li&gt;header_NAME: the value of header &lt;code&gt;NAME&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;cookie_NAME: the value of cookie &lt;code&gt;NAME&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;param_NAME:  the value of query &lt;code&gt;NAME&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;body:         the body of the request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The default key of CACHE is &lt;code&gt;method.scheme.host.uri&lt;/code&gt;, and default key of NoSQL is &lt;code&gt;GET.scheme.host.uri&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET http://www.example.com/q?name=X&amp;amp;type=Y

http header:
GET /q?name=X&amp;amp;type=Y HTTP/1.1
Host: www.example.com
ASDF: Z
Cookie: logged_in=yes; user=nuster;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Should result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;method:       GET&lt;/li&gt;
&lt;li&gt;scheme:       http&lt;/li&gt;
&lt;li&gt;host:         &lt;a href="http://www.example.com"&gt;www.example.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;uri:          /q?name=X&amp;amp;type=Y&lt;/li&gt;
&lt;li&gt;path:         /q&lt;/li&gt;
&lt;li&gt;delimiter:    ?&lt;/li&gt;
&lt;li&gt;query:        name=X&amp;amp;type=Y&lt;/li&gt;
&lt;li&gt;header_ASDF: Z&lt;/li&gt;
&lt;li&gt;cookie_user: nuster&lt;/li&gt;
&lt;li&gt;param_type:  Y&lt;/li&gt;
&lt;li&gt;body:         (empty)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So default key produces &lt;code&gt;GET\0http\0www.example.com\0/q?name=X&amp;amp;type=Y\0&lt;/code&gt;, and &lt;code&gt;key method.scheme.host.path.header_ASDF.cookie_user.param_type&lt;/code&gt; produces &lt;code&gt;GET\0http\0www.example.com\0/q\0Z\0nuster\0Y\0&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;\0&lt;/code&gt; is NULL character&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If a request has the same key as a cached HTTP response data, then cached data will be sent to the client.&lt;/p&gt;

&lt;h3&gt;
  
  
  ttl auto|TTL
&lt;/h3&gt;

&lt;p&gt;Set a TTL on key, after the TTL has expired, the key will be deleted.&lt;/p&gt;

&lt;p&gt;It accepts units like &lt;code&gt;d&lt;/code&gt;, &lt;code&gt;h&lt;/code&gt;, &lt;code&gt;m&lt;/code&gt; and &lt;code&gt;s&lt;/code&gt;. Default ttl is &lt;code&gt;0&lt;/code&gt; which does not expire the key.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;auto&lt;/code&gt; is used, the ttl is set to the value of &lt;code&gt;s-maxage&lt;/code&gt; or &lt;code&gt;max-age&lt;/code&gt; directive in the &lt;code&gt;cache-control&lt;/code&gt; header.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Other directives of &lt;code&gt;cache-control&lt;/code&gt; are not handled.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The max value of ttl is 2147483647.&lt;/p&gt;

&lt;p&gt;ttl can be automatically extended by using &lt;code&gt;extend&lt;/code&gt; keyword.&lt;/p&gt;

&lt;h3&gt;
  
  
  extend EXTEND
&lt;/h3&gt;

&lt;p&gt;Automatically extend the ttl.&lt;/p&gt;

&lt;h4&gt;
  
  
  Format
&lt;/h4&gt;

&lt;p&gt;extend on|off|n1,n2,n3,n4&lt;/p&gt;

&lt;p&gt;Default: off.&lt;/p&gt;

&lt;p&gt;n1,n2,n3,n4: positive integer less than 100, and n1 + n2 + n3 is less than 100. Together they define four time slots as following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;time:       0                                                       ttl         ttl * (1 + n4%)
access:     |            A1             |   A2    |   A3    |   A4    |         |
            |---------------------------|---------|---------|---------|---------|
percentage: |&amp;lt;- (100 - n1 - n2 - n3)% -&amp;gt;|&amp;lt;- n1% -&amp;gt;|&amp;lt;- n2% -&amp;gt;|&amp;lt;- n3% -&amp;gt;|&amp;lt;- n4% -&amp;gt;|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ttl will be extended if:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A4 &amp;gt; A3 &amp;gt; A2&lt;/li&gt;
&lt;li&gt;A new request takes place between &lt;code&gt;ttl&lt;/code&gt; and &lt;code&gt;ttl * (1 + n4%)&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;on&lt;/code&gt; equals to 33,33,33,33&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  wait on|off|TIME [cache only]
&lt;/h3&gt;

&lt;p&gt;When enabled, only one request at a time will be passed to backend server to create cache. Other identical requests will either wait until the cache is created(&lt;code&gt;wait on&lt;/code&gt;) or for the time expires(&lt;code&gt;wait TIME&lt;/code&gt;) and be forwarded to the backend server.&lt;/p&gt;

&lt;p&gt;By default, identical requests are forwarded to backend server and the first one will create the cache(&lt;code&gt;wait off&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Note that other identical requests will not wait until the first request finished the initialization process(e.g. create a cache entry).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In nosql mode, there is no wait mode. Multiple identical POST requests are served in the order it was received, and the body of the last request will be saved as the content.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The max value of wait is 2147483647.&lt;/p&gt;

&lt;h3&gt;
  
  
  use-stale on|off|TIME [cache only]
&lt;/h3&gt;

&lt;p&gt;Determines whether or not to serve stale cache to clients if it is being updated or the backend server is down.&lt;/p&gt;

&lt;p&gt;When use-stale is on, the stale cache will be used to serve clients.&lt;/p&gt;

&lt;p&gt;When use-stale is off, which is the default mode, same requests will be passed to the backend when the cache is being updated if &lt;code&gt;wait off&lt;/code&gt; is set, otherwise wait if &lt;code&gt;wait on|TIME&lt;/code&gt; is set.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;use-stale TIME&lt;/code&gt; permits using the stale cache to serve clients for TIME seconds if the cache cannot be updated due to backend error.&lt;/p&gt;

&lt;p&gt;The max value of use-stale is 2147483647.&lt;/p&gt;

&lt;h3&gt;
  
  
  inactive off|TIME
&lt;/h3&gt;

&lt;p&gt;Determines whether or not to delete the cache that are not accessed during TIME seconds regardless of the validity. By default, inactive is set to off(0).&lt;/p&gt;

&lt;p&gt;Note that it is not guaranteed that the cache get removed after TIME inactive. If the clean process accesses the cache first, then the data get removed. If a new request comes first, then the last access time of the cache gets updated and the cache will not be deleted. In the case of disk file, the atime of the file is not used, so when nuster restarts, the last access time is set to the loaded time.&lt;/p&gt;

&lt;p&gt;The max value of inactive is 2147483647.&lt;/p&gt;

&lt;h3&gt;
  
  
  code CODE1,CODE2...
&lt;/h3&gt;

&lt;p&gt;Cache only if the response status code is CODE.&lt;/p&gt;

&lt;p&gt;By default, only 200 response is cached. You can use &lt;code&gt;all&lt;/code&gt; to cache all responses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nuster rule only200
nuster rule 200and404 code 200,404
nuster rule all code all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  memory on|off
&lt;/h3&gt;

&lt;p&gt;Save data to memory or not, default on.&lt;/p&gt;

&lt;p&gt;See Store for details.&lt;/p&gt;

&lt;h3&gt;
  
  
  disk on|off|sync
&lt;/h3&gt;

&lt;p&gt;Save data to disk or not, and how, default off.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;memory on&lt;/code&gt; needs to be set in order to use &lt;code&gt;disk sync&lt;/code&gt; mode.&lt;/p&gt;

&lt;p&gt;See Store for details.&lt;/p&gt;

&lt;h3&gt;
  
  
  etag on|off
&lt;/h3&gt;

&lt;p&gt;Enable etag conditional requests handling. Add &lt;code&gt;ETag&lt;/code&gt; header if absent.&lt;/p&gt;

&lt;p&gt;Default off.&lt;/p&gt;

&lt;h3&gt;
  
  
  last-modified on|off
&lt;/h3&gt;

&lt;p&gt;Enable last-modified conditional requests handling. Add &lt;code&gt;Last-Modified&lt;/code&gt; header if absent.&lt;/p&gt;

&lt;p&gt;Default off.&lt;/p&gt;

&lt;h3&gt;
  
  
  if|unless condition
&lt;/h3&gt;

&lt;p&gt;Define when to cache using HAProxy ACL.&lt;/p&gt;

&lt;p&gt;The evaluation involves two stages: request stage and response stage.&lt;/p&gt;

&lt;p&gt;Cache will be performed if:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The evaluation in the request stage is true,&lt;/li&gt;
&lt;li&gt;The evaluation in the request stage is false but true in the response stage.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Please be very careful if you use negation in the condition or samples not available in certain stage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Cache if the request path begins with &lt;code&gt;/img/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;nuster rule img if { path_beg /img/ }&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will work because the evaluation in the request stage will either be true or false and will never be true in the response stage as &lt;code&gt;path&lt;/code&gt; is not available in the response stage.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Cache if &lt;code&gt;Content-Type&lt;/code&gt; in response is &lt;code&gt;image/jpeg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;nuster rule jpeg if { res.hdr(Content-Type) image/jpeg }&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will work because the evaluation in the request stage is always false as &lt;code&gt;res.hdr&lt;/code&gt; is not available in the request stage, and will be either true or false in the response stage.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cache if the request path begins with &lt;code&gt;/img/&lt;/code&gt; and &lt;code&gt;Content-Type&lt;/code&gt; in response is &lt;code&gt;image/jpeg&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It won't work if you define the rule as:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nuster rule img if { path_beg /img/ } { res.hdr(Content-Type) image/jpeg }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;because &lt;code&gt;path&lt;/code&gt; is not available in the response stage and &lt;code&gt;res.hdr&lt;/code&gt; is not available in the request stage, so the evaluation will never be true.&lt;/p&gt;

&lt;p&gt;In order the make this work, &lt;code&gt;path&lt;/code&gt; needs to be allocated for further use in reponse stage:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http-request set-var(txn.pathImg) path
acl pathImg var(txn.pathImg) -m beg /img/
acl resHdrCT res.hdr(Content-Type) image/jpeg
nuster rule r3 if pathImg resHdrCT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Or use &lt;code&gt;nuster.path&lt;/code&gt;(v5):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nuster rule r3 if { nuster.path -m beg /img } { res.hdr(Content-Type) image/jpeg }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Another example, cache if the request path does not begin with &lt;code&gt;/api/&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It won't work neither:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;acl NoCache path_beg /api/
nuster rule r3 if !NoCache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Because the evaluation of &lt;code&gt;NoCache&lt;/code&gt; against &lt;code&gt;/api/&lt;/code&gt; in the request stage is true, and the negation is false, which is the desired state, but in response stage, the evaluation of &lt;code&gt;NoCache&lt;/code&gt; is always false as &lt;code&gt;path&lt;/code&gt; is not available in response stage, and it will be cached as the negation &lt;code&gt;!NoCache&lt;/code&gt; is true.&lt;/p&gt;

&lt;p&gt;This will work:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http-request set-var(txn.path) path
acl NoCache var(txn.path) -m beg /api/
nuster rule r1 if !NoCache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;See Sample fetches for sample fetches introduced by nuster.&lt;/p&gt;

&lt;p&gt;See &lt;strong&gt;7. Using ACLs and fetching samples&lt;/strong&gt; section in &lt;a href="//doc/configuration.txt"&gt;HAProxy configuration&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Cache
&lt;/h1&gt;

&lt;p&gt;nuster can be used as an HTTP proxy cache server like Varnish or Nginx to cache dynamic and static HTTP response.&lt;/p&gt;

&lt;p&gt;You can use HAProxy functionalities to terminate SSL, normalize HTTP, support HTTP2, rewrite the URL or modify headers and so on, and additional functionalities provided by nuster to control cache.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global
    nuster cache on data-size 200m
frontend fe
    bind *:8080
    mode http
    default_backend be
backend be
    mode http
    nuster cache on
    nuster rule r1 if { path /a1 }
    nuster rule r2 key method.scheme.host.path.delimiter.query.cookie_userId if { path /a2 }
    nuster rule r3 ttl 10 if { path /a3 }
    nuster rule r4 disk only if { path /a4 }

    server s1 127.0.0.1:8081
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a request is accepted, nuster will check the rules one by one. Key will be created and used to lookup in the cache, and if it's a HIT, the cached data will be returned to client. Otherwise the ACL will be tested, and if it passes the test, response will be cached.&lt;/p&gt;

&lt;h1&gt;
  
  
  NoSQL
&lt;/h1&gt;

&lt;p&gt;nuster can be used as a RESTful NoSQL cache server, using HTTP &lt;code&gt;POST/GET/DELETE&lt;/code&gt; to set/get/delete Key/Value object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Operations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Set
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -v -X POST -d value1 http://127.0.0.1:8080/key1
curl -v -X POST --data-binary @icon.jpg http://127.0.0.1:8080/imgs/icon.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Get
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;curl -v http://127.0.0.1:8080/key1&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Delete
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;curl -v -X DELETE http://127.0.0.1:8080/key1&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Response
&lt;/h2&gt;

&lt;p&gt;Check status code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;200 OK

&lt;ul&gt;
&lt;li&gt;POST/GET: succeeds&lt;/li&gt;
&lt;li&gt;DELETE: always&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;400 Bad request

&lt;ul&gt;
&lt;li&gt;empty value&lt;/li&gt;
&lt;li&gt;incorrect acl, rules, etc&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;404 Not Found

&lt;ul&gt;
&lt;li&gt;POST: failed on all rule tests&lt;/li&gt;
&lt;li&gt;GET: not found&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;405 Method Not Allowed

&lt;ul&gt;
&lt;li&gt;other methods&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;500 Internal Server Error

&lt;ul&gt;
&lt;li&gt;any error occurs&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;507 Insufficient Storage

&lt;ul&gt;
&lt;li&gt;exceeds max data-size&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Headers
&lt;/h2&gt;

&lt;p&gt;Supported headers in request&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;content-type&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;Will be returned as is in GET request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cache-control&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;s-maxage&lt;/code&gt; or &lt;code&gt;max-age&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;used to set ttl when rule.ttl is &lt;code&gt;auto&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Per-user data
&lt;/h2&gt;

&lt;p&gt;By using header or cookie in key, you can save per-user data to the same endpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nuster rule r1 key method.scheme.host.uri.header_userId if { path /mypoint }
nuster rule r2 key method.scheme.host.uri.cookie_sessionId if { path /mydata }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -v -X POST -d "333" -H "userId: 1000" http://127.0.0.1:8080/mypoint
curl -v -X POST -d "555" -H "userId: 1001" http://127.0.0.1:8080/mypoint

curl -v -X POST -d "userA data" --cookie "sessionId=ijsf023xe" http://127.0.0.1:8080/mydata
curl -v -X POST -d "userB data" --cookie "sessionId=rosre329x" http://127.0.0.1:8080/mydata
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Get
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -v http://127.0.0.1:8080/mypoint
&amp;lt; 404 Not Found

curl -v -H "userId: 1000" http://127.0.0.1:8080/mypoint
&amp;lt; 200 OK
333

curl -v --cookie "sessionId=ijsf023xe" http://127.0.0.1:8080/mydata
&amp;lt; 200 OK
userA data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Clients
&lt;/h2&gt;

&lt;p&gt;You can use any tools or libs which support HTTP: &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;postman&lt;/code&gt;, python &lt;code&gt;requests&lt;/code&gt;, go &lt;code&gt;net/http&lt;/code&gt;, etc.&lt;/p&gt;

&lt;h1&gt;
  
  
  Manager
&lt;/h1&gt;

&lt;p&gt;Nuster can be managed via a manager API which endpoints is defined by &lt;code&gt;uri&lt;/code&gt; and can be accessed by making HTTP requests along with some headers&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enable and define the endpoint uri and purge method&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nuster manager on uri /internal/nuster purge-method PURGEX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage matrix
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;METHOD&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;/internal/nuster&lt;/td&gt;
&lt;td&gt;get stats&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;/internal/nuster&lt;/td&gt;
&lt;td&gt;enable and disable rule, update ttl&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;/internal/nuster&lt;/td&gt;
&lt;td&gt;advanced purge cache&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PURGEX&lt;/td&gt;
&lt;td&gt;/any/real/path&lt;/td&gt;
&lt;td&gt;basic purge&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Stats
&lt;/h2&gt;

&lt;p&gt;Nuster stats can be accessed by making HTTP GET request to the endpoint defined by &lt;code&gt;uri&lt;/code&gt;;&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;curl http://127.0.0.1/nuster&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;**NUSTER**
nuster.cache:                   on
nuster.nosql:                   on
nuster.manager:                 on

**MANAGER**
manager.uri:                    /nuster
manager.purge_method:           PURGE

**DICT**
# The size of the memory used by the cache dict in bytes defined by dict-size
dict.cache.size:                1048576
# The length of the cache dict array
dict.cache.length:              131072
# The number of used entries in the cache dict
dict.cache.used:                0
dict.cache.cleanup_idx:         0
dict.cache.sync_idx:            0
dict.nosql.size:                1048576
dict.nosql.length:              131072
dict.nosql.used:                0
dict.nosql.cleanup_idx:         0
dict.nosql.sync_idx:            0

**STORE MEMORY**
# The size of the cache memory store in bytes, approximate equals to dict-size + data-size
store.memory.cache.size:        2098200576
# The size of used memory of the cache memory store
store.memory.cache.used:        1048960
# The number of stored cache entries
store.memory.cache.count:       0
store.memory.nosql.size:        11534336
store.memory.nosql.used:        1048960
store.memory.nosql.count:       0

**STORE DISK**
store.disk.cache.dir:           /tmp/nuster/cache
store.disk.cache.loaded:        yes
store.disk.nosql.dir:           /tmp/nuster/nosql
store.disk.nosql.loaded:        yes

**STATS**
# The total number of requests
stats.cache.total:              0
# The total number of HIT requests
stats.cache.hit:                0
# The total number of MISS requests
stats.cache.fetch:              0
# The total number of bypass requests
stats.cache.bypass:             0
# The total number of aborted requests
stats.cache.abort:              0
# The total response size in bytes served by cache
stats.cache.bytes:              0
stats.nosql.total:              0
stats.nosql.get:                0
stats.nosql.post:               0
stats.nosql.delete:             0

**PROXY cache app1**
app1.rule.rule1:                state=on  memory=on  disk=off   ttl=10
app1.rule.rule2:                state=on  memory=on  disk=on    ttl=10
app1.rule.rule3:                state=on  memory=on  disk=sync  ttl=10
app1.rule.rule4:                state=on  memory=off disk=on    ttl=10
app1.rule.rule5:                state=on  memory=off disk=off   ttl=10

**PROXY nosql app2**
app2.rule.ruleA:                state=on  memory=on  disk=off   ttl=10
app2.rule.ruleB:                state=on  memory=on  disk=on    ttl=10
app2.rule.ruleC:                state=on  memory=on  disk=sync  ttl=10
app2.rule.ruleD:                state=on  memory=off disk=on    ttl=10
app2.rule.ruleE:                state=on  memory=off disk=off   ttl=10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Enable and disable rule
&lt;/h2&gt;

&lt;p&gt;Rule can be disabled at run time through manager uri. Disabled rule will not be processed, nor will the cache created by that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;headers&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;header&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;state&lt;/td&gt;
&lt;td&gt;enable&lt;/td&gt;
&lt;td&gt;enable  rule&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;disable&lt;/td&gt;
&lt;td&gt;disable rule&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;rule NAME&lt;/td&gt;
&lt;td&gt;the rule to be enabled/disabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;proxy NAME&lt;/td&gt;
&lt;td&gt;all rules of proxy NAME&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;all rules&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Keep in mind that if name is not unique, &lt;strong&gt;all&lt;/strong&gt; rules with that name will be disabled/enabled.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Examples&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Disable rule r1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;curl -X POST -H "name: r1" -H "state: disable" http://127.0.0.1/nuster&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Disable all rules defined in proxy app1b&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;curl -X POST -H "name: app1b" -H "state: disable" http://127.0.0.1/nuster&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable all rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;curl -X POST -H "name: *" -H "state: enable" http://127.0.0.1/nuster&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Update ttl
&lt;/h2&gt;

&lt;p&gt;Change the TTL. It only affects the TTL of the responses to be cached, &lt;strong&gt;does not&lt;/strong&gt; update the TTL of existing caches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;headers&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;header&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ttl&lt;/td&gt;
&lt;td&gt;new TTL&lt;/td&gt;
&lt;td&gt;see &lt;code&gt;ttl&lt;/code&gt; in &lt;code&gt;nuster rule&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;rule NAME&lt;/td&gt;
&lt;td&gt;the rule to be changed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;proxy NAME&lt;/td&gt;
&lt;td&gt;all rules of proxy NAME&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;all rules&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Examples&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST -H "name: r1" -H "ttl: 0" http://127.0.0.1/nuster
curl -X POST -H "name: r2" -H "ttl: 2h" http://127.0.0.1/nuster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update state and TTL
&lt;/h3&gt;

&lt;p&gt;state and ttl can be updated at the same time&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST -H "name: r1" -H "ttl: 0" -H "state: enabled" http://127.0.0.1/nuster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Purging
&lt;/h2&gt;

&lt;p&gt;There are two purging mode: basic and advanced.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;basic: Send HTTP method defined by &lt;code&gt;purge-method MYPURGE&lt;/code&gt; to the path you want to delete&lt;/li&gt;
&lt;li&gt;advanced: Send DELETE method to the manager uri defined by &lt;code&gt;uri&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Basic purging
&lt;/h3&gt;

&lt;p&gt;This method deletes the specific url that is being requested, like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -XPURGE http://127.0.0.1/imgs/test.jpg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Key is created in the same way when the cache created except that the &lt;code&gt;method&lt;/code&gt; is &lt;code&gt;GET&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note by default cache key contains &lt;code&gt;Host&lt;/code&gt; if you cache a request like &lt;code&gt;http://example.com/test&lt;/code&gt; and purge from localhost you need to specify &lt;code&gt;Host&lt;/code&gt; header:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -XPURGE -H "Host: example.com" http://127.0.0.1/test&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It works for both cache and nosql, it is an alias of &lt;code&gt;DELETE&lt;/code&gt; in nosql mode.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advanced purging: purge by name
&lt;/h3&gt;

&lt;p&gt;Cache can be purged by making HTTP &lt;code&gt;DELETE&lt;/code&gt; requests to the manager uri along with a &lt;code&gt;name&lt;/code&gt; HEADER.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;headers&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;header&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;nuster rule NAME&lt;/td&gt;
&lt;td&gt;caches created by rule ${NAME} will be purged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;proxy NAME&lt;/td&gt;
&lt;td&gt;caches of proxy ${NAME}&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Examples&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# purge all caches of proxy applb
curl -X DELETE -H "name: app1b" http://127.0.0.1/nuster
# purge all caches of rule r1
curl -X DELETE -H "name: r1" http://127.0.0.1/nuster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Advanced purging: purge by host
&lt;/h3&gt;

&lt;p&gt;You can also purge cache by host, all caches with that host will be deleted:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;headers&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;header&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;host&lt;/td&gt;
&lt;td&gt;HOST&lt;/td&gt;
&lt;td&gt;the ${HOST}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nuster-host&lt;/td&gt;
&lt;td&gt;HOST&lt;/td&gt;
&lt;td&gt;nuster-host has higher precedence over host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mode&lt;/td&gt;
&lt;td&gt;cache, nosql&lt;/td&gt;
&lt;td&gt;purge cache or nosql data&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Examples&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X DELETE -H "nuster-host: 127.0.0.1:8080" http://127.0.0.1/nuster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Advanced purging: purge by path
&lt;/h3&gt;

&lt;p&gt;By default, the query part is also used as a cache key, so there will be multiple caches if the query differs.&lt;/p&gt;

&lt;p&gt;For example, for rule &lt;code&gt;nuster rule imgs if { path_beg /imgs/ }&lt;/code&gt;, and request&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl http://127.0.0.1/imgs/test.jpg?w=120&amp;amp;h=120
curl http://127.0.0.1/imgs/test.jpg?w=180&amp;amp;h=180
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There will be two cache objects since the default key contains the query part.&lt;/p&gt;

&lt;p&gt;In order to delete that, you can&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;delete one by one in case you know all queries&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -XPURGE http://127.0.0.1/imgs/test.jpg?w=120&amp;amp;h=120
curl -XPURGE http://127.0.0.1/imgs/test.jpg?w=180&amp;amp;h=180
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It does not work if you don't know all queries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;use a customized key and delete once in case that the query part is irrelevant&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Define a key like &lt;code&gt;nuster rule imgs key method.scheme.host.path if { path_beg /imgs }&lt;/code&gt;, in this way only one cache will be created, and you can purge without query:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -XPURGE http://127.0.0.1/imgs/test.jpg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It does not work if the query part is required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;delete by rule NAME&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -X DELETE -H "name: imgs" http://127.0.0.1/nuster&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It does not work if the nuster rule is defined something like &lt;code&gt;nuster rule static if { path_beg /imgs/ /css/ }&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This method provides a way to purge just by path:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;headers&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;header&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;path&lt;/td&gt;
&lt;td&gt;PATH&lt;/td&gt;
&lt;td&gt;caches with ${PATH} will be purged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;host&lt;/td&gt;
&lt;td&gt;HOST&lt;/td&gt;
&lt;td&gt;and host is ${HOST}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nuster-host&lt;/td&gt;
&lt;td&gt;HOST&lt;/td&gt;
&lt;td&gt;nuster-host has higher precedence over host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mode&lt;/td&gt;
&lt;td&gt;cache, nosql&lt;/td&gt;
&lt;td&gt;purge cache or nosql data&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Examples&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#delete all caches which path is /imgs/test.jpg
curl -X DELETE -H "path: /imgs/test.jpg" http://127.0.0.1/nuster
#delete all caches which path is /imgs/test.jpg and with host of 127.0.0.1:8080
curl -X DELETE -H "path: /imgs/test.jpg" -H "nuster-host: 127.0.0.1:8080" http://127.0.0.1/nuster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Advanced purging: purge by regex
&lt;/h3&gt;

&lt;p&gt;You can also purge cache by regex, the caches which path match the regex will be deleted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;headers&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;header&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;regex&lt;/td&gt;
&lt;td&gt;REGEX&lt;/td&gt;
&lt;td&gt;caches which path match with ${REGEX} will be purged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;host&lt;/td&gt;
&lt;td&gt;HOST&lt;/td&gt;
&lt;td&gt;and host is ${HOST}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nuster-host&lt;/td&gt;
&lt;td&gt;HOST&lt;/td&gt;
&lt;td&gt;nuster-host has higher precedence over host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mode&lt;/td&gt;
&lt;td&gt;cache, nosql&lt;/td&gt;
&lt;td&gt;purge cache or nosql data&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Examples&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#delete all caches which path starts with /imgs and ends with .jpg
curl -X DELETE -H "regex: ^/imgs/.*\.jpg$" http://127.0.0.1/nuster
#delete all caches which path starts with /imgs and ends with .jpg and with host of 127.0.0.1:8080
curl -X DELETE -H "regex: ^/imgs/.*\.jpg$" -H "127.0.0.1:8080" http://127.0.0.1/nuster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;PURGE CAUTION&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ENABLE ACCESS RESTRICTION&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If there are mixed headers, use the precedence of &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;path &amp;amp; host&lt;/code&gt;, &lt;code&gt;path&lt;/code&gt;, &lt;code&gt;regex &amp;amp; host&lt;/code&gt;, &lt;code&gt;regex&lt;/code&gt;, &lt;code&gt;host&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;curl -X DELETE -H "name: rule1" -H "path: /imgs/a.jpg"&lt;/code&gt;: purge by name&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If there are redundant headers, use the first occurrence&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;curl -X DELETE -H "name: rule1" -H "name: rule2"&lt;/code&gt;: purge by &lt;code&gt;rule1&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;regex&lt;/code&gt; is &lt;strong&gt;NOT glob&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, all jpg files under /imgs should be &lt;code&gt;^/imgs/.*\.jpg$&lt;/code&gt; instead of &lt;code&gt;/imgs/*.jpg&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Purging cache files by proxy name or rule name or host or path or regex only works after the disk loader process is finished. You can check the status through stats url.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Store
&lt;/h1&gt;

&lt;p&gt;Nuster(both cache and nosql) supports different backend stores. Currently memory and disk are supported. More stores will be added.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory
&lt;/h2&gt;

&lt;p&gt;Data is stored into a memory area which size is defined by &lt;code&gt;data-size&lt;/code&gt;. Data does not persist in memory and will lost after restarts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disk
&lt;/h2&gt;

&lt;p&gt;Data is stored to disk and under the path defined by &lt;code&gt;dir&lt;/code&gt;. Data persists after restarts.&lt;/p&gt;

&lt;p&gt;There are 3 modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;off:   default, disable disk persistence.&lt;/li&gt;
&lt;li&gt;on:    save data to disk.&lt;/li&gt;
&lt;li&gt;sync:  &lt;code&gt;memory on&lt;/code&gt; has to be set in order to use this mode. Save data to memory first and data will be synced to disk later by the master process. One iteration &lt;code&gt;disk-saver&lt;/code&gt; data are checked and saved to disk.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Sample fetches
&lt;/h1&gt;

&lt;p&gt;Nuster introduced following sample fetches&lt;/p&gt;

&lt;h2&gt;
  
  
  [cache] nuster.cache.hit: boolean
&lt;/h2&gt;

&lt;p&gt;Returns a boolean indicating whether it's a HIT or not and can be used like&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http-response set-header x-cache hit if { nuster.cache.hit }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  [cache|nosql] nuster.host: string
&lt;/h2&gt;

&lt;p&gt;Same as HAProxy &lt;code&gt;req.hdr(Host)&lt;/code&gt; except that &lt;code&gt;nuster.host&lt;/code&gt; can be used in both request and response stage.&lt;/p&gt;
&lt;h2&gt;
  
  
  [cache|nosql] nuster.uri: string
&lt;/h2&gt;

&lt;p&gt;Same as HAProxy &lt;code&gt;capture.req.uri&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  [cache|nosql] nuster.path: string
&lt;/h2&gt;

&lt;p&gt;Same as HAProxy &lt;code&gt;path&lt;/code&gt; except that &lt;code&gt;nuster.path&lt;/code&gt; can be used in both request and response stage.&lt;/p&gt;
&lt;h2&gt;
  
  
  [cache|nosql] nuster.query: string
&lt;/h2&gt;

&lt;p&gt;Same as HAProxy &lt;code&gt;query&lt;/code&gt; except that &lt;code&gt;nuster.query&lt;/code&gt; can be used in both request and response stage.&lt;/p&gt;
&lt;h1&gt;
  
  
  FAQ
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Cannot start: not in master-worker mode
&lt;/h2&gt;

&lt;p&gt;Set &lt;code&gt;master-worker&lt;/code&gt; in &lt;code&gt;global&lt;/code&gt; section, or start &lt;code&gt;nuster&lt;/code&gt; with &lt;code&gt;-W&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to debug?
&lt;/h2&gt;

&lt;p&gt;Set &lt;code&gt;debug&lt;/code&gt; in &lt;code&gt;global&lt;/code&gt; section, or start &lt;code&gt;nuster&lt;/code&gt; with &lt;code&gt;-d&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nuster related debug messages start with &lt;code&gt;[nuster&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to cache POST request?
&lt;/h2&gt;

&lt;p&gt;Enable &lt;code&gt;option http-buffer-request&lt;/code&gt; and set &lt;code&gt;body&lt;/code&gt; in cache rule &lt;code&gt;key&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By default, the cache key does not include the body of the request, remember to put &lt;code&gt;body&lt;/code&gt; in key field.&lt;/p&gt;

&lt;p&gt;Note that the size of the request body must be smaller than &lt;code&gt;tune.bufsize - tune.maxrewrite - request_header_size&lt;/code&gt;, which by default is &lt;code&gt;16384 - 1024 - request_header_size&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Refer to &lt;strong&gt;option http-buffer-request&lt;/strong&gt; and &lt;strong&gt;tune.bufsize&lt;/strong&gt; section in &lt;a href="//doc/configuration.txt"&gt;HAProxy configuration&lt;/a&gt; for details.&lt;/p&gt;

&lt;p&gt;Also, it might be a good idea to put it separately in a dedicated backend as the example does.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to restrict access?
&lt;/h2&gt;

&lt;p&gt;You can use the powerful HAProxy ACL, something like this&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;acl network_allowed src 127.0.0.1
acl purge_method method PURGE
http-request deny if purge_method !network_allowed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to enable HTTP2
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bind :443 ssl crt pub.pem alpn h2,http/1.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Example
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global
    nuster manager on uri /_/nuster purge-method MYPURGE
    nuster cache on data-size 100m
    nuster nosql on data-size 100m
    master-worker # since v3
    # daemon
    # debug
defaults
    retries 3
    option redispatch
    timeout client  30s
    timeout connect 30s
    timeout server  30s
frontend web1
    bind *:8080
    mode http
    acl pathPost path /search
    use_backend app1a if pathPost
    default_backend app1b
backend app1a
    balance roundrobin
    # mode must be http
    mode http

    # http-buffer-request must be enabled to cache post request
    option http-buffer-request

    acl pathPost path /search

    # enable cache for this proxy
    nuster cache

    # cache /search for 120 seconds. Only works when POST/PUT
    nuster rule rpost key method.scheme.host.uri.body ttl 120 if pathPost

    server s1 10.0.0.10:8080
backend app1b
    balance     roundrobin
    mode http

    nuster cache on

    # cache /a.jpg, not expire
    acl pathA path /a.jpg
    nuster rule r1 ttl 0 if pathA

    # cache /mypage, key contains cookie[userId], so it will be cached per user
    acl pathB path /mypage
    nuster rule r2 key method.scheme.host.path.delimiter.query.cookie_userId ttl 60 if pathB

    # cache /a.html if response's header[cache] is yes
    http-request set-var(txn.pathC) path
    acl pathC var(txn.pathC) -m str /a.html
    acl resHdrCache1 res.hdr(cache) yes
    nuster rule r3 if pathC resHdrCache1

    # cache /heavy for 100 seconds if be_conn greater than 10
    acl heavypage path /heavy
    acl tooFast be_conn ge 100
    nuster rule heavy ttl 100 if heavypage tooFast

    # cache all if response's header[asdf] is fdsa
    acl resHdrCache2 res.hdr(asdf)  fdsa
    nuster rule resCache ttl 0 if resHdrCache1

    server s1 10.0.0.10:8080

frontend web2
    bind *:8081
    mode http
    default_backend app2
backend app2
    balance     roundrobin
    mode http

    # disable cache on this proxy
    nuster cache off
    nuster rule all

    server s2 10.0.0.11:8080

frontend nosql_fe
    bind *:9090
    default_backend nosql_be
backend nosql_be
    nuster nosql on
    nuster rule r1 ttl 3600
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Contributing
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Join the development&lt;/li&gt;
&lt;li&gt;Give feedback&lt;/li&gt;
&lt;li&gt;Report issues&lt;/li&gt;
&lt;li&gt;Send pull requests&lt;/li&gt;
&lt;li&gt;Spread nuster&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  License
&lt;/h1&gt;

&lt;p&gt;Copyright (C) 2017-present, &lt;a href="https://github.com/jiangwenyuan"&gt;Jiang Wenyuan&lt;/a&gt;, &amp;lt; koubunen AT gmail DOT com &amp;gt;&lt;/p&gt;

&lt;p&gt;All rights reserved.&lt;/p&gt;

&lt;p&gt;Licensed under GPL, the same as HAProxy&lt;/p&gt;

&lt;p&gt;HAProxy and other sources license notices: see relevant individual files.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>devops</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>Web cache server HTTP/2 performance benchmark: nuster vs nginx  </title>
      <dc:creator>Nuster Cache Server</dc:creator>
      <pubDate>Wed, 13 Jun 2018 03:35:15 +0000</pubDate>
      <link>https://dev.to/nuster/web-cache-server-http2-performance-benchmark-nuster-vs-nginx---266o</link>
      <guid>https://dev.to/nuster/web-cache-server-http2-performance-benchmark-nuster-vs-nginx---266o</guid>
      <description>&lt;p&gt;This is a simple benchmark comparing the HTTP/2 cache performance of &lt;a href="https://github.com/jiangwenyuan/nuster"&gt;nuster&lt;/a&gt; and nginx.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jiangwenyuan/nuster"&gt;https://github.com/jiangwenyuan/nuster&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I tested the RPS(Request per second) by &lt;code&gt;h2load&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The test shown that nuster is almost three times faster than nginx.&lt;/p&gt;

&lt;p&gt;Here is the result(RPS) when request &lt;code&gt;/helloworld&lt;/code&gt; URL containing &lt;code&gt;hello world&lt;/code&gt; data.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;data size&lt;/th&gt;
&lt;th&gt;CONN&lt;/th&gt;
&lt;th&gt;nuster&lt;/th&gt;
&lt;th&gt;nginx&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;12(hello world)&lt;/td&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;td&gt;338924&lt;/td&gt;
&lt;td&gt;110419&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Testing environment
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Server
&lt;/h2&gt;

&lt;p&gt;Two linux servers are used, an origin web server on server129,&lt;br&gt;
and cache server nuster/nginx on server130.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Server&lt;/th&gt;
&lt;th&gt;port&lt;/th&gt;
&lt;th&gt;app&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10.0.0.129&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;wrk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10.0.0.129&lt;/td&gt;
&lt;td&gt;8080&lt;/td&gt;
&lt;td&gt;nginx, origin web server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10.0.0.130&lt;/td&gt;
&lt;td&gt;8081&lt;/td&gt;
&lt;td&gt;nuster, all cores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10.0.0.130&lt;/td&gt;
&lt;td&gt;8083&lt;/td&gt;
&lt;td&gt;nginx, all cores&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;origin web server: set &lt;code&gt;server_tokens off;&lt;/code&gt; to make http header &lt;code&gt;server&lt;/code&gt; same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hardware
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Intel(R) Xeon(R) CPU X5650 @ 2.67GHz(12 cores)&lt;/li&gt;
&lt;li&gt;RAM 32GB&lt;/li&gt;
&lt;li&gt;1Gbps ethernet card&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Software
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;CentOS: 7.4.1708 (Core)&lt;/li&gt;
&lt;li&gt;h2load: nghttp2/1.30.0&lt;/li&gt;
&lt;li&gt;nginx: nginx/1.14.0&lt;/li&gt;
&lt;li&gt;nuster: nuster/1.8.8.2&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  System settings
&lt;/h1&gt;

&lt;h2&gt;
  
  
  /etc/sysctl.conf
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fs.file-max                    = 9999999
fs.nr_open                     = 9999999
net.core.netdev_max_backlog    = 4096
net.core.rmem_max              = 16777216
net.core.somaxconn             = 65535
net.core.wmem_max              = 16777216
net.ipv4.ip_forward            = 0
net.ipv4.ip_local_port_range   = 1025       65535
net.ipv4.tcp_fin_timeout       = 30
net.ipv4.tcp_keepalive_time    = 30
net.ipv4.tcp_max_syn_backlog   = 20480
net.ipv4.tcp_max_tw_buckets    = 400000
net.ipv4.tcp_no_metrics_save   = 1
net.ipv4.tcp_syn_retries       = 2
net.ipv4.tcp_synack_retries    = 2
net.ipv4.tcp_tw_recycle        = 1
net.ipv4.tcp_tw_reuse          = 1
net.ipv4.tcp_timestamps        = 1
vm.min_free_kbytes             = 65536
vm.overcommit_memory           = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  /etc/security/limits.conf
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* soft nofile 1000000
* hard nofile 1000000
* soft nproc  1000000
* hard nproc  1000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Config files
&lt;/h1&gt;

&lt;h2&gt;
  
  
  nuster, all cores
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global
    maxconn 1000000
    nuster cache on data-size 1g
    daemon
    nbproc 12
    tune.maxaccept -1
    tune.ssl.default-dh-param 2048
    tune.h2.max-concurrent-streams 1000
defaults
    retries 3
    maxconn 1000000
    option redispatch
    option dontlognull
    timeout client  300s
    timeout connect 300s
    timeout server  300s
    http-reuse always
frontend web1
    bind *:8081 ssl crt asdf.pem alpn h2,http/1.1
    mode http
    default_backend app1
backend app1
    balance roundrobin
    mode http
    nuster cache on
    nuster rule all ttl 0
    server a2 10.0.0.129:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  nginx, all cores
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user  nginx;
worker_processes  auto;
worker_rlimit_nofile 1000000;
error_log  /var/log/nginx/errorall.log warn;
pid        /var/run/nginxall.pid;
events {
  worker_connections  1000000;
  use epoll;
  multi_accept on;
}
http {
  include                     /etc/nginx/mime.types;
  default_type                application/octet-stream;
  access_log                  off;
  sendfile                    on;
  server_tokens               off;
  keepalive_timeout           300;
  keepalive_requests          100000;
  tcp_nopush                  on;
  tcp_nodelay                 on;
  client_body_buffer_size     128k;
  client_header_buffer_size   1m;
  large_client_header_buffers 4 4k;
  output_buffers              1 32k;
  postpone_output             1460;
  open_file_cache             max=200000 inactive=20s;
  open_file_cache_valid       30s;
  open_file_cache_min_uses    2;
  open_file_cache_errors      on;
  proxy_cache_path /tmp/cache_all levels=1:2 keys_zone=STATIC:10m inactive=24h max_size=1g;
  server {
    listen 8083 ssl http2;
    ssl on;
    ssl_session_cache shared:SSL:5m;
    ssl_session_timeout 1h;
    http2_max_concurrent_streams 1000;
    http2_max_requests 10000000;
    ssl_certificate     a.pem;
    ssl_certificate_key a.key;

    location / {
      proxy_pass        http://10.0.0.129:8080/;
      proxy_cache       STATIC;
      proxy_cache_valid any 1d;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Benchmark
&lt;/h1&gt;

&lt;h3&gt;
  
  
  nuster
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ h2load -n 10000000 -c 1000 -m 1000 -t 1000 https://10.0.0.130:8081/helloworld


finished in 29.51s, 338924.15 req/s, 48.81MB/s
requests: 10000000 total, 10000000 started, 10000000 done, 10000000 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 10000000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 1.41GB (1510024000) total, 1.13GB (1210000000) headers (space savings 34.24%), 114.44MB (120000000) data
                     min         max         mean         sd        +/- sd
time for request:    14.51ms       3.21s       2.53s    500.02ms    74.50%
time for connect:    61.12ms       1.26s    672.73ms    332.30ms    63.50%
time to 1st byte:    95.03ms       3.74s       2.68s    777.51ms    74.00%
req/s           :     339.11      459.68      358.92       17.35    76.20%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  nginx
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ h2load -n 10000000 -c 1000 -m 1000 -t 1000 https://10.0.0.130:8083/helloworld


finished in 90.56s, 110419.16 req/s, 15.62MB/s
requests: 10000000 total, 10000000 started, 10000000 done, 10000000 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 10000000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 1.38GB (1482955210) total, 1.10GB (1182906210) headers (space savings 35.01%), 114.44MB (120000000) data
                     min         max         mean         sd        +/- sd
time for request:     3.98ms      14.65s       5.14s       3.67s    70.30%
time for connect:    69.96ms       6.74s       1.35s       1.08s    88.90%
time to 1st byte:   114.92ms      15.46s       5.67s       4.06s    63.40%
req/s           :     110.43     5143.28      378.40      590.47    92.50%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Details: &lt;a href="https://github.com/jiangwenyuan/nuster"&gt;https://github.com/jiangwenyuan/nuster&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webperf</category>
      <category>devops</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
    <item>
      <title>nuster - A cache proxy server released v1.8.8.1: HTTP/2 support  </title>
      <dc:creator>Nuster Cache Server</dc:creator>
      <pubDate>Tue, 08 May 2018 01:52:18 +0000</pubDate>
      <link>https://dev.to/nuster/nuster---a-cache-proxy-server-released-v1881-http2-support---17d5</link>
      <guid>https://dev.to/nuster/nuster---a-cache-proxy-server-released-v1881-http2-support---17d5</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/jiangwenyuan/nuster"&gt;nuster&lt;/a&gt;, A caching proxy server based on HAProxy released v1.8.8.1, update to HAProxy v1.8.8, supports HTTP/2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Nuster is a high performance caching proxy server based on HAProxy.&lt;br&gt;
It is 100% compatible with HAProxy, and takes full advantage of the ACL&lt;br&gt;
functionality of HAProxy to provide fine-grained caching policy based on&lt;br&gt;
the content of request, response or server status. Its features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All features of HAProxy are inherited, 100% compatible with HAProxy&lt;/li&gt;
&lt;li&gt;Powerful dynamic cache ability

&lt;ul&gt;
&lt;li&gt;Based on HTTP method, URI, path, query, header, cookies, etc&lt;/li&gt;
&lt;li&gt;Based on HTTP request or response contents, etc&lt;/li&gt;
&lt;li&gt;Based on environment variables, server state, etc&lt;/li&gt;
&lt;li&gt;Based on SSL version, SNI, etc&lt;/li&gt;
&lt;li&gt;Based on connection rate, number, byte, etc&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Extremely fast&lt;/li&gt;
&lt;li&gt;Cache purging&lt;/li&gt;
&lt;li&gt;Cache stats&lt;/li&gt;
&lt;li&gt;Cache management&lt;/li&gt;
&lt;li&gt;HTTPS supports on both frontend and backend&lt;/li&gt;
&lt;li&gt;HTTP compression&lt;/li&gt;
&lt;li&gt;HTTP/2&lt;/li&gt;
&lt;li&gt;HTTP rewriting and redirection&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Performance
&lt;/h1&gt;

&lt;p&gt;Nuster is very fast, some test shows nuster is almost three times faster than&lt;br&gt;
nginx when both using single core, and nearly two times faster than nginx and&lt;br&gt;
three times faster than varnish when using all cores.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://github.com/jiangwenyuan/nuster/wiki/Web-cache-server-performance-benchmark:-nuster-vs-nginx-vs-varnish-vs-squid"&gt;detailed benchmark&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>devops</category>
      <category>opensource</category>
      <category>linux</category>
    </item>
    <item>
      <title>nuster - A web caching proxy server based on HAProxy </title>
      <dc:creator>Nuster Cache Server</dc:creator>
      <pubDate>Thu, 01 Feb 2018 07:59:55 +0000</pubDate>
      <link>https://dev.to/nuster/nuster---a-web-caching-proxy-server-based-on-haproxy-40k2</link>
      <guid>https://dev.to/nuster/nuster---a-web-caching-proxy-server-based-on-haproxy-40k2</guid>
      <description>&lt;p&gt;Hi all, I have created a web caching proxy server &lt;a href="https://github.com/jiangwenyuan/nuster"&gt;nuster&lt;/a&gt;, please give it a try and star:)&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Nuster is a simple yet powerful web caching proxy server based on HAProxy.&lt;br&gt;
It is 100% compatible with HAProxy, and takes full advantage of the ACL&lt;br&gt;
functionality of HAProxy to provide fine-grained caching policy based on&lt;br&gt;
the content of request, response or server status, such as,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;request url: cache only if the request url equals to X&lt;/li&gt;
&lt;li&gt;request query: cache only if the request query contains X and equls to Y&lt;/li&gt;
&lt;li&gt;cookie: cache only if cookie contains X and equls to Y&lt;/li&gt;
&lt;li&gt;response header: cache only if the response contains header X equals to Y&lt;/li&gt;
&lt;li&gt;rate: cache only if the request rate is greater than X&lt;/li&gt;
&lt;li&gt;etc, any combination of above&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Performance
&lt;/h1&gt;

&lt;p&gt;Nuster is very fast, some test shows nuster is almost three times faster than &lt;br&gt;
nginx when both using single core, and nearly two times faster than nginx and&lt;br&gt;
three times faster than varnish when using all cores.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://github.com/jiangwenyuan/nuster/wiki/Performance-benchmark:-nuster-vs-nginx-vs-varnish"&gt;detailed benchmark&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Installation
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Download
&lt;/h2&gt;

&lt;p&gt;Download stable version from &lt;a href="https://github.com/jiangwenyuan/nuster/releases"&gt;releases&lt;/a&gt; page&lt;br&gt;
for production use, otherwise git clone the source code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;make TARGET=linux2628
make install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;use &lt;code&gt;make TARGET=linux2628 USE_PTHREAD_PSHARED=1&lt;/code&gt; to use pthread lib&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;See &lt;a href="https://dev.toREADME"&gt;HAProxy README&lt;/a&gt; for details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker pull nuster/nuster
docker run -d -v /path/to/nuster.cfg:/etc/nuster/nuster.cfg:ro -p 8080:8080 nuster/nuster:1.7.9.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See usages, FAQ, examples on &lt;a href="https://github.com/jiangwenyuan/nuster/blob/master/README.md"&gt;Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>devops</category>
      <category>opensource</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
