9

I want pass any api/* route to php-fpm. Specifically to index.php as I use Symfony. This is the only route that should use php. Anything else will be loaded from /usr/share/nginx/html/public (just HTML files and CSS).

I've attempted this, but I'm getting an error:

FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream

My nginx config is below:

upstream php {
  server php:9000;
}

server {
  listen 80 default_server;
  server_name impressive.local;
  index index.html index.php;
  root /usr/share/nginx/html/public;

  location /api {
    root /usr/share/nginx/html/api;
    try_files $uri /index.php;
  }

  location ~ \.php$ {
    fastcgi_pass php;
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    include fastcgi.conf;
  }
}

I get the following error:

php_1  | [13-Jan-2019 23:22:54] NOTICE: fpm is running, pid 1
php_1  | [13-Jan-2019 23:22:54] NOTICE: ready to handle connections
php_1  | 172.25.0.3 -  13/Jan/2019:23:22:57 +0000 "GET /api/index.php" 404
web_1  | 2019/01/13 23:22:57 [error] 10#10: *1 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream,
client: 172.25.0.1, server: impressive.local, request: "GET /api/index.php HTTP/1.1", upstream: "fastcgi://172.25.0.2:9000", host: "127.0.0.1:8080"
web_1  | 172.25.0.1 - - [13/Jan/2019:23:22:57 +0000] "GET /api/index.php HTTP/1.1" 404 27 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" "-"

I've googled for hours, viewwed multiple other answers on Stack Exchange. I can't seem to figure out what is causing this. I use docker. Below is my docker-compose.yml

version: '3'
services:
  web:
    image: nginx:alpine
    volumes:
      - ./web:/usr/share/nginx/html
      - ./conf/impressive.template:/etc/nginx/conf.d/default.conf
    ports:
      - "8080:80"
    links:
      - php

  php:
    image: php:7.3.1-fpm-alpine
    volumes:
      - ./web:/usr/share/nginx/html

/usr/share/nginx/html is structured like so:

- api
    index.php
- public
    index.html
    something.html
    ...

api is a JSON API, and public is the static site.

I want any requests to api/* to call api/index.php and anything else to go via /usr/share/nginx/html/public.

2
  • What PHP script did you mean to load? Where is it located in the filesystem? Commented Jan 14, 2019 at 0:33
  • I've made some edits. Commented Jan 14, 2019 at 0:42

3 Answers 3

11

I finally solved it!

Turns out that the root location had to match the location of the files on the php-fpm container as that's what was being past through via:

fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name

I didn't need to specify that line as it was included in: include fastcgi.conf;.

I'm not sure if this is the most elegant solution:

upstream php {
  server php:9000;
}

server {
  listen 80 default_server;
  server_name _;
  index index.html index.php;
  root /usr/share/nginx/html/public;

  location /api {
    root /usr/share/nginx/html;
    try_files $uri /api/index.php$is_args$args;

    location ~ \.php$ {
      fastcgi_pass php;
      fastcgi_split_path_info ^(.+\.php)(/.*)$;
      include fastcgi.conf;
      internal;
    }
  }
}
3
  • 3
    Well, if I remove my SCRIPT_FILENAME then all I get is an empty, white, blank page. No error messages either. :/
    – Bert
    Commented Nov 5, 2019 at 9:04
  • As say Bert, In my case when i remove the SCRIPT_FILENAME i get is an empty page, blank page, no error, no messages and the log fpm figurated with 200 status Commented May 17, 2020 at 15:26
  • 1
    This is the correct answer; apparently nginx passes the absolute path to php-fpm. So app files need to be in the same path in two containers. Commented Dec 19, 2021 at 13:16
4

I can't add an comment,but answer.

If anyone runs in the same "problem" as Bert or Ivan Fretes, please check Point 4 in the Notes of: https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi

An empty page with 200 is normal, if SCRIPT_FILENAME is not set.

If this parameter is not set, PHP FPM responses 200 OK with empty content, and there is no error or warning. For more informaton about the CGI params, please refer to nginx beginners guide, $_SERVER in PHP and RFC3875.

The solution is not to leave it empty, but may to set it to an correct value. First, just try to add the most working default value:

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

But sometimes, thats not enough. For example, I run a wordpress-fpm container, which wants its files in /var/www/html. But on my host, the files a placed in /opt/wordpress/wordpress_data.

Solution one: move it from /opt/... to /var/...

Solution two: Define root normal in nginx:

root /opt/wordpress/wordpress_data;

but fix the SCRIPT_FILENAME paramter, by adding/overwriting it:

fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;

(I replaced the variable $document_root with the hardcoded path, there the files are visible inside the fpm-container)

0

For me, it was stupidly simple, my parameter were missing / at the end of document root definition e.g it was root /var/www; I change it to root /var/www/;

the reason is SCRIPT_FILENAME line was like this fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; notice there is no / between $document_root and $fastcgi_script_name

This is my PHP block in nginx.conf file

location ~ \.php$ {
  root           /var/www/;
  fastcgi_pass   unix:/run/php-fpm7/php-fpm.sock;
  fastcgi_index  index.php; 
  fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
  include        fastcgi_params;
       }

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .