24

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;
}
Felipe Neuhauss
  • 341
  • 1
  • 2
  • 6
  • 2
    If I would guess, you haven't edited the nginx config to work with Laravel and are still relying on htaccess? htaccess is an Apache config file. Nginx doesn't read or use it at all. If you search for "nginx laravel setup" you will find plenty of examples how to setup the default config. If you have any custom rules in your htaccess, you need to migrate them into the nginx config file as well. – M. Eriksson May 06 '20 at 16:59

7 Answers7

52

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
Tiago Martins Peres
  • 14,289
  • 18
  • 86
  • 145
niallD
  • 664
  • 5
  • 5
  • 10
    This is the definitive fix and the correct way to do it, specially since running commands on ebs is not a very good practice. – Carlos Luis Rojas Aragonés May 16 '20 at 01:06
  • 5
    This should be accepted as correct answer -- ElasticBeanstalk config should be done through .ebextensions/.platforms and such; and not by manually tweaking server – jOpacic Jun 03 '20 at 15:46
  • Although this solves my issue, I am having to do this everytime i update something in the ec2 instance. Any idea why could that be? – Sijan Bhattarai Jun 15 '20 at 07:17
  • Sijan Bhattarai You shouldn't need to alter the ec2 instance directly if you are using elastic beanstalk, all the settings and configuration is done with EBS either using the console or with configuration files as above. Altering the ec2 instance directly will only be a transient change. – niallD Jun 16 '20 at 16:16
  • After spending many hours, finally, this works for me. I have created file "/.platform/nginx/conf.d/elasticbeanstalk/laravel.conf" in the laravel 8 project and then push into Github, Elastic Beanstalk recognizes changes and Done. – Imran_Developer Jun 25 '21 at 08:15
  • 1
    This is the best way to do it. No need to access instances through SSH, as it's against the way EBS should be handled anyway. – Umair Malhi Sep 08 '22 at 21:54
26

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
Tiago Martins Peres
  • 14,289
  • 18
  • 86
  • 145
John Welsh
  • 379
  • 4
  • 6
  • 1
    When ssh'ing into the EC2 instance you may get the error message 'Unprotected Private Key File' in this case run the command 'sudo chmod 600 your_private_key_name.pem' and enter your password. Try ssh'ing in again and this should work. – John Welsh May 21 '20 at 08:13
  • 1
    Can we add these commands in .ebextensions folder , so that it automatically runs at start ? – Guri S Jul 04 '20 at 07:54
  • Hey why do I have to keep changing my php.conf everytime I reboot the ec2 instance? Is it expected? – Sijan Bhattarai Jul 10 '20 at 10:12
  • I've attempted this approach 3 times and it caused the whole website to fail on each occasion... – jamesbcn Jul 24 '20 at 01:39
  • @SijanBhattarai To persist the change, at the root of your project create the following directory structure: .platform/nginx/conf.d/elasticbeanstalk and add php.conf with the contents of your conf.php file in it. That worked for me; the changes remain even after a reboot. – Steve Dimock Mar 19 '21 at 04:21
5

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
2

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;
}
Mugluck
  • 499
  • 1
  • 12
  • 24
  • No worries, if this answer helped, mark it as chosen. If you had a different configuration, put yours up for others searching for the same thing. :) – Mugluck May 10 '20 at 07:44
  • Hi. I access my php.conf using the `eb ssh`. Is this correct? There was a file exactly you told me. php.conf and it seams to be correct. `root /var/www/html/public;` `index index.php index.html index.htm;` I have added your extra lines about location. But it doesn't working. Should I access my EC2 instance? would not be `eb ssh` command accessing the EC2 instance? Thank you. – Felipe Neuhauss May 11 '20 at 01:51
  • It should be the ec2 instance in this case, root /var/www/html/public will not be correct as it's not factoring in the laravel folder --- /html/laravel-folder-here/public. – Mugluck May 11 '20 at 01:53
  • Ok, I will check my EC2 instance. Thank you! I have edited my question, added my complete php.conf. – Felipe Neuhauss May 11 '20 at 01:55
  • I think it might be a new change to EB builds as I couldn't find any references to the folder change. You should be able to change the root folder in the EB settings itself by adding your app name in first with lowercase and dashes, but I haven't tested that yet so it's just a hunch. /app-name-here/public – Mugluck May 11 '20 at 02:02
  • Yeah. I'm going to try added the app name on php.conf. When I access my EC2 instance, I got the same environment like I was accessing via `eb ssh`. – Felipe Neuhauss May 11 '20 at 02:50
  • ls into cd /var/www/html, what's in there? – Mugluck May 11 '20 at 05:09
  • Yeah. /var/www/html. Before I think it was placed on /var/www/html/current. But this changed too. – Felipe Neuhauss May 11 '20 at 10:41
  • I am looking now at my php.config file and the path to my index.php is `root /var/www/html/public`, not `root /var/www/html/your-laravel-app-name/public`... – jamesbcn Jul 24 '20 at 01:53
0

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.

22289d
  • 81
  • 1
  • 7
0

Try to change the Proxy Server to Apache.

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 26 '22 at 13:33
-1

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;
}
Khaled AbuShqear
  • 1,230
  • 14
  • 24