Nginx — disable aggressive caching for WordPress admin areas

PKHunter asked:

I have a fully Nginx install now, with PHP-FPM. Coming from a world of Apache with Nginx proxying in front.

It seems Nginx has its own moody caching, very aggressive. There are a few layers of caching:

  1. Nginx’s fastcgi cache itself. In my nginx.conf I have the following settings:

    fastcgi_cache_path        /var/run/nginx-cache  levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;
    fastcgi_cache_key         "$scheme$request_method$host$request_uri";
    fastcgi_cache_use_stale   error timeout invalid_header http_500;
    fastcgi_ignore_headers    Cache-Control Expires Set-Cookie;
  2. THen there’s php opcache. I’ve disabled it for now:

  3. I also have the following skip cache directives in the server blocks:

    set $skip_cache 0;
    # POST requests and urls with a query string should always go to PHP
    if ($request_method = POST) {
            set $skip_cache 1;
    if ($query_string != "") {
            set $skip_cache 1;
    #Don't cache the following URLs
    if ($request_uri ~* "/(wp-login.php|wp-admin|login.php|backend|admin)"){
        set $skip_cache 1;
    #Don't cache if there is a cookie called PHPSESSID
    if ($http_cookie ~* "PHPSESSID"){
        set $skip_cache 1;
    #Don't cache if there is a cookie called wordpress_logged_in_[hash]
    if ($http_cookie ~* "wordpress_logged_in_"){
        set $skip_cache 1;
    # Don't cache uris containing the following segments
    if ($request_uri ~* "cms/|/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
            set $skip_cache 1;
    # For the arc 
    if ($request_uri ~* "site/|/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
            set $skip_cache 1;
    # Don't use the cache for logged in users or recent commenters
    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
            set $skip_cache 1;
  4. Then in the PHP block, I use that skip_cache stuff:

    location ~ \.php$ {
          try_files $uri $uri/ =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
            fastcgi_cache_bypass                $skip_cache;
          fastcgi_no_cache                    $skip_cache;
            fastcgi_cache                       WORDPRESS;
            fastcgi_cache_valid  200 301 302    60m;

Despite all this, my admin screens are so aggressively cached that when I activate a plugin, it shows the older screen. When the plugin was deactivated. Only when I manually refresh the page do I see that the plugin is indeed activated.

What am I missing?

My answer:

That bit of configuration looks familiar. I think it probably came from the WordPress wiki. In any event it’s way overcomplicated, and mostly unnecessary.

I’m going to pull my config from a live WordPress site:

set $fastcgi_nocache "";
if ($http_cookie ~ (comment_author_.*|wordpress_logged_in.*|wp-postpass_.*)) {
    set $fastcgi_nocache "true";
fastcgi_ignore_headers Expires Cache-Control;
fastcgi_hide_header Pragma;
fastcgi_cache_bypass $fastcgi_nocache;
fastcgi_no_cache $fastcgi_nocache;

That’s all. The only thing you really need to check is whether the user has a cookie indicating he’s logged in, left a comment and wanted to be remembered, or entered a post password. Everything else either doesn’t matter or doesn’t apply to WordPress.

View the full question and answer on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.