Skip to content

Instantly share code, notes, and snippets.

@tsolar
Last active February 5, 2025 05:29
Show Gist options
  • Save tsolar/8d45ed05bcff8eb75404 to your computer and use it in GitHub Desktop.
Save tsolar/8d45ed05bcff8eb75404 to your computer and use it in GitHub Desktop.
Laravel in subdirectory nginx example
server {
client_body_in_file_only clean;
client_body_buffer_size 32K;
client_max_body_size 300M;
sendfile on;
send_timeout 300s;
# Port that the web server will listen on.
#listen 80;
# Host that will serve this project.
server_name tsolar.com;
# Useful logs for debug.
access_log /var/log/nginx/tsolar.com-access.log;
error_log /var/log/nginx/tsolar.com-error.log;
rewrite_log on;
# The location of our projects public directory.
root /home/tom/public_html/demos/;
# Point index to the Laravel front controller.
index index.php;
location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
access_log off;
expires max;
}
location / {
# URLs to attempt, including pretty ones.
try_files $uri $uri/ /index.php?q=$uri&$args;
}
# Remove trailing slash to please routing system.
if (!-d $request_filename) {
rewrite ^/(.+)/$ /$1 permanent;
}
# version 1
location ^~ /demo1 {
alias /home/tom/public_html/demos/demo1/public;
try_files $uri $uri/ @demo1;
location ~* \.php {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(.*)$;
include /etc/nginx/fastcgi_params;
}
}
location @demo1 {
rewrite ^/demo1/(.*)$ /demo1/index.php/$1 last; # THIS IS THE IMPORTANT LINE
}
# end version 1
# version 2
# this is with `ln -s /home/tom/public_html/demos/demo1/public <document root>/demo1`
location ~ /demo1 {
try_files /demo1/$uri /demo1/$uri/ /demo1/index.php?q=$uri&$args;
}
# end version 2
# PHP FPM configuration.
location ~* \.php$ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
include /etc/nginx/fastcgi_params;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# We don't need .ht files with nginx.
location ~ /\.ht {
deny all;
}
# Set header expirations on per-project basis
location ~* \.(?:ico|css|js|jpe?g|JPG|png|svg|woff)$ {
expires 365d;
}
}
@SuryaElite
Copy link

I have done that by using below configuration and its working. The above mentioned gist was displaying 404 "Not Found".

  # sub_directory
  location ^~ /sub_directory {  
      alias /var/www/choppies/sub_directory/public;  
      try_files $uri $uri/ @sub_directory;  

      location ~ \.php {  
          include snippets/fastcgi-php.conf;
          fastcgi_pass unix:/run/php/php7.0-fpm.sock; 
          fastcgi_param SCRIPT_FILENAME /var/www/choppies/sub_directory/public/index.php;
      }  
  }  

  location @sub_directory {
      rewrite /sub_directory/(.*)$ /sub_directory/index.php?/$1 last;  
  }
  # end sub_directory

@ucandoit1010
Copy link

@SuryaElite
thank you for your example ! my website is working now !

@CreativeWolf
Copy link

Heya, I tried this, the application works as such, but the routes aren't still pointing to the base directory.

Example:
https://dev.example.com/isms/ - This points to the application correctly

I have this code in the view

<li class="nav-item"><a class="nav-link" href="/about">About</a></li>

and this code in the web.php for the route

Route::get('/about', function () {
        return view('pages.about');
});

When I hover on the browser, instead of pointing to https://dev.example.com/isms/about it points to https://dev.example.com/about

Appreciate any pointers in fixing this.

Thanks

@Loetfi
Copy link

Loetfi commented Oct 27, 2018

good reference

@subtronic
Copy link

@CreativeWolf, for the set link in view, set name for the route and use global function route().
Route::get('/about', function () { return view('pages.about'); })->name('about-page');
And in the view
<li class="nav-item"><a class="nav-link" href="{{route('about-page')}}">About</a></li>

@legoheld
Copy link

legoheld commented Mar 3, 2020

I had one small annoying issue with # version 1:

rewrite ^/demo1/(.*)$ /demo1/index.php/$1 last; # THIS IS THE IMPORTANT LINE

will always pass the matched path in the regex as a query argument to the index.php.
But in laravel this will always add the path as a query string like this: /demo/my/test

// in laravel
url()->full()
// returns 
/demo/my/test?%2Fmy%2Ftest

The laravel index.php does not need the path as an argument. It looks on the Server Request_URI for the path information.
So a routing like this should be enough:

// if you include fastcgi_params;
rewrite ^/demo1/(.*)$ /demo1/index.php last;

// or if you dont have fastcgi_params included
rewrite ^/demo1/(.*)$ /demo1/index.php?$query_string last;

@Verron
Copy link

Verron commented Jul 6, 2020

I had one small annoying issue with # version 1:

rewrite ^/demo1/(.*)$ /demo1/index.php/$1 last; # THIS IS THE IMPORTANT LINE

will always pass the matched path in the regex as a query argument to the index.php.
But in laravel this will always add the path as a query string like this: /demo/my/test

// in laravel
url()->full()
// returns 
/demo/my/test?%2Fmy%2Ftest

The laravel index.php does not need the path as an argument. It looks on the Server Request_URI for the path information.
So a routing like this should be enough:

// if you include fastcgi_params;
rewrite ^/demo1/(.*)$ /demo1/index.php last;

// or if you dont have fastcgi_params included
rewrite ^/demo1/(.*)$ /demo1/index.php?$query_string last;

This comment is so underrated. Just to explain the difference between having the ? and not, fastcgi_params adds a QUERY_STRING for you and it is set to the $query_string variable (found in $_SERVER if you're using PHP), so if you use it, you don't need index.php?. In my case, I was using index.php?/$1 from a serversforhackers.com guide.

Also, make sure the APP_URL has your subdirectory in the path so your url functions like assets/url work properly. My nginx config just in case it helps someone. I am using laravel homestead with a pretty complex app with multiple sub applications.

listen 80;
listen 443 ssl http2;
server_name .example.test;
root "/home/vagrant/code/";

index index.html index.htm index.php;

charset utf-8;

location /app1 {
    alias /home/vagrant/app1/public;
    access_log /var/log/nginx/example.test.app1-access.log;
    error_log /var/log/nginx/example.test.app1-error.log error;

    try_files $uri $uri/ @app1;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $request_filename;
    }
}

location @app1 {
    rewrite /app1/(.*)$ /app1/index.php last; # Remove ?/$1 since fastcgi_params adds query string
}

location /app2 {
    alias /home/vagrant/app2/public;
    access_log /var/log/nginx/example.test.app2-access.log;
    error_log /var/log/nginx/example.test.app2-error.log error;

    try_files $uri $uri/ @app2;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $request_filename;
    }
}

location @app2 {
    rewrite /app2/(.*)$ /app2/index.php last; # Remove ?/$1 since fastcgi_params adds query string
}

# Redirect all other traffic to app1
location / {
    rewrite ^/(.*) /app1/$1 permanent;
}

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

access_log /var/log/nginx/example.test-access.log;
error_log  /var/log/nginx/example.test-error.log error;

sendfile off;

location ~ /\.ht {
    deny all;
}

ssl_certificate     /etc/nginx/ssl/example.test.crt;
ssl_certificate_key /etc/nginx/ssl/example.test.key;

@japita-se
Copy link

@Verron
I get
rewrite or internal redirection cycle while internally redirecting to "/index.php",

@ggalvez92
Copy link

I have done that by using below configuration and its working. The above mentioned gist was displaying 404 "Not Found".

  # sub_directory
  location ^~ /sub_directory {  
      alias /var/www/choppies/sub_directory/public;  
      try_files $uri $uri/ @sub_directory;  

      location ~ \.php {  
          include snippets/fastcgi-php.conf;
          fastcgi_pass unix:/run/php/php7.0-fpm.sock; 
          fastcgi_param SCRIPT_FILENAME /var/www/choppies/sub_directory/public/index.php;
      }  
  }  

  location @sub_directory {
      rewrite /sub_directory/(.*)$ /sub_directory/index.php?/$1 last;  
  }
  # end sub_directory

It worked perfectly :) thanks you so much

@n0099
Copy link

n0099 commented Jun 8, 2023

You might need an extra line

fastcgi_param  HTTP_PROXY "";

in the location .php { block to mitigate https://httpoxy.org vulnerabilities.

@jamel3oy
Copy link

thanks you so much

@wangdachui2060
Copy link

wangdachui2060 commented Jan 15, 2024

@Verron
Works For me ,
Laravel 10

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;

    root /var/www/html/v2api;
    index index.php index.html;


    location /v2api {
        alias /var/www/html/v2api/public/;
        try_files $uri $uri/  @v2api;

        # location ~* ^/v2api/(.*\.php)$  {
        location ~ \.php$  {
            # fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_split_path_info ^(.+\.php)(/.*)$;
            fastcgi_param  PATH_INFO $fastcgi_path_info;

            fastcgi_pass v2api:9001;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $request_filename;
            # fastcgi_param SCRIPT_FILENAME $request_filename;
            # include fastcgi_params;
        }
    }

    location @v2api {
        rewrite /v2api/(.*)$ /v2api/index.php last;
    }

    location / {
        try_files $uri $uri/ /index.php?s=$uri&$args;
    }

    location ~ \.php {
       add_header 'Access-Control-Allow-Origin' $allow_origin;
       add_header 'e-flag' $allow_origin;
       add_header 'Access-Control-Allow-Credentials' 'true';
       add_header Access-Control-Allow-Methods 'PUT,DELETE,GET, POST, OPTIONS';
       add_header Access-Control-Allow-Headers 'DNT,XO,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';


       if ($request_method = 'OPTIONS') {
         return 204;
       }
        fastcgi_pass v1api:9000;
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
        fastcgi_buffer_size 64k;
        fastcgi_buffers 4 64k;
        fastcgi_busy_buffers_size 128k;
        fastcgi_temp_file_write_size 256k;

        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

qapi/api/uptime?a=b

"REQUEST_URI": "/qapi/api/uptime?a=b",
"QUERY_STRING": "a=b",

@susanBuck
Copy link

susanBuck commented Feb 16, 2024

The following config worked for me. Here's a video of it in action: Run Laravel via subdirectories on a Nginx server

server {
    listen 80;
    listen [::]:80;
    server_name yourdomain.com;

    root /var/www/main/public;

    index index.php index.html;

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

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location /admin {
 
        alias /var/www/admin/public;

        try_files $uri $uri/ @admin;

        location ~ \.php$ {
            fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME /var/www/admin/public/index.php;
        }
    }

    location @admin {
        # Take any requests that start with /admin/ and rewrite them to /admin/index.php (Laravel’s front controller)
        rewrite /admin/(.*)$ /admin/index.php last;
    }

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

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

    error_page 404 /index.php;
    charset utf-8;
}

@dhanyn10singapay
Copy link

I have done that by using below configuration and its working. The above mentioned gist was displaying 404 "Not Found".

  # sub_directory
  location ^~ /sub_directory {  
      alias /var/www/choppies/sub_directory/public;  
      try_files $uri $uri/ @sub_directory;  

      location ~ \.php {  
          include snippets/fastcgi-php.conf;
          fastcgi_pass unix:/run/php/php7.0-fpm.sock; 
          fastcgi_param SCRIPT_FILENAME /var/www/choppies/sub_directory/public/index.php;
      }  
  }  

  location @sub_directory {
      rewrite /sub_directory/(.*)$ /sub_directory/index.php?/$1 last;  
  }
  # end sub_directory

worked for me, thanks @SuryaElite

@phrfpeixoto
Copy link

As of Aug'24, this worked for me:

server {
    listen       443;
    server_name  www.example.com example.com;

    charset utf-8;

    root /var/www/www.example.com;
    access_log /var/log/nginx/ssl-access.log;
    error_log /var/log/nginx/ssl-error.log;
    rewrite_log on;

    # development settings
    client_max_body_size 50M;
    fastcgi_buffers 8 1600k;
    fastcgi_buffer_size 3200k;
    fastcgi_connect_timeout 300s;
    fastcgi_send_timeout 300s;
    fastcgi_read_timeout 300s;

    ssl on;
    ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem; # managed by Certbot
    include snippets/ssl-params.conf;

    location ~ /.well-known {
        allow all;
    }

    location ^~ /laravel {
        alias /application/laravel/public;
        access_log /var/log/nginx/laravel-access.log;
        error_log /var/log/nginx/laravel-error.log error;

        try_files $uri $uri/ @laravel;

        location ~ \.php$ {
            fastcgi_split_path_info ^\/laravel\/((?U).+\.php)(.*)$;
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param HTTP_PROXY "";
            fastcgi_param SCRIPT_FILENAME /app/public/$fastcgi_script_name;
            fastcgi_param SCRIPT_NAME /laravel/$fastcgi_script_name;
        }
    }

    location @laravel {
        rewrite /laravel/(.*)$ /laravel/index.php last; # Remove ?/$1 since fastcgi_params adds query string
    }

    ... other stuff for my website ...
}

I had to adapt the examples posted by other users because the FPM daemon is running within a docker container, but nginx is not
And nginx does need access to the files to serve them, hence:

  • The need to use an alias where the app files are present.
  • The need to set the container path (/app) on the SCRIPT_FILENAME fastcgi_param

@jinyancool
Copy link

nfiguration and its working. The above mentioned gist was dis

Using this config, npm run build not working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment