Nginx to serve php files from a different server - php

I am trying to configure nginx to serve PHP from another server.
The files can be located within a directory under /sample on the other server
Fast CGI is running on port 9000 on the other server
Here is what I have tried, which is not working at the moment.
location ~ [^/]\.php(/|$) {
proxy_pass http://192.168.x.xx;
proxy_redirect http://192.168.x.xx /sample;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name)
{
return 404;
}
# Mitigate https://httpoxy.org/ vulnerabilities
fastcgi_param HTTP_PROXY "";
fastcgi_read_timeout 150;
fastcgi_buffers 4 256k;
fastcgi_buffer_size 128k;
fastcgi_busy_buffers_size 256k;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
I also need to configure nginx to serve static files from the same server

The following configuration does exactly what you need:
server {
listen 80;
index index.php index.html;
server_name localhost;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root {STATIC-FILES-LOCATION};
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass {PHP-FPM-SERVER}:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
All you have to do is replace {STATIC-FILES-LOCATION} with the location of your static files on the Nginx server and {PHP-FPM-SERVER} with the IP of the PHP-FPM server.
This way you will serve all files without the PHP extension statically from the Nginx server and all the PHP files will be interpreted with the PHP-FPM server.
Here's a working example of a dockerised version of what you are trying to achieve - https://github.com/mikechernev/dockerised-php/. It serves the static files from Nginx and interprets the PHP files via the PHP-FPM container. In the accompanying blog post (http://geekyplatypus.com/dockerise-your-php-application-with-nginx-and-php7-fpm/) I go in lengths about the whole connection between Nginx and PHP-FPM.
EDIT: One important thing to keep in mind is that the paths in both the Nginx and PHP-FPM servers should match. So you will have to put your php files in the same directory on the PHP-FPM server as your static files on the Nginx one ({STATIC-FILES-LOCATION}).
An example would be to have /var/www/ on Nginx holding your static files and /var/www on PHP-FPM to hold your php files.
Hope this helps :)

You don't have to use proxy_ directives, because they work with HTTP protocol, but in this case FastCGI protocol is used. Also, as it was said in comments, no need for if statement, because Nginx server cannot determine if the file on a remote server exists.
You could try this configuration:
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
# Mitigate https://httpoxy.org/ vulnerabilities
fastcgi_param HTTP_PROXY "";
fastcgi_read_timeout 150;
fastcgi_buffers 4 256k;
fastcgi_buffer_size 128k;
fastcgi_busy_buffers_size 256k;
fastcgi_pass 192.168.x.xx:9000; #not 127.0.0.1, because we must send request to remote PHP-FPM server
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /path/to/site/root$fastcgi_script_name;
}
You will need to replace /path/to/site/root with a real path on the PHP-FPM server. For example, if the request http://example.com/some/file.php must be handled by /var/www/some/file.php, then set it like this:
fastcgi_param SCRIPT_FILENAME /var/www$fastcgi_script_name;
Also, to make PHP-FPM server be able to receive requests from outside, edit your FPM pool configuration (on Debian it usually located in /etc/php5/fpm/pool.d/www.conf, on Centos - /etc/php-fpm.d/www.conf):
Replace
listen = 127.0.0.1:9000
with:
listen = 9000
or:
listen = 192.168.x.xx:9000 # FPM server IP
Probably you will also need to edit allowed_clients directive:
listen.allowed_clients = 127.0.0.1,192.168.y.yy # Nginx server IP
I also need to configure nginx to serve static files from the same server
If I understand correctly, and you want to serve static files from the server, Nginx is working on, then you may just add another location to your Nginx configuration.

You should not use proxy_* directives. using Nginx as a proxy would be done only if a distant server has rendered the page (and you would request it with HTTP protocol).
Here the thing you want to proxy is a fastcgi server, not an HTTP server.
So the key is:
fastcgi_pass 127.0.0.1:9000;
Where you currently say you want to reach a fastcgi server on IP 127.0.0.1 port 900, which seems quite wrong.
Use instead:
fastcgi_pass 192.168.x.xx:9000;
And remove proxy_* stuff.
Edit: also, as stated in comments by #Bart, you should not use an if testing that a local file in the document root, matching the php script name does exists. The php files are not on this server. So remove this file.
If you want to apply some security check, you would, later, alter your very generic location [^/]\.php(/|$) to something more specific, like location=/index\.php, or some others variations.

No need to give /sample path
location ~ [^/]\.php(/|$) {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
# Mitigate https://httpoxy.org/ vulnerabilities
fastcgi_param HTTP_PROXY "";
fastcgi_pass IP:9000;
fastcgi_index index.php;
include fastcgi_params;
}
For static files from nginx server you need to use try_files for that.
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
// other CGI parameters
}
Make sure you're aware of common pitfalls.
If you want to access static files from another server you need to run a webserver there and just proxy pass from Nginx

Related

Laravel app with separate php-fpm and nginx servers

Is it possible to run a Laravel app on two separated server, one with NGINX, another with PHP-FPM?
I wanted to create an upstream of PHP-FPM servers for load balancing. I've tried some NGINX configurations but it seems that both NGINX and PHP-FPM needs Laravel app files.
Note: I have separate server for static files.
[user] -request-> [nginx without laravel files] -> [php-fpm upstream with laravel files]
UPDATE
upstream php_pool {
server 192.168.1.1:9000;
}
server {
listen 80;
server_name www.example.com;
index index.php;
access_log /var/log/nginx/q_access.log;
error_log /var/log/nginx/q_error.log info;
location / {
try_files $uri $uri/index.php /index.php;
}
location ~ \.php$ {
index index.php;
fastcgi_pass php_pool;
fastcgi_index index.php;
include fastcgi_params;
}
}
I don't know what should i set for root directory cause there isn't any Laravel app files in that server. And how config \.php$ location properly?
We found solution for our scenario. PHP location should be like this:
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass php_pool;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/app/public$fastcgi_script_name;
}
With this change (SCRIPT_FILENAME) there isn't need for Laravel app files to be on the NGINX server cause all PHP requests will proxied to PHP-FPM servers.

Nginx + PHP on docker serving static files

I have two containers: nginx and php-fpm. The files are stored on the php-fpm container. There is no problem with serving PHP files, but I need to serve static files as well, and I have a problem with the location configuration.
No idea how to configure it correctly.
location /static/ {
fastcgi_pass api:9000;
}
or I tried:
location /vendor/ {
root api:9000/public/vendor/;
}
This is the config file:
server {
listen 80 default_server;
root /app/api/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location /static/ {
fastcgi_pass api:9000;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_index index.php;
fastcgi_intercept_errors on;
fastcgi_pass api:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_read_timeout 3600;
}
}
Thank you!
As #slauth mentioned, there is no way to access files to another container.
I decided to serve static images using PHP. Here is a good tutorial: https://grahamlikesto.codes/slim-php-how-to-serve-static-files-with-slim-php/
This is not the best solution. My app is a small app with little traffic, and serving assets is not a big deal, but you should change your architecture if you run this issue.

How to make self-contained nginx and php-fpm containers properly

I have two docker-containers: nginx and php-fpm.
I want to make them self-contained (containers will clone repo from git on build) for production. But after cloning repo I need to make some initial stuff, like composer install in project folder. I can do it inside php-fpm container, because I have php there. But how to prepare code in nginx container? I don't have php there for composer.
Everything is fine, when I mount same initialized folder into both containers.
Maybe I'm doing something wrong, what is best way to do self-contained container for nginx+php-fpm?
For now I have this nginx-config:
server {
listen 80;
server_name localhost;
index index.php index.html;
# I need only /api/ path
location /api/ {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
root /var/www/public;
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass api:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
You should only have the PHP files on the FPM server. As you previously noted, you should have php cli to run composer on that server. You shouldn't need any PHP files on the nginx server. SCRIPT_FILENAME will be resolved by the CGI server so that location does not need to exist on the web proxy. If you need to make config changes to the nginx server, you probably want to use something more system oriented like Salt, Chef or Puppet.
location ~ \.php$ {
# This is the webserver root for static junk
root /var/www/public;
...
# Point this somewhere else if the docroot is in a different location on the FPM server.
fastcgi_param SCRIPT_FILENAME /home/php-fpm/wwwroot/$fastcgi_script_name;
}

Run multiple nginx on one dedicated server ubuntu

Is it possible to run multiple NGINX on a single Dedicated server?
I have a dedicated server with 256gb of ram, and I am running multiple PHP scripts on it but it's getting hangs because of memory used with PHP.
when I check
free -m
it's not even using 1% of memory.
So, I am guessing its has some to do with NGINX.
Can I install multiple NGINX on this server and use them like
5.5.5.5:8080, 5.5.5.5:8081, 5.5.5.5:8082
I have already allocated 20 GB memory to PHP, but still not working Properly.
Reason :- NGINX gives 504 Gateway Time-out
Either PHP or NGINX is misconfigured
You may run multiple instances of nginx on the same server provided that some conditions are met. But this is not the solution you should look for (also this may not solve your problem at all).
I got my Ubuntu / PHP / Nginx server set this way (it actually also runs some Node.js servers in parallel). Here is a configuration example which works fine on a AWS EC2 medium instance (m3).
upstream xxx {
# server unix:/var/run/php5-fpm.sock;
server 127.0.0.1:9000 max_fails=0 fail_timeout=10s weight=1;
ip_hash;
keepalive 512;
}
server {
listen 80;
listen 8080;
listen 443 ssl;
#listen [::]:80 ipv6only=on;
server_name xxx.mydomain.io yyy.mydomain.io;
if ( $http_x_forwarded_proto = 'http' ) {
return 301 https://$server_name$request_uri;
}
root /home/ubuntu/www/xxxroot;
index index.php;
location / {
try_files $uri $uri/ /index.php;
}
location ~ ^/(status|ping)$ {
access_log off;
allow 127.0.0.1;
#allow 1.2.3.4#your-ip;
#deny all;
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass adn;
#fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
#fastcgi_param SCRIPT_FILENAME /xxxroot/$fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME $request_filename;
#fastcgi_param DOCUMENT_ROOT /home/ubuntu/www/xxxroot;
# send bad requests to 404
#fastcgi_intercept_errors on;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
Hope it helps,
I think you are running into a timeout. Your PHP-Scripts seams to run to long.
Check following:
max_execution_time in your php.ini
request_terminate_timeout in www.conf of your PHP-FPM configuration
fastcgi_read_timeout in http section or location section of your nginx configuration.
Nginx is designed more to be used as a reverse proxy or load balancer than to control application logic and run php scripts. Running multiple instances of nginx that each execute php isn't really playing to the server application's strengths. As an alternative, I'd recommend using nginx to proxy between one or more apache instances, which are better suited to executing heavy php scripts. http://kbeezie.com/apache-with-nginx/ contains information on getting apache and nginx to play nicely together.

How do I configure Nginx to serve two locations with separate root directives when only one location is path-specific?

I am attempting to configure an Nginx server block in such a manner that it achieves two objectives:
To have a subdomain example.domain.com that serves an index page and pages from various paths such as /app1 and /app2; with all of these pages/paths sharing a common root of /srv/www/example.
To have the subdomain in the previous objective serve pages from a path such as /app3, but in this case having a root of /srv/www/example/app3/web.
I was able to achieve the first and second objectives, but never at the same time. Some resources I have made use of include:
Programming Junk: Nginx multiple sites in subdirectories
Martin Fjordvald: How to solve “No input file specified" with PHP and Nginx
CakePHP in a subdirectory using nginx (Rewrite rules?)
Here is my current configuration that is currently only serving the index, /app1, and /app2 correctly as a result of moving the root directive up out of the location / { directive.
server {
listen 80;
root /srv/www/example;
index index.php index.html index.htm;
server_name example.domain.com;
location /app3/ {
root /srv/www/example/app3/web;
try_files #app3 #app3;
}
location ~ /app3/.+\.(jpg|jpeg|gif|css|png|svg|js|ico|)$ {
root /srv/www/example;
}
location #app3 {
include /etc/nginx/fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_param SCRIPT_FILENAME /srv/www/example/app3/web/index.php;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT /srv/www/example/app3/web;
}
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
}
What do I need to change to achieve both objectives in a single server block? If there is some way to get this working with multiple server blocks that both access the same subdomain and listen on the same port that would also be acceptable.

Categories