FastCGI sent in stderr: "Primary script unknown" - URL working fine without mentioning index.php using nginx reverse proxy

Viewed 406

I have prepared a docker environment to run certain PHP based websites using nginx reverse proxy. Things mostly work except for one glitch. The URLs return the output of index.php just fine without mentioning index.php http://web.local/web, however, when I do it like http://web.local/web/index.php or any .php file for that matter.

web container gives the following error.

2021/10/24 11:18:19 [error] 28#28: *3 FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream, client: 192.168.224.6, server: proxy, request: "GET /web/index.php HTTP/1.0", upstream: "fastcgi://192.168.224.4:9000", host: "web.local"

and nginx container gives following error.

192.168.224.1 - - [24/Oct/2021:11:18:19 +0000] "GET /web/index.php HTTP/1.1" 404 27 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36"

I've tried to search previous posts of this FastCGI sent in stderr error but nothing matches my problem.

Possible issues seem to be difference in users. NGINX proxy container uses root whereas PHP-FPM container uses www-data. Below are my configuration files.

NGINX (proxy) nginx.conf

user root;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 1024;
}

http {

    upstream nginx-web {
        server web:8110;
    }

    upstream nginx-portal {
        server portal:8115;
    }

    upstream nginx-api {
        server api:8120;
    }

    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Host $server_name;

    server {
        listen 80;
        server_name proxy;

        location /web {
            proxy_pass          http://nginx-web;
        }

        location /portal {
            proxy_pass          http://nginx-portal;
        }

        location /api {
            proxy_pass          http://nginx-api;
        }
    }
}

Server block (web) default.conf

server {
    listen 8110;
    root /var/www/web;
    server_name proxy;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
        index index.php;
    }

    location ~ ^/.+\.php(/|$) {
        fastcgi_pass  php:9000;
        fastcgi_index index.php;
        include       fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

docker-compose.yml

version: "3.9"

services:
  db:
    container_name: db
    image: mysql:5.7
    ports:
      - "3306:3306"
    volumes:
      - "${PROJECT_ROOT}/db:/var/lib/mysql"
      - ./conf/db/my.cnf:/etc/mysql/conf.d/my.cnf:ro
    env_file:
      - .env
    networks:
      - backend

  proxy:
    container_name: proxy
    image: nginx:mainline-alpine
    volumes:
      - ./conf/proxy/nginx.conf:/etc/nginx/nginx.conf:ro
    ports:
      - "80:80"
      - "8110:8110"
      - "8115:8115"
      - "8120:8120"
    depends_on:
      - web
      - portal
      - api
    networks:
      - backend

  web:
    container_name: web
    image: nginx:mainline-alpine
    volumes:
      - "${PROJECT_ROOT}/web:/var/www/web"
      - ./conf/web/default.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - php
    networks:
      - backend

  portal:
    container_name: portal
    image: nginx:mainline-alpine
    volumes:
      - "${PROJECT_ROOT}/portal:/var/www/portal"
      - ./conf/portal/default.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - db
      - php
    networks:
      - backend

  api:
    container_name: api
    image: nginx:mainline-alpine
    volumes:
      - "${PROJECT_ROOT}/api:/var/www/api"
      - ./conf/api/default.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - php
    networks:
      - backend

  php:
    container_name: php
    image: maciejslawik/php-fpm-xdebug:latest
    ports:
      - "9000:9000"
    volumes:
      - "${PROJECT_ROOT}/web:/var/www/web"
      - "${PROJECT_ROOT}/portal:/var/www/portal"
      - "${PROJECT_ROOT}/api:/var/www/api"
      - ./conf/php/docker-php-ext-xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini:ro
    networks:
      - backend

  composer:
    container_name: composer
    image: composer:2
    restart: "no"
    command: install
    volumes:
      - "${PROJECT_ROOT}/composer:/app"
      - ./composer/composer.json:/app/composer.json
    networks:
      - backend

  phinx:
    container_name: phinx
    image: vegbrasil/phinx:latest
    volumes:
      - "${PROJECT_ROOT}/migrations/database/migrations:/app/database/migrations"
      - "${PROJECT_ROOT}/migrations/database/seeds:/app/database/seeds"
      - ./conf/phinx/phinx.php:/app/phinx.php:ro
    env_file:
      - .env
    depends_on:
      - db
    restart: "no"
    command: "status"
    environment:
      - TESTS_PHINX_DB_ADAPTER_MYSQL_HOST=db
    networks:
      - backend

  schemaspy:
    container_name: schemaspy
    image: schemaspy/schemaspy:latest
    volumes:
      - "${PROJECT_ROOT}/schemaspy/output:/output"
      - ./conf/schemaspy/schemaspy.properties:/schemaspy.properties:ro
    restart: "no"
    depends_on:
      - db
    networks:
      - backend

networks:
  backend:

I've tried to check the output of return 200 $document_root$fastcgi_script_name; and it returns correct values.

The default PHP-FPM user www-data doesn't have permission to chmod or chcon any file or directory.

$_SERVER vardump

array (size=53)
  'PHP_EXTRA_CONFIGURE_ARGS' => string '--enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data --disable-cgi' (length=77)
  'HOSTNAME' => string '4b4c2f5dcdb7' (length=12)
  'PHP_INI_DIR' => string '/usr/local/etc/php' (length=18)
  'HOME' => string '/var/www' (length=8)
  'PHP_LDFLAGS' => string '-Wl,-O1 -Wl,--hash-style=both -pie' (length=34)
  'PHP_CFLAGS' => string '-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64' (length=83)
  'PHP_MD5' => string '' (length=0)
  'PHP_VERSION' => string '7.4.0' (length=5)
  'GPG_KEYS' => string '42670A7FE4D0441C8E4632349E4FDC074A4EF02D 5A52880781F755608BF815FC910DEB46F53EA312' (length=81)
  'PHP_CPPFLAGS' => string '-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64' (length=83)
  'PHP_ASC_URL' => string 'https://www.php.net/get/php-7.4.0.tar.xz.asc/from/this/mirror' (length=61)
  'PHP_URL' => string 'https://www.php.net/get/php-7.4.0.tar.xz/from/this/mirror' (length=57)
  'PATH' => string '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' (length=60)
  'PHPIZE_DEPS' => string 'autoconf         dpkg-dev        file        g++         gcc         libc-dev        make        pkg-config      re2c' (length=76)
  'PWD' => string '/var/www/html' (length=13)
  'PHP_SHA256' => string '9bb751b20e5d6cc1ea9b1ebf23ef2d5f07f99b2d9cc417bf1d70c04f8b20ec42' (length=64)
  'USER' => string 'www-data' (length=8)
  'HTTP_ACCEPT_LANGUAGE' => string 'en-US,en;q=0.9,ur;q=0.8' (length=23)
  'HTTP_ACCEPT_ENCODING' => string 'gzip, deflate' (length=13)
  'HTTP_ACCEPT' => string 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' (length=135)
  'HTTP_USER_AGENT' => string 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36' (length=114)
  'HTTP_UPGRADE_INSECURE_REQUESTS' => string '1' (length=1)
  'HTTP_CACHE_CONTROL' => string 'max-age=0' (length=9)
  'HTTP_CONNECTION' => string 'close' (length=5)
  'HTTP_X_FORWARDED_HOST' => string 'proxy' (length=5)
  'HTTP_X_FORWARDED_FOR' => string '192.168.224.1' (length=13)
  'HTTP_X_REAL_IP' => string '192.168.224.1' (length=13)
  'HTTP_HOST' => string 'web.local' (length=9)
  'SCRIPT_FILENAME' => string '/var/www/web/index.php' (length=22)
  'REDIRECT_STATUS' => string '200' (length=3)
  'SERVER_NAME' => string 'proxy' (length=5)
  'SERVER_PORT' => string '8110' (length=4)
  'SERVER_ADDR' => string '192.168.224.7' (length=13)
  'REMOTE_PORT' => string '54314' (length=5)
  'REMOTE_ADDR' => string '192.168.224.6' (length=13)
  'SERVER_SOFTWARE' => string 'nginx/1.21.3' (length=12)
  'GATEWAY_INTERFACE' => string 'CGI/1.1' (length=7)
  'REQUEST_SCHEME' => string 'http' (length=4)
  'SERVER_PROTOCOL' => string 'HTTP/1.0' (length=8)
  'DOCUMENT_ROOT' => string '/var/www/web' (length=12)
  'DOCUMENT_URI' => string '/index.php' (length=10)
  'REQUEST_URI' => string '/web/' (length=5)
  'SCRIPT_NAME' => string '/index.php' (length=10)
  'CONTENT_LENGTH' => string '' (length=0)
  'CONTENT_TYPE' => string '' (length=0)
  'REQUEST_METHOD' => string 'GET' (length=3)
  'QUERY_STRING' => string '' (length=0)
  'FCGI_ROLE' => string 'RESPONDER' (length=9)
  'PHP_SELF' => string '/index.php' (length=10)
  'REQUEST_TIME_FLOAT' => float 1635101620.5358
  'REQUEST_TIME' => int 1635101620
  'argv' => 
    array (size=0)
      empty
  'argc' => int 0

Update: I've changed the server > location block for php as below.

    location ~ ^/.+\.php(/|$) {
        return 200 $document_root$fastcgi_script_name;
        fastcgi_pass  php:9000;
#       fastcgi_index index.php;
        include       fastcgi_params;
#        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SCRIPT_FILENAME /var/www/web/help.php;
    }

Result: Even though I open the URL http://web.local/web/help.php, it downloads a file with content /var/www/web/index.php. With hardcoded SCRIPT_FILENAME it shows me the output of correct file i.e. help.php so doesn't look like a permission issue as I had felt earlier. I notice that fastcgi_index is also irrelevant.

Question: Where is the value of $document_root$fastcgi_script_name coming from?

0 Answers
Related