5

I have recently migrated our home site to ASP.NET Core 1.0. This allowed me to move website in linux environment. We also have /blog under this site which is a wordpress blog. All migrated properly except W3 Total Cache. Here is what I did.

Installed PHP-FPM and DNX both are behind reverse proxy on Nginx. Here is folder hierarchy. /var/www/aspnet /var/www/wordpress

Here are all Nginx related config files

/etc/nginx/nginx.conf

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    log_format scripts '$document_root$fastcgi_script_name > $request';
    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;

}

/etc/nginx/sites-available/xyz.com

server {
    listen 443 ssl http2;
    server_name xyz.com www.xyz.com;
    ssl_certificate /etc/ssl/certs/cert_chain.crt;
    ssl_certificate_key /etc/ssl/private/xyz.private.txt;   
    access_log /var/log/nginx/scripts.log scripts;

    # Global restrictions configuration file.
    # Designed to be included in any server {} block.
    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

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

    # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
    # Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
    location ~ /\. {
        deny all;
    }

    # Deny access to any files with a .php extension in the uploads directory
    # Works in sub-directory installs and also in multisite network
    # Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
    location ~* /blog/(?:uploads|files)/.*\.php$ {
        deny all;
    }

    gzip_types text/css text/x-component application/x-javascript application/javascript text/javascript text/x-js text/richtext image/svg+xml text/plain text/xsd text/xsl text/xml image/x-icon;
    location ~ ^/blog/\.(css|htc|less|js|js2|js3|js4)$ {
        expires 31536000s;
        add_header Pragma "public";
        add_header Cache-Control "max-age=31536000, public";
    }
    location ~ \.(html|htm|rtf|rtx|svg|svgz|txt|xsd|xsl|xml)$ {
        expires 3600s;
        add_header Pragma "public";
        add_header Cache-Control "max-age=3600, public";
    }
    location ~ \.(asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|json|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|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|ttc|wav|wma|wri|woff|xla|xls|xlsx|xlt|xlw|zip)$ {
        expires 31536000s;
        add_header Pragma "public";
        add_header Cache-Control "max-age=31536000, public";
    }
    location / {
        proxy_pass http://unix:/var/www/aspnet/kestrel.sock;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection keep-alive;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_cache_bypass $http_upgrade;
    }
    location /phpmyadmin/ {
        alias /var/www/phpMyAdmin/;
        index index.php;
    }

    location ~ ^/phpmyadmin/(.+\.php)$ {

        alias /var/www/phpMyAdmin/$1;
        fastcgi_pass   unix:/run/php/phpmyadmin.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $request_filename;

        # From fastcgi_params
        fastcgi_param  QUERY_STRING       $query_string;
        fastcgi_param  REQUEST_METHOD     $request_method;
        fastcgi_param  CONTENT_TYPE       $content_type;
        fastcgi_param  CONTENT_LENGTH     $content_length;
        fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
        fastcgi_param  REQUEST_URI        $request_uri;
        fastcgi_param  DOCUMENT_URI       $document_uri;
        fastcgi_param  DOCUMENT_ROOT      /var/www/phpMyAdmin;
        fastcgi_param  SERVER_PROTOCOL    $server_protocol;
        fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
        fastcgi_param  REMOTE_ADDR        $remote_addr;
        fastcgi_param  REMOTE_PORT        $remote_port;
        fastcgi_param  SERVER_ADDR        $server_addr;
        fastcgi_param  SERVER_PORT        $server_port;
        fastcgi_param  SERVER_NAME        $server_name;
        fastcgi_param  REDIRECT_STATUS    200;
    }

    location /blog/ {           
        try_files $uri $uri/ index.php?q=$request_uri;
        alias /var/www/wordpress/;
        index index.php;                        
    }   

    location ~ \.php$ {             
        include /var/www/wordpress/nginx.conf;
        try_files $uri $uri/ index.php?q=$request_uri =404;
        alias /var/www/wordpress/$1;
        fastcgi_pass   unix:/run/php/phpmyadmin.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;


        # From fastcgi_params
        fastcgi_param  QUERY_STRING       $query_string;
        fastcgi_param  REQUEST_METHOD     $request_method;
        fastcgi_param  CONTENT_TYPE       $content_type;
        fastcgi_param  CONTENT_LENGTH     $content_length;
        fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
        fastcgi_param  REQUEST_URI        $request_uri;
        fastcgi_param  DOCUMENT_URI       $document_uri;
        fastcgi_param  DOCUMENT_ROOT      /var/www/wordpress;
        fastcgi_param  SERVER_PROTOCOL    $server_protocol;
        fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
        fastcgi_param  REMOTE_ADDR        $remote_addr;
        fastcgi_param  REMOTE_PORT        $remote_port;
        fastcgi_param  SERVER_ADDR        $server_addr;
        fastcgi_param  SERVER_PORT        $server_port;
        fastcgi_param  SERVER_NAME        $server_name;
        fastcgi_param  REDIRECT_STATUS    200;          
    }
}

/var/www/wordpress/nginx.conf - This is the file generated by W3 Total Cache plugin.

# BEGIN W3TC Page Cache core
set $w3tc_rewrite 1;
if ($request_method = POST) {
    set $w3tc_rewrite 0;
}
if ($query_string != "") {
    set $w3tc_rewrite 0;
}
if ($request_uri !~ \/$) {
    set $w3tc_rewrite 0;
}
if ($http_cookie ~* "(comment_author|wp\-postpass|w3tc_logged_out|wordpress_logged_in|wptouch_switch_toggle)") {
    set $w3tc_rewrite 0;
}
if ($http_cookie ~* "(w3tc_preview)") {
    set $w3tc_rewrite _preview;
}
set $w3tc_ssl "";
if ($scheme = https) {
    set $w3tc_ssl _ssl;
}
set $w3tc_enc "";
if ($http_accept_encoding ~ gzip) {
    set $w3tc_enc _gzip;
}
set $w3tc_ext "";
if (-f "$document_root/var/www/wordpress/wp-content/cache/page_enhanced/$http_host/$request_uri/_index$w3tc_ssl$w3tc_rewrite.html$w3tc_enc") {
    set $w3tc_ext .html;
}
if (-f "$document_root/var/www/wordpress/wp-content/cache/page_enhanced/$http_host/$request_uri/_index$w3tc_ssl$w3tc_rewrite.xml$w3tc_enc") {
    set $w3tc_ext .xml;
}
if ($w3tc_ext = "") {
  set $w3tc_rewrite 0;
}
if ($w3tc_rewrite = 1) {
    rewrite .* "/var/www/wordpress/wp-content/cache/page_enhanced/$http_host/$request_uri/_index$w3tc_ssl$w3tc_rewrite$w3tc_ext$w3tc_enc" last;
}
# END W3TC Page Cache core

Once I have done above configuration. I am able to run permalinks of wordpress. However when I open /blog/ or /blog/wp-admin/ it shows not found. For troubleshooting purpose I added some custom logging in nginx as follows.

log_format scripts '$document_root$fastcgi_script_name > $request';

Here is what logs showed

/var/www/wordpress//blog/wp-admin/index.php > GET /blog/wp-admin/index.php HTTP/2.0 /var/www/wordpress//blog/index.php > GET /blog/ HTTP/2.0

I tried many solution. All of them assume that parent site would be wordpress. In my case parent site is built on DotNet Core 1. /blog is my wordpress blog. The issue must be one of the wrong rewrite rules.

To summarise the issue, I W3 Total Cache is not an issue. I can live without that. The issue on hand is regarding rewriting rules when you host a wordpress site as a subdomain to a static site. One can ignore W3 total cache configuration part. I have hosted site like mydomain.com/blog and rewriting rules are not getting applied. I tried many alternatives as of now. If somebody has implemented Wordpress as a pure subdirectory and not multisite subdirectory. They can provide their successful configuration.

  • What does the nginx error log say about that 404 error exactly? – JayMcTee Apr 11 '16 at 10:46
  • 2016/04/11 06:58:49 [error] 15843#15843: *2 "/var/www/wordpress/how-to-make-wordpress-work-with-dnx/index.php" is not found (2: No such file or directory), client: x.x.x.x, server: example.org, request: "GET /blog/how-to-make-wordpress-work-with-dnx/ HTTP/2.0", host: "www.example.org", referrer: "example.org/blog" – Chintan Shah Apr 11 '16 at 11:03
  • Remove W3 total cache and remove that configuration from above. Show us a CURL of the root of the wordpress site, with the full applicable entry from the nginx access, error, and php logs. Not abbreviated entries, full entries. – Tim Apr 14 '16 at 19:12
  • @ChintanShah this question has been bumped to the home page because no answer was selected. Could you please mark the most helpful answer as the solution. – Tim Aug 31 '17 at 0:54
1

This doesn't directly answer your question, but is probably a better option you may not have considered. Instead of using a plugin to do caching, using Nginx page caching. It's much faster because you don't have to make a call to PHP, which eliminates a lot of overhead.

The downside is it's tricky to invalidate the Nginx cache unless you pay for the commercial version of Nginx. You can build Nginx with plugins that do the job, but the Wordpress / Nginx caching integration is not great. None I've found work well. So you need to set your cache maximum life carefully. Interestingly, on a busy site caching for even a few seconds can have benefits. My sites change rarely, and if I need to I can just rm -rf the correct directories where the nginx page cache lives - which is actually in memory.

I have a tutorial on this here, and there will be many others around. There's a great article on Nginx microcaching here.

SF likes actual data on the page in case websites disappear.

In your nginx.conf

fastcgi_cache_key "$scheme$request_method$host$request_uri";

At the top of your site file, or in your nginx config

fastcgi_cache_path /dev/shm/nginxcache levels=1:2 keys_zone=CACHENAME:10m inactive=1440m; # Centos / Amazon Linux in RAM, 1440 minutes = 24 hours

In your location block that calls PHP

fastcgi_pass php56-fpm;
include        fastcgi_params;
fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;

fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
fastcgi_cache CACHENAME;
fastcgi_cache_valid 200 1440m;
fastcgi_cache_valid 403 404 405 410 414 301 302 307 60m;
add_header X-Cache $upstream_cache_status; # This can be removed if desired

fastcgi_cache_methods GET HEAD;
fastcgi_keep_conn on;

That tutorial I linked to has a lot more information and explanation.

  • As you pointed out, Nginx has better caching performance. I am using nginx's caching only. It's the plugin which creates static files on disk and serves it. This eliminates invalidation issue and also gets performance of nginx level caching. My main issue here is url rewriting rules. If I get that correct. All will be good. – Chintan Shah Apr 14 '16 at 5:02
  • You don't need to create static files on disk, nginx will cache the php output. You may just need to do a little header rewriting to make sure nginx will cache it. My point is W3 total cache isn't at all necessary, and you're going to a lot of trouble for what on the surface seems like no real gain. – Tim Apr 14 '16 at 5:31
  • Even if I remove plugin my problem is not solved. The problem is only related to rewriting rules. – Chintan Shah Apr 14 '16 at 12:01
  • Please edit your question to be a little more clear, or expand on the problem a bit more. If W3 isn't important perhaps note that. Please put in actual Nginx access and error logs, logs for PHP if applicable, not just parts of it. – Tim Apr 14 '16 at 18:03
  • I have summarized a bit more for clarification. Hope that helps. – Chintan Shah Apr 14 '16 at 18:15
0

You need a few steps along the way to fix the issue (from the current situation)...

In the filesystem...

See: https://codex.wordpress.org/Giving_WordPress_Its_Own_Directory

  1. Move WordPress core files from /var/www/wordpress to /var/www/wordpress/blog. (Hint: mv /var/www/wordpress /var/www/blog && mkdir /var/www/wordpress && mv /var/www/blog /var/www/wordpress)

  2. Copy /var/www/wordpress/blog/index.php to the directory /var/www/wordpress/.

  3. Edit the /var/www/wordpress/index.php file and change the line require( dirname( __FILE__ ) . '/wp-blog-header.php' ); to require( dirname( __FILE__ ) . '/blog/wp-blog-header.php' );.

Nginx:

Now, the Nginx part. Here are the changes in the relevant part/s...

location /blog {           
    root /var/www/wordpress;
    index index.php;
    try_files $uri $uri/ /blog/index.php?q=$request_uri;                        
}   

location ~ \.php$ {             
    root /var/www/wordpress;
    index index.php;
    try_files $uri $uri/ /blog/index.php?q=$request_uri =404;

    # other configuration directives
}

There are two primary changes:

  1. The alias directive becomes root
  2. The try_files directive contains /blog/ before index.php.

I hope this helps!

  • Tried this solution, It didn't worked. It shows same 404 error. – Chintan Shah Apr 21 '16 at 3:03
  • Strange. It worked on a test site/s. Sorry. I couldn't help further. – Pothi Kalimuthu Apr 21 '16 at 14:44

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.