Laravel in a sub-directory using NGINX with preserved routing - laravel

I'm currently trying to install a Laravel app in a sub-directory of a site using nginx to direct any traffic to that app.
I have followed the suggestions in the following Stackoverflow question, and it works perfectly Config nginx for Laravel In a subfolder
However, when using this method it removes the need for the sub-directory to be in the Laravel apps routes.
An example.
Say I am pointing all requests to https://example.com/shop to a /shop subdirectory using the following nginx entry...
location /shop {
alias /var/www/shop/public;
try_files $uri $uri/ #shop;
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
}
location #shop {
rewrite /shop/(.*)$ /shop/index.php last;
}
As stated, this works but the route for the shops "homepage" in the app will actually be
Route::get('/', ShopController::class)->name('shop.home');
Whereas I need it to be
Route::get('/shop', ShopController::class)->name('shop.home');
I don't have control over all the routing etc due to it being in packages, and there are various other reasons why this would be preferable for me anyway.
Is there a way to adapt the above nginx entry to achieve this? I have tried numerous things but can not seem to get it to work.
Thanks in advance.

You need to set dynamicaly and change the fastcgi_param REQUEST_URI $request_url.
Basically to remove or add (depend on your needs) the word /shop from the REQUEST_URI
You may need to remove REQUEST_URI from fastcgi_params file.
More info and example can found in
https://serverfault.com/questions/697569/rewrite-url-with-fastcgi-in-nginx
I didn't tested it so maybe some changes need to made in some lines or change the order of things...
but you can try to use something like
location /shop {
alias /var/www/shop/public;
try_files $uri $uri/ #shop;
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param REQUEST_URI /shop$request_uri;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
}
location #shop {
rewrite /shop/(.*)$ /shop/index.php last;
}

I got this working thanks to a clue from #shushu304
I just updated the REQUEST_URI using the following.
location /shop {
alias /var/www/shop/public;
try_files $uri $uri/ #shop;
location ~ \.php$ {
include fastcgi_params;
fastcgi_param REQUEST_URI /shop$request_uri; <--------
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
}
location #shop {
rewrite /shop/(.*)$ /shop/index.php last;
}

Related

Nested Laravel-inertia-react App using nginx+phpfpm

I'm currently building a server running multiple laravel apps with inertia-vite-react stack, the file structure is like this:
/var/www/app1
/var/www/app2
this is my nginx config:
location /app1 {
alias /var/www/app1/public/;
try_files $uri $uri/ #app1;
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME $request_filename;
include fastcgi_params;
}
}
location #app1 {
rewrite /app1/(.*)$ /app1/index.php?/$1 last;
}
and I'm facing a problem that Inertia(maybe?) keep adding the app1 after the url, like this:
http://localhost:8080/app1 becomes http://localhost:8080/app1/app1
the page renders correctly when I enter http://localhost:8080/app1,
but was changed automatically and returning 404 after I refresh with the changed url. So I'm guessing this is a inertia issue or somewhere wrong with my nginx config.

Nginx and Laravel: How to restrict "location" block to from "/" to "/api"?

I have a Laravel application that I would like to use only for its /api routes. When /, /login, /profile, etc are accessed, I would like nginx to serve the index file located in the base root, /var/www/html/index.html.
Here's my current default.conf. The /api routes work, but it also serves / from the backend, which I don't want.
If I simply change location / to location /api, then the /api routes become inaccessible, and trying to access them returns the index file located in the base root, /var/www/html/index.html. This is the opposite of what I am trying to achieve. Haha.
How can I keep the /api routes accessible, while also preventing / from being served by the backend?
server {
listen 80;
root /var/www/html;
server_name _;
index index.php index.html index.htm;
# API routes should be handled by the backend (Laravel).
##### I want to change the following line from "/" to "/api".
location / {
root /var/www/backend/public;
try_files $uri $uri/ /index.php?$query_string;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_index index.php;
include fastcgi_params;
}
}
}
According to your configuration, that should already be happening.
the directive:
try_files $uri $uri/ /index.php?$query_string;
Will attempt first to locate the static file, and if the static file exists and is not a php file, it will be served by nginx directly. Only if it is a php file will it be served with the php backend.
If you want to prevent .php files from being executed at all, you can modify to separate the / location from the /api location:
location ~ ^/api/.*\.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_index index.php;
include fastcgi_params;
}
I accomplished this, but somewhat inelegantly.
I have 2 location blocks:
location ~ "^(?!/api).*$" matches all routes except those that begin with /api.
location / matches all other routes. The reason that it does not match all routes is simply that nginx matches location blocks with regular expressions first.
Strangely, using a regular expression for the second block to match all routes that do begin with /api did not work. I still don't understand why.
server {
listen 80;
root /var/www/html;
server_name _;
index index.php index.html index.htm;
# All non-API routes should be handled by the frontend.
# Use a regular expression to identify all requests
# that do NOT begin with "/api".
location ~ "^(?!/api).*$" {
root /var/www/frontend/public;
try_files $uri $uri/ /index.html =404;
}
# API routes should be handled by the backend (Laravel).
# (Since regex-based location blocks are matched first,
# this will be a fallback to the above location block).
location / {
root /var/www/backend/public;
try_files $uri $uri/ /index.php?$query_string;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_index index.php;
include fastcgi_params;
}
}
}

Updating nginx config while attempting to invert directory structure

I am trying to flip the directory structure of a PHP app that contains a Laravel sub-app that currently has the following directory structure:
/-
/directory1-
script1.php
/laravel-
/public-
/css-
some-file.css
... other laravel files ...
What I'm trying to do is now flip the "legacy" code in the parent directory into the Laravel application so that the directory structure now looks like this:
/-
/legacy-
/directory1-
script1.php
/public-
/css-
some-file.css
... other laravel files ...
I'm running into difficulty with the nginx configuration, I am able to successfully run the /legacy scripts and load the static public files in Laravel (such as some-file.css above), but none of my Laravel routes are working correctly. This is complicated by the fact that I don't want any of the legacy paths to change (I still want / to go to the now /legacy/index.php) and I want the Laravel app to be prefixed by /laravel (since I have front-end code calling an API at /laravel/api/v1 that I don't want to update just yet).
Here's what I have for the nginx config for the two different locations:
server {
# ...
root /var/www/legacy;
index index.php index.html index.htm;
location ~ \.php$ {
fastcgi_pass php-upstream;
fastcgi_index index.php;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location / {
try_files $uri $uri/ $uri.html $uri.php?$query_string;
}
location /laravel {
fastcgi_index index.php;
include fastcgi_params;
rewrite ^/laravel/public/(.*) /../public/$1;
try_files $uri /../public/index.php?$query_string;
}
}
The error I am getting from nginx is: FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, which I think is talking about the SCRIPT_FILENAME FastCGI param. I tried adding a named location for this, similar to the approach in this answer:
location / {
try_files $uri $uri/ $uri.html $uri.php?$query_string #laravel;
}
location #laravel {
fastcgi_pass php-upstream;
fastcgi_index index.php;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
fastcgi_param SCRIPT_FILENAME /var/www/public/index.php?$query_string;
include fastcgi_params;
}
But this has the same effect. If someone has a solution that will be able to route requests from both /laravel/api/v1/.* and /api/v1/.* to the Laravel app that would also be appreciated.
Assuming the parent directory is www, I think the below config (from this post) will work:
server {
# ...
root /var/www/legacy;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ $uri.html $uri.php?$query_string;
}
location /laravel {
alias /var/www/public;
try_files $uri $uri/ #laravel;
location ~ \.php {
fastcgi_index index.php;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_pass php-upstream;
}
}
location #laravel {
rewrite /laravel/(.*)$ /laravel/index.php?/$1 last;
}
location ~ \.php$ {
fastcgi_index index.php;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass php-upstream;
}
}
To deal with duplicate fastcgi_* declarations, you can either declare them in the server block or copy them in a file and include it, this article explains how inheritance in Nginx works.

Nginx disable url rewrite for specific path / url

I have the following nginx configuration for the url rewrite
location / { ##merge
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location /devtools/phpmyadmin/ { ##merge
root /var/www/domain.tld/web;
location ~ \.php$ {
try_files $uri =404;
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/var/lib/php5-fpm/web2.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors on;
}
}
in the /var/www/domain.tld/web/ directory have an /api/ directory and I want disable for the url rewrite for this. So if I woud like access from url with index.php: http://domain.tld/api/index.php/function/method
How can I modify the nginx config file?
Edit:
I try the following rewrite, but not working:
location = /api {
rewrite ^ /api/index.php;
}
I confess that I do not understand your configuration file. Generally, you would define a root to be inherited by all (or most) of your location blocks. And usually a separate location ~ \.php$ block to handle off-loading .php scripts to a PHP processor via FastCGI.
Ignoring your location /devtools/phpmyadmin/ block for the moment, a typical implementation would look like this:
root /var/www/domain.tld/web;
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~ \.php$ {
try_files $uri =404;
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/var/lib/php5-fpm/web2.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors on;
}
The nginx directives are documented here.
If you want URIs that begin with /api to use a different controller, you could add:
location /api {
try_files $uri $uri/ /api/index.php;
}
I cannot see the purpose of the location /devtools/phpmyadmin/ block, as it does not seem to add any more functionality.

Codeigniter nginx 404 error

I am not sure how many times this question has been answered before, but every answer that I look at gives a different approach to solving this problem of which none of them worked. I am migrating from Apache to Nginx and am facing some serious problems with setting it up. My /etc/nginx/sites-available/default looks like this...
server {
#listen 80; ## listen for ipv4; this line is default and implied
#listen [::]:80 default ipv6only=on; ## listen for ipv6
root /usr/share/nginx/www/flo2go/;
index index.php index.html index.htm;
if ($request_filename !~ (js|css|images|robots\.txt|index\.php.*) ) {
rewrite ^/(.*)$ /index.php/$1 last;
}
# Make site accessible from http://localhost/
server_name localhost;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to index.html
try_files $uri $uri/ /index.php;
# Uncomment to enable naxsi on this location
# include /etc/nginx/naxsi.rules
}
location ~ /index.php/
{
include /etc/nginx/fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/www/flo2go/index.php;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
location /doc/ {
alias /usr/share/doc/;
autoindex on;
allow 127.0.0.1;
deny all;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
#
# # With php5-cgi alone:
# fastcgi_pass 127.0.0.1:9000;
# # With php5-fpm:
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
I have tried everything to make my web application work. All I keep getting is the 404:Page Not Found error. The site was working perfectly on Apache and after spending almost 3-4 hours in solving this problem I thought that it would be better to seek the advise of experts on this forum. Hope somebody can bail me out of this situation :(
Right config for your situation must look simular to this:
server {
server_name yoursitename.com;
root /usr/share/nginx/www/flo2go/;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php;
}
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
expires 15d;
}
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/www/flo2go/index.php;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
}
Main problem with current config is 2 .php location blocks and if which is evil.
please add following lines to your config
if (!-e $request_filename) {
rewrite ^.*$ /index.php last;
}
it works for me
Check the naming s of you Controller , View, Model and Database.
if you do this in your controller:
$this->load->view('main');
then the filename of your view must be same as you wrote in your controller:
main.php
nginx is more picky about case of file names than apache.
my controller was called Proto and in a file called proto.php. I renamed it to Proto.php and it started working.
Nginx is sensitive about case of controller file name.

Resources