11

I am trying to setup my development nginx/PHP server with a basic master/catch-all vhost config so that I can created unlimited ___.framework.loc domains as needed.

server {
        listen 80;
        index index.html index.htm index.php;

        # Test 1
        server_name ~^(.+)\.frameworks\.loc$;
        set $file_path $1;
        root    /var/www/frameworks/$file_path/public;

        include /etc/nginx/php.conf;
}

However, nginx responds with a 404 error for this setup. I know nginx and PHP are working and have permission because the localhost config I'm using works fine.

server {
        listen 80 default;
        server_name localhost;
        root /var/www/localhost;
        index index.html index.htm index.php;

        include /etc/nginx/php.conf;
}

What should I be checking to find the problem? Here is a copy of that php.conf they are both loading.

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

location ~ \.php$ {

        try_files $uri =404;

        include fastcgi_params;
        fastcgi_index index.php;

        # Keep these parameters for compatibility with old PHP scripts using them.
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        # Some default config
        fastcgi_connect_timeout        20;
        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;
        fastcgi_intercept_errors    on;
        fastcgi_ignore_client_abort off;
        fastcgi_pass 127.0.0.1:9000;

}
12

Why not just use:

server_name *.frameworks.loc;
root /var/www/frameworks/$http_host/public;
| improve this answer | |
  • This is just what I was looking for! – Xeoncross Dec 22 '12 at 18:28
13
+50

Nginx config is not a program, it's a declaration. When you are using config like this:

server {
        server_name ~^(.+)\.frameworks\.loc$;
        ...
        set $file_path $1;
        root    /var/www/frameworks/$file_path/public;
}

There's no way to ensure that your set directive will execute before root.

But there's a trick with map directive I like to use. It relies on fact that map is evaluated before location

http {
  map $http_host $rootpath {
    ~^(.?<mypath>+)\.frameworks\.loc$  $mypath;
    default                            /      ;
  }
  ....
  root /var/www/frameworks/$rootpath
}
| improve this answer | |
  • This looks like fun, I plan on playing more with map now. I also was not aware that the configuration files were not processed in a linear fashion. – Xeoncross Dec 22 '12 at 18:29
  • What's the point of $mypath here? It's not used anywhere. – kodeart Jun 11 '16 at 19:50
  • @kodeart $mypath is the result group for regex ~^(.?<mypath>+)\.frameworks\.loc$ and $rootpath is the result for whole map trick. – Fabio Montefuscolo Jun 14 '16 at 12:50
4

In addition to great DukeLion's answer, I needed to change line

~^(.?<mypath>+)\.frameworks\.loc$ $mypath;

to

~^(?P<mypath>.+)\.frameworks\.loc$ $mypath;

in my /etc/nginx/nginx.conf file as suggested here.

Adding

root /var/www/frameworks/$rootpath

in /etc/nginx/sites-available/default worked fine after that.

| improve this answer | |
0

Maybe you can look into lighttpd also. It has build in support for exactly what you are asking here. It is call mod_evhost.

Enable evhost

Add following lines into your lighttpd.conf. If you are using Debian/Ubuntu base distribution, just soft link or copy from /etc/lighttpd/conf-available/10-evhost.conf to /etc/lighttpd/conf-enabled/.

    # http://redmine.lighttpd.net/wiki/1/Docs:ModEVhost
    server.modules += ( "mod_evhost" )
    evhost.path-pattern = "/home/www/%_"

The %_ (wildcard) in evhost.path-patten means use the full domain name (eg. www.example.com). A request for www.example.com will automatically direct to document-root /home/www/www.example.com/.

Adding additional site is as easy as creating another directory under /home/www with full domain name. No change to Lighttpd config file.

There are other wildcards and can be used to build directory structure. They are as follow

    %% => % sign
    %0 => domain name + tld
    %1 => tld
    %2 => domain name without tld
    %3 => subdomain 1 name
    %4 => subdomain 2 name
    %_ => full domain name

Detail information is here.

PS: Enabling PHP is also easy if you are on debian/ubuntu platform. Just enable 10-fastcgi.conf and 15-fastcgi-php.conf.

| improve this answer | |
0

NGINX uses the PCRE regular expression library.
As of NGINX v0.8.25 server_name directive allows named captures.

Named captures in regular expressions create variables (0.8.25) that can later be used in other directives While using named parenthesis, NGINX automatically sets a variable for each named parenthesis, during server names evaluation (I guess).

I use the following snippet to "fence" developers environments. «user» refers to their username and «proj» the project they work on:

# ...
server_name ~^(?<user>[^.]+)\.(?<proj>[^.]+).dev.local-server.com;
root /home/$user/www/$proj;
# ...

Note that nginx configuration is declarative, and as such, static declarations might always be faster compared to run-time calculated values and variables. Regular expressions evaluation is relatively costly, I guess it has to be used with parsimony in heavy loaded (production) environments.

| improve this answer | |

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.