5

I'm trying to create subdomains with my web application, however, I'm not experienced in nginx that much, I've been trying to find a stable solution from SF, but unfortunately I can't find any good solution.

The problem I'm trying to do is create flexible subdomains, for example if I have any subdomain like dev.example.com it should go along the file directory of /var/www/example.com/www/dev, and any type of subdomain (except the WWW) will attempt to find a directory, if it exists, make it the root.

/var/www/example.com/www/{subdomain}

Is the current directory to look for, if it doesn't exists, the default root would be:

/var/www/example.com/www/

This is my sites-enabled configuration file for my domain.

server {

    server_name     example.com www.example.com;
    root            /var/www/example.com/www;
    index           index.php index.htm index.html;
    error_page      404 /404.html;
    error_page      500 502 503 504  /50x.html;

    access_log      /var/www/example.com/logs/access.log;
    error_log       /var/www/example.com/logs/errors.log;

    error_page 404 /index.php;

    location ~ \.php$
    {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /var/www/example.com/www$fastcgi_script_name;
        include fastcgi_params;
    }

    location /pma {
        auth_basic            "Website development";
        auth_basic_user_file  /var/www/example.com/www/dev/authfile;
    }

    location /dev {
        auth_basic            "Website development";
        auth_basic_user_file  /var/www/example.com/www/dev/authfile;
    }

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

server {

    server_name     pma.example.com;
    index           index.php;
    root            /var/www/example.com/www/pma;

    access_log      /var/www/example.com/logs/access.log;
    error_log       /var/www/example.com/logs/errors.log;

    location ~ \.php$
    {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /var/www/example.com/www$fastcgi_script_name;
        include fastcgi_params;
    }

    location / {
        auth_basic            "Website development";
        auth_basic_user_file  /var/www/example.com/www/dev/authfile;
    }
}

server {

    server_name     dev.example.com;
    index           index.php;
    root            /var/www/example.com/www/dev;

    access_log      /var/www/example.com/logs/access.log;
    error_log       /var/www/example.com/logs/errors.log;

    location ~ \.php$
    {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /var/www/example.com/www$fastcgi_script_name;
        include fastcgi_params;
    }

    location / {
        auth_basic            "Website development";
        auth_basic_user_file  /var/www/example.com/www/dev/authfile;

        if ($request_uri ~* ^(/home(/index)?|/index(.php)?)/?$)
        {
            rewrite ^(.*)$ / permanent;
        }

        if ($host ~* ^www\.(.*))
        {
            set $host_without_www $1;
            rewrite ^/(.*)$ $scheme://$host_without_www/$1 permanent;
        }

        if ($request_uri ~* index/?$)
        {
            rewrite ^/(.*)/index/?$ /$1 permanent;
        }

        if (!-d $request_filename)
        {
            rewrite ^/(.+)/$ /$1 permanent;
        }

        if ($request_uri ~* ^/system)
        {
            rewrite ^/(.*)$ /index.php?/$1 last;
            break;
        }

        if (!-e $request_filename)
        {
            rewrite ^/(.*)$ /index.php?/$1 last;
            break;
        }
    }

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

EDIT: Updated conf file:

server {

    #regex capture assigning the subdomain to $subdomain
    server_name ~^(?<subdomain>.+)\.example\.com$;

    if ($host ~* ^www\.(.*)) {
        set $remove_www $1;
        rewrite ^(.*)$ http://$remove_www$1 permanent;
    }

    #if the directory doesn't exist, redirect to the main site
    if (!-d /var/www/example.com/www/$subdomain) {
        rewrite . example.com redirect;
    }

    #if we have made it here, set the root to the above directory
    root /var/www/example.com/www/$subdomain;

    #the rest of your config
    index           index.php;
    access_log      /var/www/example.com/logs/access.log;
    error_log       /var/www/example.com/logs/errors.log;

    location ~ \.php$
    {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /var/www/example.com/$subdomain$fastcgi_script_name;
        include fastcgi_params;
    }

    # this needs to be enabled for dev.example.com and pma.example.com only
    location / {
        auth_basic            "Authentication Required";
        auth_basic_user_file  /var/www/example.com/$subdomain/authfile;
    }

    location ~ /\.ht{
        deny all;
    }
}
Joel Coel
  • 12,932
  • 14
  • 62
  • 100
Lewis
  • 51
  • 1
  • 3
  • You can create 'flexible subdomains' by using named regex captures in your server_name, but only if the subdomains are configured the same (i.e. only a few paths change). If you have very different rules for each subdomain (e.g. your dev and pma subdomains have different rewrites) you will have have to note the differences manually. Also consider putting your subdomains above your main web root. server_name ~^(?.+)\.domain\.com$; if (!-d /var/www/domain.com/subdomains/$subdomain/www) {rewrite . http://www.domain.com/ redirect;} root /var/www/domain.com/subdomains/$subdomain/www; – cyberx86 Nov 21 '11 at 05:36
  • You can make this into an answer, it's easier to read and understand at the same time. – Lewis Nov 21 '11 at 12:39
  • Well, I had meant it more as a suggestion for a possible implementation, since I wasn't quite how different your subdomains would be (or how automated their creation was to be). I've added a bit more detail in my answer. – cyberx86 Nov 21 '11 at 13:16

1 Answers1

1

If you are looking for automatic subdomains, based on a standard template (e.g. a subdomain for every user) you can use regular expression captures in your server_name directive. This approach will allow you to assign part of the server_name to a variable for use elsewhere in your configuration (e.g. to set a path).

It is generally good practice to put 'real' subdomains above the web root, to better separate the sites (and it has the advantage of preventing access via the main site), and to prevent ambiguity as to whether or not a directory maps to a subdomain or not. For example, consider the following path for the root of your 'dev' subdomain: /var/www/example.com/subdomains/dev/www. This would also let you maintain separate logs for your dev site, e.g. /var/www/example.com/subdomains/dev/logs).

The example below uses your pma subdomain as a template, and keeps the subdomain root under the main site.

server{
    #regex capture assigning the subdomain to $subdomain
    server_name ~^(?<subdomain>.+)\.example\.com$;

    #if the directory doesn't exist, redirect to the main site
    if (!-d /var/www/example.com/www/$subdomain) {
        rewrite . example.com redirect;
    }

    #if we have made it here, set the root to the above directory
    root /var/www/example.com/www/$subdomain;

    #the rest of your config
    index           index.php;
    access_log      /var/www/example.com/logs/access.log;
    error_log       /var/www/example.com/logs/errors.log;

    location ~ \.php$
    {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /var/www/domain.com/$subdomain$fastcgi_script_name;
        include fastcgi_params;
    }

    location / {
        auth_basic            "Authentication Required";
        auth_basic_user_file  /var/www/example.com/$subdomain/authfile;
    }

    location ~ /\.ht{
        deny all;
    }

}

The above idea only really works if all the subdomains are going to follow the same template. In the configuration you have posted, the pma subdomain and the dev subdomain are substantially different (in that the dev subdomain has many rewrites that the pma one does not). Any subdomains that do not follow the 'template' you are using, will need their own server block and config. It is worth mentioning that in the case of two server blocks being applicable (e.g. one with a static server_name and one with a regex server_name), the static server_name will take precedence.

Joel Coel
  • 12,932
  • 14
  • 62
  • 100
cyberx86
  • 20,805
  • 1
  • 62
  • 81
  • But I need to have multiple subdomains, I won't able to put `dev` and `pma` in it at the same time? – Lewis Nov 21 '11 at 17:08
  • Any server blocks with a static (i.e. explicitly stated) server_name will take precedence over the regex. So you can use the example above for your 'automatic' subdomains, and also create additional server blocks for your dev and pma subdomains. – cyberx86 Nov 21 '11 at 17:13
  • Okay... I got an error when trying to restart nginx: `Restarting nginx: nginx: [emerg] pcre_compile() failed: unrecognized character after (? or (?- in "^(?dev.+)\.domain\.com$" at "dev.+)\.domain\.com$" in /etc/nginx/sites-enabled/domain.com:4`. – Lewis Nov 21 '11 at 17:24
  • Don't put your static subdomains in regular expressions. Just keep them as `server_name dev.domain.com;` for those. Essentially, add the above server block to your original configuration. The example I posted is to capture an unknown/arbitrary subdomain - one where you don't know the subdomain at the time you configure nginx. It will figure out the matching subdomain from the pattern, and set a variable to it. – cyberx86 Nov 21 '11 at 17:45
  • Okay, I only want `dev` and `pma` to have the authencation, whereas the root `domain.com` to have no authencation nor other subdomains, how do I do this? – Lewis Nov 21 '11 at 17:54
  • Remove the `location / {...}` block from the example above to not have authentication on the automatic subdomains. Your previous config doesn't have authentication on the main site (domain.com), so you don't have to change anything there. – cyberx86 Nov 21 '11 at 18:02
  • You got me confused a bit, I'm using your conf file and I don't have the previous config, except the one in my post, but it's replaced with the latest one I have (see my edit). – Lewis Nov 21 '11 at 18:21
  • Sorry - I don't think I was quite clear. The config above is ONLY for automatic subdomains. All additional subdomains need to be specified in their own server block. So, you should have all 3 server blocks from your original configuration (for the main site, your dev and pma subdomains), and also the server block I provided (modified with your changes - e.g. removing authentication) - for a total of 4 server blocks. Your original ones will handle your main site, and 2 subdomains; the one from my example will handle the 'flexible' subdomains your app uses. – cyberx86 Nov 21 '11 at 18:25