Create internal connection between React and Laravel in Docker containers on server - reactjs

I am using a React app as frontend and a Laravel app for backend. These two are connected with each other through Laravel Sanctum APIs. The whole environment is deployed on the server using Docker, frontend & backend being separate containers, but connected with network: someNetwork
The API call is done from the frontend using the URL HTTP://myserverip:8000 - this is working, but I would like to close the 8000 port (externally) and just keep open the 3000 port where the frontend is working. Now when I'm closing the 8000 port (with firewall), and trying to make API request from frontend I get a network error.
The question is, how to make the API request internally so I can keep only 3000 open, do I need some kind of redirection inside the .conf file of the nginx? This is my .conf file:
server {
listen 80;
index index.php index.html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/public;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
}
Thanks, any hint would be appreciated.

What you are trying to do will never work.
ReactJS (I guess thats what you mean by ReactApp) should be "build" before used in production. The result will be a build folder with a bunch of static files.
These files can be deployed / serverd using NGINX. The API-Calls from ReactJS (your Frontend App) will always come from outside of your network as the client / customer will not be part of your Docker NAT network (I guess).
I would use NGINX as a Webserver for your ReactApp (ReactJS Build) as well as a reverse Proxy / Proxy for your Laravel Backend.
Something like:
server {
listen 443 ssl;
server_name example.com
.....
root /path/to/your/reactapp/static/files;
location / {
try_files $uri /index.html;
}
}
server {
listen 443 ssl;
server_name api.example.com;
...all the laravel PHP config here
}
if you can not or want not create a subdomain for your API use a location
server {
listen 443 ssl;
server_name example.com
.....
root /path/to/your/reactapp/static/files;
location / {
try_files $uri /index.html;
}
location /api/ {
Do your Laravel config here (use nested locations for handling the php files)
Or do a `proxy_pass` and configure an internal server (listen `8000`) and do not expose it.
}
}

Related

In frontend nginx check backend health for custom error page

I have simple configuration of nginx for React application:
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server_tokens off;
server {
listen 80;
location / {
limit_req zone=mylimit burst=10;
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html =404;
}
}
Let's say that our backend load balancer address is 10.0.0.0:443. We can check it's health with going to /health endpoint. How nginx configuration should look like to have logic: if backend health returns 200 - use React app, if not - open simple error.html page. Thank you

How to access public folder in laravel through reactjs when I serve them in NginX?

I'm developing a project with Reactjs and Laravel(Breeze version).
The project is dockerized and for serving, I use Nginx as the web serve. I configure it to access laravel backend by adding /api to the end of the frontend url.
every thing is fine but when I try to access the uploaded images files on public folder (in backend side ) I'v got 404 eror.
this is my nginx config file:
.
.
.
# laravel backend
location ~ /api {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
root /var/www/html/backend/public;
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass laravel:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_hide_header X-Powered-By;
}
.
.
.
.
I have another root in my nginx config file for my frontend :
server {
listen 80 default_server;
server_name _;
server_tokens off;
root /var/www/html/frontend;
.
.
.
The issue was solved after spending some hours just by adding the new location for my upload folder(Inside the laravel public folder) in Nginx config file:
location /uploads/ {
alias /var/www/html/backend/public/uploads/;
}

Why Nginx load balancer is not serving js/css files from nginx nodes?

I have load balancer with really simple config for domain.com:
server {
listen 80;
server_name domain.com;
location / {
proxy_pass http://dev-admin;
}
}
upstream dev-admin {
server ip1:8001;
server ip2:8001;
server ip3:8001;
}
IMPORTANT:
Ip1, Ip2 and Ip3 are docker containers that are made by making docker swarm service.
Now when you open ip1:8001 or any other ip2 or ip3 you got website and all is good. Website is from react build.
On each node ip1, ip2 and ip3 i have nginx with this config:
server {
listen 80;
listen [::]:80;
root /usr/share/nginx/html;
index index.html index.htm index.nginx-debian.html;
server_name localhost;
location / {
try_files $uri /index.html;
}
}
So when you try website on domain.com instead serving css or js files it is serving index.html response. So domain.com/static/some.js -> this shows in the response index.html content.
I have no idea what else to debug.
Help. Please.
It turned, out I was missing $uri/ on nodes config.
So it is:
location / {
try_files $uri $uri/ /index.html;
}

Nginx React App - Allowing only one location to be accessible

I have a server on DigitalOcean that hosts my web app.
The server hosts the API (using Flask) and my web app (React).
I managed to set up the Nginx to serve the app and the API using 2 different domains.
Now I'm facing a problem.
I'm, trying to add another domain that I need to be able to access only one page in the react app.
I can't find a way to set up the configuration to allow that.
server {
server_name www.domain domain;
root /var/www/path/html;
index index.html index.htm index.nginx-debian.html;
location / { deny all; }
location = / { }
location /test {
try_files $uri /index.html;
}
location /favicon.ico {
try_files $uri /index.html;
}
location /static/ {
try_files $uri /index.html;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/domain/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/domain/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot }
In my other config files I just use try_files $uri /index.html; and it works perfectly.
I need this domain to be able to accept requests for one path only (domain.com/confirm/token)

Deploy Laravel and React spa

How can I deploy these two together, I don't like the Laravel React preset, I want to separate both, bundle the React app and deploy them together with any web server (apache, nginx...)
EDIT
This is my config for Laravel, but it isn't loading the routes
server {
listen 8000;
server_name 127.0.0.1
root "..\..\Proyecto\Backend\JWT\public";
add_header 'Access-Control-Allow-Origin' '*';
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
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;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
You can run them separately using nginx
you run each on separate ports and use methods (POST/GET) to push/get data
use pm2 (http://pm2.keymetrics.io/) for running React (I recommend it because you can monitor the activity of the react app and if you want to do maintenance you can stop the current app process and run a "under maintenance" app process)
you can read more about running laravel on nginx here (https://www.digitalocean.com/community/tutorials/how-to-deploy-a-laravel-application-with-nginx-on-ubuntu-16-04)
as for running react without pm2, you have to build the project yarn build and tell nginx that the file you want to load is the index.html inside of the build file
assuming that you are using an ubuntu server and you uploaded your code to github or gitlab
server {
listen 50;
root /var/www/[Your repo name]/build;
server_name [your.domain.com] [your other domain if you want to];
index index.html;
location / {
try_files $uri /index.html;
}
}
you write this inside of your nginx configuration along with the laravel configuration on a separate port
hope my answer helped a bit
This was proving to be very tricky and it took me at least 3 days to put everything together. Here is what you have to do.
Run
npm run build in the react project.
Copy the contents of the build folder to the server
scp react_project/build/* <server name or ip>:/var/www/html/react
Change the ownership of the project folders to the user www-data or add your user id to the group www-data.
Now. set up the Laravel project in a different directory (in /var/www/html/laravel, for example).
Set up the database, environment variables.
Run
php artisan key:generate
php artisan config:clear
php artisan config:cache
Now, proceed with nginx configuration. Create 2 configs for react and laravel projects as given below. Make sure that the listen ports are different for both projects.
Create configuration files for react and laravel projects under /etc/nginx/sites-available
Create symlinks to the created configs under /etc/nginx/sites-enabled as given below
sudo ln -s /etc/nginx/sites-available/react_conf /etc/nginx/sites-enabled/react_conf
sudo ln -s /etc/nginx/sites-available/laravel_conf /etc/nginx/sites-enabled/laravel_conf
And for the contents,
react_conf:
server {
listen 80;
server_name <server_ip or hostname>;
charset utf-8;
root /var/www/html/react;
index index.html index.htm;
# Always serve index.html for any request
location / {
root /var/www/html/react;
try_files $uri /index.html;
}
error_log /var/log/nginx/react-app-error.log;
access_log /var/log/nginx/react-app-access.log;
}
laravel_conf:
server {
listen 90;
server_name <server ip or hostname>;
charset utf-8;
root /var/www/html/laravel/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.php index.html index.htm;
# Always serve index.html for any request
location /api {
try_files $uri $uri/ /index.php?$query_string;
}
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;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
error_log /var/log/nginx/laravel-app-error.log;
access_log /var/log/nginx/laravel-app-access.log;
}
Now, delete the default config present in /etc/nginx/sites-enabled
Also, verify that /etc/nginx/nginx.conf contains the following include directive where the server configs are expected(under http)
include /etc/nginx/sites-enabled/*;
Verify that the config is fine by running
sudo nginx -t
Restart the server
sudo service nginx restart
Now, you should be up and running.
You can approach it by two ways .
First one is when the you are creating react-app in different folder than the laravel project folder . In such case just deploy laravel app and react app in two different url .
The second condition is when the react-app is inside the laravel app . In such case build the react project and put the dist folder in views folder of the laravel project . So in routes/web.php add this
//Used for handling the html file of react project
View::addExtension('html', 'php');
Route::get('/{any}', function () {
//path to dist folder index.html inside the views directory
return view('build/index');
})->where('any', '.*');
Laravel will not server the required js and css file from inside the views folder . So you need copy and paste all the content of the dist folder to public folder of the laravel project . No need to copy paste index.html file but other file need to placed in the pubic folder .
After that visit the root url of the laravel project in the browser the react app should be working

Resources