'Any AWS EB Laravel route getting 404 Not Found nginx/1.16.1

I've just deploy a new laravel 7 application on AWS Elastic beanstalk. I've noticed they changed the Apache server to Nginx server.

https://docs.aws.amazon.com/elasticbeanstalk/latest/platforms/platform-history-php.html

This is my api backend URL: http://mappab-api-staging.mappab.com.br/

This is the login route: http://mappab-api-staging.mappab.com.br/login - 404 status.

Did you get the same problem? How can I fix it?

My php.conf placed at /etc/nginx/conf.d/elasticbeanstalk/ is:

root /var/www/html/public;

index index.php index.html index.htm;

location / {
   try_files $uri $uri/ /index.php?$query_string;
}

location ~ /\.ht {
   deny all;
}

location ~ /.well-known {
   allow all;
}

location ~ \.(php|phar)(/.*)?$ {
    fastcgi_split_path_info ^(.+\.(?:php|phar))(/.*)$;

    fastcgi_intercept_errors on;
    fastcgi_index  index.php;

    fastcgi_param  QUERY_STRING       $query_string;
    fastcgi_param  REQUEST_METHOD     $request_method;
    fastcgi_param  CONTENT_TYPE       $content_type;
    fastcgi_param  CONTENT_LENGTH     $content_length;

    fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
    fastcgi_param  REQUEST_URI        $request_uri;
    fastcgi_param  DOCUMENT_URI       $document_uri;
    fastcgi_param  DOCUMENT_ROOT      $document_root;
    fastcgi_param  SERVER_PROTOCOL    $server_protocol;
    fastcgi_param  REQUEST_SCHEME     $scheme;
    fastcgi_param  HTTPS              $https if_not_empty;

    fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
    fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

    fastcgi_param  REMOTE_ADDR        $remote_addr;
    fastcgi_param  REMOTE_PORT        $remote_port;
    fastcgi_param  SERVER_ADDR        $server_addr;
    fastcgi_param  SERVER_PORT        $server_port;
    fastcgi_param  SERVER_NAME        $server_name;

    # PHP only, required if PHP was built with --enable-force-cgi-redirect
    fastcgi_param  REDIRECT_STATUS    200;

    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_param  PATH_INFO $fastcgi_path_info;
    fastcgi_pass   php-fpm;
}


Solution 1:[1]

If you are using Amazon Linux 2 with Elastic Beanstalk with an NGINX server then you need to follow this documentation.

Basically all you need to do is create a folder structure mapping the NGINX config location you want to place you config file with .platform as the topmost folder this should be in your application root

i.e. in a laravel app create a folder called .platform in the same level as the app folder. Within this .platform folder create the following

/nginx/conf.d/elasticbeanstalk

so you have a folder structure like .platform/nginx/conf.d/elasticbeanstalk

enter image description here

in this last folder elasticbeanstalk place your config file

e.g. laravel.conf

location / {
    try_files $uri $uri/ /index.php?$query_string;
    gzip_static on;
}

enter image description here

Once you upload the application to EB it will copy the file to the same location on the server and restart NGINX.


Extra

In some cases this might not be enough and when you try to go to any specific route you'll get a

419 | PAGE EXPIRED

enter image description here

To fix that simply SSH into your instance, go to the project location and clear the cache

php artisan cache:clear

Solution 2:[2]

I encountered the same issue, since April 30th 2020 EB is auto configured to nginx instead of apache so the htaccess file no longer works. So when I uploaded my code the front page (index.php) was working but not the api. This is what I did to solve the issue - taken from the AWS developer group: https://forums.aws.amazon.com/thread.jspa?messageID=942914&#942914

  1. SSH into the elastic beanstalk environment (you can generate a keypair in the EC2 instance, this will download a pem (private key file) and then attach the keypair in configurations/security in the elastic beanstalk environment).
  2. In terminal (on mac), navigate to where your private key is stored and use:
ssh -i "your_private_key_name.pem" ec2-user@your_server

You may get the error message that your PEM is too open in which case use the command:

chmod 400 your_private_key_name.pem
  1. Navigate to the php.conf file using:
cd /etc/nginx/conf.d/elasticbeanstalk
  1. Use this to enter the file:
sudo nano php.conf
  1. This will open the php.conf file which will look
# This file is managed by Elastic Beanstalk
#
# pass the PHP scripts to FastCGI server
#
# See conf.d/php-fpm.conf for socket configuration
#
root /var/www/html/public;

index index.php index.html index.htm;

location ~ \.(php|phar)(/.*)?$ {
    fastcgi_split_path_info ^(.+\.(?:php|phar))(/.*)$;

    fastcgi_intercept_errors on;
    fastcgi_index  index.php;

    fastcgi_param  QUERY_STRING       $query_string;
    fastcgi_param  REQUEST_METHOD     $request_method;
    fastcgi_param  CONTENT_TYPE       $content_type;
    fastcgi_param  CONTENT_LENGTH     $content_length;

    fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
    fastcgi_param  REQUEST_URI        $request_uri;
    fastcgi_param  DOCUMENT_URI       $document_uri;
    fastcgi_param  DOCUMENT_ROOT      $document_root;
    fastcgi_param  SERVER_PROTOCOL    $server_protocol;
    fastcgi_param  REQUEST_SCHEME     $scheme;
    fastcgi_param  HTTPS              $https if_not_empty;

    fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
    fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

    fastcgi_param  REMOTE_ADDR        $remote_addr;
    fastcgi_param  REMOTE_PORT        $remote_port;
    fastcgi_param  SERVER_ADDR        $server_addr;
    fastcgi_param  SERVER_PORT        $server_port;
    fastcgi_param  SERVER_NAME        $server_name;

    # PHP only, required if PHP was built with --enable-force-cgi-redirect
    fastcgi_param  REDIRECT_STATUS    200;

    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_param  PATH_INFO $fastcgi_path_info;
    fastcgi_pass   php-fpm;
}
  1. Insert the following into this after index and before location
location / {
    try_files $uri $uri/ /index.php?$query_string;
    gzip_static on;
}
  1. Save the document

  2. Run this command to restart nginx

sudo nginx -s reload
  1. Exit the environment, you're api should now work

Solution 3:[3]

I was in the same situation and I prepared a config file like below to update the default nginx setting that Elastic Beanstalk automatically provides.

  1. Prepare a file (nginx.conf) of your own nginx setting in a Laravel project.
~/workspace/your-laravel-app/
|-- .platform
|   -- nginx
|      -- nginx.conf
|-- other source files
  1. Edit your own nginx.conf like below.
user                    nginx;
error_log               /var/log/nginx/error.log warn;
pid                     /var/run/nginx.pid;
worker_processes        auto;
worker_rlimit_nofile    32153;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    include       conf.d/*.conf;

    map $http_upgrade $connection_upgrade {
        default     "upgrade";
    }

    server {
        listen        80 default_server;
        access_log    /var/log/nginx/access.log main;

        client_header_timeout 60;
        client_body_timeout   60;
        keepalive_timeout     60;
        gzip                  off;
        gzip_comp_level       4;
        gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;

        # Do not include the Elastic Beanstalk generated locations
        # include conf.d/elasticbeanstalk/*.conf;

        # Move Elastic Beanstalk healthd.conf content here
        if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2})") {
            set $year $1;
            set $month $2;
            set $day $3;
            set $hour $4;
        }

        access_log /var/log/nginx/healthd/application.log.$year-$month-$day-$hour healthd;

        # Move Elastic Beanstalk php.conf content here
        root /var/www/html/public;

        index index.php index.html index.htm;

        # This is an additional configuration
        location / {
            try_files $uri $uri/ /index.php?$query_string;
            gzip_static on;
        }

        location ~ \.(php|phar)(/.*)?$ {
            fastcgi_split_path_info ^(.+\.(?:php|phar))(/.*)$;

            fastcgi_intercept_errors on;
            fastcgi_index  index.php;

            fastcgi_param  QUERY_STRING       $query_string;
            fastcgi_param  REQUEST_METHOD     $request_method;
            fastcgi_param  CONTENT_TYPE       $content_type;
            fastcgi_param  CONTENT_LENGTH     $content_length;

            fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
            fastcgi_param  REQUEST_URI        $request_uri;
            fastcgi_param  DOCUMENT_URI       $document_uri;
            fastcgi_param  DOCUMENT_ROOT      $document_root;
            fastcgi_param  SERVER_PROTOCOL    $server_protocol;
            fastcgi_param  REQUEST_SCHEME     $scheme;
            fastcgi_param  HTTPS              $https if_not_empty;

            fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
            fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

            fastcgi_param  REMOTE_ADDR        $remote_addr;
            fastcgi_param  REMOTE_PORT        $remote_port;
            fastcgi_param  SERVER_ADDR        $server_addr;
            fastcgi_param  SERVER_PORT        $server_port;
            fastcgi_param  SERVER_NAME        $server_name;

            # PHP only, required if PHP was built with --enable-force-cgi-redirect
            fastcgi_param  REDIRECT_STATUS    200;

            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            fastcgi_param  PATH_INFO $fastcgi_path_info;
            fastcgi_pass   php-fpm;
        }
    }
}
  1. Deploy your change and your new configuration should be loaded.
$ eb deploy

Solution 4:[4]

So I just had this issue and had to figure it out. The default php implementation doesn't factor in the folder difference that laravel causes (and this isn't mentioned anywhere in the docs)

You need to track down your nginx site config on your ec2 server. For me it was:

/etc/nginx/conf.d/elasticbeanstalk/php.conf

sudo nano php.conf

root default is /var/www/html; This is incorrect, the laravel folder is added here, you need to add this in:

root /var/www/html/your-laravel-app-name/public;

You will need to be in your ec2 server for this, so you can always navigate to that folder and check it.

I'm sure other people will be able to provide what's need to auto-configure this in the elastic beanstalk environment.

I also added the following lines to the nginx config for a base laravel config:

location / {
   try_files $uri $uri/ /index.php?$query_string;
}

location ~ /\.ht {
   deny all;
}

location ~ /.well-known {
   allow all;
}

Solution 5:[5]

I ran into the same problem and solved it by realizing I misunderstood the AWS docs.

https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/php-laravel-tutorial.html#php-laravel-tutorial-generate

Where it says to 'Install Laravel and generate a website'

It does not mean to do this on AWS. You are to do this locally. And then deploy it to AWS via the Source Bundle, described next.

After doing this, it worked.

Solution 6:[6]

Try to change the Proxy Server to Apache.

Solution 7:[7]

I ran into the same problem, in my case it was solved by removing error_page directive from laravel.conf file

here is my configs file:

add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";

client_max_body_size 10M;

index index.php;

charset utf-8;

location / {
    try_files $uri $uri/ /index.php?$query_string;
    gzip_static on;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt  { access_log off; log_not_found off; }

#error_page 404 index.php;

location ~ /\.(?!well-known).* {
    deny all;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tiago Martins Peres
Solution 2 Tiago Martins Peres
Solution 3 Takuya Watahiki
Solution 4
Solution 5 22289d
Solution 6 sncrr20
Solution 7