Search code examples
nginxlaravelurl-rewritingfastcgihhvm

NGINX rewrite with Laravel and HHVM


New to nginx and running into some problems with rewrites.

I have a website that is linked to a subdomain test.mydomain.com. My current nginx config:

server {
    listen 80 default_server;

    root /test/public;
    index index.html index.htm index.php;

    server_name localhost;

    access_log /var/log/nginx/localhost.laravel-access.log;
    error_log  /var/log/nginx/locahost.laravel-error.log error;

    charset utf-8;

    location /admin/ {
        alias /test/public/admin/public/;
        try_files $uri $uri/ /admin/index.php?$query_string;
    }

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { log_not_found off; access_log off; }
    location = /robots.txt  { log_not_found off; access_log off; }

    error_page 404 /index.php;      

    include hhvm.conf;  # The HHVM Magic Here

    # Deny .htaccess file access
    location ~ /\.ht {
        deny all;
    }
}

Below is the content of the (default) hhvm.conf

location ~ \.(hh|php)$ {
    fastcgi_keep_conn on;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

I visit test.mydomain.com and everything works perfectly fine. However! I also have an admin panel on test.mydomain.com/admin. All requests to test.mydomain.com/admin/* should be rewritten to /test/public/admin/public/*, instead with my current configuration they are all rewritten to public/index.

My folder structure looks a bit like this:

/test
    /admin
        project.stuff
        /public
            index.php
            etc.php
    /public
        index.php
        etc.php

MAJOR EDIT

I added the following conditional to my hhvm.conf:

if ($request_uri ~* /admin) {
    root /test/admin/public;
}

/admin requests now get rewritten accordingly. The nginx docs state that if two location patterns match, only the most simple one will be used (sort-of). All that remains now is getting this to work with not only .hh and .php files but with asset files (js, css, jpg etc) as well.

I thought something similar would suffice but sadly it doesn't:

location ~ \.(js|css)$ {
    if ($request_uri ~* /admin) {
        root /test/admin/public;
    }
}

Solution

  • This part applies to the initial edition of the question

    root directive can be used inside location {}, so in your case the configuration might look like this:

    server {
        listen 80 default_server;
        server_name localhost;
        index index.html index.htm index.php;
        try_files $uri $uri/ =404;
        ...
    
        location / {
            root /test/public;
            ...
        }
    
        location /admin/ {
            root /test;
            ...
        }
    }
    

    http://nginx.org/en/docs/http/ngx_http_core_module.html#root

    Minor update:

    I have replaced try_files $uri $uri/ index.php?$query_string; with try_files $uri $uri/ =404 as it seems more logical for me, considering index index.html index.htm index.php is here.


    This part applies to the second major edition of the question

    This is correct version of the configuration based on information you provided so far:

    server {
        listen 80 default_server;
        server_name localhost;
    
        root /test/public;
        index index.html index.htm index.php;
        ...
    
        location / {
            try_files $uri $uri/ /index.php?$query_string;
            ...
        }
    
        location /admin/ {
            alias /test/public/admin/public/;
            try_files $uri $uri/ /admin/index.php?$query_string;
            ...
        }
    }
    

    However, based on your statement that after you moved root into locations your regular site stopped working, it can be concluded that you have not provided all needed information, and there is something else wrong in your configuration, that's why I asked you to append to your question your complete nginx configuration, it will make life much easier for both of us...


    This part applies to the third major edition of the question

    This should finally work for you:

    server {
        listen 80 default_server;
    
        root /test/public;
        index index.html index.htm index.php;
    
        server_name localhost;
    
        access_log /var/log/nginx/localhost.laravel-access.log;
        error_log  /var/log/nginx/locahost.laravel-error.log error;
    
        charset utf-8;
    
        location /admin/ {
            alias /test/admin/public/;
            try_files $uri $uri/ /admin/index.php?$query_string;
            include hhvm.conf;
        }
    
        location / {
            try_files $uri $uri/ /index.php?$query_string;
            include hhvm.conf;
        }
    
        location = /favicon.ico { log_not_found off; access_log off; }
        location = /robots.txt  { log_not_found off; access_log off; }
    
        error_page 404 /index.php;
    
        # Deny .htaccess file access
        location ~ /\.ht {
            deny all;
        }
    }
    

    UPDATE

    Probably you also need to replace in the hhvm.conf file and in the fastcgi_params file this line:

    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    

    with the following:

    fastcgi_param  SCRIPT_FILENAME $request_filename;