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 any other answers on Server Fault.

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