0

I'm trying to set up a new local development server and instead of Apache I've decided to go with nginx.

What I'd like to do is have each WordPress site live within its own directory inside /usr/share/nginx/www. The sites are only going to available on our local network. So for example:

/usr/share/nginx/www/ourcompanywebsite -> http://192.168.2.250/ourcompanywebsite

/usr/share/nginx/www/firstclientwebsite -> http://192.168.2.250/firstclientwebsite

/usr/share/nginx/www/secondclientwebsite -> http://192.168.2.250/secondclientwebsite

/usr/share/nginx/www/sitefortestingthings -> http://192.168.2.250/sitefortestingthings

Getting that setup is fairly trivial. In fact, I've got it working just fine. The problem is that pretty permalinks do not work. Unfortunately I don't know enough about nginx to make this happen.

Here's my current nginx sites-enabled/default.conf file. Please excuse any obvious amateur mistakes; I really cannot stress how little I know about setting up nginx.

server {
    listen 80;
    listen [::]:80 default ipv6only=on;

    root /usr/share/nginx/www;
    index index.php index.html index.htm;

    location / {
        auth_basic "You shall not pass!";
        auth_basic_user_file /home/mojo/src/config/nginx/htpasswd;
        try_files $uri $uri/ /index.html;
    }

    location /doc {
        root /usr/share;
        autoindex on;
        allow 127.0.0.1;
        deny all;
    }

    location /images {
        root /usr/share;
        autoindex off;
    }

    error_page 500 502 503 504 /50x.html;

    location = /50x.html {
        root /usr/share/nginx/www;
    }

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }
}

I've seen guides on how to setup pretty permalinks with nginx but they all seem to assume that you'll just have one site or that your separate sites are on separate domains.

So, is the setup I want possible? If so, what do I need to do to make it happen? If not, or if it's a really bad idea, then what is a similar setup that lets me have multiple WordPress installs with pretty permalinks? Any other useful tips that might improve my configuration are appreciated.

Worst case scenario I can go back to Apache (where I had my desired setup working), but I'd rather figure this out.

2
  • I have not done a similar set up. But, this try_files $uri $uri/ /index.html; should be try_files $uri $uri/ /index.php; for any traditional WordPress setups. Commented Feb 17, 2012 at 12:57
  • Hi, I tested the scenario you mentioned on Nginx on one of my spare domains (please let me know if you'd like to see the sites in that domain). The permalinks work fine with the change I mentioned in the above comment. So, I'm posting it as an answer with an explanation too. Commented Feb 17, 2012 at 13:38

3 Answers 3

1

For the multiple sites to work you need to give each a separate server entry. Think of it the same way Apache vhosts work.

You need to specify a document root and server name for each domain or use the $host alias. It is also a good idea to create a hosts file entry on your local machine to correspond with each domain name so this: http://192.168.2.250/ourcompanywebsite would become: http://ourcompanywebsite

Example server file loaded via an include from nginx.conf

server {
    listen 80;
    server_name ourcompanywebsite firstclientwebsite secondclientwebsite;       
    root /usr/share/nginx/www/$host;
    error_log /var/log/nginx/error.log;

    include global.restrictions.conf;
    include global-wp.conf;
}

global-wp.conf

   #The section below contains your WordPress rewrite rules.
   location / {
          try_files $uri $uri/ /index.php?q=$uri&$args;
    }

  fastcgi_intercept_errors off;
  location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
    expires max;
    add_header Pragma public;
    add_header Cache-Control "public, must-revalidate, proxy-revalidate";
 }

location ~ \.php {
    try_files $uri =404; #This line closes a big security hole
                         #see: http://forum.nginx.org/read.php?2,88845,page=3
    fastcgi_index index.php;
    include fastcgi_params;

    fastcgi_pass 127.0.0.1:9000;
}    

global.restrictions.conf

# Global restrictions configuration file.
# Designed to be included in any server {} block.</p>
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).
location ~ /\. {
    deny all;
    access_log off;
    log_not_found off;
}

For more detailed information on a complete Nginx with WordPress setup see my tutorial: WordPress Performance Server – Debian “squeeze” with Nginx, APC and PHP from the Dotdeb repos

*Note: Nginx with php-fpm is much better performance wise than using Apache as a backend proxy unless you have a huge list of 301 and 302 redirects.

0

On your "location /" block

try_files $uri $uri/ /index.html;

The try_files directive does not pass certain WP specific files to PHP-FPM. So, to make the permalink work, the "location /" should have either of the following code...

try_files $uri $uri/ /index.php;

or

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

BTW, Nginx can work very well with Apache as backend. To let Apache work as backend, please change the port (and/or IP) that Apache listens to (example 81 at 127.0.0.1) and then use the following code to pass all dynamic content to Apache (including permalinks).

location ~* \.(css|js|jpg|png|gif|xml|ico) {
   root /path/to/standard/wordpress/installation;
   expires 31d;
}

location / {
   proxy_pass http://127.0.0.1:81;
}

For more details, please check out Nginx on WordPress Codex or WordPress on Nginx wiki.

0

Try this, I faced a similar issue:

set $dir "";

if ($request_uri ~ ^/([^/]*)/.*$ ) {
    set $dir1 /$1;
}

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

Explanation:

As each WordPress installation is inside a directory, we match the directory name as pass it to try_files. If you had written for each installation manually it'd look something like this:

location /firstclientwebsite/ {
    try_files $uri $uri/  firstclientwebsite/index.php?$args;
}
2
  • While this solution may work, it doesn't provide any insight into what the issue actually was or how this code addresses it. Please take a moment to review the "How to Answer" page in our help center :)
    – bosco
    Commented Jun 4, 2018 at 7:22
  • @bosco answer updated
    – Pradeep
    Commented Jun 4, 2018 at 13:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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