Example: configure WordPress with a static cache

Introduction

If you want to use Caddy 2 for a WordPress site and you are using a static cache that generates html file on the server, you can use a config to bypass entirely WordPress and php-fpm. That way, you will really quickly serve static files to your users, without cluttering the server.

That solution is common with most WordPress static cache plugins. In order to work, you must define some exceptions for all requests that need to hit WordPress and not the cache. For instance, if you are the administrator of the site and if you are connected, you don’t want to see the cached pages. Likewise, if you are in the admin interface of WP, you should go directly to php-fpm without going to the static cache first.

Choose the correct configuration depending on the WordPress plugin you’re using. And if your plugin is not on this list, you can use the comment to offer your configuration or request for help.

Cache enabler

The configuration has been tried by @nicolinux and it is working.

You can use the plugin default settings.

domain.com {
    # Change the path here according to your setup
	root * /var/www/domain.com
	encode zstd gzip
	file_server

	@cache {
		not header_regexp Cookie "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in"
		not path_regexp "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(index)?.xml|[a-z0-9-]+-sitemap([0-9]+)?.xml)"
		not method POST
		not expression {query} != ''
    }

    route @cache {
        try_files /wp-content/cache/cache-enabler/{host}{uri}/https-index.html /wp-content/cache/cache-enabler/{host}{uri}/index.html {path} {path}/index.php?{query}
    }
       
    # Change the path here according to your server
    php_fastcgi unix//run/php/php7.4-fpm.sock
}

WP Super Cache

The configuration has been tried by @Kyle_Chen and it is working.

Configure the plugin to use the expert mode and ignore the alert about .htaccess. You can find additional details in this other post.

domain.com {
    # Change the path here according to your setup
	root * /var/www/domain.com
	encode zstd gzip
	file_server

    @cache {
		not header_regexp Cookie "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in"
		not path_regexp "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(index)?.xml|[a-z0-9-]+-sitemap([0-9]+)?.xml)"
		not method POST
		not expression {query} != ''
	 }

     route @cache {
        try_files /wp-content/cache/supercache/{host}{uri}/index-https.html /wp-content/cache/supercache/{host}{uri}/index.html {path} {path}/index.php?{query}
     }

   # Change the path here according to your server
    php_fastcgi unix//run/php/php7.4-fpm.sock
}

WP-Rocket

This configuration was never tried. Let us know if it works in the comments.

The default configuration should work.

:warning: This configuration does not use the separate mobile cache that WP-Rocket creates. Help would be appreciated to use both with Caddy 2. Here’s the nginx file to translate.

domain.com {
    # Change the path here according to your setup
	root * /var/www/domain.com
	encode zstd gzip
	file_server

	@cache {
		not header_regexp Cookie "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in"
		not path_regexp "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(index)?.xml|[a-z0-9-]+-sitemap([0-9]+)?.xml)"
		not method POST
		not expression {query} != ''
    }

    route @cache {
        try_files /wp-content/cache/wp-rocket/{host}{uri}/index-https.html /wp-content/cache/wp-rocket/{host}{uri}/index.html {path} {path}/index.php?{query}
    }
       
   # Change the path here according to your server
    php_fastcgi unix//run/php/php7.4-fpm.sock
}

WP Fastest cache

This configuration was never tried. Let us know if it works in the comments.

The default configuration should work.

:warning: This configuration does not use the separate mobile cache that WP Fastest cache premium creates. Help would be appreciated to use both with Caddy 2. Here’s the nginx file to translate.

domain.com {
    # Change the path here according to your setup
	root * /var/www/domain.com
	encode zstd gzip
	file_server

	@cache {
		not header_regexp Cookie "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in"
		not path_regexp "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(index)?.xml|[a-z0-9-]+-sitemap([0-9]+)?.xml)"
		not method POST
		not expression {query} != ''
    }

    route @cache {
        try_files /wp-content/cache/all/{uri}/index.html {path} {path}/index.php?{query}
    }
       
   # Change the path here according to your server
    php_fastcgi unix//run/php/php7.4-fpm.sock
}

W3 Total Cache

This configuration was never tried. Let us know if it works in the comments.

Configure the plugin to activate the static page on disk with the advanced option.

:warning: This configuration does not use the multiple cache versions that W3 Total Cache creates. Help would be appreciated to use both with Caddy 2. Here’s the nginx file to translate.

domain.com {
    # Change the path here according to your setup
	root * /var/www/domain.com
	encode zstd gzip
	file_server

    @cache {
		not header_regexp Cookie "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in"
		not path_regexp "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(index)?.xml|[a-z0-9-]+-sitemap([0-9]+)?.xml)"
		not method POST
		not expression {query} != ''
	 }

     route @cache {
        try_files /wp-content/cache/page_enhanced/{host}{uri}/_index_ssl.html /wp-content/cache/page_enhanced/{host}{uri}/_index.html {path} {path}/index.php?{query}
     }

   # Change the path here according to your server
    php_fastcgi unix//run/php/php7.4-fpm.sock
}

Wiki changelog

  • 17 May 2020 : first version ;
  • 29 June 2020 : Caddy 2.1 warning and W3 Total cache untested configuration ;
  • 1 July 2020 : removed the Caddy 2.1 warning, use at least Caddy 2.1.1 ;
  • 25 August 2020 : fixed the Cache Enabler snippet for the latest versions of the plugin (source).
10 Likes

This is some hard work!

I find the detection of mobile device is matching http_user_agent with android|ip(ad|hone|od)|kindle.
May need to duplicate @cache to @cache-mobile, both adding the line of the user_agent match, only one of the named matchers will return valid. But this is not elegant.

1 Like

I have not looked into it, maybe it’s easy indeed. The main issue, these plugins are premium, paid options so we can’t easily try them.

thx. How about W3 total cache?

I forgot you could have the same setting with W3 Total Cache.

Can you try this setup and let us know if it works ?

domain.com {
    # Change the path here according to your setup
	root * /var/www/domain.com
	encode zstd gzip
	file_server

    @cache {
		not header_regexp Cookie "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in"
		not path_regexp "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(index)?.xml|[a-z0-9-]+-sitemap([0-9]+)?.xml)"
		not method POST
		not expression {query} != ''
	 }

     route @cache {
        try_files /wp-content/cache/page_enhanced/{host}{uri}/_index_ssl.html /wp-content/cache/page_enhanced/{host}{uri}/_index.html {path} {path}/index.php?{query}
     }

   # Change the path here according to your server
    php_fastcgi unix//run/php/php7.4-fpm.sock
}

I’m not sure the syntax is correct for non SSL files (or even if they exist ?). And I noticed the nginx configuration is more complicated than that : Setup W3 Total Cache (W3TC) on NGINX – John Dugan

If you could try that and let us know if something is missing or broken, it would be great. :slight_smile: Once we have a confirmed working setup, I’ll update the first post with it.

I have an nginx.conf file created by W3TC. Can you translate this too?

I think it would be a perfect example if you translate this.

# BEGIN W3TC Browser Cache
gzip on;
gzip_types text/css text/x-component application/x-javascript application/javascript text/javascript text/x-js text/richtext text/plain text/xsd text/xsl text/xml image/bmp application/java application/msword application/vnd.ms-fontobject application/x-msdownload image/x-icon application/json application/vnd.ms-access video/webm application/vnd.ms-project application/x-font-otf application/vnd.ms-opentype application/vnd.oasis.opendocument.database application/vnd.oasis.opendocument.chart application/vnd.oasis.opendocument.formula application/vnd.oasis.opendocument.graphics application/vnd.oasis.opendocument.spreadsheet application/vnd.oasis.opendocument.text audio/ogg application/pdf application/vnd.ms-powerpoint image/svg+xml application/x-shockwave-flash image/tiff application/x-font-ttf audio/wav application/vnd.ms-write application/font-woff application/font-woff2 application/vnd.ms-excel;
location ~ \.(css|htc|less|js|js2|js3|js4)$ {
    expires 31536000s;
    etag on;
    if_modified_since exact;
    add_header Pragma "public";
    add_header Cache-Control "public";
    add_header X-Powered-By "W3 Total Cache/0.14.1";
    add_header Referrer-Policy "no-referrer-when-downgrade";
    try_files $uri $uri/ /index.php?$args;
}
location ~ \.(html|htm|rtf|rtx|txt|xsd|xsl|xml)$ {
    etag on;
    if_modified_since exact;
    add_header Pragma "public";
    add_header Cache-Control "max-age=3600, public";
    add_header X-Powered-By "W3 Total Cache/0.14.1";
    add_header Referrer-Policy "no-referrer-when-downgrade";
    try_files $uri $uri/ /index.php?$args;
}
location ~ \.(asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|webp|json|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|webm|mpp|_otf|odb|odc|odf|odg|odp|ods|odt|ogg|pdf|png|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|tif|tiff|_ttf|wav|wma|wri|xla|xls|xlsx|xlt|xlw|zip)$ {
    etag on;
    if_modified_since exact;
    add_header Pragma "public";
    add_header Cache-Control "max-age=31536000, public";
    add_header X-Powered-By "W3 Total Cache/0.14.1";
    add_header Referrer-Policy "no-referrer-when-downgrade";
    try_files $uri $uri/ /index.php?$args;
}
add_header Referrer-Policy "no-referrer-when-downgrade";
# END W3TC Browser Cache
# BEGIN W3TC Minify core
rewrite ^/wp-content/cache/minify/ /index.php last;
# END W3TC Minify core

@nicolinux In the Cache Enabler sample, do you know of a way to serve precompressed gz since it have generated those too?

When I’ve tried the last comment with text/html type for HTML files, I got a garbage characters:

You’ll have to give more detail about that. Please open a new help thread instead and fill out the template. Every problem is different.

A post was split to a new topic: WP Performance from Apache

Here’s what I’ve been using for

WP-Rocket

	@cache {
		not header_regexp Cookie "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in" 
		not path_regexp "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(index)?.xml|[a-z0-9-]+-sitemap([0-9]+)?.xml)"
		not method POST
		not expression {query} != ''
    }

route @cache {
    try_files /wp-content/cache/wp-rocket/{host}{uri}/index-https.html /wp-content/cache/wp-rocket/{host}{uri}/index.html {path} {path}/index.php?{query}
}

} 

I have that in an include/import and just plop it into any server block that uses Wordpress (another block) and php-fpm (I have a couple different php blocks for different server blocks).

2 Likes

2 posts were split to a new topic: Precompressed files for WordPress