20151029 wp multisite on nginx - plembo/onemoretech GitHub Wiki

title: WP multisite on nginx link: https://onemoretech.wordpress.com/2015/10/29/wp-multisite-on-nginx/ author: phil2nc description: post_id: 10198 created: 2015/10/29 13:58:24 created_gmt: 2015/10/29 17:58:24 comment_status: closed post_name: wp-multisite-on-nginx status: publish post_type: post

WP multisite on nginx

There are a lot of articles out there on how to configure nginx to publish WordPress blogs in multisite mode. All of them are fatally incomplete. What follows is the exception. That's kind of harsh, I know. Actually I did find one article that does a damn good job on this subject: How to configure Nginx for Wordpress Multisite with subdirectories Maybe it's that I wasn't a fan of jigsaw puzzles as a kid, but I've always had a problem with most of what passes for technical documentation due to its incompleteness. Take Nginx on the WordPress Codex, the main article on setting up nginx to work with WordPress. It's not bad, really. I actually like the framework they put together. But, as acknowledged on the page itself, it is misleadingly incomplete when it comes to supporting multisite. What's missing are two critical pieces: 1. A definition for the $blogid variable; and 2. How to get it. These two missing pieces are supplied in How to configure Nginx for Wordpress Multisite with subdirectories, where the author provides an nginx map statement for multisite nginx virtual hosts (called "server blocks" in nginx-speak), and recommends the installation of the Nginx Helper plugin for getting the blog id values for each sub site on a multisite network. Starting from scratch, here's how I set things up on a CentOS 7 server. 1. Install nginx and all WordPress prerequisites (php, mariadb, mariadb-server, etc). 2. Create a database for the WordPress using the mysql client (after properly configuring the database server -- at a minimum running mysql_secure_installation to set a root password and remove sample users and data). 3. Use this /etc/nginx/nginx.conf (basically the default nginx.conf that comes in the package with the addition of an include for "sites-enabled"): [code language="bash" gutter="false"] # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/conf.d/.conf; include /etc/nginx/sites-enabled/.conf; server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /var/www/html; # Load configuration files for the default server block. include /etc/nginx/default.d/.conf; location / { } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } } [/code] 4. Create an /etc/nginx/conf.d/php-fpm.conf file with the following contents: [code language="bash" gutter="false"] upstream php { server 127.0.0.1:9000; } [/code] 5. Create a /etc/nginx/global/restrictions.conf file with these contents (this is verbatim from the WordPress Codex article): [code language="bash" gutter="false"] # 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 ~* /(?:uploads|files)/.\.php$ { deny all; } [/code] 6. Next make this /etc/nginx/global/wp-single.conf file (also verbatim from the Codex): [code language="bash" gutter="false"] # WordPress single site rules. # Designed to be included in any server {} block. # This order might seem weird - this is attempted to match last if rules below fail. # http://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 ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ { access_log off; log_not_found off; expires max; } # Uncomment one of the lines below for the appropriate caching plugin (if used). #include global/wordpress-wp-super-cache.conf; #include global/wordpress-w3-total-cache.conf; # Pass all .php files onto a php-fpm/php-fcgi server. location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+?\.php)(/.)$; if (!-f $document_root$fastcgi_script_name) { return 404; } # This is a robust solution for path info security issue and works with "cgi.fix_pathinfo = 1" in /etc/php.ini (default) include fastcgi.conf; fastcgi_index index.php; # fastcgi_intercept_errors on; fastcgi_pass php; } [/code] 7. Also make this /etc/nginx/global/wp-multi-sf.conf file (verbatim from the Codex): [code language="bash" gutter="false"] # 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. # http://wiki.nginx.org/HttpCoreModule location / { try_files $uri $uri/ /index.php?$args; } # 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; } location ~ ^/[_0-9a-zA-Z-]+/files/(.*)$ { try_files /wp-content/blogs.dir/$blogid/files/$2 /wp-includes/ms-files.php?file=$2 ; access_log off; log_not_found off; expires max; } #avoid php readfile() location ^ /blogs.dir { internal; alias /var/www/example.com/htdocs/wp-content/blogs.dir ; access_log off; log_not_found off; expires max; } # 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 /wp-admin$ $scheme://$host$uri/ permanent; rewrite ^/[_0-9a-zA-Z-]+(/wp-.) $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. # http://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)(/.+)$; #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

Copyright 2004-2019 Phil Lembo