Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nginx with multiple sites in subfolders

Tags:

nginx

I'd like to configure Nginx in such way that I need minimal amount of efforts to add new sites.

I see this in the following way: when creating new site I put it in subfolder under /var/www, add new location in nginx config file which just includes config template for required site type. It can look like this:

server 
{
  listen 80;
  server_name localhost;
  root /var/www;        

  location /site1
  {
    include drupal.conf;
  }

  location /site2
  {
    include wordpress.conf;
  }
}

But, unfortunately, this doesn't work in my case. The issue is with nested locations. I have the following lines in one of included templates:

...

location  /core/ 
{
  deny all;
}

location / 
{
  try_files $uri $uri/ @rewrite;
}

....

Nginx gives me the following errors:

location "/core/" is outside location "/site1" in ...

location "/" is outside location "/site1" in ...

So I need to specify full path for each site (like /site1/core/), but then I will not be able to extract it as one reusable piece.

Previously, as alternative, I configured multiple server directives with different server_name (site1.locahost, site2.localhost ...) and edited /etc/hosts file. In this case I didn't need nested locations as long as everything was under the root of domain. But, as I said, I'm looking for a way to simplify the workflow as much as possible and editing /etc/hosts seems to me like extra action which I' like to avoid.

So the question is how to best handle this situations? How do you organize work on different sites locally?

like image 200
Stas S Avatar asked Jul 15 '13 21:07

Stas S


1 Answers

At home and at work I use a combination of Bind9 and Nginx to solve this problem. It does require some setup, but once it's up you shouldn't ever need to touch your nginx config file again. I've added some limitations at the bottom.

Setup

Setup a DNS Server, (Bind9, dnsmasq)

1) Setup a local DNS server, and create a host called DEV 2) Create a A name entry in DEV for

* A 127.0.0.1

And restart your DNS server. 3) Make sure you can dig *.dev and verify that you get back 127.0.0.1.

Setup Nginx

1) In your nginx.conf or wherever you're storing your conf.d stuff, create a vHost entry that looks more or less like this: you can adapt it to your needs.

server {
    listen   80;
    server_name *.dev;
    access_log  /var/log/nginx/access.log;
    error_log   /var/log/nginx/error.log;

    if ($host ~* ^(.*).dev$) {
        set $site $1;
    }

    if (!-d /var/www/$site/) {
        return 404;
    }

     location ~ index.php$ {
        fastcgi_split_path_info ^(.+\.php)(.*)$;
        fastcgi_pass   backend;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  /var/www/$site/$fastcgi_script_name;
        include 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_intercept_errors        on;
        fastcgi_ignore_client_abort     off;
        fastcgi_connect_timeout 60;
        fastcgi_send_timeout 180;
        fastcgi_read_timeout 180;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 256k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
    }

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

2) Restart nginx service.

3) Profit


Once this is setup, to create a new site all you have to do is create a new folder in /var/www/.

mkdir -p /var/www/sitename/

That site, and the PHP underneath it can be accessed via sitename.dev.

As stated earlier, there are a couple limitations with this. sitename has to be all lower case, and contain no spaces or special characters (periods included). Secondly, it really only works for sites that are bootstrapped through index.php.

If you have radically different site structures, you can modify a couple of things to give you a more robust setup. For example you could write your config out so that it looked something like this.

server {
    listen   80;
    server_name *.*.dev;

    [...]

    if ($host ~* ^(.*).(.*).dev$) {
        set $site $1;
        set $folder $2;
    }

    if (!-d /var/www/$folder/$site/) {
        return 404;
    }

    [...]
        fastcgi_param  SCRIPT_FILENAME  /var/www/$folder/$site/$fastcgi_script_name;
    [...]

}

And assuming you update your dns server to response to ..dev, then you could write our directories as follows, just to give you an idea.

/var/www/wordpress/site1
/var/www/wordpress/site2
/var/www/wordpress/site3

/var/www/zend/site1
/var/www/zend/site2
/var/www/zend/site3

Like I said earlier, I use this setup at home and at work with +15 people. Our work setup is a little more complex (shared server, everyone has their own home folder), but it works just fine there. Personally I prefer working on subdomains rather than localhost paths.

Hope this helps!

like image 68
Charles R. Portwood II Avatar answered Nov 15 '22 22:11

Charles R. Portwood II