Deploy Laravel Project with Nginx on Linux. ⚡ 2 configuration only in .conf file

Deploy Laravel Project with Nginx Server on Ubuntu or Debian. This blog will show you how to install Laravel with Nginx on Ubuntu/Debian.

I faced an error while deploying Laravel project. The error how to fix index.php because this file is in public folder. Now it is fixed. As we simply add /public for root, e.g. root /home/hassam.dev/public_html/public I shared my Nginx config file. Hope it’ll be definitely helpful to you.

My Debian 11 and Nginx Server Details

Below are my server details, you can follow this tutorial on Ubuntu, PHP7+, and Nginx server.

  • Hetzner.com CPX11 Package [https://www.hetzner.com/cloud]
  • Debian 11
  • 2 Cores AMD Processor
  • 2GB RAM + 1GB Swap RAM
  • Virtualmin (website control panel)
  • Nginx
  • MySQL, MariaDB
  • PHP 8.2

Quick overview: Nginx Configuration for Laravel

In localhost, we ran a command php artisan serve to start the project and npm run dev to start Vite server. As we know index.php falls in public folder. To access index.php we need to visit http:hassam.dev/public So, how we can fix it? The solution is using Virtual Host so, it should route the traffic into the public directory inside the project directory.

1st change is to add /public on root variable 🖥

Here just add /public at the end of root. As we know index.php is in public folder, and normally we hit command php artisan serve on local server, and this is not recommand to use this command on a live server REASON we can’t access 127.0.0.1:8000 😅 So, by adding /public we set a project bootstrap path.

#! /bin/bash
sudo nano /etc/nginx/sites-available/hassam.dev.conf

#Before
listen 142.00.000.00;
root /home/hassam.dev/public_html;
index index.php index.htm index.html;

#After
listen 142.00.000.00;
root /home/hassam.dev/public_html/public;        #imp
index index.php index.htm index.html;

2nd change is to add fastcgi_param values 🎯

In location ~ ".php(/|$)" { we need to set fastcgi_param having value SCRIPT_FILENAME $realpath_root$fastcgi_script_name; and add include fastcgi_params; also. It will fix “no files available” error message.

#! /bin/bash
sudo nano /etc/nginx/sites-available/hassam.dev.conf



#Before
location ~ "\.php(/|$)" {
	try_files $uri $fastcgi_script_name =404;
	default_type application/x-httpd-php;
	fastcgi_pass unix:/var/php-fpm/168540012913414.sock;
}


#After
location ~ "\.php(/|$)" {
	try_files $uri $fastcgi_script_name =404;
	default_type application/x-httpd-php;
	fastcgi_pass unix:/var/php-fpm/168540012913414.sock;

	#fixing
	fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
	include fastcgi_params;
	#fixing
}
add fastcgi param values to fix files not found

All done. Configuration is completed, But if you want to learn how to enable gzip, add expiry headers and sitemap .xml issues then read the full article. 🧠

Complete .conf file for how to host Laravel on Nginx

I provided a full .conf file below.

#! /bin/bash
sudo nano /etc/nginx/sites-available/domain1.conf

Open up the config file from your terminal with this command sudo nano /etc/nginx/sites-available/hassam.dev.conf and update the code to the following: Replace hassam.dev with your domain name.

server {
    server_name domain1.com www.domain1.com;
    listen 143.190.21X.1XX;
    root /home/hassam.dev/public_html/public;    #important
    index index.php index.htm index.html;
    access_log /var/log/virtualmin/hassam.dev_access_log;
    error_log /var/log/virtualmin/hassam.dev_error_log;
    fastcgi_param GATEWAY_INTERFACE CGI/1.1;
    fastcgi_param SERVER_SOFTWARE nginx;
    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_FILENAME "/home/hassam.dev/public_html$fastcgi_script_name";
    fastcgi_param SCRIPT_NAME $fastcgi_script_name;
    fastcgi_param REQUEST_URI $request_uri;
    fastcgi_param DOCUMENT_URI $document_uri;
    fastcgi_param DOCUMENT_ROOT /home/hassam.dev/public_html;
    fastcgi_param SERVER_PROTOCOL $server_protocol;
    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;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param HTTPS $https;

    #not important but you can add
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    #important
    #fixed permalink_issues
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    #fixed permalink_issues

    location ^~ /.well-known/ {
        try_files $uri /;
    }
    location ~ "\.php(/|$)" {
        try_files $uri $fastcgi_script_name =404;
        default_type application/x-httpd-php;
        fastcgi_pass unix:/var/php-nginx/1671702822117723.sock/socket;

        #fixed index
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
        #fixed index
    }
    fastcgi_split_path_info "^(.+\.php)(/.+)$";
    location /cgi-bin/ {
        gzip off;
        root /home/domain1/cgi-bin;
        fastcgi_pass unix:/var/fcgiwrap/1671702822117723.sock/socket;
        fastcgi_param SCRIPT_FILENAME "/home/hassam.dev$fastcgi_script_name";
        fastcgi_param GATEWAY_INTERFACE CGI/1.1;
        fastcgi_param SERVER_SOFTWARE nginx;
        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 /home/hassam.dev/public_html;
        fastcgi_param SERVER_PROTOCOL $server_protocol;
        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;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS $https;
    }
    fastcgi_read_timeout 60;

    listen 143.198.21X.1XX:443 ssl;
    ssl_certificate /etc/ssl/virtualmin/1671702822XX7723/ssl.combined;
    ssl_certificate_key /etc/ssl/virtualmin/1671702822117XX3/ssl.key;
}

Save the file and restart Nginx with the following command

service nginx configtest
service nginx restart

How to enable GZIP on Nginx server

server {
    ....
    ....

    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_types
      application/geo+json
      application/javascript
      application/x-javascript
      application/json
      application/ld+json
      application/manifest+json
      application/rdf+xml
      application/rss+xml
      application/xhtml+xml
      application/xml
      font/eot
      font/otf
      font/ttf
      image/svg+xml
      text/css
      text/javascript
      text/plain
      text/xml;
    client_max_body_size 48M;
}

How to add Expires Headers for Nginx server

It’s best to set ExpiresByType headers for most of your site resources, including your HTML, CSS, JavaScript, and XML files and images and other media files. Then you can set an ExpiresDefault as a catch-all for the rest of your content. Expires headers tell the browser whether they should request a specific file from the server or whether they should grab it from the browser’s cache.

server {
    ....
    ....

	# Expiry Headers
	location ~* \.(jpg|jpeg|gif|png)$ {
    	expires 365d;
	}

	location ~* \.(pdf|css|html|js|swf)$ {
    	expires 30d;
	}
    location ~* \.(png|jpg|jpeg|gif)$ {
        expires 365d;
        add_header Cache-Control "public, no-transform";
    }

    location ~* \.(js|css|pdf|html|swf)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
	# END Expiry Headers
}

How to fix the sitemap issue on Nginx Server

server {
    ....
    ....

    # START Nginx Rewrites for Sitemaps
    rewrite ^/sitemap_index.xml$ /index.php?sitemap=1 last;
    rewrite ^/([^/]+?)-sitemap([0-9]+)?.xml$ /index.php?sitemap=$1&sitemap_n=$2 last;
    rewrite ^/([a-z]+)?-sitemap\.xsl$ /index.php?xsl=$1 last;
    # END Nginx Rewrites for Sitemaps
}

Related Articles

How to calculate VAT in PHP Laravel

Laravel CSRF Token Mismatch and 419 Page Expire

Should I use UUID as the primary key 🚨

72 / 100
Hassam
Hassam

I am passionate about open-source software, privacy, best practices, standards, user experience, and developer experience. My favorite stack these days are Laravel, Vue, and Tailwind. And focusing on Solid Principles, Data Structures, and Design Patterns.

Articles: 26

Leave a Reply

Your email address will not be published. Required fields are marked *