Nested Laravel-inertia-react App using nginx+phpfpm - laravel

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.

Related

LARAVEL application with NGINX server showing 404 error in windows

I am new to PHP and Laravel.I have cloned a laravel project from git and save my local directory
"C:\Projects\TestProject\public".
NGINX folder C:\nginx
php folder C:\PHP
My NGINX Config is as below
server {
listen 80;
server_name localhost;
root C:/Projects/TestProject/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
index index.html index.htm index.php;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9999;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
I have also installed composer and necessary dependecies.But when i try to access http://localhost/TestProject/public/index.phpits showing 404 and showing No input file specified.
I have created a sample php file Test.php with phpinfo() int the same folder root.When i acces http://localhost/TestProject/public/Test.php it is displaying the PHP information on browser but the network shows 404 for the url. My PHP version is 7.4.
You have to include the params' file in the configuration block:
include fastcgi.conf;
Then the final block should be:
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9999;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
include fastcgi.conf;
}

Laravel in a sub-directory using NGINX with preserved routing

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;
}

Multiple Laravel Applications Using Nginx - Windows

I have two different laravel application on my server machine.
They are located at:
D:/APPLICATION/application1
and
D:/APPLICATION/application2
Below is my nginx.conf content:
server {
listen 80;
server_name localhost;
location / {
root "D:/APPLICATION/application1/public";
try_files $uri $uri/ /index.php?$query_string;
index index.php index.html index.htm;
location ~ \.php$ {
try_files $uri /index.php = 404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
location ^~ /application2 {
alias "D:/APPLICATION/application2/public";
try_files $uri $uri/ /index.php?$query_string;
index index.php index.html index.htm;
location ~ \.php$ {
try_files $uri /index.php = 404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
}
If I browse http://x.x.x.x/, my first laravel web application comes out perfectly.
But if I browse http://x.x.x.x/application2 I am having No input file specified.
Anything I am missing here?
For windows use fastcgi_pass as 127.0.0.1:9000 instead of unix socket.
Please make sure your php cgi is running. If not, you can start it by
1. Open command prompt
2. Go to path of php-cgi file. (e.g. C:\php-7.3.11, here you'll find fast-cgi.exe).
2. php-cgi.exe -b 127.0.0.1:9000
Nginx configuration with rewrite module.
# Nginx.conf
# App 1(Path: D:/APPLICATION/application1, Url: http://localhost)
# App 2(Path: D:/APPLICATION/application2, Url: http://localhost/application2)
server {
# Listing port and host address
# If 443, make sure to include ssl configuration for the same.
listen 80;
listen [::]:80;
server_name localhost;
# Default index pages
index index.php;
# Root for / project
root "D:/APPLICATION/application1/public";
# Handle main root / project
location / {
#deny all;
try_files $uri $uri/ /index.php?$args;
}
# Handle application2 project
location /application2 {
# Root for this project
root "D:/APPLICATION/application2/public";
# Rewrite $uri=/application2/xyz back to just $uri=/xyz
rewrite ^/application2/(.*)$ /$1 break;
# Try to send static file at $url or $uri/
# Else try /index.php (which will hit location ~\.php$ below)
try_files $uri $uri/ /index.php?$args;
}
# Handle all locations *.php files (which will always be just /index.php)
# via factcgi PHP-FPM unix socket
location ~ \.php$ {
# We don't want to pass /application2/xyz to PHP-FPM, we want just /xyz to pass to fastcgi REQUESTE_URI below.
# So laravel route('/xyz') responds to /application2/xyz as you would expect.
set $newurl $request_uri;
if ($newurl ~ ^/application2(.*)$) {
set $newurl $1;
root "D:/APPLICATION/application2/public";
}
# Pass all PHP files to fastcgi php fpm unix socket
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# Use php fastcgi rather than php fpm sock
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
# Here we are telling php fpm to use updated route that we've created to properly
# response to laravel routes.
fastcgi_param REQUEST_URI $newurl;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# Deny .ht* access
location ~ /\.ht {
deny all;
}
}
Note: When we're using session based laravel setup, all the route generator functions(url(), route()) use hostname localhost as root url not localhost/application2. To resolve this issue please do following changes in laravel app.
Define APP_URL in .env file as APP_URL="localhost/application2"
Go to RouteServiceProvider which is located at app/Providers/RouteServiceProvider and force laravel to use APP_URL as root url for your app.
public function boot()
{
parent::boot();
// Add following lines to force laravel to use APP_URL as root url for the app.
$strBaseURL = $this->app['url'];
$strBaseURL->forceRootUrl(config('app.url'));
}
Update: Make sure to run php artisan config:clear or php artisan config:cache command to load the updated value of APP_URL.
For Linux System : Nginx: Serve multiple Laravel apps with same url but two different sub locations in Linux

Deploying Vue Cli 3 SPA with Laravel backend

I have a Vue Cli 3 SPA application which makes api calls to a Laravel Backend. I've created a LEMP droplet on DigitalOcean, and I've cloned the two projects in the /var/www/html directory. api/ for the backend, web/ for the frontend. I've configured nginx root to web/dist/index.html. Now, how can I make api calls, since the root of the project is index.html?
I've searched a lot. I saw solutions where I must copy the dist folder's contents to api/public, and adjust nginx's root to be api/public/index.html. But that doesn't change the fact that I still can't make api calls, because index.php is never reached.
Could you please advice me how you do it? Should I create a subdomain?
Thanks!
UPDATE
I've tried this according to oshell's answer:
# For the vue app
server {
listen 80;
root /var/www/html/web/dist;
index index.html;
server_name XXX.XXX.XX.XXX # the ip addreess that I have
error_page 404 /;
location / {
try_files $uri $uri/ /index.html;
}
}
# for the laravel application
server {
listen 80;
root /var/www/html/api/public;
index index.php;
server_name XXX.XXX.XX.XXX/api;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Now whatever I open, it just goes to the vue application. If I try to make an api call to XXX.XXX.XX.XXX/api/something from the vue app, I've got 405 Method not allowed
You need to setup two separated servers for frontend and backend. You could make api reachable via api.example.com and frontend via example.com. The nginx config should look something like this:
#laravel.conf
server {
listen 80;
root /var/www/html/project_name/api;
index index.php index.html index.htm;
server_name api.example.com www.api.example.com;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
#vue.conf
server {
listen 80;
root /var/www/html/project_name/web/dist;
index index.html;
server_name example.com www.example.com;
location / {
try_files $uri $uri/ /index.html;
}
}
You could also direct all traffic to you index.php and set it up so Route::any('/') returns the static page, including the static assets and all api routes are handled via Route::any('/api/foo').
The following configuration works for me on local environment - home directory on ubuntu.
Folder structure
example/dist - vue application
example/laravel - laravel api application
example/laravel/public - laravel public directory
example/laravel/public/images - laravel api images directory
Urls
example.lo - vue application
example.lo/api - laravel api
server {
# server name and logs
server_name example.lo;
access_log /var/log/nginx/example.lo_access.log;
error_log /var/log/nginx/example.lo_error.log;
root /home/username/example/laravel/public/;
index index.html index.php;
# location for vue app
location / {
root /home/username/example/dist/;
try_files $uri $uri/ /index.html;
}
# location for laravel api
location /api {
try_files $uri $uri/ /index.php$is_args$args;
}
# location for api images
location /images {
try_files $uri $uri/ =404;
}
# pass the PHP scripts to FastCGI
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
}
}

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;
}
}
}

Resources