0

I've got 2 AWS EC2 instances, one of which resides in a public subnet and is configured to act as a NAT instance, and runs Nginx. The other instance resides in a private subnet, but can communicate with the public one. The respective IP addresses of the instances are, for example:

  • 172.25.48.14 - Nginx instance in a public subnet (172.25.48.0/28), has an Elastic IP assigned
  • 172.25.48.140 - instance running php-fpm in a private subnet (172.25.48.128/28)

The thing is, I want this website to be accessible by a certain URL - I supposed Nginx to act as a reverse proxy server which maps requests to certain subdomains or URLs to respective resources. So, here is my Nginx configuration:

http { sendfile on; tcp_nopush on; types_hash_max_size 2048; server_names_hash_bucket_size 128; include /etc/nginx/mime.types; default_type text/html; proxy_headers_hash_bucket_size; access_log /var/log/nginx/access.log error_log /var/log/nginx/error.log server { listen 80; location ~ ^/site1(.*)$ { # These are commented out because no matter if specified or not the result is the same # index index.php; # try_files $uri $uri/ /site1/index.php?$request_uri; location ~ \.php$ { include fastcgi.conf; try $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass 172.25.48.140:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } } } 

And here is, respectively, the php-fpm pool configuration for the site in the private instance:

[site1] user = www-data group = www-data listen = 172.25.48.140:9000 listen.allowed_clients = 172.25.48.14, 172.25.48.140, 127.0.0.1 php_admin_value[disable_functions] = exec, passthru, shell_exec, system php_admin_flag[allow_url_fopen] = off pm = dynamic pm.max_children = 10 pm.start_servers = 1 pm.min_spare_servers = 1 pm.max_spare_servers = 8 pm.process_idle_timeout = 30s pm.status_path = /php_status ping.path = /ping ping.response = wrrrrrrrrryyyyyyyyyyy access.log = /var/log/php/8.3/$pool.access.log access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{milli}d %{kilo}M %C%%" 

For the sake of simplicity let's assume I have only a single index.php file, which resides in the private instance as well at /apps/site1/, which has a symlink at /var/www/html/site1.

The problem is that no matter what I try, I get 404, and judging by the logs on the private instance side, the request doesn't even get there - even though I know I have the instance security groups configured properly and on the right ports, because otherwise I can connect from the private instance to the public one and vice versa without any problems. The only time I got a request through to the php-fpm (albeit a 404 as well) was when I moved the deep-most "location" lookup (the one that matches for the .php scripts) to the server top level - so basically the request went straight to 172.25.48.14, and not to 172.25.48.14/site1 as I intended.

Am I missing something? Could the issue be that the source files are located on the same instance as php-fpm, and not on the Nginx side? Am I getting the concept of how it works wrong? Please, if you have any ideas on this, I'll be extremely grateful for your help. Thanks in advance!

1
  • " the request doesn't even get there" - yes it does, otherwise changing the PHP on the origin server would not change the behaviour. A lot of nginx distributions don't log 404s Commented Nov 13, 2024 at 10:16

2 Answers 2

3
  1. Your config, being tested with nginx -t command, should give you an error message like

    nginx: [emerg] unknown directive "try" in ... 

    due to the

    try $uri =404; 

    line. If it was supposed to be the

    try_files $uri =404; 

    directive, it also won't work. This directive makes nginx checking your request URI to be a physical file relative to your web server root (which isn't defined at all), obviously failing (since your PHP file is located at the other host). This line should be removed from your nested location.

  2. Since you didn't explicitly define your website root, by default it is equal to {prefix}/html where {prefix} is some precompiled value (can be viewed using nginx -V command). So whatever you passing to your private instance via the

    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 

    directive, most likely it isn't correct one. You should use either

    root /apps/site1; 

    or

    root /var/www/html/site1; 

    within your nested location (although I don't know how PHP-FPM will treat the paths with symlinks included).

  3. As already being said at StackOverflow:

    You have a nested location in there that processes .php requests, but it doesn't look like you're requesting an actual PHP file in your test URL. The typical pattern would be to have a try_files directive which attempts to load the requested file / directory on disk, or fall back to routing the request through an index.php file as a front controller. You don't seem to have this.

    Add either

    try_files $uri /site1/index.php$is_args$args; 

    or

    error_page 404 = /site1/index.php$is_args$args; 

    to your parent location.

  4. You don't need to use both

    include fastcgi.conf; 

    and

    include fastcgi_params; 

    in your nested location. They are almost the same, the only difference is that fastcgi.conf file includes the

    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 

    line while fastcgi_params doesn't (when using the fastcgi_params file rather than fastcgi.conf, you should include this line yourself).

  5. Any PATH_INFO related stuff such as

    fastcgi_split_path_info ^(.+\.php)(/.+)$; 

    makes no sense at the location ~ \.php$ { ... } locations (in opposite to location ~ \.php(?:/|$) { ... } ones).

  6. Why do not use a simply prefix location like

    location /site1/ { ... } 

    or

    location ^~ /site1/ { ... } 

    (especially sinсe you don't make use of the regex capture group anyway)?

1
  • Thank you! I've updated the configs and it worked. Commented Nov 13, 2024 at 19:27
1

Your setup, where Nginx acts as a reverse proxy for a remote php-fpm server, is generally correct, but a few configuration adjustments can help resolve the 404 errors and ensure requests reach the php-fpm server as expected.

1. Adjusting Nginx Configuration

In the nginx.conf file, try the following changes to the configuration to better handle proxying to the remote php-fpm server.

Correct the location and try_files Directives

The Nginx configuration can be simplified by ensuring try_files is set correctly and by making sure fastcgi_pass directs to the remote server. Here’s an adjusted example:

http { sendfile on; tcp_nopush on; types_hash_max_size 2048; server_names_hash_bucket_size 128; include /etc/nginx/mime.types; default_type text/html; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; server { listen 80; location /site1 { # Forward all requests under /site1 to the php-fpm server try_files $uri $uri/ /site1/index.php?$query_string; location ~ \.php$ { include fastcgi.conf; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass 172.25.48.140:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/html/site1$fastcgi_script_name; include fastcgi_params; } } } } 

Explanation of Changes:

  • try_files $uri $uri/ /site1/index.php?$query_string;: This tries to serve a file under /site1 or falls back to /site1/index.php, passing the query string.
  • fastcgi_param SCRIPT_FILENAME /var/www/html/site1$fastcgi_script_name;: Adjusted to reflect the path where php-fpm expects to find index.php on the private server.

2. Configure php-fpm Pool for Remote Access

Your php-fpm configuration generally looks correct, but ensure listen.allowed_clients includes the IP address of the Nginx server and that listen = 172.25.48.140:9000 is properly bound to the private instance’s IP.

3. Security Group and Firewall Settings

Verify that:

  • The security group for the php-fpm server allows incoming connections on port 9000 from the Nginx server's IP (172.25.48.14).
  • Outbound rules for the Nginx server security group allow traffic to the private IP of the php-fpm server (172.25.48.140).

4. Confirm the Directory Structure on the php-fpm Server

Since your index.php file resides in /apps/site1/, confirm that this directory is accessible to php-fpm and that permissions allow www-data to read and execute files.


Try these adjustments and restart Nginx and php-fpm to see if the issue is resolved.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.