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;
    }
}
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 ~^(?<subdomain>.+)\.domain\.com$; if (!-d /var/www/domain.com/subdomains/$subdomain/www) {rewrite . domain.com redirect;} root /var/www/domain.com/subdomains/$subdomain/www;
    – cyberx86
    Nov 21, 2011 at 5:36
  • You can make this into an answer, it's easier to read and understand at the same time.
    – Lewis
    Nov 21, 2011 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, 2011 at 13:16

1 Answer 1

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.

8
  • 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, 2011 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, 2011 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, 2011 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, 2011 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, 2011 at 17:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .