Mass virtual hosting and global redirect

Hello everyone! I recently switched my main webserver (where I host
clients’ websites) from apache to nginx and I wrote a custom generic
configuration file to handle everything in one place, so domains and
subdomains are handled on the fly by creating directories and
subdirectories. Here’s the relevant snippet:

server {

    listen                  80 default;

    if ($host ~* ^(.*)\.(.*\..*)$)  {
    set $sub $1;
    set $domain $2;

}

    server_name             _;
    server_name_in_redirect off;
    root                    /var/www/vhosts/$domain/$sub;
    access_log              /var/log/nginx/access.log combined;
    error_log               /var/log/nginx/error.log error;

    include /etc/nginx/conf/wordpress_params;

location / {

    root    /var/www/vhosts/$domain/$sub;
    index   index.php index.html;

Everything works just fine as nginx is a great product :wink: Now, my only
problem lays in the fact I haven’t been able to write a regexp to setup
a global redirect from, eg, domain.com to www.domain.com. Could anyone
help me on this?

Thanks,
Alessio

Posted at Nginx Forum:

On Mon, Jun 15, 2009 at 09:30:47AM -0400, NoSync wrote:

    root    /var/www/vhosts/$domain/$sub;
    index   index.php index.html; 

Everything works just fine as nginx is a great product :wink: Now, my only problem lays in the fact I haven’t been able to write a regexp to setup a global redirect from, eg, domain.com to www.domain.com. Could anyone help me on this?

Use server_name. Instead of

 if ($host ~* ^(.*)\.(.*\..*)$)  {
     set $sub $1;
     set $domain $2;
 }

you may write in 0.7.x

server {
listen 80 default;
server_name ~^(.).(...*)$;
set $sub $1;
set $domain $2;

     ...

}

As to the redirect:

server {
listen 80 default;
server_name _;
rewrite ^ http://www.$host$request_uri?;
}

server {
listen 80 default;
server_name www.*;

}

Thanks Igor. I was thinking about this as well, but while I’d like to
add the www part only if there’s no subdomain at all, I take it this
would prepend the “www” part to any host?

Posted at Nginx Forum:

On Mon, Jun 15, 2009 at 11:23:38AM -0400, NoSync wrote:

Thanks Igor. I was thinking about this as well, but while I’d like to add the www part only if there’s no subdomain at all, I take it this would prepend the “www” part to any host?

I do not understand. Could you show examples of redirects ?

I could be wrong, but with your snippet I’d get domain.com redirected to
www.domain.com, but also sub.domain.com redirected to
www.sub.domain.com. Very possible I’m missing something here, though.
:slight_smile:

Posted at Nginx Forum:

On Mon, Jun 15, 2009 at 12:22:39PM -0400, NoSync wrote:

I could be wrong, but with your snippet I’d get domain.com redirected to www.domain.com, but also sub.domain.com redirected to www.sub.domain.com. Very possible I’m missing something here, though. :slight_smile:

server {
listen 80;
server_name ~^[^.]+.[^.]+$; # domain.com
rewrite ^ http://www.$host$request_uri?;
}

server {
listen 80;
server_name www.*; # www.domain.com
server_name ~^[^.]+.[^.]+.[^.]+$; # sub.domain.com

}

As suggested, I tried using servername in place of the if block:

server_name ~^(.).(...*)$;
set $sub $1;
set $domain $2;

but I get errors like this:

2009/06/16 13:33:20 6443#0: 4 malloc() 18446744073709551612 bytes
failed (12: ), client: 89.96.xxx.xxx, server: ~^(.
).(...)$,
request: “GET / HTTP/1.1”, host: “www.xxxxxxx.eu”
2009/06/16 13:33:24 6443#0: 15 malloc() 18446744073709551612 bytes
failed (12: ), client: 89.96.xxx.xxx, server: ~^(.
).(...)$,
request: “GET / HTTP/1.1”, host: “www.yyyyyyy.it”

while with the previous configuration everything’s fine. Rewrites from
non-www to www are also perfectly working with your regexp (thanks). I’m
using nginx 0.7.51 on Ubuntu Jaunty. I could find some earlier
discussions about similar problems, but my russian ain’t the best
despite some courses I took in the past. :slight_smile:

Posted at Nginx Forum:

On Tue, Jun 16, 2009 at 09:43:24AM -0400, NoSync wrote:

while with the previous configuration everything’s fine. Rewrites from non-www to www are also perfectly working with your regexp (thanks). I’m using nginx 0.7.51 on Ubuntu Jaunty. I could find some earlier discussions about similar problems, but my russian ain’t the best despite some courses I took in the past. :slight_smile:

Could you create debug log of a request ?

There you go:

2009/06/16 14:27:46 6580#0: 21 malloc() 18446744073709551612 bytes
failed (12: ), client: 89.96.xxx.xxx, server: ~^(.
).(...)$,
request: “GET / HTTP/1.1”, host: “www.digitalnatives.eu”

And here’s a strace:

accept(7, {sa_family=AF_INET, sin_port=htons(41325),
sin_addr=inet_addr(“89.96.xxx.xxx”)}, [7899595229974495248]) = 8
ioctl(8, FIONBIO, [1]) = 0
epoll_ctl(10, EPOLL_CTL_ADD, 8, {EPOLLIN|EPOLLET, {u32=7199456,
u64=7199456}}) = 0
epoll_wait(10, {{EPOLLIN, {u32=7199456, u64=7199456}}}, 512, 60000) = 1
gettimeofday({1245162214, 677575}, NULL) = 0
recvfrom(8, “GET / HTTP/1.1\r\nHost: www.digital”…, 1024, 0, NULL,
NULL) = 592
open(“/var/www/vhosts/digitalnatives.eu/www/”, O_RDONLY) = 11
fstat(11, {st_mode=S_IFDIR|0770, st_size=4096, …}) = 0
close(11) = 0
open(“/var/www/vhosts/digitalnatives.eu/www/”, O_RDONLY) = 11
fstat(11, {st_mode=S_IFDIR|0770, st_size=4096, …}) = 0
close(11) = 0
open(“/var/www/vhosts/digitalnatives.eu/www/”, O_RDONLY) = 11
fstat(11, {st_mode=S_IFDIR|0770, st_size=4096, …}) = 0
close(11) = 0
open(“/var/www/vhosts/digitalnatives.eu/www/”, O_RDONLY) = 11
fstat(11, {st_mode=S_IFDIR|0770, st_size=4096, …}) = 0
close(11) = 0
open(“/var/www/vhosts/digitalnatives.eu/www/index.php”, O_RDONLY) = 11
fstat(11, {st_mode=S_IFREG|0674, st_size=397, …}) = 0
write(3, “2009/06/16 14:23:34 6538#”…, 198) = 198
writev(8, [{“HTTP/1.1 500 Internal Server Erro”…, 162}, {“\r\n500
Internal”…, 140}, {“nginx/0.7.51”…, 53}], 3) = 355
write(4, “89.96.100.196 - - [16/Jun/2009:14”…, 200) = 200
close(11) = 0

Nginx gives 500 error, as you can see, while it works perfectly using
the if’s. To be noted, it works perfectly if I try to access any URL
deeper than first level (www.domain.com/something works, www.domain.com
or Domain.com does not).

Posted at Nginx Forum:

On Tue, Jun 16, 2009 at 10:32:03AM -0400, NoSync wrote:

gettimeofday({1245162214, 677575}, NULL) = 0
open(“/var/www/vhosts/digitalnatives.eu/www/”, O_RDONLY) = 11
fstat(11, {st_mode=S_IFDIR|0770, st_size=4096, …}) = 0
close(11) = 0
open(“/var/www/vhosts/digitalnatives.eu/www/index.php”, O_RDONLY) = 11
fstat(11, {st_mode=S_IFREG|0674, st_size=397, …}) = 0
write(3, “2009/06/16 14:23:34 6538#”…, 198) = 198
writev(8, [{“HTTP/1.1 500 Internal Server Erro”…, 162}, {“\r\n500 Internal”…, 140}, {“nginx/0.7.51”…, 53}], 3) = 355
write(4, “89.96.100.196 - - [16/Jun/2009:14”…, 200) = 200
close(11) = 0

Nginx gives 500 error, as you can see, while it works perfectly using the if’s. To be noted, it works perfectly if I try to access any URL deeper than first level (www.domain.com/something works, www.domain.com or Domain.com does not).

No, I meant:

./configure --with-debug …

nginx.conf:

error_log /path/to/log debug;

BTW, nginx tests the same file 4 times, it’s not good.
Could you show configuration ?

This is the whole conf:

nginx.conf:

user www-data;
worker_processes 1;

error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

access_log  /var/log/nginx/access.log;

sendfile on;
tcp_nopush on;
tcp_nodelay off;
keepalive_timeout 3;

gzip on;
gzip_comp_level 1;
gzip_proxied any;
gzip_min_length 1024;
gzip_types text/plain text/css application/x-javascript text/xml
application/xml application/xml+rss text/javascript;

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

}

and this is the enabled server file:

server {
listen 80;
server_name ~^[^.]+.[^.]+$; # domain.com
rewrite ^ http://www.$host$request_uri?;
}

server {
listen 80 default;
server_name ~^(.).(...*)$;
set $sub $1;
set $domain $2;
root /var/www/vhosts/$domain/$sub;
access_log /var/log/nginx/access.log combined;
error_log /var/log/nginx/error.log error;

include /etc/nginx/conf/wordpress_params;

location / {
root /var/www/vhosts/$domain/$sub;
index index.php index.html;

if (-f $request_filename) {
expires 30d;
break;
}

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

location ~* i.+.(css|js|jpg|jpeg|gif|png)$ {
expires 7d;
}

location ~ “^(.+.php)($|/)” {
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
}

location ~ /.ht {
deny all;
}
}

and here’s the wordpress_params file which is also included:

if (-f $request_filename) {
break;
}

set $supercache_file ‘’;

set $supercache_uri $request_uri;

if ($request_method = POST) {
set $supercache_uri ‘’;
}

Using pretty permalinks, so bypass the cache for any query string

if ($query_string) {
set $supercache_uri ‘’;
}

if ($http_cookie ~* “comment_author_|wordpress|wp-postpass_” ) {
set $supercache_uri ‘’;
}

if we have not bypassed the cache, specify our supercache file

if ($supercache_uri ~ ^(.+)$) {
set $supercache_file
/wp-content/cache/supercache/$http_host/$1index.html;
}

only rewrite to the supercache file if it actually exists

if (-f $document_root$supercache_file) {
rewrite ^(.*)$ $supercache_file break;
}

all other requests go to Wordpress

if (!-e $request_filename) {
rewrite . /index.php last;
}

Unfortunately I can’t recompile and install with debug flags right now
as this is a production server. :-/

Posted at Nginx Forum:

On Tue, Jun 16, 2009 at 10:06 PM, NoSync[email protected] wrote:

events {
    tcp_nopush        on;
  include /etc/nginx/sites-enabled/*;
server {
 location / {
        break;
    fastcgi_index  index.php;
break;

Using pretty permalinks, so bypass the cache for any query string

set $supercache_file /wp-content/cache/supercache/$http_host/$1index.html;
}

Unfortunately I can’t recompile and install with debug flags right now as this is a production server. :-/

you can -
just install to different path