Nginx托管应用程序在不同的位置


Nginx to host app in different location

我试图在nginx + php-fpm中在特定位置提供CachetHQ。文档给出了在status.example.com中服务的示例(可以工作):

server {
    listen 80;
    server_name status.example.com;
    root /var/www/Cachet/public;
    index index.php;
    location / {
        try_files $uri /index.php$is_args$args;
    }
    location ~ '.php$ {
         include fastcgi_params;
         fastcgi_pass 127.0.0.1:9000;
         fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
         fastcgi_index index.php;
         fastcgi_keep_conn on;
    }
}

但是,我想在example.com/status服务,而不是在status.example.com服务。

我期待这将工作,但从error.log我看到它正在尝试/etc/nginx/htmlindex.php,但它应该是/mnt/data/site/www-cachet/public/index.php:

location /status/ {
    index index.php;
    root /mnt/data/site/www-cachet/public;
    try_files $uri index.php$is_args$args;
    location ~ ^/status/.+'.php$ {
        root /mnt/data/site/www-cachet/public;
        include fastcgi_params;
        fastcgi_pass   unix:/tmp/php-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_index index.php;
        fastcgi_keep_conn on;
    }
}

让我从您声称有效的原始配置开始,并尝试根据您的需求修改它,结果如下:

location ^~ /status {
    alias /var/www/Cachet/public;
    index index.php;
    location = /status {
        return 302 /status/;
    }
    location / {
        try_files $uri /status/index.php$is_args$args;
    }
    location ~ '.php$ {
         include fastcgi_params;
         fastcgi_pass 127.0.0.1:9000;
         rewrite ^/status/(.*) /$1;
         rewrite ^(.*)/ $1/index.php; # who knows what fastcgi_index is for?
         fastcgi_param SCRIPT_FILENAME $document_root$uri;
         fastcgi_keep_conn on;
    }
}

基本上,您希望在这里使用alias而不是root,并且可能在最终的try_files中也有绝对路径。我不认为在嵌套位置中添加额外的前缀是必要的,但是您可能希望确保根位置与^~修饰符最终匹配。

我想,主要的技巧是,即使使用alias指令,事情也不像使用适当的root那么好,所以,你必须确保SCRIPT_FILENAME设置正确。这部分似乎没有很清楚地记录,我懒得测试$fastcgi_script_name ngx变量和fastcgi_index指令是否与alias发挥良好作用-而不是试图确定这些工作方式(或不),我们只是做了一些适用的rewrite规则,并根据我们重写规则的结果构建SCRIPT_FILENAME。: -)

然而,话虽如此,我认为第二个重写规则(以及它取代的fastcgi_index)也可能是一个no-op,因为如果$uri没有在.php中结束,我们怎么应该在'.php$ location中结束呢?(同样,您也可以自由地尝试删除第一条重写规则,并将SCRIPT_FILENAME中的$uri替换为$fastcgi_script_name,看看事情是否仍然有效,但2009年的互联网可能表明它们没有。)

您的try_files不正确。
你可以这样做:

index index.php;
root /mnt/data/site/www-cachet/public;
location / {
    if (!-e $request_filename) {
        rewrite ^(.*)$ /index.php?$1 last;
        break;
    }
}  
location ~ ^/status/.+'.php$ {
    root /mnt/data/site/www-cachet/public;
    include fastcgi_params;
    fastcgi_pass   unix:/tmp/php-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_index index.php;
    fastcgi_keep_conn on;
}

经过这么长时间的尝试,我得到了它工作的方法是:

location ^~  /status {
    alias /mnt/data/site/www-cachet/public;
    try_files $uri $uri/ @status;
    location = /status/ {
        rewrite /status/$ /status/index.php;
    }
    location ~ ^/status/(.+'.php)$ {
        fastcgi_pass unix:/tmp/php-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /mnt/data/site/www-cachet/public/$1;
        include fastcgi_params;
    }
}
location @status {
    rewrite /status/(.*)$ /status/index.php?/$1 last;
}

最重要的是fastcgi_param,我必须将其设置为绝对路径,而不是$document_root$fastcgi_script_name或类似的东西。我不确定这是否是一个好的做法,但是将alias添加到块中只是不起作用,nginx或FastCGI都没有向我们显示他们试图读取的文件的路径。

然而,我不能得到CachetHQ工作良好。问题是源代码中的所有路径都是绝对的,所以它们不会指向我们的文件所在的子目录。解决方案是做一些我从一开始就不愿意做的事情:将它托管在子域中。