Forum Replies Created

Viewing 15 replies - 31 through 45 (of 59 total)
  • Thread Starter bigsite

    (@bigsite)

    Thanks.

    It is not an intuitive or a particularly useful change for us. Why was this change made?

    Thread Starter bigsite

    (@bigsite)

    Here is the configuration for multisite subdirectory I’m using for my 3.1 installation:

    # WordPress multisite subdirectory rules.
    # Designed to be included in any server {} block.
    
    # This order might seem weird - this is attempted to match last if rules below fail.
    # https://wiki.nginx.org/HttpCoreModule
    location / {
    	try_files $uri $uri/ /index.php?$args;
    }
    
    # Add trailing slash to */wp-admin requests.
    rewrite /wp-admin$ $scheme://$host$uri/ permanent;
    
    # Directives to send expires headers and turn off 404 error logging.
    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
    	expires 24h;
    	log_not_found off;
    }
    
    # Pass uploaded files to wp-includes/ms-files.php.
    rewrite /files/$ /index.php last;
    
    # For multisite:  Use a caching plugin that creates symlinks to the correct subdirectory structure to get some performance gains.
    set $cachetest "$document_root/wp-content/cache/ms-filemap/${host}${uri}";
    if ($uri ~ /$) {
    	set $cachetest "";
    }
    if (-f $cachetest) {
    	# Rewrites the URI and stops rewrite processing so it doesn't start over and attempt to pass it to the next rule.
    	rewrite ^ /wp-content/cache/ms-filemap/${host}${uri} break;
    }
    
    if ($uri !~ wp-content/plugins) {
    	rewrite /files/(.+)$ /wp-includes/ms-files.php?file=$1 last;
    }
    
    # Uncomment one of the lines below for the appropriate caching plugin (if used).
    include global/wordpress-ms-subdir-wp-super-cache.conf;
    # include global/wordpress-ms-subdir-w3-total-cache.conf;
    
    # Rewrite multisite '.../wp-.*' and '.../*.php'.
    if (!-e $request_filename) {
    	rewrite ^/[_0-9a-zA-Z-]+(/wp-.*) $1 last;
    	rewrite ^/[_0-9a-zA-Z-]+.*(/wp-admin/.*\.php)$ $1 last;
    	rewrite ^/[_0-9a-zA-Z-]+(/.*\.php)$ $1 last;
    }
    
    # Pass all .php files onto a php-fpm/php-fcgi server.
    location ~ \.php$ {
    	# Zero-day exploit defense.
    	# https://forum.nginx.org/read.php?2,88845,page=3
    	# Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
    	# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine.  And then cross your fingers that you won't get hacked.
    	try_files $uri =404;
    
    	fastcgi_split_path_info ^(.+\.php)(/.+)$;
    	include fastcgi_params;
    	fastcgi_index index.php;
    	fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    #	fastcgi_intercept_errors on;
    	fastcgi_pass php;
    }

    Note the one extra rule. And, since I’ve been all over the place with changes, here is nginx.conf:

    # Generic startup file.
    user user {user} {group};
    worker_processes  2;
    
    error_log  /var/log/nginx/error.log;
    pid        /var/run/nginx.pid;
    
    # Keeps the logs free of messages about not being able to bind().
    daemon     off;
    
    events {
    	worker_connections  1024;
    }
    
    http {
    #	rewrite_log on;
    
    	include mime.types;
    	default_type       application/octet-stream;
    	access_log         /var/log/nginx/access.log;
    	sendfile           on;
    #	tcp_nopush         on;
    	keepalive_timeout  3;
    #	tcp_nodelay        on;
    #	gzip               on;
    	client_max_body_size 13m;
    	index              index.php index.html index.htm;
    
    	# Upstream to abstract backend connection(s) for PHP.
    	upstream php {
    		server unix:/tmp/php-fpm.sock;
    #		server 127.0.0.1:9000;
    	}
    
    	include sites-enabled/*;
    }

    And then in ‘sites-enabled’ is a symlink to each file in ‘sites-available’ as discussed at the top of this post. Then, in ‘sites-available/mysite.com.conf’:

    server {
    	server_name *.mysite.com;
    	root /var/www/mysite.com;
    
    	if ($http_host != "mysite.com") {
    		rewrite ^ https://mysite.com$request_uri permanent;
    	}
    
    	include global/restrictions.conf;
    
    	// Additional rules go here.
    
    	include global/wordpress-ms-subdir.conf;
    }

    I haven’t changed the other files.

    For subdomain, I’d start with subdirectory rules above and then tweak using rewrites in the ‘if (!-e $request_filename) { … }’ block and base the rewrites on the .htaccess Apache rules. This approach will work a lot better than redirecting everything to WP.

    Thread Starter bigsite

    (@bigsite)

    @hybridindie – It looks like subdomain is very similar to subdirectory. I do have a few comments though. By dropping a ‘root’ into the configuration, your configuration isn’t generic.

    I’m not sure why fastcgi_split_path_info got commented out and WP doesn’t really utilize that approach anyway, so it probably doesn’t hurt anything.

    Redirecting all 404 errors to WP is probably not a good idea. Invoking the WP engine is a resource utilization cost that should be avoided. I’m thinking you might be missing a rewrite somewhere that could eliminate the 404 handler altogether and revert the exploit defense mechanism back to “try_files $uri =404;”

    I’m starting the 3.1 upgrade process myself, so I’ll post an updated config for subdirectory when I’m done.

    Thread Starter bigsite

    (@bigsite)

    @johnnymestizo – If you could copy and paste both the WP and WP Super Cache rules from an Apache .htaccess file, I’ll give it a whirl. I don’t have any subdomain installs of WP multisite but I know nginx pretty well.

    Thread Starter bigsite

    (@bigsite)

    @sparanoid – That might be your symbolic links kicking in. Don’t do rm -rf in the /cache subdirectory or let any scripts do the same.

    If you are concerned about this, maybe move the symlinks to another directory instead of the /cache directory. Also, of course, keep regular backups.

    Thread Starter bigsite

    (@bigsite)

    @serversreview – These rules are intended for WP Super Cache in ‘mod_rewrite’ mode. If you aren’t running in this mode, you are invoking PHP every page load under nginx. You can certainly run WP Super Cache that way, but it isn’t as efficient. Unless, of course, I misunderstood what you mean.

    Thread Starter bigsite

    (@bigsite)

    @sparanoid – For your first question, it might be your permalink structure choice. For WP Super Cache to work properly, it prefers a “fancy permalink structure”, which I’m not quite sure what that means. I’m not sure how a permalink structure of /%post_id%/ fits into that picture. Using the supplied rules, as a visitor, the URLs without trailing slashes redirects to the correct location for me, which means the visitor is probably hitting WP. To get past that redirect issue using nginx rules, I would change the WP Super Cache rules slightly:

    set $supercacheuri "";
    set $supercachefile "$document_root/wp-content/cache/supercache/${http_host}${uri}/index.html";
    if (-e $supercachefile) {
    	set $supercacheuri "/wp-content/cache/supercache/${http_host}${uri}/index.html";
    }
    
    ...
    
    # Stop processing if the supercache file is valid.
    if ($supercacheuri) {
    	rewrite [^/]$ $scheme://$host$uri/ permanent;
    	rewrite ^ $supercacheuri break;
    }

    That should detect that there is a cache file available with a trailing slash, then detect that the current $uri doesn’t have a trailing slash, and execute a redirect to the correct URL. These changes are untested but should work.

    As to the second question, that is experimental, custom PHP code that requires tweaking for your specific setup. In theory, you should be able to create a new subdirectory on your server inside your WP install, upload a .php file with the code provided above (modified to point at the correct paths), and then run the PHP file using a web browser. It will create symbolic links in the correct place for each blog. The nginx rules will automatically pick this up and start serving images without passing the request to PHP. IMO, you should ask Donncha to add similar functionality to WP Super Cache, because it really makes more sense to be part of a caching plugin and not in some hacky solution. The code provided is just an example.

    Thread Starter bigsite

    (@bigsite)

    One more modification. Most of us know about PHP upload limits, but nginx has its own upload limits as well:

    https://wiki.nginx.org/NginxHttpCoreModule#client_max_body_size

    If you attempt to upload a file that is too large, WordPress displays “HTTP error.” Which is super descriptive. I recommend setting the nginx ‘client_max_body_size’ to something a bit larger than PHP’s ‘post_max_size’ setting, which should be larger than PHP’s ‘upload_max_filesize’ setting. Can be in the ‘http’ block or the ‘server’ block. Depends on your preference where you want it. I just stuffed it into the ‘http’ block.

    http {
    	client_max_body_size 13m;
    ...
    }
    Thread Starter bigsite

    (@bigsite)

    Only slightly related. I needed SCRIPT_URI to be passed to PHP. So I ended up adding:

    fastcgi_param  SCRIPT_URI         $scheme://$host$request_uri;

    To the ‘/etc/nginx/fastcgi_params’ file. Probably not perfect (maybe $scheme://$host$uri instead?), but it’ll work.

    Thread Starter bigsite

    (@bigsite)

    Another minor modification. URLs like https://mysite.com./ will create a new WP Super Cache directory called “mysite.com.” (note the extra ‘.’). The server configuration rules need to be changed to:

    server {
    	server_name *.mysite.com;
    	root /var/www;
    
    	# Redirect everything to mysite.com
    	if ($http_host != "mysite.com") {
    		rewrite ^ https://mysite.com$request_uri permanent;
    	}
    
    	include global/restrictions.conf;
    	include global/wordpress-ms-subdir.conf;
    }

    This is actually a little simpler than the previous file but technically slightly slower due to the ‘if’ statement since ‘if’ is part of the nginx ‘rewrite’ module. If you don’t care about ‘mysite.com.’ (possibly a SEO issue) being redirected or you garbage collect cached files, then the former approach will work just fine.

    Thread Starter bigsite

    (@bigsite)

    Minor correction needed. If you use weird permalinks or use plugins with AJAX callbacks, you might need to modify:

    rewrite ^/[_0-9a-zA-Z-]+(/wp-.*) $1 last;

    To be more like:

    rewrite ^/[_0-9a-zA-Z-]+(/[_0-9a-zA-Z-]+)?(/wp-.*) $2 last;

    OR, what I ended up doing:

    # Rewrite multisite '.../wp-.*' and '.../*.php'.
    if (!-e $request_filename) {
    	rewrite ^/[_0-9a-zA-Z-]+(/wp-.*) $1 last;
    	rewrite ^/[_0-9a-zA-Z-]+.*(/wp-admin/.*\.php)$ $1 last;
    	rewrite ^/[_0-9a-zA-Z-]+(/.*\.php)$ $1 last;
    }

    To handle URLs like:

    https://mywebsite.com/secondblog/archives/wp-admin/admin-ajax.php

    IMO, the latter approach seems cleaner. The only real issue is AJAX, so the second approach solves the problem a bit more cleanly.

    Thread Starter bigsite

    (@bigsite)

    @sparanoid – Getting nginx, php-fpm, APC, and WP Super Cache working together really depends on the environment. If you can get just APC and WP Super Cache working, you are going to see drastic improvements to performance. nginx and php-fpm are only going to add marginal improvement and require a lot more effort to set up than it might be worth.

    APC can be installed in module form (.so) via PECL directly on most Linux hosts. PECL is like PEAR but for extensions to PHP. This post should make installing APC easier:

    https://www.agileapproach.com/blog-entry/howto-install-pecl-apc-cache-centos-without-xampp

    While the PECL approach results in a slightly slower APC build than compiling it directly into the PHP binary, the actual difference is negligible and results in far fewer headaches. Well, fewer headaches as long as it works the during first attempt to compile APC.

    If you are using Mac OS X Server, PECL won’t likely work or won’t generate correct binaries. Apple is always lagging behind anyway with their third-party server software, but you’ll have to drop Apple Apache and Apple PHP if you want to use APC. MacPorts makes it easy to build a version of PHP that works with APC, but you’ll also need to use MacPorts Apache as the version of PHP MacPorts builds will crash Apple Apache for some reason. Building a MacPorts php-fpm is rather difficult at the moment and requires editing portfiles to add a ‘fpm’ “variant” to the PHP build process. MacPorts has a nginx build though that uses the latest source code.

    If you really want to go down the nginx + php-fpm route, these instructions are useful as general-purpose guidelines that you’ll need to adapt to your specific setup:

    https://blogs.sitepoint.com/2010/11/19/lightning-fast-wordpress-with-php-fpm-and-nginx/

    If you build one (nginx or php-fpm), you might as well build the other as they work rather well together. Skip those nginx configuration directions and use the ones here and you probably already have WP installed or know how to do it, so skip those directions too. Building nginx from source is the best way to go because most repositories are generally several versions behind. Building PHP from source with the –enable-fpm option is really the only way to get a php-fpm binary. The “you have to build from source” annoyance will hopefully change in the future.

    Thread Starter bigsite

    (@bigsite)

    You’re welcome! I agree with your position on automation of nginx rules in WP Super Cache. Especially since nginx configurations are usually only able to be modified by the superuser. The easiest way to make sure everything syncs up is to compare the .htaccess rules the plugin generates with the rules in the nginx configuration and then manually make any changes as necessary. The similarities are fairly obvious but documentation on the Rewrite module may help anyone needing them:

    https://wiki.nginx.org/HttpRewriteModule

    I forgot to one thing in my original post. The first two lines of nginx.conf are:

    user {user} {group};
    worker_processes  3;

    The ‘user’ line is the user and group to run the nginx as (e.g. ‘user www-data www-data’). The ‘worker_processes’ line should relate to how many CPUs to occupy/dedicate to nginx. I’m experimenting with 3, but most people set it to 2. Don’t set it to more than the total number of processors available.

    Obviously, this configuration is still a little bit of a work in progress but it does work and is running smoothly on a production server.

    Thread Starter bigsite

    (@bigsite)

    Okay. After reverting to WP Cache 2, the bug is still happening. That rules out WP Super Cache. Of course, I’m now left wondering what one of a dozen things I’ve made changes to caused the issue.

    Thread Starter bigsite

    (@bigsite)

    I’ve just been ordered to revert to WP Cache 2. This bug on our live site is causing numerous issues for Ordinary Joe who is sending e-mail complaints. Sorry, this bug is a critical issue for us. We’ll try it again once it has been permanently squashed.

    We’ve seen the RSS feed issue crop up everywhere, not just the homepage. It seems to happen more frequently when there are momentary spikes in traffic. Seemingly random bugs are the hardest to track down and squash – I know because I’ve been there. I’ll still try to see if I can track down the problem because we really do need static caching.

Viewing 15 replies - 31 through 45 (of 59 total)