Nginx -- disable aggressive caching for Wordpress admin areas

Solution 1:

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.

Solution 2:

The way @MichaelHampton suggested is IMHO best (easiest, most efficient), but here's an alternative / additional approach that may be useful in some situations. It comes from my Wordpress / Nginx tutorial. Some themes mess with caching headers in a really bad way, so I basically want to rewrite all the headers differently for different areas of the website. I also remove the old Pragma header.

I define blocks for specific URLs or subdirectories so I can rate limit or control headers more precisely.

Note that "more_clear_headers" and "add_header" are part of the Headers More Nginx extension. If you look at the tutorial I linked to above, part two, it gives step by step instructions how to build Nginx with that module - it's pretty easy.

# Rate limiting for login pages
limit_req_zone $binary_remote_addr zone=login:1m rate=5r/m;

# Rate limit wp-login.php to help prevent brute force attacks
location = /blog/wp-login.php {
  # Next line applies the rate limit defined above
  limit_req zone=login burst=3;       
  fastcgi_keep_conn on;
  fastcgi_intercept_errors on;
  fastcgi_pass   php;
  include        fastcgi_params;
  fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
  more_clear_headers "Cache-Control";
  more_clear_headers Server; more_clear_headers "Pragma"; more_clear_headers "Expires";

  # No caching
  more_clear_headers "Cache-Control";
  add_header Cache-Control "private, max-age=0, no-cache, no-store";
  more_clear_headers "Expires";

  # Debugging aid - remove
  # add_header Z_LOCATION "WP-LOGIN"; add_header URI $uri;
}

# Wordpress admin caching headers are generally set correctly, for pages and resources. The only reason we define
# this block separately is to avoid messing with the headers in the main php block.
# This is probably unnecessary because of the skip_cache variable and may be removed
location ~* wp-admin {
  fastcgi_keep_conn on;
  fastcgi_intercept_errors on;
  fastcgi_pass   php;
  include        fastcgi_params;
  fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;

  # Debugging aid - remove
  # add_header Z_LOCATION "WP_ADMIN"; add_header URI $uri; add_header "Z_SKIP_CACHE" $skip_cache;
}

To add something else to add to Michael's answer, I also use this block. It disables caching for Wordpress Admin in a second way, and also disables caching for feeds, sitemap, xmlrpc, and a few others. Part of it's for Wordpress, I suspect part of it's for a custom written PHP website I run.

if ($request_uri ~* "/wp-admin/|/admin-*|/purge*|/xmlrpc.php|wp-.*.php|/feed/|sitemap(_index)?.xml|wp-cron") {
  set $fastcgi_nocache "true";
}