Setup: Wordpress with WordFence on Nginx with FastCGI enabled + PHP7.0 with opcache enabled (validate timestamps is false)

Story: With the above setup and confirmed that both FastCGI has HTML cached and PHP Opcache have all PHP files cached or so I assume (it has files but maybe missing some?) when I change the source files (Like mistakenly gzip each file - Oops!) the site goes down. In theory should the site not continue to send the cached files?

As I mentioned above ever so slightly I mistakenly gzip each file and the response from the server was 403 error, which makes sense because gz files are not accessible! But it seemed like it was trying to call something from source. Even more, as I ran the command to unzip everything, the site was still coming back online but was still throwing errors as some files had not been unzipped yet. It just seemed like the system is pulling from source and not cache? After the files unzipped I checked hits on PHP files in cache and confirmed the system is hitting cache.

So again, MAIN Question - Why did the site go down instead of defaulting to cache? If source files were not available but in cache it seemed to not request them or maybe checked if source still existed (even with validate timestamp set to false).


# Global settings

        index index.htm index.html index.php;

        gzip on;
        gzip_disable "msie6";

        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_min_length 256;
        gzip_types text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;

# Global Security settings

server {
        listen         80;
        listen         [::]:80;
        listen 443 ssl http2;
        listen [::]:443 ssl http2;

    # Force all HTTP to HTTPS
        server_name    _;
        return         301 https://$host$request_uri;



fastcgi_cache_path /var/cache/html levels=1:2 keys_zone=FASTCGICACHE:500m inactive=10080m;
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;

map $uri $blogname{
    ~^(?P<blogpath>/[^/]+/)files/(.*)       $blogpath ;

# redirect non-www to www
server {
    server_name example.com;
    return 301 $scheme://www.example.com$request_uri;
server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 1h;
    ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
    ssl_prefer_server_ciphers on;
    ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DHE+AES128:!ADH:!AECDH:!MD5;
    server_tokens off;
    ssl_dhparam /etc/ssl/certs/dhparams.pem; #Need to run openssl dhparam -out dhparams.pem 4096

    ##buffer policy
    # proxy_buffering on;
    # proxy_buffer_size 1k;
    # proxy_buffers 24 4k;
    # proxy_busy_buffers_size 8k;
    # proxy_max_temp_file_size 2048m;
    # proxy_temp_file_write_size 32k;
    ##end buffer policy

    server_name *.example.com;
    root /pat/to/files/;

    client_max_body_size 1000m;
    add_header Strict-Transport-Security "max-age=15768000" always;
    add_header X-XSS-Protection "1; mode=block";

    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 uris containing the following segments
    if ($request_uri ~* "/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;

    location / {
                try_files $uri $uri/ /index.php?$args;

    location ~ \.php$ {
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
                fastcgi_index index.php;
                include fastcgi.conf;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
        fastcgi_cache FASTCGICACHE;
        fastcgi_cache_valid 10080m;
        add_header X-FastCGI-Cache $upstream_cache_status;

    if (!-e $request_filename) {
        rewrite /wp-admin$ $scheme://$host$uri/ permanent;
        rewrite ^(/[^/]+)?(/wp-.*) $2 last;
        rewrite ^(/[^/]+)?(/.*\.php) $2 last;

        # Restrict access to System Status files
        location ^~ /secure-some-files/ {
                auth_basic "Site Administrator's Area";
                auth_basic_user_file /etc/nginx/.htpasswd;
                fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        location ~ /\.ht {
                deny  all;

        location ~* \.(?:css|gif|ico|jpeg|jpg|js|png)$ {
        expires max;
        add_header Pragma public;
        add_header Cache-Control "public";
        log_not_found off;

        # Deny access to sensitive extensions
        location ~\.(ini|log|conf)$ {
                deny all;

        location = /favicon.ico { log_not_found off; access_log off; allow all; }
        location = /robots.txt { log_not_found off; access_log off; allow all; }

    # Deny access to uploads that aren�t images, videos, music, etc.
    location ~* ^/wp-content/uploads/.*.(html|htm|shtml|php|js|swf)$ {
        deny all;

        # Deny public access to wp-config.php
        location ~* wp-config.php {
                deny all;

    ssl_certificate /path/to/pem/fullchain.pem; # managed by Certbot
    ssl_certificate_key /path/to/pem//privkey.pem; # managed by Certbot



listen = /var/run/php-fpm/php-fpm.sock
listen.owner = ec2-user
listen.group = ec2-user
listen.mode = 0664
user = ec2-user
group = ec2-user

Headers when site loads correctly

Request URL: https://www.example.com/
Request Method: GET
Status Code: 200 
Remote Address: XX.XXX.XXX.XXX:443
Referrer Policy: no-referrer-when-downgrade

*Response Header*
content-encoding: gzip
content-type: text/html; charset=UTF-8
date: Thu, 03 Jan 2019 09:34:54 GMT
link: <https://www.example.com/wp-json/>; rel="https://api.w.org/"
link: <https://www.example.com/>; rel=shortlink
server: nginx
status: 200
vary: Accept-Encoding
x-fastcgi-cache: HIT
x-powered-by: PHP/7.0.32

*Request Header*
:authority: www.example.com
:method: GET
:path: /
:scheme: https
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
cache-control: no-cache
cookie: {deleted} ; wp-settings-1=libraryContent%3Dbrowse%26advImgDetails%3Dshow%26editor%3Dhtml%26editor_expand%3Don; wp-settings-time-1=1542639953; {deleted}; PHPSESSID={deleted}; wordpress_test_cookie=WP+Cookie+check; _gat_gtag_UA_{deleted}_1=1; nQ_visitId={deleted}
pragma: no-cache
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Mobile Safari/537.36
  • Check your error log. Jan 3, 2019 at 14:14
  • That is the upsetting part. I had updated Nginx a week or so before and that had broken logging errors. I found that out the hard way! I fixed that issue because of the issue above and needing to figure out why we were getting 403 errors.
    – Kalman
    Jan 8, 2019 at 13:32


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.