5

I have a React frontend and a Symfony backend I'm trying to serve on the same domain. The React frontend needs to serve assets if they exist otherwise fallback to serve index.html.

I'd like to serve the php Symfony app when /api is in the request uri. Similar to the React app, I need all requests to go to the index.php file.

The frontend is being served correctly but not the api. I get a 404 from nginx when i hit /api in the browser.

I feel like i'm close but for some reason nginx doesn't have the correct $document_root. I'm adding a header(X-script) to test what the variables are and I'm getting the following:

X-script: /usr/share/nginx/html/index.php

Here's my nginx config.

server {
    listen 80 default_server;
    index index.html index.htm;

    access_log /var/log/nginx/my-site.com.log;
    error_log /var/log/nginx/my-site.com-error.log error;

    charset utf-8;

    location /api {
        root /var/www/my-site.com/backend;
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location / {
        root /var/www/my-site.com/frontend;
        try_files $uri /index.html;
    }
    location ~* \.php$ {
        add_header X-script "$document_root$fastcgi_script_name" always;
        try_files $fastcgi_script_name =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS off;
    }
}

Any help would be much appreciated.

0

3 Answers 3

1

The web root of a Symfony 4 project must include the public subfolder. I am not using NGINX but I think this is the correct configuration:

location /api {
    root /var/www/my-site.com/backend/public;
Sign up to request clarification or add additional context in comments.

1 Comment

hey thanks but that's not the problem. i took symfony out of the equation and it still didn't work. /var/www/my-site.com/backend/index.php exists and just has phpinfo(); in it but it's still not being served.
1
+100

In the following vhost, the most important changes I made are :

  • commented out index directive in server block : it is handled directly in locations blocks
  • added a slash after location /api/ and remove unnecessary $uri/ in the same api location block
  • moved the php_fpm logic to index.php location block : you want all requests to be passed to front controller in Symfony app
  • For the same reason, moved the 404 logic to a general php block, which will handle any other php file request

server {
    listen 80 default_server;

    access_log /var/log/nginx/my-site.com.log;
    error_log /var/log/nginx/my-site.com-error.log error;

    charset utf-8;

    location /api/ {
        root /var/www/my-site.com/backend;
        try_files $uri  /index.php$is_args$args;
    }

    location / {
        root /var/www/my-site.com/frontend;
        try_files $uri /index.html;
    }

    location ~ ^/index\.php(/|$) {
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        fastcgi_param HTTPS off;

        internal;
    }

    # return 404 for all other php files not matching the front controller
    # this prevents access to other php files you don't want to be accessible.
    location ~ \.php$ {
        return 404;
    }
}

Last, I bet you'll have to add symfony public folder into api location block root directive.

This vhost was tested fine on my localhost with following tree.

api_test
  - backend
    - index.php
  - frontend
    - index.html

I can successfully access to

  • backend/index.php from api_test.dv/api
  • frontend/index.html from api_test.dv/

Comments

0

Kojos answer is excellent, but to make it completely functional a root directive needs to be added under server or an error message “primary script unknown” will be observed. This is almost always related to a wrongly set SCRIPT_FILENAME in the nginx fastcgi_param directive.

# Nginx configuration
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name ${NGINX_HOST};

    root /var/www/html/backend/public;

    access_log /var/log/nginx/access_log.log;
    error_log /var/log/nginx/error.log error;

    charset utf-8;

    location / {
        root /var/www/html/frontend/build;
        try_files $uri /index.html;
    }

    location /api {
        alias /var/www/html/backend/public;
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/index\.php(/|$) {
        fastcgi_pass php-fpm:9000;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;

        internal;
    }

    # return 404 for all other php files not matching the front controller
    # this prevents access to other php files you don't want to be accessible.
    location ~ \.php$ {
        return 404;
    }
}

1 Comment

it return me an empty page and it also doesn't show any error in log

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.