Search code examples
laravelsslnginxlets-encryptvesta

How to fix 404 nginx error on routers after letsencrypt installation


I'm setting up a new server running on vestaCP+NGINX+php-fpm and laravel backend , after installing letsencrypt , I'm encountering with 404 error on all of my routers except the main page . the laravel .env is ok and my nginx conf is as follows , also , another nginx conf file has been created for ssl by the control panel . The site works without any problem on http protocol .

server {
    listen      xx.xxx.xxx.xx:443;
    server_name example.com www.example.com;
    root        /home/admin/web/example.com/public_html;
    index       index.php index.html index.htm;
    access_log  /var/log/nginx/domains/example.com.log combined;
    access_log  /var/log/nginx/domains/example.com.bytes bytes;
    error_log   /var/log/nginx/domains/example.com.error.log error;


    ssl         on;
    ssl_certificate      /home/admin/conf/web/ssl.example.com.pem;
    ssl_certificate_key  /home/admin/conf/web/ssl.example.com.key;

    location / {
             try_files $uri $uri/ /index.php$is_args$args;
    location ~* ^.+\.(jpeg|jpg|png|gif|bmp|ico|svg|css|js)$ {
        expires     max;
    }
    location ~ [^/]\.php(/|$) {
        fastcgi_param SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        if (!-f $document_root$fastcgi_script_name) {
        fastcgi_pass    127.0.0.1:9001;

        fastcgi_index   index.php;
        include         /etc/nginx/fastcgi_params;
    }
}

error_page  403 /error/404.html;
error_page  404 /error/404.html;
error_page  500 502 503 504 /error/50x.html;

location /error/ {
    alias   /home/admin/web/example.com/document_errors/;
}

location ~* "/\.(htaccess|htpasswd)$" {
    deny    all;
    return  404;
}
location /vstats/ {
    alias   /home/admin/web/example.com/stats/;
    include /home/admin/conf/web/example.com.auth*;
}

include     /etc/nginx/conf.d/phpmyadmin.inc*;
include     /etc/nginx/conf.d/phppgadmin.inc*;
include     /etc/nginx/conf.d/webmail.inc*;

include     /home/admin/conf/web/nginx.example.com.conf*;
}

Solution

  • The Problem

    I am not a Nginx expert, but it seems to me that all location directives should be inside the server directive, and currently they aren't. Also you have nested location directives that I think they aren't necessary...

    Start by trying to fix that with this:

    server {
        listen      xx.xxx.xxx.xx:443;
        server_name example.com www.example.com;
        root        /home/admin/web/example.com/public_html;
        index       index.php index.html index.htm;
        access_log  /var/log/nginx/domains/example.com.log combined;
        access_log  /var/log/nginx/domains/example.com.bytes bytes;
        error_log   /var/log/nginx/domains/example.com.error.log error;
    
    
        ssl         on;
        ssl_certificate      /home/admin/conf/web/ssl.example.com.pem;
        ssl_certificate_key  /home/admin/conf/web/ssl.example.com.key;
    
        location / {
            try_files $uri $uri/ /index.php$is_args$args;
        }
    
        location ~* ^.+\.(jpeg|jpg|png|gif|bmp|ico|svg|css|js)$ {
            expires     max;
        }
    
        location ~ \.php$ {
            # https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/
            #try_files $uri =404;
            #try index.php =404;
    
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            #fastcgi_pass php:9000;
            fastcgi_pass  127.0.0.1:9001;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_intercept_errors off;
            fastcgi_buffer_size 16k;
            fastcgi_buffers 4 16k;
        }
    
        error_page  403 /error/404.html;
        error_page  404 /error/404.html;
        error_page  500 502 503 504 /error/50x.html;
    
        location /error/ {
            alias   /home/admin/web/example.com/document_errors/;
        }
    
        location ~* "/\.(htaccess|htpasswd)$" {
            deny    all;
            return  404;
        }
    
        location /vstats/ {
            alias   /home/admin/web/example.com/stats/;
            include /home/admin/conf/web/example.com.auth*;
        }
    
        include     /etc/nginx/conf.d/phpmyadmin.inc*;
        include     /etc/nginx/conf.d/phppgadmin.inc*;
        include     /etc/nginx/conf.d/webmail.inc*;
    
        include     /home/admin/conf/web/nginx.example.com.conf*;
    }
    

    NOTE: This isn't tested, thus try it in development and if you fix any syntax in the file or an error please let me know so that I can update the answer. If you can't fix please let us know what went wrong so that we can try further help.

    Possible Improvement

    Once you use Laravel you can try to follow the Nginx configuration Php Docker Stack that works straight out of the box with Laravel.

    The bit you need to copy to replace the current one in your Nginx conf server{} directive is this one:

    
        # In Laravel we only need serve index.php
        location @proxyphp {
            rewrite (.*) /index.php;
        }
    
        # serving only index.php increases the security in your application. 
        location ~ /index\.php$ {
            # https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/
            #try_files $uri =404;
            #try index.php =404;
    
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass php:9000;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_intercept_errors off;
            fastcgi_buffer_size 16k;
            fastcgi_buffers 4 16k;
        }
    
        # Deny access to all php files that are not index.php
        location ~ \.php$ {
            deny all;
        }
    

    The Security Improvments

    In Laravel we only need to serve index.php and doing it so increases the security in your application, once it only have 1 public entry point, instead of being accessible by any *.php in the public folder of Laravel app.